diff --git a/financial-services-accelerator/components/org.wso2.financial.services.accelerator.consent.mgt.dao/src/main/java/org/wso2/financial/services/accelerator/consent/mgt/dao/ConsentCoreDAO.java b/financial-services-accelerator/components/org.wso2.financial.services.accelerator.consent.mgt.dao/src/main/java/org/wso2/financial/services/accelerator/consent/mgt/dao/ConsentCoreDAO.java index a856dfde0..ca6f7a032 100644 --- a/financial-services-accelerator/components/org.wso2.financial.services.accelerator.consent.mgt.dao/src/main/java/org/wso2/financial/services/accelerator/consent/mgt/dao/ConsentCoreDAO.java +++ b/financial-services-accelerator/components/org.wso2.financial.services.accelerator.consent.mgt.dao/src/main/java/org/wso2/financial/services/accelerator/consent/mgt/dao/ConsentCoreDAO.java @@ -197,6 +197,16 @@ void updateAuthorizationUser(Connection connection, String authorizationID, Stri boolean updateAuthorizationResources(Connection connection, List authorizationResources) throws ConsentDataUpdationException; + /** + * This method is used to delete the given list of authorization resources. + * + * @param connection connection object + * @param authorizationResourceIds a list of authorization resource IDs that should be deleted + * @throws ConsentDataDeletionException thrown if a database error occurs + */ + boolean deleteAuthorizationResources(Connection connection, List authorizationResourceIds) + throws ConsentDataDeletionException; + /** * This method is used to store the consent mapping resource in the database. The request consent mapping object * must contain all the data in it without the consent mapping ID. It will be generated and set to the response @@ -259,6 +269,16 @@ void updateConsentMappingStatus(Connection connection, ArrayList mapping public boolean updateConsentMappingResources(Connection connection, List consentMappingResources) throws ConsentDataUpdationException; + /** + * This method is used to delete the given list of consent mapping resource Ids. + * + * @param connection connection object + * @param consentMappingResourceIds a list of consent mapping resource Ids that should be deleted + * @throws ConsentDataDeletionException thrown if a database error occurs + */ + boolean deleteConsentMappingResources(Connection connection, List consentMappingResourceIds) + throws ConsentDataDeletionException; + /** * This method is used to store the consent attributes in the database. The request consent attributes object * must be set with a consent ID and consent attribute map. diff --git a/financial-services-accelerator/components/org.wso2.financial.services.accelerator.consent.mgt.dao/src/main/java/org/wso2/financial/services/accelerator/consent/mgt/dao/constants/ConsentMgtDAOConstants.java b/financial-services-accelerator/components/org.wso2.financial.services.accelerator.consent.mgt.dao/src/main/java/org/wso2/financial/services/accelerator/consent/mgt/dao/constants/ConsentMgtDAOConstants.java index c997a2a93..7f79807e0 100644 --- a/financial-services-accelerator/components/org.wso2.financial.services.accelerator.consent.mgt.dao/src/main/java/org/wso2/financial/services/accelerator/consent/mgt/dao/constants/ConsentMgtDAOConstants.java +++ b/financial-services-accelerator/components/org.wso2.financial.services.accelerator.consent.mgt.dao/src/main/java/org/wso2/financial/services/accelerator/consent/mgt/dao/constants/ConsentMgtDAOConstants.java @@ -126,6 +126,8 @@ public class ConsentMgtDAOConstants { "authorization user in the database"; public static final String CONSENT_AUTHORIZATION_RESOURCE_UPDATE_ERROR_MSG = "Error occurred while updating " + "authorization resource in the database"; + public static final String CONSENT_AUTHORIZATION_RESOURCE_DELETE_ERROR_MSG = "Error occurred while deleting " + + "authorization resource in the database"; public static final String CONSENT_MAPPING_RESOURCE_STORE_ERROR_MSG = "Error occurred while storing consent " + "mapping resource in the database"; public static final String CONSENT_MAPPING_RETRIEVE_ERROR_MSG = "Error occurred while retrieving consent mapping " + @@ -134,6 +136,8 @@ public class ConsentMgtDAOConstants { "mapping status in the database"; public static final String CONSENT_MAPPING_RESOURCE_UPDATE_ERROR_MSG = "Error occurred while updating consent " + "mapping resource in the database"; + public static final String CONSENT_MAPPING_RESOURCE_DELETE_ERROR_MSG = "Error occurred while deleting consent " + + "mapping resource in the database"; public static final String CONSENT_ATTRIBUTES_STORE_ERROR_MSG = "Error occurred while storing consent attributes " + "in the database"; public static final String CONSENT_ATTRIBUTES_RETRIEVE_ERROR_MSG = "Error occurred while retrieving consent " + diff --git a/financial-services-accelerator/components/org.wso2.financial.services.accelerator.consent.mgt.dao/src/main/java/org/wso2/financial/services/accelerator/consent/mgt/dao/impl/ConsentCoreDAOImpl.java b/financial-services-accelerator/components/org.wso2.financial.services.accelerator.consent.mgt.dao/src/main/java/org/wso2/financial/services/accelerator/consent/mgt/dao/impl/ConsentCoreDAOImpl.java index 90ea3bfa0..46defc190 100644 --- a/financial-services-accelerator/components/org.wso2.financial.services.accelerator.consent.mgt.dao/src/main/java/org/wso2/financial/services/accelerator/consent/mgt/dao/impl/ConsentCoreDAOImpl.java +++ b/financial-services-accelerator/components/org.wso2.financial.services.accelerator.consent.mgt.dao/src/main/java/org/wso2/financial/services/accelerator/consent/mgt/dao/impl/ConsentCoreDAOImpl.java @@ -546,6 +546,41 @@ public boolean updateAuthorizationResources(Connection connection, List authorizationResourceIds) + throws ConsentDataDeletionException { + + log.info(String.format("Deleting authorization resources. Count: %s", authorizationResourceIds.size())); + String deleteAuthorizationResourcePrepStatement = + sqlStatements.getDeleteAuthorizationResourcePreparedStatement(); + + try (PreparedStatement deleteAuthorizationResourcePreparedStmt = + connection.prepareStatement(deleteAuthorizationResourcePrepStatement)) { + + log.debug("Setting parameters to prepared statement to batch delete authorization resources"); + + for (String authId : authorizationResourceIds) { + deleteAuthorizationResourcePreparedStmt.setString(1, authId); + deleteAuthorizationResourcePreparedStmt.addBatch(); + } + + int[] results = deleteAuthorizationResourcePreparedStmt.executeBatch(); + boolean allDeleted = Arrays.stream(results) + .allMatch(result -> result > 0 || result == java.sql.Statement.SUCCESS_NO_INFO); + if (allDeleted) { + log.debug("Batch delete for authorization resources completed successfully."); + return true; + } else { + log.error("Some or all rows were not deleted in batch delete for authorization resources."); + throw new ConsentDataDeletionException("Failed to delete one or more authorization resources."); + } + } catch (SQLException e) { + log.error(ConsentMgtDAOConstants.CONSENT_AUTHORIZATION_RESOURCE_DELETE_ERROR_MSG, e); + throw new ConsentDataDeletionException( + ConsentMgtDAOConstants.CONSENT_AUTHORIZATION_RESOURCE_DELETE_ERROR_MSG, e); + } + } + @Override public ConsentMappingResource storeConsentMappingResource(Connection connection, @@ -733,6 +768,40 @@ public boolean updateConsentMappingResources(Connection connection, List consentMappingResourceIds) + throws ConsentDataDeletionException { + + log.info(String.format("Deleting consent mapping resources. Count: %s", consentMappingResourceIds.size())); + String deleteConsentMappingResourcePrepStatement = + sqlStatements.getDeleteConsentMappingResourcePreparedStatement(); + + try (PreparedStatement deleteConsentMappingResourcePreparedStmt = + connection.prepareStatement(deleteConsentMappingResourcePrepStatement)) { + + log.debug("Setting parameters to prepared statement to batch delete consent mapping resources"); + + for (String mappingId : consentMappingResourceIds) { + deleteConsentMappingResourcePreparedStmt.setString(1, mappingId); + deleteConsentMappingResourcePreparedStmt.addBatch(); + } + + int[] results = deleteConsentMappingResourcePreparedStmt.executeBatch(); + boolean allDeleted = Arrays.stream(results) + .allMatch(result -> result > 0 || result == java.sql.Statement.SUCCESS_NO_INFO); + if (allDeleted) { + log.debug("Batch delete for consent mapping resources completed successfully."); + return true; + } else { + log.error("Some or all rows were not deleted in batch delete for consent mapping resources."); + throw new ConsentDataDeletionException("Failed to delete one or more consent mapping resources."); + } + } catch (SQLException e) { + log.error(ConsentMgtDAOConstants.CONSENT_MAPPING_RESOURCE_DELETE_ERROR_MSG, e); + throw new ConsentDataDeletionException(ConsentMgtDAOConstants.CONSENT_MAPPING_RESOURCE_DELETE_ERROR_MSG, e); + } + } + @Override public boolean storeConsentAttributes(Connection connection, ConsentAttributes consentAttributes) diff --git a/financial-services-accelerator/components/org.wso2.financial.services.accelerator.consent.mgt.dao/src/main/java/org/wso2/financial/services/accelerator/consent/mgt/dao/queries/ConsentMgtCommonDBQueries.java b/financial-services-accelerator/components/org.wso2.financial.services.accelerator.consent.mgt.dao/src/main/java/org/wso2/financial/services/accelerator/consent/mgt/dao/queries/ConsentMgtCommonDBQueries.java index 5c9574063..7dfd66ca4 100644 --- a/financial-services-accelerator/components/org.wso2.financial.services.accelerator.consent.mgt.dao/src/main/java/org/wso2/financial/services/accelerator/consent/mgt/dao/queries/ConsentMgtCommonDBQueries.java +++ b/financial-services-accelerator/components/org.wso2.financial.services.accelerator.consent.mgt.dao/src/main/java/org/wso2/financial/services/accelerator/consent/mgt/dao/queries/ConsentMgtCommonDBQueries.java @@ -41,7 +41,7 @@ public String getGetConsentWithConsentAttributesPreparedStatement() { return "SELECT FS_CONSENT.CONSENT_ID, RECEIPT, CREATED_TIME, UPDATED_TIME, CLIENT_ID, CONSENT_TYPE, " + "CURRENT_STATUS, CONSENT_FREQUENCY, VALIDITY_TIME, RECURRING_INDICATOR, " + - "FS_CONSENT_ATTRIBUTE.ATT_KEY, FS_CONSENT_ATTRIBUTE.ATT_VALUE FROM FS_CONSENT RIGHT JOIN " + + "FS_CONSENT_ATTRIBUTE.ATT_KEY, FS_CONSENT_ATTRIBUTE.ATT_VALUE FROM FS_CONSENT LEFT JOIN " + "FS_CONSENT_ATTRIBUTE ON FS_CONSENT.CONSENT_ID = FS_CONSENT_ATTRIBUTE.CONSENT_ID WHERE FS_CONSENT" + ".CONSENT_ID = ?"; } @@ -125,6 +125,11 @@ public String getUpdateAuthorizationResourcePreparedStatement() { "WHERE AUTH_ID = ?"; } + public String getDeleteAuthorizationResourcePreparedStatement() { + + return "DELETE FROM FS_CONSENT_AUTH_RESOURCE WHERE AUTH_ID = ?"; + } + public String getStoreConsentMappingPreparedStatement() { return "INSERT INTO FS_CONSENT_MAPPING (MAPPING_ID, AUTH_ID, ACCOUNT_ID, PERMISSION, MAPPING_STATUS) VALUES " + @@ -146,6 +151,12 @@ public String getUpdateConsentMappingResourcePreparedStatement() { return "UPDATE FS_CONSENT_MAPPING SET PERMISSION = ?, MAPPING_STATUS = ? WHERE MAPPING_ID = ?"; } + public String getDeleteConsentMappingResourcePreparedStatement() { + + return "DELETE FROM FS_CONSENT_MAPPING WHERE MAPPING_ID = ? "; + } + + public String getStoreConsentAttributesPreparedStatement() { return "INSERT INTO FS_CONSENT_ATTRIBUTE (CONSENT_ID, ATT_KEY, ATT_VALUE) VALUES (?, ?, ?)"; diff --git a/financial-services-accelerator/components/org.wso2.financial.services.accelerator.consent.mgt.dao/src/test/java/org/wso2/financial/services/accelerator/consent/mgt/dao/impl/ConsentCoreDAOTests.java b/financial-services-accelerator/components/org.wso2.financial.services.accelerator.consent.mgt.dao/src/test/java/org/wso2/financial/services/accelerator/consent/mgt/dao/impl/ConsentCoreDAOTests.java index ab5987a06..f08403b0a 100644 --- a/financial-services-accelerator/components/org.wso2.financial.services.accelerator.consent.mgt.dao/src/test/java/org/wso2/financial/services/accelerator/consent/mgt/dao/impl/ConsentCoreDAOTests.java +++ b/financial-services-accelerator/components/org.wso2.financial.services.accelerator.consent.mgt.dao/src/test/java/org/wso2/financial/services/accelerator/consent/mgt/dao/impl/ConsentCoreDAOTests.java @@ -47,6 +47,7 @@ import java.sql.SQLException; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collections; import java.util.List; import java.util.Map; import java.util.UUID; @@ -675,6 +676,44 @@ public void testUpdateAuthorizationUserWithUnmatchedAuthID() throws Exception { } } + @Test + public void testDeleteAuthorizationResource() throws Exception { + + ConsentResource storedConsentResource; + AuthorizationResource storedAuthorizationResource; + ConsentResource consentResource = ConsentMgtDAOTestData.getSampleTestConsentResource(); + + try (Connection connection = DAOUtils.getConnection(DB_NAME)) { + + storedConsentResource = consentCoreDAO.storeConsentResource(connection, consentResource); + Assert.assertNotNull(storedConsentResource.getConsentID()); + + AuthorizationResource authorizationResource = new AuthorizationResource(); + authorizationResource.setConsentID(storedConsentResource.getConsentID()); + authorizationResource.setAuthorizationType(ConsentMgtDAOTestData.SAMPLE_AUTHORIZATION_TYPE); + authorizationResource.setUserID(ConsentMgtDAOTestData.SAMPLE_USER_ID); + authorizationResource.setAuthorizationStatus(ConsentMgtDAOTestData.SAMPLE_AUTHORIZATION_STATUS); + + storedAuthorizationResource = consentCoreDAO.storeAuthorizationResource(connection, + authorizationResource); + + Assert.assertNotNull(storedAuthorizationResource.getConsentID()); + Assert.assertNotNull(storedAuthorizationResource.getAuthorizationID()); + + boolean result = consentCoreDAO.deleteAuthorizationResources(connection, + Collections.singletonList(storedAuthorizationResource.getAuthorizationID())); + Assert.assertTrue(result); + } + } + + @Test(expectedExceptions = ConsentDataDeletionException.class) + public void testDeleteAuthorizationResourceError() throws Exception { + + Mockito.doThrow(SQLException.class).when(mockedConnection).prepareStatement(Mockito.anyString()); + + consentCoreDAO.deleteAuthorizationResources(mockedConnection, Collections.singletonList("1234")); + } + @Test public void testStoreConsentMappingResource() throws Exception { @@ -850,6 +889,57 @@ public void testUpdateConsentMappingStatusSQLError() throws Exception { ConsentMgtDAOTestData.SAMPLE_MAPPING_STATUS); } + @Test + public void testDeleteConsentMappingResource() throws Exception { + + ConsentResource storedConsentResource; + AuthorizationResource storedAuthorizationResource; + ConsentMappingResource storedConsentMappingResource; + ConsentResource consentResource = ConsentMgtDAOTestData.getSampleTestConsentResource(); + + try (Connection connection = DAOUtils.getConnection(DB_NAME)) { + + storedConsentResource = consentCoreDAO.storeConsentResource(connection, consentResource); + Assert.assertNotNull(storedConsentResource.getConsentID()); + + AuthorizationResource authorizationResource = new AuthorizationResource(); + authorizationResource.setConsentID(storedConsentResource.getConsentID()); + authorizationResource.setAuthorizationType(ConsentMgtDAOTestData.SAMPLE_AUTHORIZATION_TYPE); + authorizationResource.setUserID(ConsentMgtDAOTestData.SAMPLE_USER_ID); + authorizationResource.setAuthorizationStatus(ConsentMgtDAOTestData.SAMPLE_AUTHORIZATION_STATUS); + + storedAuthorizationResource = consentCoreDAO.storeAuthorizationResource(connection, + authorizationResource); + + Assert.assertNotNull(storedAuthorizationResource.getConsentID()); + Assert.assertNotNull(storedAuthorizationResource.getAuthorizationID()); + + ConsentMappingResource consentMappingResource = new ConsentMappingResource(); + consentMappingResource.setAuthorizationID(storedAuthorizationResource.getAuthorizationID()); + consentMappingResource.setAccountID(ConsentMgtDAOTestData.SAMPLE_ACCOUNT_ID); + consentMappingResource.setPermission(ConsentMgtDAOTestData.SAMPLE_PERMISSION); + consentMappingResource.setMappingStatus(ConsentMgtDAOTestData.SAMPLE_MAPPING_STATUS); + + storedConsentMappingResource = consentCoreDAO.storeConsentMappingResource(connection, + consentMappingResource); + + Assert.assertNotNull(storedConsentMappingResource.getMappingID()); + Assert.assertNotNull(storedConsentMappingResource.getAuthorizationID()); + + boolean result = consentCoreDAO.deleteConsentMappingResources(connection, + Collections.singletonList(storedConsentMappingResource.getMappingID())); + Assert.assertTrue(result); + } + } + + @Test(expectedExceptions = ConsentDataDeletionException.class) + public void testDeleteConsentMappingResourceError() throws Exception { + + Mockito.doThrow(SQLException.class).when(mockedConnection).prepareStatement(Mockito.anyString()); + + consentCoreDAO.deleteConsentMappingResources(mockedConnection, Collections.singletonList("1234")); + } + @Test public void testStoreConsentAttributes() throws Exception { diff --git a/financial-services-accelerator/components/org.wso2.financial.services.accelerator.consent.mgt.extensions/src/main/java/org/wso2/financial/services/accelerator/consent/mgt/extensions/common/ConsentExtensionConstants.java b/financial-services-accelerator/components/org.wso2.financial.services.accelerator.consent.mgt.extensions/src/main/java/org/wso2/financial/services/accelerator/consent/mgt/extensions/common/ConsentExtensionConstants.java index 385ab458c..ed146f94f 100644 --- a/financial-services-accelerator/components/org.wso2.financial.services.accelerator.consent.mgt.extensions/src/main/java/org/wso2/financial/services/accelerator/consent/mgt/extensions/common/ConsentExtensionConstants.java +++ b/financial-services-accelerator/components/org.wso2.financial.services.accelerator.consent.mgt.extensions/src/main/java/org/wso2/financial/services/accelerator/consent/mgt/extensions/common/ConsentExtensionConstants.java @@ -27,10 +27,12 @@ public class ConsentExtensionConstants { public static final String ACCOUNTS = "accounts"; public static final String PAYMENTS = "payments"; public static final String FUNDS_CONFIRMATIONS = "fundsconfirmations"; + public static final String INTERNAL_UPDATE = "internal-consent-update"; public static final String DEFAULT = "default"; public static final String ACCOUNT_CONSENT_PATH = "account-access-consents"; public static final String COF_CONSENT_PATH = "funds-confirmation-consents"; public static final String PAYMENT_CONSENT_PATH = "payment-consents"; + public static final String CONSENT_UPDATE_PATH = "^consent/([^/?]+)$"; public static final String CONSENT_DATA = "consentData"; public static final String CONSUMER_DATA = "consumerData"; public static final String TITLE = "title"; diff --git a/financial-services-accelerator/components/org.wso2.financial.services.accelerator.consent.mgt.extensions/src/main/java/org/wso2/financial/services/accelerator/consent/mgt/extensions/manage/impl/DefaultConsentManageHandler.java b/financial-services-accelerator/components/org.wso2.financial.services.accelerator.consent.mgt.extensions/src/main/java/org/wso2/financial/services/accelerator/consent/mgt/extensions/manage/impl/DefaultConsentManageHandler.java index b7ba55933..204c620ac 100644 --- a/financial-services-accelerator/components/org.wso2.financial.services.accelerator.consent.mgt.extensions/src/main/java/org/wso2/financial/services/accelerator/consent/mgt/extensions/manage/impl/DefaultConsentManageHandler.java +++ b/financial-services-accelerator/components/org.wso2.financial.services.accelerator.consent.mgt.extensions/src/main/java/org/wso2/financial/services/accelerator/consent/mgt/extensions/manage/impl/DefaultConsentManageHandler.java @@ -149,16 +149,41 @@ public void handleGet(ConsentManageData consentManageData) throws ConsentExcepti ConsentOperationEnum.CONSENT_RETRIEVE); try { + if (ConsentManageUtils.isInternalConsentRequest(consentManageData)) { + // Allowing consent retrieval for internal purpose. Retrieving the detailed consent and response back + // for internal consent retrieval requests + log.info(String.format("Processing internal consent retrieval request for consentId: %s", + consentId.replaceAll("[\r\n]+", " "))); + DetailedConsentResource detailedConsentResource = consentCoreService.getDetailedConsent(consentId); + if (detailedConsentResource == null) { + log.error(String.format("Consent not found for consent ID: %s", + consentId.replaceAll("[\r\n]+", " "))); + throw new ConsentException(ResponseStatus.BAD_REQUEST, "Consent not found", + ConsentOperationEnum.CONSENT_RETRIEVE); + } + if (!detailedConsentResource.getClientID().equals(consentManageData.getClientId())) { + //Throwing this error in a generic manner since client will not be able to identify if consent + // exists if consent does not belong to them + log.error(ConsentManageConstants.CLIENT_ID_MISMATCH_ERROR); + throw new ConsentException(ResponseStatus.BAD_REQUEST, + ConsentManageConstants.CLIENT_ID_MISMATCH_ERROR, ConsentOperationEnum.CONSENT_RETRIEVE); + } + consentManageData.setResponsePayload(ConsentManageUtils + .constructInternalConsentResponse(detailedConsentResource)); + consentManageData.setResponseStatus(ResponseStatus.OK); + return; + } + ConsentResource consent = consentCoreService.getConsent(consentId, false); if (consent == null) { - log.error("Consent not found"); + log.error(String.format("Consent not found for consent ID: %s", consentId.replaceAll("[\r\n]+", " "))); throw new ConsentException(ResponseStatus.BAD_REQUEST, "Consent not found", ConsentOperationEnum.CONSENT_RETRIEVE); } // Check whether the client id is matching if (!consent.getClientID().equals(consentManageData.getClientId())) { - log.error("Client ID mismatch"); - throw new ConsentException(ResponseStatus.BAD_REQUEST, "Client ID mismatch", + log.error(ConsentManageConstants.CLIENT_ID_MISMATCH_ERROR); + throw new ConsentException(ResponseStatus.BAD_REQUEST, ConsentManageConstants.CLIENT_ID_MISMATCH_ERROR, ConsentOperationEnum.CONSENT_RETRIEVE); } @@ -228,7 +253,7 @@ public void handlePost(ConsentManageData consentManageData) throws ConsentExcept if (!FinancialServicesUtils.isValidClientId(consentManageData.getClientId())) { log.error("Client ID does not exist in the system."); throw new ConsentException(ResponseStatus.BAD_REQUEST, "Client ID does not exist in the system.", - ConsentOperationEnum.CONSENT_RETRIEVE); + ConsentOperationEnum.CONSENT_CREATE); } //Validate Initiation headers @@ -352,7 +377,7 @@ public void handleDelete(ConsentManageData consentManageData) throws ConsentExce if (!FinancialServicesUtils.isValidClientId(consentManageData.getClientId())) { log.error("Client ID does not exist in the system."); throw new ConsentException(ResponseStatus.BAD_REQUEST, "Client ID does not exist in the system.", - ConsentOperationEnum.CONSENT_RETRIEVE); + ConsentOperationEnum.CONSENT_DELETE); } //Validate Initiation headers @@ -388,9 +413,9 @@ public void handleDelete(ConsentManageData consentManageData) throws ConsentExce if (!consentResource.getClientID().equals(consentManageData.getClientId())) { //Throwing this error in a generic manner since client will not be able to identify if consent // exists if consent does not belong to them - log.error(ConsentManageConstants.NO_CONSENT_FOR_CLIENT_ERROR); - throw new ConsentException(ResponseStatus.BAD_REQUEST, - ConsentManageConstants.NO_CONSENT_FOR_CLIENT_ERROR, ConsentOperationEnum.CONSENT_DELETE); + log.error(ConsentManageConstants.CLIENT_ID_MISMATCH_ERROR); + throw new ConsentException(ResponseStatus.BAD_REQUEST, ConsentManageConstants.CLIENT_ID_MISMATCH_ERROR, + ConsentOperationEnum.CONSENT_DELETE); } if (isExtensionsEnabled && isExternalPreConsentRevocationEnabled) { @@ -446,9 +471,77 @@ public void handleDelete(ConsentManageData consentManageData) throws ConsentExce @Override public void handlePut(ConsentManageData consentManageData) throws ConsentException { - log.error("Method PUT is not supported"); - throw new ConsentException(ResponseStatus.METHOD_NOT_ALLOWED, "Method PUT is not supported", + if (consentManageData.getRequestPath() == null) { + log.error("Resource Path Not Found"); + throw new ConsentException(ResponseStatus.BAD_REQUEST, "Resource Path Not Found", + ConsentOperationEnum.CONSENT_UPDATE); + } + + if (!consentManageData.getRequestPath().matches(ConsentExtensionConstants.CONSENT_UPDATE_PATH) && + !ConsentManageUtils.isInternalConsentRequest(consentManageData)) { + log.error("Method PUT is not supported"); + throw new ConsentException(ResponseStatus.METHOD_NOT_ALLOWED, "Method PUT is not supported", + ConsentOperationEnum.CONSENT_UPDATE); + } + + //Check whether client ID exists + if (StringUtils.isEmpty(consentManageData.getClientId())) { + log.error("Client ID missing in the request."); + throw new ConsentException(ResponseStatus.BAD_REQUEST, "Client ID missing in the request.", + ConsentOperationEnum.CONSENT_UPDATE); + } + + //Check whether client ID is valid + if (!FinancialServicesUtils.isValidClientId(consentManageData.getClientId())) { + log.error("Client ID does not exist in the system."); + throw new ConsentException(ResponseStatus.BAD_REQUEST, "Client ID does not exist in the system.", + ConsentOperationEnum.CONSENT_UPDATE); + } + + String consentId = ConsentManageUtils.extractConsentIdFromPath(consentManageData.getRequestPath(), ConsentOperationEnum.CONSENT_UPDATE); + + try { + + DetailedConsentResource storedConsentResource = consentCoreService.getDetailedConsent(consentId); + + if (storedConsentResource == null) { + log.error("Consent not found"); + throw new ConsentException(ResponseStatus.BAD_REQUEST, "Consent not found", + ConsentOperationEnum.CONSENT_UPDATE); + } + log.info(String.format("Retrieved consent for ID: %s", consentId.replaceAll("[\r\n]+", " "))); + + if (!storedConsentResource.getClientID().equals(consentManageData.getClientId())) { + //Throwing this error in a generic manner since client will not be able to identify if consent + // exists if consent does not belong to them + log.error(ConsentManageConstants.CLIENT_ID_MISMATCH_ERROR); + throw new ConsentException(ResponseStatus.BAD_REQUEST, ConsentManageConstants.CLIENT_ID_MISMATCH_ERROR, + ConsentOperationEnum.CONSENT_UPDATE); + } + + ConsentPayloadValidationResult validationResponse = ConsentManageUtils.getConsentManageValidator() + .validateRequestPayload(consentManageData, ConsentExtensionConstants.INTERNAL_UPDATE); + if (!validationResponse.isValid()) { + log.error(validationResponse.getErrorMessage().replaceAll("[\r\n]+", " ")); + throw new ConsentException(validationResponse.getHttpCode(), validationResponse.getErrorCode(), + validationResponse.getErrorMessage()); + } + + DetailedConsentResource updatedConsent = consentCoreService.updateDetailedConsent(ConsentManageUtils + .constructDetailedConsentResourceFromUpdatePayload(consentId, storedConsentResource, + consentManageData.getPayload())); + log.info(String.format("Successfully updated consent with ID: %s", + consentId.replaceAll("[\r\n]+", " "))); + + consentManageData.setResponsePayload(ConsentManageUtils.constructInternalConsentResponse(updatedConsent)); + consentManageData.setResponseStatus(ResponseStatus.OK); + + } catch (ConsentManagementException e) { + log.error("Error Occurred while updating the consent", e); + throw new ConsentException(ResponseStatus.INTERNAL_SERVER_ERROR, + "Error Occurred while updating the consent", ConsentOperationEnum.CONSENT_UPDATE); + } } @Override @@ -473,7 +566,7 @@ public void handleFileUploadPost(ConsentManageData consentManageData) throws Con //Check whether client ID exists if (StringUtils.isEmpty(consentManageData.getClientId())) { log.error("Client ID is missing in the request."); - throw new ConsentException(ResponseStatus.BAD_REQUEST, "Client ID id missing in the request.", + throw new ConsentException(ResponseStatus.BAD_REQUEST, "Client ID missing in the request.", ConsentOperationEnum.CONSENT_FILE_UPLOAD); } @@ -481,7 +574,7 @@ public void handleFileUploadPost(ConsentManageData consentManageData) throws Con if (!FinancialServicesUtils.isValidClientId(consentManageData.getClientId())) { log.error("Client ID does not exist in the system."); throw new ConsentException(ResponseStatus.BAD_REQUEST, "Client ID does not exist in the system.", - ConsentOperationEnum.CONSENT_RETRIEVE); + ConsentOperationEnum.CONSENT_FILE_UPLOAD); } String resourcePath = consentManageData.getRequestPath(); @@ -491,7 +584,7 @@ public void handleFileUploadPost(ConsentManageData consentManageData) throws Con ConsentOperationEnum.CONSENT_FILE_UPLOAD); } String consentId = ConsentManageUtils.extractConsentIdFromPath(resourcePath, - ConsentOperationEnum.CONSENT_DELETE); + ConsentOperationEnum.CONSENT_FILE_UPLOAD); //Perform idempotency validation if (consentManageData.getHeaders().containsKey(idempotencyHeaderName) && @@ -590,7 +683,7 @@ public void handleFileGet(ConsentManageData consentManageData) throws ConsentExc //Check whether client ID exists if (StringUtils.isEmpty(consentManageData.getClientId())) { log.error("Client ID is missing in the request."); - throw new ConsentException(ResponseStatus.BAD_REQUEST, "Client ID id missing in the request.", + throw new ConsentException(ResponseStatus.BAD_REQUEST, "Client ID missing in the request.", ConsentOperationEnum.CONSENT_FILE_RETRIEVAL); } @@ -598,7 +691,7 @@ public void handleFileGet(ConsentManageData consentManageData) throws ConsentExc if (!FinancialServicesUtils.isValidClientId(consentManageData.getClientId())) { log.error("Client ID does not exist in the system."); throw new ConsentException(ResponseStatus.BAD_REQUEST, "Client ID does not exist in the system.", - ConsentOperationEnum.CONSENT_RETRIEVE); + ConsentOperationEnum.CONSENT_FILE_RETRIEVAL); } String resourcePath = consentManageData.getRequestPath(); @@ -619,8 +712,8 @@ public void handleFileGet(ConsentManageData consentManageData) throws ConsentExc } // Check whether the client id is matching if (!consent.getClientID().equals(consentManageData.getClientId())) { - log.error("Client ID mismatch"); - throw new ConsentException(ResponseStatus.BAD_REQUEST, "Client ID mismatch", + log.error(ConsentManageConstants.CLIENT_ID_MISMATCH_ERROR); + throw new ConsentException(ResponseStatus.BAD_REQUEST, ConsentManageConstants.CLIENT_ID_MISMATCH_ERROR, ConsentOperationEnum.CONSENT_FILE_RETRIEVAL); } ConsentFile consentFile = consentCoreService.getConsentFile(consentId); diff --git a/financial-services-accelerator/components/org.wso2.financial.services.accelerator.consent.mgt.extensions/src/main/java/org/wso2/financial/services/accelerator/consent/mgt/extensions/manage/impl/DefaultConsentManageValidator.java b/financial-services-accelerator/components/org.wso2.financial.services.accelerator.consent.mgt.extensions/src/main/java/org/wso2/financial/services/accelerator/consent/mgt/extensions/manage/impl/DefaultConsentManageValidator.java index 6c49b4efe..3f7ad029b 100644 --- a/financial-services-accelerator/components/org.wso2.financial.services.accelerator.consent.mgt.extensions/src/main/java/org/wso2/financial/services/accelerator/consent/mgt/extensions/manage/impl/DefaultConsentManageValidator.java +++ b/financial-services-accelerator/components/org.wso2.financial.services.accelerator.consent.mgt.extensions/src/main/java/org/wso2/financial/services/accelerator/consent/mgt/extensions/manage/impl/DefaultConsentManageValidator.java @@ -18,6 +18,8 @@ package org.wso2.financial.services.accelerator.consent.mgt.extensions.manage.impl; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; import org.apache.commons.lang3.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -30,6 +32,7 @@ import org.wso2.financial.services.accelerator.consent.mgt.extensions.manage.ConsentManageValidator; import org.wso2.financial.services.accelerator.consent.mgt.extensions.manage.model.ConsentManageData; import org.wso2.financial.services.accelerator.consent.mgt.extensions.manage.model.ConsentPayloadValidationResult; +import org.wso2.financial.services.accelerator.consent.mgt.extensions.manage.model.InternalConsentUpdateRequestDTO; import org.wso2.financial.services.accelerator.consent.mgt.extensions.manage.utils.ConsentManageUtils; import java.util.Arrays; @@ -69,6 +72,8 @@ public ConsentPayloadValidationResult validateRequestPayload(ConsentManageData c return validateCOFRequestPayload(requestPayload); case ConsentExtensionConstants.PAYMENTS: return validatePaymentRequestPayload(requestPayload); + case ConsentExtensionConstants.INTERNAL_UPDATE: + return validateConsentUpdatePayload(requestPayload); default: return new ConsentPayloadValidationResult(false, ResponseStatus.BAD_REQUEST, "invalid_consent_type", "Invalid consent type"); @@ -475,4 +480,26 @@ private static ConsentPayloadValidationResult validateCreditorAccount(JSONObject return new ConsentPayloadValidationResult(true); } + + /** + * Method to validate consent update request payload. + * + * @param request Request payload for consent update + * @return ConsentPayloadValidationResult Validation response + */ + public static ConsentPayloadValidationResult validateConsentUpdatePayload(JSONObject request) { + + log.info("Validating consent update request payload"); + try { + ObjectMapper objectMapper = new ObjectMapper(); + objectMapper.readValue(request.toString(), InternalConsentUpdateRequestDTO.class); + return new ConsentPayloadValidationResult(true); + } catch (JsonProcessingException e) { + log.error(String.format("Failed to validate consent update payload: %s", + e.getMessage().replaceAll("[\r\n]", ""))); + return new ConsentPayloadValidationResult(false, ResponseStatus.BAD_REQUEST, + ResponseStatus.BAD_REQUEST.getReasonPhrase(), + "Invalid request payload: " + e.getMessage()); + } + } } diff --git a/financial-services-accelerator/components/org.wso2.financial.services.accelerator.consent.mgt.extensions/src/main/java/org/wso2/financial/services/accelerator/consent/mgt/extensions/manage/model/InternalConsentUpdateRequestDTO.java b/financial-services-accelerator/components/org.wso2.financial.services.accelerator.consent.mgt.extensions/src/main/java/org/wso2/financial/services/accelerator/consent/mgt/extensions/manage/model/InternalConsentUpdateRequestDTO.java new file mode 100644 index 000000000..6748d5d4e --- /dev/null +++ b/financial-services-accelerator/components/org.wso2.financial.services.accelerator.consent.mgt.extensions/src/main/java/org/wso2/financial/services/accelerator/consent/mgt/extensions/manage/model/InternalConsentUpdateRequestDTO.java @@ -0,0 +1,196 @@ +/** + * Copyright (c) 2026, WSO2 LLC. (https://www.wso2.com). + *

+ * WSO2 LLC. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + *

+ * http://www.apache.org/licenses/LICENSE-2.0 + *

+ * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.wso2.financial.services.accelerator.consent.mgt.extensions.manage.model; + +import java.util.List; +import java.util.Map; + +/** + * Internal Consent Update Request DTO. + */ +public class InternalConsentUpdateRequestDTO { + + private String consentID; + private String receipt; + private String status; + private int consentFrequency; + private long validityPeriod; + private boolean recurringIndicator; + private Map consentAttributes; + private List authorizationResources; + + public String getConsentID() { + return consentID; + } + + public void setConsentID(String consentID) { + this.consentID = consentID; + } + + public String getReceipt() { + return receipt; + } + + public void setReceipt(String receipt) { + this.receipt = receipt; + } + + public String getStatus() { + return status; + } + + public void setStatus(String status) { + this.status = status; + } + + public int getConsentFrequency() { + return consentFrequency; + } + + public void setConsentFrequency(int consentFrequency) { + this.consentFrequency = consentFrequency; + } + + public long getValidityPeriod() { + return validityPeriod; + } + + public void setValidityPeriod(long validityPeriod) { + this.validityPeriod = validityPeriod; + } + + public boolean isRecurringIndicator() { + return recurringIndicator; + } + + public void setRecurringIndicator(boolean recurringIndicator) { + this.recurringIndicator = recurringIndicator; + } + + public Map getConsentAttributes() { + return consentAttributes; + } + + public void setConsentAttributes(Map consentAttributes) { + this.consentAttributes = consentAttributes; + } + + public List getAuthorizationResources() { + return authorizationResources; + } + + public void setAuthorizationResources(List authorizationResources) { + this.authorizationResources = authorizationResources; + } + + /** + * Authorization. + */ + public static class Authorization { + + private String authorizationID; + private String userID; + private String authorizationType; + private String authorizationStatus; + private List resources; + + public String getAuthorizationID() { + return authorizationID; + } + + public void setAuthorizationID(String authorizationID) { + this.authorizationID = authorizationID; + } + + public String getUserID() { + return userID; + } + + public void setUserID(String userID) { + this.userID = userID; + } + + public String getAuthorizationType() { + return authorizationType; + } + + public void setAuthorizationType(String authorizationType) { + this.authorizationType = authorizationType; + } + + public String getAuthorizationStatus() { + return authorizationStatus; + } + + public void setAuthorizationStatus(String authorizationStatus) { + this.authorizationStatus = authorizationStatus; + } + + public List getResources() { + return resources; + } + + public void setResources(List resources) { + this.resources = resources; + } + } + + /** + * Consent Mapping Resource. + */ + public static class Resource { + + private String mappingID; + private String accountID; + private String permission; + private String mappingStatus; + + public String getMappingID() { + return mappingID; + } + + public void setMappingID(String mappingID) { + this.mappingID = mappingID; + } + + public String getAccountID() { + return accountID; + } + + public void setAccountID(String accountID) { + this.accountID = accountID; + } + + public String getPermission() { + return permission; + } + + public void setPermission(String permission) { + this.permission = permission; + } + + public String getMappingStatus() { + return mappingStatus; + } + + public void setMappingStatus(String mappingStatus) { + this.mappingStatus = mappingStatus; + } + } +} diff --git a/financial-services-accelerator/components/org.wso2.financial.services.accelerator.consent.mgt.extensions/src/main/java/org/wso2/financial/services/accelerator/consent/mgt/extensions/manage/model/InternalConsentUpdateResponseDTO.java b/financial-services-accelerator/components/org.wso2.financial.services.accelerator.consent.mgt.extensions/src/main/java/org/wso2/financial/services/accelerator/consent/mgt/extensions/manage/model/InternalConsentUpdateResponseDTO.java new file mode 100644 index 000000000..8dafc7fdd --- /dev/null +++ b/financial-services-accelerator/components/org.wso2.financial.services.accelerator.consent.mgt.extensions/src/main/java/org/wso2/financial/services/accelerator/consent/mgt/extensions/manage/model/InternalConsentUpdateResponseDTO.java @@ -0,0 +1,299 @@ +/** + * Copyright (c) 2026, WSO2 LLC. (https://www.wso2.com). + *

+ * WSO2 LLC. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + *

+ * http://www.apache.org/licenses/LICENSE-2.0 + *

+ * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.wso2.financial.services.accelerator.consent.mgt.extensions.manage.model; + +import org.wso2.financial.services.accelerator.consent.mgt.dao.models.ConsentMappingResource; +import org.wso2.financial.services.accelerator.consent.mgt.dao.models.DetailedConsentResource; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.stream.Collectors; + +/** + * Internal Consent Update Request DTO. + */ +public class InternalConsentUpdateResponseDTO { + + private String consentID; + private String clientID; + private String receipt; + private String status; + private String consentType; + private int consentFrequency; + private long validityPeriod; + private boolean recurringIndicator; + private long createdTime; + private long updatedTime; + private Map consentAttributes; + private List authorizationResources; + + public InternalConsentUpdateResponseDTO(DetailedConsentResource detailedConsent) { + + this.consentID = detailedConsent.getConsentID(); + this.clientID = detailedConsent.getClientID(); + this.consentType = detailedConsent.getConsentType(); + this.status = detailedConsent.getCurrentStatus(); + this.consentFrequency = detailedConsent.getConsentFrequency(); + this.validityPeriod = detailedConsent.getValidityPeriod(); + this.createdTime = detailedConsent.getCreatedTime(); + this.updatedTime = detailedConsent.getUpdatedTime(); + this.recurringIndicator = detailedConsent.isRecurringIndicator(); + + // Convert receipt String to Map + if (detailedConsent.getReceipt() != null && !detailedConsent.getReceipt().isEmpty()) { + this.receipt = detailedConsent.getReceipt(); + } else { + this.receipt = null; + } + + this.consentAttributes = detailedConsent.getConsentAttributes(); + + // Group ConsentMappingResources by AuthorizationID + Map> mappingsByAuthId = Optional.ofNullable( + detailedConsent.getConsentMappingResources()) + .orElse(new ArrayList<>()) + .stream() + .collect(Collectors.groupingBy(ConsentMappingResource::getAuthorizationID)); + + // Build authorizations list + this.authorizationResources = Optional.ofNullable(detailedConsent.getAuthorizationResources()) + .orElse(new ArrayList<>()) + .stream() + .map(auth -> { + InternalConsentUpdateResponseDTO.Authorization authorization = + new InternalConsentUpdateResponseDTO.Authorization(); + authorization.setAuthorizationID(auth.getAuthorizationID()); + authorization.setUserID(auth.getUserID()); + authorization.setAuthorizationType(auth.getAuthorizationType()); + authorization.setAuthorizationStatus(auth.getAuthorizationStatus()); + + List resources = mappingsByAuthId + .getOrDefault(auth.getAuthorizationID(), Collections.emptyList()) + .stream() + .map(mapping -> { + InternalConsentUpdateResponseDTO.Resource resource = + new InternalConsentUpdateResponseDTO.Resource(); + resource.setMappingID(mapping.getMappingID()); + resource.setAccountID(mapping.getAccountID()); + resource.setPermission(mapping.getPermission()); + resource.setMappingStatus(mapping.getMappingStatus()); + return resource; + }) + .collect(Collectors.toList()); + + authorization.setResources(resources); + return authorization; + }) + .collect(Collectors.toList()); + } + + public String getConsentID() { + return consentID; + } + + public void setConsentID(String consentID) { + this.consentID = consentID; + } + + public String getClientID() { + return clientID; + } + + public void setClientID(String clientID) { + this.clientID = clientID; + } + + public String getReceipt() { + return receipt; + } + + public void setReceipt(String receipt) { + this.receipt = receipt; + } + + public String getStatus() { + return status; + } + + public void setStatus(String status) { + this.status = status; + } + + public String getConsentType() { + return consentType; + } + + public void setConsentType(String consentType) { + this.consentType = consentType; + } + + public int getConsentFrequency() { + return consentFrequency; + } + + public void setConsentFrequency(int consentFrequency) { + this.consentFrequency = consentFrequency; + } + + public long getValidityPeriod() { + return validityPeriod; + } + + public void setValidityPeriod(long validityPeriod) { + this.validityPeriod = validityPeriod; + } + + public boolean isRecurringIndicator() { + return recurringIndicator; + } + + public void setRecurringIndicator(boolean recurringIndicator) { + this.recurringIndicator = recurringIndicator; + } + + public long getCreatedTime() { + return createdTime; + } + + public void setCreatedTime(long createdTime) { + this.createdTime = createdTime; + } + + public long getUpdatedTime() { + return updatedTime; + } + + public void setUpdatedTime(long updatedTime) { + this.updatedTime = updatedTime; + } + + public Map getConsentAttributes() { + return consentAttributes; + } + + public void setConsentAttributes(Map consentAttributes) { + this.consentAttributes = consentAttributes; + } + + public List getAuthorizationResources() { + return authorizationResources; + } + + public void setAuthorizationResources(List authorizationResources) { + this.authorizationResources = authorizationResources; + } + + /** + * Authorization. + */ + public static class Authorization { + + private String authorizationID; + private String userID; + private String authorizationType; + private String authorizationStatus; + private List resources; + + public String getAuthorizationID() { + return authorizationID; + } + + public void setAuthorizationID(String authorizationID) { + this.authorizationID = authorizationID; + } + + public String getUserID() { + return userID; + } + + public void setUserID(String userID) { + this.userID = userID; + } + + public String getAuthorizationType() { + return authorizationType; + } + + public void setAuthorizationType(String authorizationType) { + this.authorizationType = authorizationType; + } + + public String getAuthorizationStatus() { + return authorizationStatus; + } + + public void setAuthorizationStatus(String authorizationStatus) { + this.authorizationStatus = authorizationStatus; + } + + public List getResources() { + return resources; + } + + public void setResources(List resources) { + this.resources = resources; + } + } + + /** + * Consent Mapping Resource. + */ + public static class Resource { + + private String mappingID; + private String accountID; + private String permission; + private String mappingStatus; + + public String getMappingID() { + return mappingID; + } + + public void setMappingID(String mappingID) { + this.mappingID = mappingID; + } + + public String getAccountID() { + return accountID; + } + + public void setAccountID(String accountID) { + this.accountID = accountID; + } + + public String getPermission() { + return permission; + } + + public void setPermission(String permission) { + this.permission = permission; + } + + public String getMappingStatus() { + return mappingStatus; + } + + public void setMappingStatus(String mappingStatus) { + this.mappingStatus = mappingStatus; + } + } +} diff --git a/financial-services-accelerator/components/org.wso2.financial.services.accelerator.consent.mgt.extensions/src/main/java/org/wso2/financial/services/accelerator/consent/mgt/extensions/manage/utils/ConsentManageConstants.java b/financial-services-accelerator/components/org.wso2.financial.services.accelerator.consent.mgt.extensions/src/main/java/org/wso2/financial/services/accelerator/consent/mgt/extensions/manage/utils/ConsentManageConstants.java index 83405d968..78c0179ac 100644 --- a/financial-services-accelerator/components/org.wso2.financial.services.accelerator.consent.mgt.extensions/src/main/java/org/wso2/financial/services/accelerator/consent/mgt/extensions/manage/utils/ConsentManageConstants.java +++ b/financial-services-accelerator/components/org.wso2.financial.services.accelerator.consent.mgt.extensions/src/main/java/org/wso2/financial/services/accelerator/consent/mgt/extensions/manage/utils/ConsentManageConstants.java @@ -25,4 +25,7 @@ public class ConsentManageConstants { public static final String NO_CONSENT_FOR_CLIENT_ERROR = "No valid consent found for given information"; public static final String CONSENT_TYPE_MISMATCH_ERROR = "Consent Type mismatch"; + public static final String INTERNAL_API_REQUEST_HEADER = "x-wso2-internal-request"; + public static final String CLIENT_ID_MISMATCH_ERROR = "Client Id in the request does not match with the client Id" + + " associated to the consent"; } diff --git a/financial-services-accelerator/components/org.wso2.financial.services.accelerator.consent.mgt.extensions/src/main/java/org/wso2/financial/services/accelerator/consent/mgt/extensions/manage/utils/ConsentManageUtils.java b/financial-services-accelerator/components/org.wso2.financial.services.accelerator.consent.mgt.extensions/src/main/java/org/wso2/financial/services/accelerator/consent/mgt/extensions/manage/utils/ConsentManageUtils.java index 18a41c3f0..6d7df0344 100644 --- a/financial-services-accelerator/components/org.wso2.financial.services.accelerator.consent.mgt.extensions/src/main/java/org/wso2/financial/services/accelerator/consent/mgt/extensions/manage/utils/ConsentManageUtils.java +++ b/financial-services-accelerator/components/org.wso2.financial.services.accelerator.consent.mgt.extensions/src/main/java/org/wso2/financial/services/accelerator/consent/mgt/extensions/manage/utils/ConsentManageUtils.java @@ -18,11 +18,17 @@ package org.wso2.financial.services.accelerator.consent.mgt.extensions.manage.utils; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.json.JSONObject; import org.wso2.financial.services.accelerator.common.config.FinancialServicesConfigParser; import org.wso2.financial.services.accelerator.common.constant.FinancialServicesConstants; +import org.wso2.financial.services.accelerator.common.exception.ConsentManagementException; +import org.wso2.financial.services.accelerator.consent.mgt.dao.models.AuthorizationResource; +import org.wso2.financial.services.accelerator.consent.mgt.dao.models.ConsentMappingResource; +import org.wso2.financial.services.accelerator.consent.mgt.dao.models.DetailedConsentResource; import org.wso2.financial.services.accelerator.consent.mgt.extensions.common.ConsentException; import org.wso2.financial.services.accelerator.consent.mgt.extensions.common.ConsentExtensionConstants; import org.wso2.financial.services.accelerator.consent.mgt.extensions.common.ConsentExtensionExporter; @@ -30,6 +36,9 @@ import org.wso2.financial.services.accelerator.consent.mgt.extensions.common.ResponseStatus; import org.wso2.financial.services.accelerator.consent.mgt.extensions.manage.ConsentManageValidator; import org.wso2.financial.services.accelerator.consent.mgt.extensions.manage.builder.ConsentManageBuilder; +import org.wso2.financial.services.accelerator.consent.mgt.extensions.manage.model.ConsentManageData; +import org.wso2.financial.services.accelerator.consent.mgt.extensions.manage.model.InternalConsentUpdateRequestDTO; +import org.wso2.financial.services.accelerator.consent.mgt.extensions.manage.model.InternalConsentUpdateResponseDTO; import java.time.Instant; import java.time.OffsetDateTime; @@ -39,7 +48,9 @@ import java.util.Arrays; import java.util.EnumSet; import java.util.List; +import java.util.Map; import java.util.Optional; +import java.util.UUID; import java.util.regex.Pattern; /** @@ -283,4 +294,96 @@ public static long getValidityTime(Object payload, String consentType) { } } } + + /** + * Method to get whether the request is an internal consent API request. + * + * @param consentManageData consentManageData + * @return boolean whether the request is an internal consent API request + */ + public static boolean isInternalConsentRequest(ConsentManageData consentManageData) { + Map headers = consentManageData.getHeaders(); + if (headers != null && headers.containsKey(ConsentManageConstants.INTERNAL_API_REQUEST_HEADER)) { + return Boolean.parseBoolean(headers.get(ConsentManageConstants.INTERNAL_API_REQUEST_HEADER)); + } + return false; + } + + /** + * Construct DetailedConsentResource from the update consent request payload. For fields that are not present in the + * update consent request payload, values from the stored consent will be used. + * + * @param consentId consent id + * @param storedConsent consent stored in the database before the update operation + * @param requestPayload request payload of the update consent request + * @return DetailedConsentResource constructed from the update consent request payload and stored consent + * @throws ConsentManagementException if there is an error while processing the request payload + */ + public static DetailedConsentResource constructDetailedConsentResourceFromUpdatePayload(String consentId, + DetailedConsentResource storedConsent, Object requestPayload) + throws ConsentManagementException { + + log.info(String.format("Constructing DetailedConsentResource from update payload for consentId: %s", + consentId.replaceAll("[\r\n]", ""))); + try { + ObjectMapper objectMapper = new ObjectMapper(); + InternalConsentUpdateRequestDTO updateRequestDTO = objectMapper.readValue(requestPayload.toString(), + InternalConsentUpdateRequestDTO.class); + + ArrayList authorizationResources = new ArrayList<>(); + ArrayList consentMappingResources = new ArrayList<>(); + if (updateRequestDTO.getAuthorizationResources() != null) { + for (InternalConsentUpdateRequestDTO.Authorization authorization: + updateRequestDTO.getAuthorizationResources()) { + String authId = authorization.getAuthorizationID() != null ? authorization.getAuthorizationID() : + UUID.randomUUID().toString(); + AuthorizationResource authorizationResource = new AuthorizationResource(consentId, + authorization.getUserID(), authorization.getAuthorizationStatus(), + authorization.getAuthorizationType(), 0L); + authorizationResource.setAuthorizationID(authId); + authorizationResources.add(authorizationResource); + + if (authorization.getResources() != null) { + for (InternalConsentUpdateRequestDTO.Resource resource: authorization.getResources()) { + String mappingId = resource.getMappingID() != null ? resource.getMappingID() : + UUID.randomUUID().toString(); + ConsentMappingResource consentMappingResource = new ConsentMappingResource(authId, + resource.getAccountID(), resource.getPermission(), resource.getMappingStatus()); + consentMappingResource.setMappingID(mappingId); + consentMappingResources.add(consentMappingResource); + } + } + } + } else { + // If the request doesn't contain authorization resources, use the existing authorization resources + // of the consent + authorizationResources = storedConsent.getAuthorizationResources(); + consentMappingResources = storedConsent.getConsentMappingResources(); + } + + return new DetailedConsentResource(consentId, + storedConsent.getClientID(), updateRequestDTO.getReceipt(), storedConsent.getConsentType(), + updateRequestDTO.getStatus(), updateRequestDTO.getConsentFrequency(), + updateRequestDTO.getValidityPeriod(), storedConsent.getCreatedTime(), 0L, + updateRequestDTO.isRecurringIndicator(), updateRequestDTO.getConsentAttributes(), + authorizationResources, consentMappingResources); + + } catch (JsonProcessingException e) { + log.error(String.format("Failed to parse update consent request payload for consentId: %s. Error: %s", + consentId.replaceAll("[\r\n]", ""), e.getMessage().replaceAll("[\r\n]", ""))); + throw new ConsentManagementException("Invalid request payload", e); + } + } + + /** + * Construct InternalConsentUpdateResponseDTO from DetailedConsentResource. This will be used to send the response + * of the update consent request to the internal API caller. + * + * @param consent DetailedConsentResource object to construct the response DTO + * @return constructed response from the DetailedConsentResource + */ + public static JSONObject constructInternalConsentResponse(DetailedConsentResource consent) { + InternalConsentUpdateResponseDTO responseDTO = new InternalConsentUpdateResponseDTO(consent); + return new JSONObject(responseDTO); + } } diff --git a/financial-services-accelerator/components/org.wso2.financial.services.accelerator.consent.mgt.extensions/src/test/java/org/wso2/financial/services/accelerator/consent/mgt/extensions/manage/DefaultConsentManageHandlerTest.java b/financial-services-accelerator/components/org.wso2.financial.services.accelerator.consent.mgt.extensions/src/test/java/org/wso2/financial/services/accelerator/consent/mgt/extensions/manage/DefaultConsentManageHandlerTest.java index 54ded133f..da7bbdcf2 100644 --- a/financial-services-accelerator/components/org.wso2.financial.services.accelerator.consent.mgt.extensions/src/test/java/org/wso2/financial/services/accelerator/consent/mgt/extensions/manage/DefaultConsentManageHandlerTest.java +++ b/financial-services-accelerator/components/org.wso2.financial.services.accelerator.consent.mgt.extensions/src/test/java/org/wso2/financial/services/accelerator/consent/mgt/extensions/manage/DefaultConsentManageHandlerTest.java @@ -22,10 +22,10 @@ import org.mockito.Mock; import org.mockito.MockedStatic; import org.mockito.Mockito; +import org.testng.Assert; import org.testng.annotations.AfterClass; import org.testng.annotations.BeforeClass; import org.testng.annotations.Test; -import org.wso2.carbon.identity.oauth2.IdentityOAuth2Exception; import org.wso2.financial.services.accelerator.common.config.FinancialServicesConfigParser; import org.wso2.financial.services.accelerator.common.constant.FinancialServicesConstants; import org.wso2.financial.services.accelerator.common.exception.ConsentManagementException; @@ -50,6 +50,7 @@ import org.wso2.financial.services.accelerator.consent.mgt.extensions.manage.model.ExternalAPIPreConsentGenerateResponseDTO; import org.wso2.financial.services.accelerator.consent.mgt.extensions.manage.model.ExternalAPIPreFileUploadRequestDTO; import org.wso2.financial.services.accelerator.consent.mgt.extensions.manage.model.ExternalAPIPreFileUploadResponseDTO; +import org.wso2.financial.services.accelerator.consent.mgt.extensions.manage.utils.ConsentManageConstants; import org.wso2.financial.services.accelerator.consent.mgt.extensions.manage.utils.ExternalAPIConsentManageUtils; import org.wso2.financial.services.accelerator.consent.mgt.extensions.util.DataProviders; import org.wso2.financial.services.accelerator.consent.mgt.extensions.util.TestConstants; @@ -76,8 +77,6 @@ public class DefaultConsentManageHandlerTest { DefaultConsentManageHandler defaultConsentManageHandler; DefaultConsentManageHandler externalServiceConsentManageHandler; @Mock - ConsentManageData consentManageDataMock; - @Mock ConsentCoreServiceImpl consentCoreServiceMock; private static Map headers; private static Map configs; @@ -86,9 +85,8 @@ public class DefaultConsentManageHandlerTest { private MockedStatic financialServicesUtilsMockedStatic; @BeforeClass - public void initTest() throws ConsentManagementException, IdentityOAuth2Exception { + public void initTest() throws ConsentManagementException { - consentManageDataMock = mock(ConsentManageData.class); consentCoreServiceMock = mock(ConsentCoreServiceImpl.class); consentExtensionsDataHolder = mockStatic(ConsentExtensionsDataHolder.class); configParser = mockStatic(FinancialServicesConfigParser.class); @@ -110,6 +108,7 @@ public void initTest() throws ConsentManagementException, IdentityOAuth2Exceptio .getConsentAttributes(anyString()); doReturn(true).when(consentCoreServiceMock).revokeConsent(anyString(), any(), any(), anyBoolean()); + doReturn(TestUtil.getSampleDetailedConsentResource()).when(consentCoreServiceMock).updateDetailedConsent(any()); configs = new HashMap(); configs.put(FinancialServicesConstants.MAX_INSTRUCTED_AMOUNT, "1000"); @@ -151,79 +150,117 @@ public void tearDown() { financialServicesUtilsMockedStatic.close(); } - @Test(expectedExceptions = ConsentException.class) + @Test public void testHandlePostWithoutClientId() { - setConsentManageBuilder(); - JSONObject payload = new JSONObject(TestConstants.VALID_INITIATION); - doReturn(payload).when(consentManageDataMock).getPayload(); - - defaultConsentManageHandler.handlePost(consentManageDataMock); + try { + setConsentManageBuilder(); + ConsentManageData consentManageDataMock = mock(ConsentManageData.class); + doReturn(null).when(consentManageDataMock).getClientId(); + + defaultConsentManageHandler.handlePost(consentManageDataMock); + } catch (ConsentException e) { + Assert.assertEquals(e.getPayload().getJSONObject("error").getString("description"), + "Client ID missing in the request."); + } } - @Test(expectedExceptions = ConsentException.class) + @Test public void testHandlePostWithInvalidHeaders() { - setConsentManageBuilderForErrorScenario(); - JSONObject payload = new JSONObject(TestConstants.VALID_INITIATION); - doReturn(payload).when(consentManageDataMock).getPayload(); - doReturn(TestConstants.SAMPLE_CLIENT_ID).when(consentManageDataMock).getClientId(); - - defaultConsentManageHandler.handlePost(consentManageDataMock); + try { + setConsentManageBuilderForErrorScenario(); + ConsentManageData consentManageDataMock = mock(ConsentManageData.class); + JSONObject payload = new JSONObject(TestConstants.VALID_INITIATION); + doReturn(payload).when(consentManageDataMock).getPayload(); + doReturn(TestConstants.SAMPLE_CLIENT_ID).when(consentManageDataMock).getClientId(); + + defaultConsentManageHandler.handlePost(consentManageDataMock); + } catch (ConsentException e) { + Assert.assertEquals(e.getPayload().getJSONObject("error").getString("description"), + "Invalid headers"); + } } - @Test(expectedExceptions = ConsentException.class) + @Test public void testHandlePostWithoutRequestPath() { - setConsentManageBuilder(); - JSONObject payload = new JSONObject(TestConstants.VALID_INITIATION); - doReturn(payload).when(consentManageDataMock).getPayload(); - doReturn(TestConstants.SAMPLE_CLIENT_ID).when(consentManageDataMock).getClientId(); - - defaultConsentManageHandler.handlePost(consentManageDataMock); + try { + setConsentManageBuilder(); + ConsentManageData consentManageDataMock = mock(ConsentManageData.class); + JSONObject payload = new JSONObject(TestConstants.VALID_INITIATION); + doReturn(payload).when(consentManageDataMock).getPayload(); + doReturn(TestConstants.SAMPLE_CLIENT_ID).when(consentManageDataMock).getClientId(); + doReturn(null).when(consentManageDataMock).getRequestPath(); + + defaultConsentManageHandler.handlePost(consentManageDataMock); + } catch (ConsentException e) { + Assert.assertEquals(e.getPayload().getJSONObject("error").getString("description"), + "Resource Path Not Found"); + } } - @Test(expectedExceptions = ConsentException.class) + @Test public void testHandlePostWithInvalidRequestPath() { - setConsentManageBuilder(); - JSONObject payload = new JSONObject(TestConstants.VALID_INITIATION); - doReturn(payload).when(consentManageDataMock).getPayload(); - doReturn(TestConstants.INVALID_REQUEST_PATH).when(consentManageDataMock).getRequestPath(); - doReturn(TestConstants.SAMPLE_CLIENT_ID).when(consentManageDataMock).getClientId(); - doReturn(headers).when(consentManageDataMock).getHeaders(); - - defaultConsentManageHandler.handlePost(consentManageDataMock); + try { + setConsentManageBuilder(); + ConsentManageData consentManageDataMock = mock(ConsentManageData.class); + JSONObject payload = new JSONObject(TestConstants.VALID_INITIATION); + doReturn(payload).when(consentManageDataMock).getPayload(); + doReturn(TestConstants.INVALID_REQUEST_PATH).when(consentManageDataMock).getRequestPath(); + doReturn(TestConstants.SAMPLE_CLIENT_ID).when(consentManageDataMock).getClientId(); + doReturn(headers).when(consentManageDataMock).getHeaders(); + + defaultConsentManageHandler.handlePost(consentManageDataMock); + } catch (ConsentException e) { + Assert.assertEquals(e.getPayload().getJSONObject("error").getString("description"), + "Invalid request path found."); + } } - @Test(expectedExceptions = ConsentException.class) + @Test public void testHandlePostWithInvalidPayload() { - setConsentManageBuilder(); - doReturn(TestConstants.INVALID_REQUEST_PATH).when(consentManageDataMock).getRequestPath(); - doReturn(TestConstants.SAMPLE_CLIENT_ID).when(consentManageDataMock).getClientId(); - doReturn(TestConstants.INVALID_INITIATION_OBJECT).when(consentManageDataMock) - .getPayload(); - defaultConsentManageHandler.handlePost(consentManageDataMock); + try { + setConsentManageBuilder(); + ConsentManageData consentManageDataMock = mock(ConsentManageData.class); + doReturn(ConsentExtensionConstants.ACCOUNT_CONSENT_PATH).when(consentManageDataMock).getRequestPath(); + doReturn(TestConstants.SAMPLE_CLIENT_ID).when(consentManageDataMock).getClientId(); + doReturn(TestConstants.INVALID_INITIATION_OBJECT).when(consentManageDataMock) + .getPayload(); + + defaultConsentManageHandler.handlePost(consentManageDataMock); + } catch (ConsentException e) { + Assert.assertEquals(e.getPayload().getJSONObject("error").getString("description"), + "Payload is not in the correct format"); + } } - @Test(expectedExceptions = ConsentException.class, dataProvider = "AccountInitiationDataProvider", - dataProviderClass = DataProviders.class) - public void testHandlePostWithInvalidInitiation(String initiation) { - - setConsentManageBuilder(); - JSONObject payload = new JSONObject(initiation); - doReturn(payload).when(consentManageDataMock).getPayload(); - doReturn(ConsentExtensionConstants.ACCOUNT_CONSENT_PATH).when(consentManageDataMock) - .getRequestPath(); + @Test(dataProvider = "AccountInitiationDataProvider", dataProviderClass = DataProviders.class) + public void testHandlePostWithInvalidInitiation(String initiation, String errorMessage) { - defaultConsentManageHandler.handlePost(consentManageDataMock); + try { + setConsentManageBuilder(); + ConsentManageData consentManageDataMock = mock(ConsentManageData.class); + JSONObject payload = new JSONObject(initiation); + doReturn(payload).when(consentManageDataMock).getPayload(); + doReturn(ConsentExtensionConstants.ACCOUNT_CONSENT_PATH).when(consentManageDataMock) + .getRequestPath(); + doReturn(TestConstants.SAMPLE_CLIENT_ID).when(consentManageDataMock).getClientId(); + + defaultConsentManageHandler.handlePost(consentManageDataMock); + } catch (ConsentException e) { + Assert.assertEquals(e.getPayload().getJSONObject("error").getString("description"), + errorMessage); + } } @Test public void testHandlePostForAccounts() { setConsentManageBuilder(); + ConsentManageData consentManageDataMock = mock(ConsentManageData.class); doReturn(headers).when(consentManageDataMock).getHeaders(); doReturn(TestConstants.SAMPLE_CLIENT_ID).when(consentManageDataMock).getClientId(); doReturn(ConsentExtensionConstants.ACCOUNT_CONSENT_PATH).when(consentManageDataMock) @@ -232,12 +269,18 @@ public void testHandlePostForAccounts() { doReturn(payload).when(consentManageDataMock).getPayload(); defaultConsentManageHandler.handlePost(consentManageDataMock); + + + Mockito.verify(consentManageDataMock, Mockito.times(2)).getRequestPath(); + Mockito.verify(consentManageDataMock, Mockito.times(3)).getClientId(); + Mockito.verify(consentManageDataMock).setResponseStatus(ResponseStatus.CREATED); } @Test public void testHandlePostForAccountsWithExtensionEnabled() { setConsentManageBuilder(); + ConsentManageData consentManageDataMock = mock(ConsentManageData.class); JSONObject payload = new JSONObject(TestConstants.VALID_INITIATION); doReturn(payload).when(consentManageDataMock).getPayload(); doReturn(TestConstants.ACCOUNT_CONSENT_GET_PATH).when(consentManageDataMock).getRequestPath(); @@ -259,6 +302,10 @@ public void testHandlePostForAccountsWithExtensionEnabled() { .thenReturn(postConsentGenerateResponseDTO); externalServiceConsentManageHandler.handlePost(consentManageDataMock); + + Mockito.verify(consentManageDataMock, Mockito.times(3)).getRequestPath(); + Mockito.verify(consentManageDataMock, Mockito.times(3)).getClientId(); + Mockito.verify(consentManageDataMock).setResponseStatus(ResponseStatus.CREATED); } } @@ -266,6 +313,7 @@ public void testHandlePostForAccountsWithExtensionEnabled() { public void testHandlePostForCOF() { setConsentManageBuilder(); + ConsentManageData consentManageDataMock = mock(ConsentManageData.class); doReturn(headers).when(consentManageDataMock).getHeaders(); doReturn(TestConstants.SAMPLE_CLIENT_ID).when(consentManageDataMock).getClientId(); doReturn(ConsentExtensionConstants.COF_CONSENT_PATH).when(consentManageDataMock) @@ -274,12 +322,17 @@ public void testHandlePostForCOF() { doReturn(payload).when(consentManageDataMock).getPayload(); defaultConsentManageHandler.handlePost(consentManageDataMock); + + Mockito.verify(consentManageDataMock, Mockito.times(2)).getRequestPath(); + Mockito.verify(consentManageDataMock, Mockito.times(3)).getClientId(); + Mockito.verify(consentManageDataMock).setResponseStatus(ResponseStatus.CREATED); } @Test public void testHandlePostForPayments() { setConsentManageBuilder(); + ConsentManageData consentManageDataMock = mock(ConsentManageData.class); doReturn(headers).when(consentManageDataMock).getHeaders(); doReturn(TestConstants.SAMPLE_CLIENT_ID).when(consentManageDataMock).getClientId(); doReturn(ConsentExtensionConstants.PAYMENT_CONSENT_PATH).when(consentManageDataMock) @@ -288,68 +341,101 @@ public void testHandlePostForPayments() { doReturn(payload).when(consentManageDataMock).getPayload(); defaultConsentManageHandler.handlePost(consentManageDataMock); + + Mockito.verify(consentManageDataMock, Mockito.times(2)).getRequestPath(); + Mockito.verify(consentManageDataMock, Mockito.times(3)).getClientId(); + Mockito.verify(consentManageDataMock).setResponseStatus(ResponseStatus.CREATED); } - @Test(expectedExceptions = ConsentException.class) + @Test public void testHandleFilePostWithoutClientId() { - setConsentManageBuilder(); - consentManageDataMock = mock(ConsentManageData.class); - doReturn(TestConstants.SAMPLE_CONSENT_FILE).when(consentManageDataMock).getPayload(); - doReturn(TestConstants.PAYMENTS_FILE_UPLOAD_PATH).when(consentManageDataMock).getRequestPath(); - defaultConsentManageHandler.handleFileUploadPost(consentManageDataMock); + try { + setConsentManageBuilder(); + ConsentManageData consentManageDataMock = mock(ConsentManageData.class); + doReturn(TestConstants.SAMPLE_CONSENT_FILE).when(consentManageDataMock).getPayload(); + doReturn(TestConstants.PAYMENTS_FILE_UPLOAD_PATH).when(consentManageDataMock).getRequestPath(); + + defaultConsentManageHandler.handleFileUploadPost(consentManageDataMock); + } catch (ConsentException e) { + Assert.assertEquals(e.getPayload().getJSONObject("error").getString("description"), + "Client ID missing in the request."); + } } - @Test(expectedExceptions = ConsentException.class) + @Test public void testHandleFilePostWithoutRequestPath() { - setConsentManageBuilder(); - consentManageDataMock = mock(ConsentManageData.class); - doReturn(TestConstants.SAMPLE_CONSENT_FILE).when(consentManageDataMock).getPayload(); - doReturn(TestConstants.SAMPLE_CLIENT_ID).when(consentManageDataMock).getClientId(); - defaultConsentManageHandler.handleFileUploadPost(consentManageDataMock); + try { + setConsentManageBuilder(); + ConsentManageData consentManageDataMock = mock(ConsentManageData.class); + doReturn(TestConstants.SAMPLE_CONSENT_FILE).when(consentManageDataMock).getPayload(); + doReturn(TestConstants.SAMPLE_CLIENT_ID).when(consentManageDataMock).getClientId(); + + defaultConsentManageHandler.handleFileUploadPost(consentManageDataMock); + } catch (ConsentException e) { + Assert.assertEquals(e.getPayload().getJSONObject("error").getString("description"), + "Resource path not found in the request"); + } } - @Test(expectedExceptions = ConsentException.class) + @Test public void testHandleFilePostWithInvalidRequestPath() { - setConsentManageBuilder(); - consentManageDataMock = mock(ConsentManageData.class); - doReturn(TestConstants.SAMPLE_CONSENT_FILE).when(consentManageDataMock).getPayload(); - doReturn(TestConstants.INVALID_REQUEST_PATH).when(consentManageDataMock).getRequestPath(); - doReturn(TestConstants.SAMPLE_CLIENT_ID).when(consentManageDataMock).getClientId(); - doReturn(headers).when(consentManageDataMock).getHeaders(); - - defaultConsentManageHandler.handleFileUploadPost(consentManageDataMock); + try { + setConsentManageBuilder(); + ConsentManageData consentManageDataMock = mock(ConsentManageData.class); + doReturn(TestConstants.SAMPLE_CONSENT_FILE).when(consentManageDataMock).getPayload(); + doReturn(TestConstants.INVALID_REQUEST_PATH).when(consentManageDataMock).getRequestPath(); + doReturn(TestConstants.SAMPLE_CLIENT_ID).when(consentManageDataMock).getClientId(); + doReturn(headers).when(consentManageDataMock).getHeaders(); + + defaultConsentManageHandler.handleFileUploadPost(consentManageDataMock); + } catch (ConsentException e) { + Assert.assertEquals(e.getPayload().getJSONObject("error").getString("description"), + "Invalid Request Path. Valid consent id not found."); + } } - @Test(expectedExceptions = ConsentException.class) + @Test public void testHandleFilePostWithNullPayload() { - setConsentManageBuilder(); - consentManageDataMock = mock(ConsentManageData.class); - doReturn(TestConstants.PAYMENTS_FILE_UPLOAD_PATH).when(consentManageDataMock).getRequestPath(); - doReturn(TestConstants.SAMPLE_CLIENT_ID).when(consentManageDataMock).getClientId(); - doReturn(null).when(consentManageDataMock).getPayload(); - defaultConsentManageHandler.handleFileUploadPost(consentManageDataMock); + try { + setConsentManageBuilder(); + ConsentManageData consentManageDataMock = mock(ConsentManageData.class); + doReturn(TestConstants.PAYMENTS_FILE_UPLOAD_PATH).when(consentManageDataMock).getRequestPath(); + doReturn(TestConstants.SAMPLE_CLIENT_ID).when(consentManageDataMock).getClientId(); + doReturn(null).when(consentManageDataMock).getPayload(); + + defaultConsentManageHandler.handleFileUploadPost(consentManageDataMock); + } catch (ConsentException e) { + Assert.assertEquals(e.getPayload().getJSONObject("error").getString("description"), + "Invalid file content found in the request."); + } } @Test public void testHandlePostForFilePayments() { setConsentManageBuilder(); + ConsentManageData consentManageDataMock = mock(ConsentManageData.class); doReturn(headers).when(consentManageDataMock).getHeaders(); doReturn(TestConstants.SAMPLE_CONSENT_FILE).when(consentManageDataMock).getPayload(); doReturn(TestConstants.PAYMENTS_FILE_UPLOAD_PATH).when(consentManageDataMock).getRequestPath(); doReturn(TestConstants.SAMPLE_CLIENT_ID).when(consentManageDataMock).getClientId(); defaultConsentManageHandler.handleFileUploadPost(consentManageDataMock); + + Mockito.verify(consentManageDataMock).getRequestPath(); + Mockito.verify(consentManageDataMock, Mockito.times(2)).getClientId(); + Mockito.verify(consentManageDataMock).setResponseStatus(ResponseStatus.OK); } @Test public void testHandlePostForFilePaymentsWithExtensionEnabled() { setConsentManageBuilder(); + ConsentManageData consentManageDataMock = mock(ConsentManageData.class); doReturn(TestConstants.SAMPLE_CONSENT_FILE).when(consentManageDataMock).getPayload(); doReturn(TestConstants.PAYMENTS_FILE_UPLOAD_PATH).when(consentManageDataMock).getRequestPath(); doReturn(TestConstants.SAMPLE_CLIENT_ID).when(consentManageDataMock).getClientId(); @@ -362,82 +448,164 @@ public void testHandlePostForFilePaymentsWithExtensionEnabled() { ExternalAPIPreFileUploadRequestDTO.class))).thenReturn(preFileUploadResponseDTO); mockedStatic.when(() -> ExternalAPIConsentManageUtils.callExternalService(any( ExternalAPIPostFileUploadRequestDTO.class))).thenReturn(modifiedResponseDTO); + externalServiceConsentManageHandler.handleFileUploadPost(consentManageDataMock); + + Mockito.verify(consentManageDataMock, Mockito.times(2)).getRequestPath(); + Mockito.verify(consentManageDataMock, Mockito.times(2)).getClientId(); + Mockito.verify(consentManageDataMock).setResponseStatus(ResponseStatus.OK); } } - @Test(expectedExceptions = ConsentException.class) + @Test public void testHandleGetWithoutClientId() { - setConsentManageBuilder(); - doReturn(null).when(consentManageDataMock).getClientId(); - defaultConsentManageHandler.handleGet(consentManageDataMock); + try { + setConsentManageBuilder(); + ConsentManageData consentManageDataMock = mock(ConsentManageData.class); + doReturn(null).when(consentManageDataMock).getClientId(); + + defaultConsentManageHandler.handleGet(consentManageDataMock); + } catch (ConsentException e) { + Assert.assertEquals(e.getPayload().getJSONObject("error").getString("description"), + "Client ID missing in the request."); + } } - @Test(expectedExceptions = ConsentException.class) + @Test public void testHandleGetWithInvalidHeaders() { - setConsentManageBuilderForErrorScenario(); - - JSONObject payload = new JSONObject(TestConstants.VALID_INITIATION); - doReturn(payload).when(consentManageDataMock).getPayload(); - doReturn(TestConstants.SAMPLE_CLIENT_ID).when(consentManageDataMock).getClientId(); - - defaultConsentManageHandler.handleGet(consentManageDataMock); + try { + setConsentManageBuilderForErrorScenario(); + ConsentManageData consentManageDataMock = mock(ConsentManageData.class); + JSONObject payload = new JSONObject(TestConstants.VALID_INITIATION); + doReturn(payload).when(consentManageDataMock).getPayload(); + doReturn(TestConstants.SAMPLE_CLIENT_ID).when(consentManageDataMock).getClientId(); + + defaultConsentManageHandler.handleGet(consentManageDataMock); + } catch (ConsentException e) { + Assert.assertEquals(e.getPayload().getJSONObject("error").getString("description"), + "Invalid headers"); + } } - @Test(expectedExceptions = ConsentException.class) + @Test public void testHandleGetWithoutRequestPath() { - setConsentManageBuilder(); - doReturn(TestConstants.SAMPLE_CLIENT_ID).when(consentManageDataMock).getClientId(); - doReturn(null).when(consentManageDataMock).getRequestPath(); - - defaultConsentManageHandler.handleGet(consentManageDataMock); + try { + setConsentManageBuilder(); + ConsentManageData consentManageDataMock = mock(ConsentManageData.class); + doReturn(TestConstants.SAMPLE_CLIENT_ID).when(consentManageDataMock).getClientId(); + doReturn(null).when(consentManageDataMock).getRequestPath(); + + defaultConsentManageHandler.handleGet(consentManageDataMock); + } catch (ConsentException e) { + Assert.assertEquals(e.getPayload().getJSONObject("error").getString("description"), + "Resource path not found in the request"); + } } - @Test(expectedExceptions = ConsentException.class) + @Test public void testHandleGetWithInvalidRequestPath() { - setConsentManageBuilder(); - JSONObject payload = new JSONObject(TestConstants.VALID_INITIATION); - doReturn(payload).when(consentManageDataMock).getPayload(); - doReturn(TestConstants.INVALID_REQUEST_PATH).when(consentManageDataMock).getRequestPath(); - doReturn(TestConstants.SAMPLE_CLIENT_ID).when(consentManageDataMock).getClientId(); - doReturn(headers).when(consentManageDataMock).getHeaders(); - - defaultConsentManageHandler.handleGet(consentManageDataMock); + try { + setConsentManageBuilder(); + ConsentManageData consentManageDataMock = mock(ConsentManageData.class); + JSONObject payload = new JSONObject(TestConstants.VALID_INITIATION); + doReturn(payload).when(consentManageDataMock).getPayload(); + doReturn(TestConstants.INVALID_REQUEST_PATH).when(consentManageDataMock).getRequestPath(); + doReturn(TestConstants.SAMPLE_CLIENT_ID).when(consentManageDataMock).getClientId(); + doReturn(headers).when(consentManageDataMock).getHeaders(); + + defaultConsentManageHandler.handleGet(consentManageDataMock); + } catch (ConsentException e) { + Assert.assertEquals(e.getPayload().getJSONObject("error").getString("description"), + "Invalid Request Path. Valid consent id not found."); + } } - @Test(expectedExceptions = ConsentException.class) + @Test public void testHandleGetWithInvalidConsentId() { + try { + setConsentManageBuilder(); + ConsentManageData consentManageDataMock = mock(ConsentManageData.class); + doReturn(TestConstants.REQUEST_PATH_WITH_INVALID_CONSENT_ID).when(consentManageDataMock).getRequestPath(); + doReturn(TestConstants.SAMPLE_CLIENT_ID).when(consentManageDataMock).getClientId(); + doReturn(TestConstants.INVALID_INITIATION_OBJECT).when(consentManageDataMock) + .getPayload(); + + defaultConsentManageHandler.handleGet(consentManageDataMock); + } catch (ConsentException e) { + Assert.assertEquals(e.getPayload().getJSONObject("error").getString("description"), + "Invalid Request Path. Valid consent id not found."); + } + } + + @Test + public void testHandleGetWithInvalidClientId() { + + try { + setConsentManageBuilder(); + ConsentManageData consentManageDataMock = mock(ConsentManageData.class); + doReturn(TestConstants.ACCOUNT_CONSENT_GET_PATH).when(consentManageDataMock).getRequestPath(); + doReturn("TestClient").when(consentManageDataMock).getClientId(); + doReturn(TestConstants.INVALID_INITIATION_OBJECT).when(consentManageDataMock) + .getPayload(); + + defaultConsentManageHandler.handleGet(consentManageDataMock); + } catch (ConsentException e) { + Assert.assertEquals(e.getPayload().getJSONObject("error").getString("description"), + ConsentManageConstants.CLIENT_ID_MISMATCH_ERROR); + } + } + + @Test + public void testHandleGet() { + setConsentManageBuilder(); - doReturn(TestConstants.REQUEST_PATH_WITH_INVALID_CONSENT_ID).when(consentManageDataMock).getRequestPath(); + ConsentManageData consentManageDataMock = mock(ConsentManageData.class); + JSONObject payload = new JSONObject(); + doReturn(payload).when(consentManageDataMock).getPayload(); + doReturn(TestConstants.ACCOUNT_CONSENT_GET_PATH).when(consentManageDataMock) + .getRequestPath(); doReturn(TestConstants.SAMPLE_CLIENT_ID).when(consentManageDataMock).getClientId(); - doReturn(TestConstants.INVALID_INITIATION_OBJECT).when(consentManageDataMock) - .getPayload(); + defaultConsentManageHandler.handleGet(consentManageDataMock); + + Mockito.verify(consentManageDataMock, Mockito.times(2)).getRequestPath(); + Mockito.verify(consentManageDataMock, Mockito.times(3)).getClientId(); + Mockito.verify(consentManageDataMock).setResponseStatus(ResponseStatus.OK); } @Test - public void testHandleGet() { + public void testHandleGetForInternalRequests() { setConsentManageBuilder(); + ConsentManageData consentManageDataMock = mock(ConsentManageData.class); JSONObject payload = new JSONObject(); doReturn(payload).when(consentManageDataMock).getPayload(); doReturn(TestConstants.ACCOUNT_CONSENT_GET_PATH).when(consentManageDataMock) .getRequestPath(); doReturn(TestConstants.SAMPLE_CLIENT_ID).when(consentManageDataMock).getClientId(); + Map headers = new HashMap<>(); + headers.put(ConsentManageConstants.INTERNAL_API_REQUEST_HEADER, "true"); + doReturn(headers).when(consentManageDataMock).getHeaders(); + defaultConsentManageHandler.handleGet(consentManageDataMock); + + Mockito.verify(consentManageDataMock).getRequestPath(); + Mockito.verify(consentManageDataMock, Mockito.times(3)).getClientId(); + Mockito.verify(consentManageDataMock).setResponseStatus(ResponseStatus.OK); } @Test public void testHandleGetWithExtensionEnabled() { setConsentManageBuilder(); + ConsentManageData consentManageDataMock = mock(ConsentManageData.class); JSONObject payload = new JSONObject(); doReturn(payload).when(consentManageDataMock).getPayload(); doReturn(TestConstants.ACCOUNT_CONSENT_GET_PATH).when(consentManageDataMock).getRequestPath(); @@ -451,31 +619,49 @@ public void testHandleGetWithExtensionEnabled() { ).thenReturn(mockResponse); externalServiceConsentManageHandler.handleGet(consentManageDataMock); + + Mockito.verify(consentManageDataMock, Mockito.times(2)).getRequestPath(); + Mockito.verify(consentManageDataMock, Mockito.times(3)).getClientId(); + Mockito.verify(consentManageDataMock).setResponseStatus(ResponseStatus.OK); } } - @Test(expectedExceptions = ConsentException.class) + @Test public void testHandleFileGetWithoutClientId() { - setConsentManageBuilder(); - doReturn(null).when(consentManageDataMock).getClientId(); - defaultConsentManageHandler.handleFileGet(consentManageDataMock); + try { + setConsentManageBuilder(); + ConsentManageData consentManageDataMock = mock(ConsentManageData.class); + doReturn(null).when(consentManageDataMock).getClientId(); + + defaultConsentManageHandler.handleFileGet(consentManageDataMock); + } catch (ConsentException e) { + Assert.assertEquals(e.getPayload().getJSONObject("error").getString("description"), + "Client ID missing in the request."); + } } - @Test(expectedExceptions = ConsentException.class) + @Test public void testHandleFileGetWithoutRequestPath() { - setConsentManageBuilder(); - doReturn(TestConstants.SAMPLE_CLIENT_ID).when(consentManageDataMock).getClientId(); - doReturn(null).when(consentManageDataMock).getRequestPath(); - - defaultConsentManageHandler.handleFileGet(consentManageDataMock); + try { + setConsentManageBuilder(); + ConsentManageData consentManageDataMock = mock(ConsentManageData.class); + doReturn(TestConstants.SAMPLE_CLIENT_ID).when(consentManageDataMock).getClientId(); + doReturn(null).when(consentManageDataMock).getRequestPath(); + + defaultConsentManageHandler.handleFileGet(consentManageDataMock); + } catch (ConsentException e) { + Assert.assertEquals(e.getPayload().getJSONObject("error").getString("description"), + "Resource path not found in the request"); + } } @Test public void testHandleFileGet() throws ConsentManagementException { setConsentManageBuilder(); + ConsentManageData consentManageDataMock = mock(ConsentManageData.class); JSONObject payload = new JSONObject(); doReturn(payload).when(consentManageDataMock).getPayload(); doReturn(TestConstants.ACCOUNT_CONSENT_GET_PATH).when(consentManageDataMock) @@ -485,12 +671,17 @@ public void testHandleFileGet() throws ConsentManagementException { .getConsentFile(anyString()); defaultConsentManageHandler.handleFileGet(consentManageDataMock); + + Mockito.verify(consentManageDataMock, Mockito.times(2)).getRequestPath(); + Mockito.verify(consentManageDataMock, Mockito.times(3)).getClientId(); + Mockito.verify(consentManageDataMock).setResponseStatus(ResponseStatus.OK); } @Test public void testHandleFileGetWithExtensionEnabled() throws ConsentManagementException { setConsentManageBuilder(); + ConsentManageData consentManageDataMock = mock(ConsentManageData.class); JSONObject payload = new JSONObject(); doReturn(payload).when(consentManageDataMock).getPayload(); doReturn(TestConstants.ACCOUNT_CONSENT_GET_PATH).when(consentManageDataMock).getRequestPath(); @@ -506,66 +697,103 @@ public void testHandleFileGetWithExtensionEnabled() throws ConsentManagementExce ).thenReturn(mockResponse); externalServiceConsentManageHandler.handleFileGet(consentManageDataMock); + + Mockito.verify(consentManageDataMock, Mockito.times(2)).getRequestPath(); + Mockito.verify(consentManageDataMock, Mockito.times(3)).getClientId(); + Mockito.verify(consentManageDataMock).setResponseStatus(ResponseStatus.OK); } } - @Test(expectedExceptions = ConsentException.class) + @Test public void testHandleDeleteWithoutClientId() { - setConsentManageBuilder(); - doReturn(null).when(consentManageDataMock).getClientId(); - defaultConsentManageHandler.handleDelete(consentManageDataMock); + try { + setConsentManageBuilder(); + ConsentManageData consentManageDataMock = mock(ConsentManageData.class); + doReturn(null).when(consentManageDataMock).getClientId(); + + defaultConsentManageHandler.handleDelete(consentManageDataMock); + } catch (ConsentException e) { + Assert.assertEquals(e.getPayload().getJSONObject("error").getString("description"), + "Client ID missing in the request."); + } } - @Test(expectedExceptions = ConsentException.class) + @Test public void testHandleDeleteWithInvalidHeaders() { - setConsentManageBuilderForErrorScenario(); - JSONObject payload = new JSONObject(TestConstants.VALID_INITIATION); - doReturn(payload).when(consentManageDataMock).getPayload(); - doReturn(TestConstants.SAMPLE_CLIENT_ID).when(consentManageDataMock).getClientId(); - - defaultConsentManageHandler.handleDelete(consentManageDataMock); + try { + setConsentManageBuilderForErrorScenario(); + ConsentManageData consentManageDataMock = mock(ConsentManageData.class); + JSONObject payload = new JSONObject(TestConstants.VALID_INITIATION); + doReturn(payload).when(consentManageDataMock).getPayload(); + doReturn(TestConstants.SAMPLE_CLIENT_ID).when(consentManageDataMock).getClientId(); + + defaultConsentManageHandler.handleDelete(consentManageDataMock); + } catch (ConsentException e) { + Assert.assertEquals(e.getPayload().getJSONObject("error").getString("description"), + "Invalid headers"); + } } - @Test(expectedExceptions = ConsentException.class) + @Test public void testHandleDeleteWithoutRequestPath() { - setConsentManageBuilder(); - doReturn(TestConstants.SAMPLE_CLIENT_ID).when(consentManageDataMock).getClientId(); - doReturn(null).when(consentManageDataMock).getRequestPath(); - - defaultConsentManageHandler.handleDelete(consentManageDataMock); + try { + setConsentManageBuilder(); + ConsentManageData consentManageDataMock = mock(ConsentManageData.class); + doReturn(TestConstants.SAMPLE_CLIENT_ID).when(consentManageDataMock).getClientId(); + doReturn(null).when(consentManageDataMock).getRequestPath(); + + defaultConsentManageHandler.handleDelete(consentManageDataMock); + } catch (ConsentException e) { + Assert.assertEquals(e.getPayload().getJSONObject("error").getString("description"), + "Resource Path Not Found"); + } } - @Test(expectedExceptions = ConsentException.class) + @Test public void testHandleDeleteWithInvalidRequestPath() { - setConsentManageBuilder(); - JSONObject payload = new JSONObject(TestConstants.VALID_INITIATION); - doReturn(payload).when(consentManageDataMock).getPayload(); - doReturn(TestConstants.INVALID_REQUEST_PATH).when(consentManageDataMock).getRequestPath(); - doReturn(TestConstants.SAMPLE_CLIENT_ID).when(consentManageDataMock).getClientId(); - doReturn(headers).when(consentManageDataMock).getHeaders(); - - defaultConsentManageHandler.handleDelete(consentManageDataMock); + try { + setConsentManageBuilder(); + ConsentManageData consentManageDataMock = mock(ConsentManageData.class); + JSONObject payload = new JSONObject(TestConstants.VALID_INITIATION); + doReturn(payload).when(consentManageDataMock).getPayload(); + doReturn(TestConstants.INVALID_REQUEST_PATH).when(consentManageDataMock).getRequestPath(); + doReturn(TestConstants.SAMPLE_CLIENT_ID).when(consentManageDataMock).getClientId(); + doReturn(headers).when(consentManageDataMock).getHeaders(); + + defaultConsentManageHandler.handleDelete(consentManageDataMock); + } catch (ConsentException e) { + Assert.assertEquals(e.getPayload().getJSONObject("error").getString("description"), + "Invalid Request Path. Valid consent id not found."); + } } - @Test(expectedExceptions = ConsentException.class) + @Test public void testHandleDeleteWithInvalidConsentId() { - setConsentManageBuilder(); - doReturn(TestConstants.REQUEST_PATH_WITH_INVALID_CONSENT_ID).when(consentManageDataMock).getRequestPath(); - doReturn(TestConstants.SAMPLE_CLIENT_ID).when(consentManageDataMock).getClientId(); - doReturn(TestConstants.INVALID_INITIATION_OBJECT).when(consentManageDataMock) - .getPayload(); - defaultConsentManageHandler.handleDelete(consentManageDataMock); + try { + setConsentManageBuilder(); + ConsentManageData consentManageDataMock = mock(ConsentManageData.class); + doReturn(TestConstants.REQUEST_PATH_WITH_INVALID_CONSENT_ID).when(consentManageDataMock).getRequestPath(); + doReturn(TestConstants.SAMPLE_CLIENT_ID).when(consentManageDataMock).getClientId(); + doReturn(TestConstants.INVALID_INITIATION_OBJECT).when(consentManageDataMock) + .getPayload(); + + defaultConsentManageHandler.handleDelete(consentManageDataMock); + } catch (ConsentException e) { + Assert.assertEquals(e.getPayload().getJSONObject("error").getString("description"), + "Invalid Request Path. Valid consent id not found."); + } } @Test public void testHandleDelete() { setConsentManageBuilder(); + ConsentManageData consentManageDataMock = mock(ConsentManageData.class); JSONObject payload = new JSONObject(); doReturn(payload).when(consentManageDataMock).getPayload(); doReturn(TestConstants.ACCOUNT_CONSENT_GET_PATH).when(consentManageDataMock) @@ -573,12 +801,17 @@ public void testHandleDelete() { doReturn(TestConstants.SAMPLE_CLIENT_ID).when(consentManageDataMock).getClientId(); defaultConsentManageHandler.handleDelete(consentManageDataMock); + + Mockito.verify(consentManageDataMock, Mockito.times(2)).getRequestPath(); + Mockito.verify(consentManageDataMock, Mockito.times(3)).getClientId(); + Mockito.verify(consentManageDataMock).setResponseStatus(ResponseStatus.NO_CONTENT); } @Test public void testHandleDeleteWithExtensionEnabled() { setConsentManageBuilder(); + ConsentManageData consentManageDataMock = mock(ConsentManageData.class); JSONObject payload = new JSONObject(); doReturn(payload).when(consentManageDataMock).getPayload(); doReturn(TestConstants.ACCOUNT_CONSENT_GET_PATH).when(consentManageDataMock).getRequestPath(); @@ -593,19 +826,153 @@ public void testHandleDeleteWithExtensionEnabled() { ).thenReturn(mockResponse); externalServiceConsentManageHandler.handleDelete(consentManageDataMock); + + Mockito.verify(consentManageDataMock).getRequestPath(); + Mockito.verify(consentManageDataMock, Mockito.times(3)).getClientId(); + Mockito.verify(consentManageDataMock).setResponseStatus(ResponseStatus.NO_CONTENT); + } + } + + @Test + public void testHandlePutWithoutRequestPath() { + + try { + ConsentManageData consentManageDataMock = mock(ConsentManageData.class); + doReturn(TestConstants.SAMPLE_CLIENT_ID).when(consentManageDataMock).getClientId(); + doReturn(null).when(consentManageDataMock).getRequestPath(); + defaultConsentManageHandler.handlePut(consentManageDataMock); + } catch (ConsentException e) { + Assert.assertEquals(e.getPayload().getJSONObject("error").getString("description"), + "Resource Path Not Found"); } } - @Test(expectedExceptions = ConsentException.class) + @Test + public void testHandlePutForExternalRequests() { + + try { + ConsentManageData consentManageDataMock = mock(ConsentManageData.class); + doReturn(TestConstants.SAMPLE_CLIENT_ID).when(consentManageDataMock).getClientId(); + doReturn(TestConstants.ACCOUNT_CONSENT_GET_PATH).when(consentManageDataMock).getRequestPath(); + defaultConsentManageHandler.handlePut(consentManageDataMock); + } catch (ConsentException e) { + Assert.assertEquals(e.getPayload().getJSONObject("error").getString("description"), + "Method PUT is not supported"); + } + } + + @Test + public void testHandlePutWithoutClientId() { + + try { + ConsentManageData consentManageDataMock = mock(ConsentManageData.class); + doReturn(Map.of(ConsentManageConstants.INTERNAL_API_REQUEST_HEADER, "true")) + .when(consentManageDataMock).getHeaders(); + doReturn(null).when(consentManageDataMock).getClientId(); + doReturn(TestConstants.CONSENT_UPDATE_PATH).when(consentManageDataMock).getRequestPath(); + defaultConsentManageHandler.handlePut(consentManageDataMock); + } catch (ConsentException e) { + Assert.assertEquals(e.getPayload().getJSONObject("error").getString("description"), + "Client ID missing in the request."); + } + } + + @Test + public void testHandlePutWithInvalidConsentId() { + + try { + ConsentManageData consentManageDataMock = mock(ConsentManageData.class); + setConsentManageBuilder(); + doReturn(Map.of(ConsentManageConstants.INTERNAL_API_REQUEST_HEADER, "true")) + .when(consentManageDataMock).getHeaders(); + doReturn("/consent/1234").when(consentManageDataMock).getRequestPath(); + doReturn(TestConstants.SAMPLE_CLIENT_ID).when(consentManageDataMock).getClientId(); + doReturn(TestConstants.INVALID_INITIATION_OBJECT).when(consentManageDataMock) + .getPayload(); + defaultConsentManageHandler.handlePut(consentManageDataMock); + } catch (ConsentException e) { + Assert.assertEquals(e.getPayload().getJSONObject("error").getString("description"), + "Invalid Request Path. Valid consent id not found."); + } + } + + @Test + public void testHandlePutWithUnMatchingClientID() { + + try { + ConsentManageData consentManageDataMock = mock(ConsentManageData.class); + doReturn(Map.of(ConsentManageConstants.INTERNAL_API_REQUEST_HEADER, "true")) + .when(consentManageDataMock).getHeaders(); + doReturn("test123").when(consentManageDataMock).getClientId(); + doReturn(TestConstants.CONSENT_UPDATE_PATH).when(consentManageDataMock).getRequestPath(); + defaultConsentManageHandler.handlePut(consentManageDataMock); + } catch (ConsentException e) { + Assert.assertEquals(e.getPayload().getJSONObject("error").getString("description"), + ConsentManageConstants.CLIENT_ID_MISMATCH_ERROR); + } + } + + @Test + public void testHandlePutWithInvalidRequestPath() { + + try { + ConsentManageData consentManageDataMock = mock(ConsentManageData.class); + doReturn("consent/1213").when(consentManageDataMock).getRequestPath(); + doReturn(TestConstants.SAMPLE_CLIENT_ID).when(consentManageDataMock).getClientId(); + doReturn(headers).when(consentManageDataMock).getHeaders(); + defaultConsentManageHandler.handlePut(consentManageDataMock); + } catch (ConsentException e) { + Assert.assertEquals(e.getPayload().getJSONObject("error").getString("description"), + "Invalid Request Path. Valid consent id not found."); + } + } + + @Test + public void testHandlePutWithInvalidRequestPayload() { + + try { + setConsentManageBuilder(); + ConsentManageData consentManageDataMock = mock(ConsentManageData.class); + doReturn(TestConstants.CONSENT_UPDATE_PATH).when(consentManageDataMock).getRequestPath(); + doReturn(TestConstants.SAMPLE_CLIENT_ID).when(consentManageDataMock).getClientId(); + doReturn(TestConstants.INVALID_INITIATION_OBJECT).when(consentManageDataMock) + .getPayload(); + defaultConsentManageHandler.handlePut(consentManageDataMock); + } catch (ConsentException e) { + Assert.assertEquals(e.getPayload().getJSONObject("error").getString("description"), + "Payload is not in the correct format"); + } + } + + @Test public void testHandlePut() { + setConsentManageBuilder(); + ConsentManageData consentManageDataMock = mock(ConsentManageData.class); + doReturn(TestConstants.CONSENT_UPDATE_PATH).when(consentManageDataMock).getRequestPath(); + doReturn(TestConstants.SAMPLE_CLIENT_ID).when(consentManageDataMock).getClientId(); + JSONObject payload = new JSONObject(TestConstants.CONSENT_UPDATE_PAYLOAD); + doReturn(payload).when(consentManageDataMock).getPayload(); + doReturn(Map.of(ConsentManageConstants.INTERNAL_API_REQUEST_HEADER, "false")) + .when(consentManageDataMock).getHeaders(); + defaultConsentManageHandler.handlePut(consentManageDataMock); + + Mockito.verify(consentManageDataMock, Mockito.times(3)).getRequestPath(); + Mockito.verify(consentManageDataMock, Mockito.times(3)).getClientId(); + Mockito.verify(consentManageDataMock).setResponseStatus(ResponseStatus.OK); } - @Test(expectedExceptions = ConsentException.class) + @Test public void testHandlePatch() { - defaultConsentManageHandler.handlePatch(consentManageDataMock); + try { + ConsentManageData consentManageDataMock = mock(ConsentManageData.class); + defaultConsentManageHandler.handlePatch(consentManageDataMock); + } catch (ConsentException e) { + Assert.assertEquals(e.getPayload().getJSONObject("error").getString("description"), + "Method PATCH is not supported"); + } } private static void setConsentManageBuilder() { diff --git a/financial-services-accelerator/components/org.wso2.financial.services.accelerator.consent.mgt.extensions/src/test/java/org/wso2/financial/services/accelerator/consent/mgt/extensions/util/DataProviders.java b/financial-services-accelerator/components/org.wso2.financial.services.accelerator.consent.mgt.extensions/src/test/java/org/wso2/financial/services/accelerator/consent/mgt/extensions/util/DataProviders.java index b8cc89d75..581e09e10 100644 --- a/financial-services-accelerator/components/org.wso2.financial.services.accelerator.consent.mgt.extensions/src/test/java/org/wso2/financial/services/accelerator/consent/mgt/extensions/util/DataProviders.java +++ b/financial-services-accelerator/components/org.wso2.financial.services.accelerator.consent.mgt.extensions/src/test/java/org/wso2/financial/services/accelerator/consent/mgt/extensions/util/DataProviders.java @@ -29,18 +29,18 @@ public class DataProviders { Object[][] getAccountInitiationDataProvider() { return new Object[][]{ - {"{}"}, - {INITIATION_WITHOUT_ACCOUNT_PERMISSION}, - {INITIATION_WITH_UNACCEPTABLE_PERMISSION}, - {INITIATION_WITHOUT_EXPIRATION_DATES}, - {INITIATION_NON_STRING_EXPIRATION_DATES}, - {INITIATION_WITH_INVALID_EXPIRATION_DATES}, - {INITIATION_WITH_PAST_EXPIRATION_DATES}, - {INITIATION_NON_STRING_TRANS_FROM_DATES}, - {INITIATION_WITH_INVALID_TRANS_FROM_DATES}, - {INITIATION_NON_STRING_TRANS_TO_DATES}, - {INITIATION_WITH_INVALID_TRANS_TO_DATES}, - {INITIATION_WITH_PAST_TRANS_TO_DATES} + {"{}", "Invalid request payload"}, + {INITIATION_WITHOUT_ACCOUNT_PERMISSION, "Permissions are invalid"}, + {INITIATION_WITH_UNACCEPTABLE_PERMISSION, "Permissions are invalid"}, + {INITIATION_WITHOUT_EXPIRATION_DATES, "ExpirationDateTime is invalid"}, + {INITIATION_NON_STRING_EXPIRATION_DATES, "ExpirationDateTime is invalid"}, + {INITIATION_WITH_INVALID_EXPIRATION_DATES, "ExpirationDateTime is invalid"}, + {INITIATION_WITH_PAST_EXPIRATION_DATES, "ExpirationDateTime should be a future date"}, + {INITIATION_NON_STRING_TRANS_FROM_DATES, "TransactionFromDateTime is invalid"}, + {INITIATION_WITH_INVALID_TRANS_FROM_DATES, "TransactionFromDateTime is invalid"}, + {INITIATION_NON_STRING_TRANS_TO_DATES, "TransactionToDateTime is invalid"}, + {INITIATION_WITH_INVALID_TRANS_TO_DATES, "TransactionToDateTime is invalid"}, + {INITIATION_WITH_PAST_TRANS_TO_DATES, "TransactionToDateTime should be after TransactionFromDateTime"} }; } diff --git a/financial-services-accelerator/components/org.wso2.financial.services.accelerator.consent.mgt.extensions/src/test/java/org/wso2/financial/services/accelerator/consent/mgt/extensions/util/TestConstants.java b/financial-services-accelerator/components/org.wso2.financial.services.accelerator.consent.mgt.extensions/src/test/java/org/wso2/financial/services/accelerator/consent/mgt/extensions/util/TestConstants.java index f5d431269..cd8841793 100644 --- a/financial-services-accelerator/components/org.wso2.financial.services.accelerator.consent.mgt.extensions/src/test/java/org/wso2/financial/services/accelerator/consent/mgt/extensions/util/TestConstants.java +++ b/financial-services-accelerator/components/org.wso2.financial.services.accelerator.consent.mgt.extensions/src/test/java/org/wso2/financial/services/accelerator/consent/mgt/extensions/util/TestConstants.java @@ -39,6 +39,7 @@ public class TestConstants { public static final String INVALID_REQUEST_PATH = "accounts"; public static final String REQUEST_PATH_WITH_INVALID_CONSENT_ID = "accounts/1234"; public static final String ACCOUNT_CONSENT_GET_PATH = "account-access-consents/" + SAMPLE_CONSENT_ID; + public static final String CONSENT_UPDATE_PATH = "consent/" + SAMPLE_CONSENT_ID; public static final String PAYMENTS_FILE_UPLOAD_PATH = "fileUpload/" + SAMPLE_CONSENT_ID; public static final String INVALID_INITIATION_OBJECT = "Invalid Object"; public static final int SAMPLE_CONSENT_FREQUENCY = 1; @@ -617,4 +618,31 @@ public class TestConstants { " ]\n" + "}"; + public static final String CONSENT_UPDATE_PAYLOAD = "{\n" + + " \"consentID\": \"" + SAMPLE_CONSENT_ID + "\",\n" + + " \"status\": \"authorised\",\n" + + " \"validityPeriod\": 0,\n" + + " \"recurringIndicator\": true,\n" + + " \"consentFrequency\": 0,\n" + + " \"receipt\": \"\",\n" + + " \"consentAttributes\": {\n" + + " \"key1\": \"value1\",\n" + + " \"key2\": \"value2\"\n" + + " },\n" + + " \"authorizationResources\": [\n" + + " {\n" + + " \"userID\": \"admin@wso2.com\",\n" + + " \"authorizationType\": \"auth\",\n" + + " \"authorizationStatus\": \"active\",\n" + + " \"resources\": [\n" + + " {\n" + + " \"accountID\": \"1962368\",\n" + + " \"permission\": \"account\",\n" + + " \"mappingStatus\": \"active\"\n" + + " }\n" + + " ]\n" + + " }\n" + + " ]\n" + + "}"; + } diff --git a/financial-services-accelerator/components/org.wso2.financial.services.accelerator.consent.mgt.service/src/main/java/org/wso2/financial/services/accelerator/consent/mgt/service/ConsentCoreService.java b/financial-services-accelerator/components/org.wso2.financial.services.accelerator.consent.mgt.service/src/main/java/org/wso2/financial/services/accelerator/consent/mgt/service/ConsentCoreService.java index 6496d28b1..04c4df9f3 100644 --- a/financial-services-accelerator/components/org.wso2.financial.services.accelerator.consent.mgt.service/src/main/java/org/wso2/financial/services/accelerator/consent/mgt/service/ConsentCoreService.java +++ b/financial-services-accelerator/components/org.wso2.financial.services.accelerator.consent.mgt.service/src/main/java/org/wso2/financial/services/accelerator/consent/mgt/service/ConsentCoreService.java @@ -120,6 +120,17 @@ ConsentResource getConsent(String consentID, boolean withConsentAttributes) DetailedConsentResource storeDetailedConsentResource(DetailedConsentResource detailedConsentResource) throws ConsentManagementException; + /** + * This method is used to update a detailed consent along with its associated authorizations, + * account mappings, and attributes. An audit record will be created after storage. + * + * @param detailedConsentResource the consent resource with updated values and new associations + * @return the updated detailed consent resource + * @throws ConsentManagementException thrown if an error occurs during the operation + */ + DetailedConsentResource updateDetailedConsent(DetailedConsentResource detailedConsentResource) + throws ConsentManagementException; + /** * This method is used to update an existing consent (excluding client ID and CreatedTime) and create * new authorization and mapping records based on the given detailed consent. diff --git a/financial-services-accelerator/components/org.wso2.financial.services.accelerator.consent.mgt.service/src/main/java/org/wso2/financial/services/accelerator/consent/mgt/service/constants/ConsentCoreServiceConstants.java b/financial-services-accelerator/components/org.wso2.financial.services.accelerator.consent.mgt.service/src/main/java/org/wso2/financial/services/accelerator/consent/mgt/service/constants/ConsentCoreServiceConstants.java index 4a4ce7d84..a9af72608 100644 --- a/financial-services-accelerator/components/org.wso2.financial.services.accelerator.consent.mgt.service/src/main/java/org/wso2/financial/services/accelerator/consent/mgt/service/constants/ConsentCoreServiceConstants.java +++ b/financial-services-accelerator/components/org.wso2.financial.services.accelerator.consent.mgt.service/src/main/java/org/wso2/financial/services/accelerator/consent/mgt/service/constants/ConsentCoreServiceConstants.java @@ -45,6 +45,7 @@ public class ConsentCoreServiceConstants { public static final String USER_ACCOUNTS_BINDING_REASON = "Bind user accounts to consent"; public static final String CONSENT_REVOKE_REASON = "Revoke the consent"; public static final String CONSENT_REAUTHORIZE_REASON = "Reauthorize consent"; + public static final String DETAIL_CONSENT_UPDATE_REASON = "Update detailed consent"; public static final String CONSENT_AMEND_REASON = "Amend consent"; public static final String DEFAULT_PERMISSION_VALUE = "n/a"; public static final String ADDITIONAL_AUTHORIZATION_RESOURCES = "AdditionalAuthorizationResources"; diff --git a/financial-services-accelerator/components/org.wso2.financial.services.accelerator.consent.mgt.service/src/main/java/org/wso2/financial/services/accelerator/consent/mgt/service/impl/ConsentCoreServiceImpl.java b/financial-services-accelerator/components/org.wso2.financial.services.accelerator.consent.mgt.service/src/main/java/org/wso2/financial/services/accelerator/consent/mgt/service/impl/ConsentCoreServiceImpl.java index 1e28ca041..db7dd5df2 100644 --- a/financial-services-accelerator/components/org.wso2.financial.services.accelerator.consent.mgt.service/src/main/java/org/wso2/financial/services/accelerator/consent/mgt/service/impl/ConsentCoreServiceImpl.java +++ b/financial-services-accelerator/components/org.wso2.financial.services.accelerator.consent.mgt.service/src/main/java/org/wso2/financial/services/accelerator/consent/mgt/service/impl/ConsentCoreServiceImpl.java @@ -280,6 +280,92 @@ public DetailedConsentResource storeDetailedConsentResource(DetailedConsentResou } } + @Override + public DetailedConsentResource updateDetailedConsent(DetailedConsentResource detailedConsentResource) + throws ConsentManagementException { + + if (detailedConsentResource == null || StringUtils.isBlank(detailedConsentResource.getConsentID())) { + log.error("Consent resource or consentId is missing"); + throw new ConsentManagementException("Consent resource or consentId is missing"); + } + log.info(String.format("Updating consent with ID: %s", + detailedConsentResource.getConsentID().replaceAll("[\r\n]", ""))); + + Connection connection = DatabaseUtils.getDBConnection(); + try { + ConsentCoreDAO consentCoreDAO = ConsentStoreInitializer.getInitializedConsentCoreDAOImpl(); + String consentIdToUpdate = detailedConsentResource.getConsentID(); + + DetailedConsentResource previousConsent = consentCoreDAO.getDetailedConsentResource(connection, + consentIdToUpdate); + /* Update the base consent using updated values from ConsentResource. + Immutable parameters are ignored in the update (i.e. clientId, createdTime) at DAO level.*/ + ConsentResource consentResourceToUpdate = new ConsentResource(detailedConsentResource); + if (log.isDebugEnabled()) { + log.debug(String.format("Updating the consent for consent ID: %s", + consentIdToUpdate.replaceAll("[\r\n]", ""))); + } + consentCoreDAO.updateConsentResource(connection, consentResourceToUpdate); + + // Update consent attributes + // Delete existing attributes and store new attributes. + if (detailedConsentResource.getConsentAttributes() != null) { + ConsentCoreServiceUtil.deleteExistingConsentAttributes(consentCoreDAO, connection, consentIdToUpdate, + previousConsent); + ConsentCoreServiceUtil.addConsentAttributes(consentCoreDAO, connection, detailedConsentResource); + } + + // Update Consent Mapping Resources + // Delete existing consent mapping resources + if (detailedConsentResource.getConsentMappingResources() != null) { + ConsentCoreServiceUtil.deleteExistingConsentMappings(consentCoreDAO, connection, consentIdToUpdate, + previousConsent); + } + + // Update Authorization Resources + // Delete existing authorization resources and store new authorization resources. + if (detailedConsentResource.getAuthorizationResources() != null) { + ConsentCoreServiceUtil.deleteExistingAuthorizationResources(consentCoreDAO, connection, + consentIdToUpdate, previousConsent); + ConsentCoreServiceUtil.addAuthorizationResources(consentCoreDAO, connection, + detailedConsentResource.getAuthorizationResources(), consentIdToUpdate); + } + + // Update Consent Mapping Resources + // Store new consent mapping resources after adding the consent auth resources. + if (detailedConsentResource.getConsentMappingResources() != null) { + ConsentCoreServiceUtil.addConsentMappingResources(consentCoreDAO, connection, + detailedConsentResource.getConsentMappingResources(), consentIdToUpdate); + } + + // Add audit record + HashMap consentDataMap = new HashMap<>(); + consentDataMap.put(ConsentCoreServiceConstants.CONSENT_RESOURCE, detailedConsentResource); + String actionByUser = ConsentCoreServiceUtil.resolveActionByUser(detailedConsentResource); + + ConsentCoreServiceUtil.postStateChange(connection, consentCoreDAO, consentIdToUpdate, actionByUser, + detailedConsentResource.getCurrentStatus(), previousConsent.getCurrentStatus(), + ConsentCoreServiceConstants.DETAIL_CONSENT_UPDATE_REASON, detailedConsentResource.getClientID(), + consentDataMap + ); + + DatabaseUtils.commitTransaction(connection); + log.debug("Updated the basic consent details, consent attributes, authorization resources and " + + "mapping resource successfully."); + + return getDetailedConsent(consentIdToUpdate); + + } catch (ConsentDataInsertionException | ConsentDataUpdationException | ConsentDataDeletionException | + ConsentDataRetrievalException e) { + log.error("Error during updating consent, rolling back", e); + DatabaseUtils.rollbackTransaction(connection); + throw new ConsentManagementException("Failed to update consent and create related records", e); + } finally { + log.debug(ConsentCoreServiceConstants.DATABASE_CONNECTION_CLOSE_LOG_MSG); + DatabaseUtils.closeConnection(connection); + } + } + @Override public DetailedConsentResource updateConsentAndCreateAuthResources(DetailedConsentResource detailedConsentResource, String primaryUserId) throws ConsentManagementException { diff --git a/financial-services-accelerator/components/org.wso2.financial.services.accelerator.consent.mgt.service/src/main/java/org/wso2/financial/services/accelerator/consent/mgt/service/util/ConsentCoreServiceUtil.java b/financial-services-accelerator/components/org.wso2.financial.services.accelerator.consent.mgt.service/src/main/java/org/wso2/financial/services/accelerator/consent/mgt/service/util/ConsentCoreServiceUtil.java index 2706f4048..6c1bd2319 100644 --- a/financial-services-accelerator/components/org.wso2.financial.services.accelerator.consent.mgt.service/src/main/java/org/wso2/financial/services/accelerator/consent/mgt/service/util/ConsentCoreServiceUtil.java +++ b/financial-services-accelerator/components/org.wso2.financial.services.accelerator.consent.mgt.service/src/main/java/org/wso2/financial/services/accelerator/consent/mgt/service/util/ConsentCoreServiceUtil.java @@ -22,6 +22,7 @@ import net.minidev.json.JSONObject; import net.minidev.json.parser.JSONParser; import net.minidev.json.parser.ParseException; +import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.collections4.MapUtils; import org.apache.commons.lang3.StringUtils; import org.apache.commons.logging.Log; @@ -770,4 +771,138 @@ public static String resolveActionByUser(DetailedConsentResource detailedConsent return ""; } + /** + * Method to delete the existing consent attributes of a consent. + * + * @param consentCoreDAO Consent core DAO + * @param connection Database connection + * @param consentId Consent ID + * @param previousConsent Previous consent resource containing the existing consent attributes + * @throws ConsentDataDeletionException If an error occurs when deleting the existing consent attributes + */ + public static void deleteExistingConsentAttributes(ConsentCoreDAO consentCoreDAO, Connection connection, + String consentId, DetailedConsentResource previousConsent) + throws ConsentDataDeletionException { + + if (MapUtils.isNotEmpty(previousConsent.getConsentAttributes())) { + if (log.isDebugEnabled()) { + log.debug(String.format("Deleting existing consent attributes for consent ID: %s", + consentId.replaceAll("[\r\n]", ""))); + } + ArrayList existingAttributeKeys = previousConsent.getConsentAttributes().keySet() + .stream().collect(ArrayList::new, ArrayList::add, ArrayList::addAll); + consentCoreDAO.deleteConsentAttributes(connection, consentId, existingAttributeKeys); + } + } + + /** + * Method to add the consent attributes of a consent. + * + * @param consentCoreDAO Consent core DAO + * @param connection Database connection + * @param detailedConsentToUpdate Detailed consent resource containing the new consent attributes to be added + * @throws ConsentDataInsertionException If an error occurs when inserting the new consent attributes + */ + public static void addConsentAttributes(ConsentCoreDAO consentCoreDAO, Connection connection, + DetailedConsentResource detailedConsentToUpdate) + throws ConsentDataInsertionException { + + ConsentAttributes attributes = ConsentCoreServiceUtil.getConsentAttributes(detailedConsentToUpdate); + if (log.isDebugEnabled()) { + log.debug(String.format("Adding new consent attributes for consent ID: %s", + detailedConsentToUpdate.getConsentID().replaceAll("[\r\n]", ""))); + } + consentCoreDAO.storeConsentAttributes(connection, attributes); + } + + /** + * Method to delete the existing authorization resources of a consent. + * @param consentCoreDAO Consent core DAO + * @param connection Database connection + * @param consentId Consent ID + * @param previousConsent Previous consent resource containing the existing authorization resources + * @throws ConsentDataDeletionException If an error occurs when deleting the existing authorization resources + */ + public static void deleteExistingAuthorizationResources(ConsentCoreDAO consentCoreDAO, Connection connection, + String consentId, DetailedConsentResource previousConsent) + throws ConsentDataDeletionException { + + if (CollectionUtils.isNotEmpty(previousConsent.getAuthorizationResources())) { + if (log.isDebugEnabled()) { + log.debug(String.format("Deleting existing authorization resources for consent ID: %s", + consentId.replaceAll("[\r\n]", ""))); + } + List authIdsToDelete = previousConsent.getAuthorizationResources().stream() + .map(AuthorizationResource::getAuthorizationID).collect(ArrayList::new, ArrayList::add, + ArrayList::addAll); + consentCoreDAO.deleteAuthorizationResources(connection, authIdsToDelete); + } + } + + /** + * Method to add the authorization resources of a consent. + * + * @param consentCoreDAO Consent core DAO + * @param connection Database connection + * @param authorizationResources List of authorization resources to be added + * @param consentId Consent ID + * @throws ConsentDataInsertionException If an error occurs when inserting the new authorization resources + */ + public static void addAuthorizationResources(ConsentCoreDAO consentCoreDAO, Connection connection, + List authorizationResources, String consentId) + throws ConsentDataInsertionException { + + if (log.isDebugEnabled()) { + log.debug(String.format("Adding new authorization resources for consent ID: %s", + consentId.replaceAll("[\r\n]", ""))); + } + for (AuthorizationResource authResource : authorizationResources) { + consentCoreDAO.storeAuthorizationResource(connection, authResource); + } + } + + /** + * Method to delete the existing consent mapping resources of a consent. + * + * @param consentCoreDAO Consent core DAO + * @param connection Database connection + * @param consentId Consent ID + * @param previousConsent Previous consent resource containing the existing consent mapping resources + * @throws ConsentDataDeletionException If an error occurs when deleting the existing consent mapping resources + */ + public static void deleteExistingConsentMappings(ConsentCoreDAO consentCoreDAO, Connection connection, + String consentId, DetailedConsentResource previousConsent) + throws ConsentDataDeletionException { + + if (CollectionUtils.isNotEmpty(previousConsent.getConsentMappingResources())) { + if (log.isDebugEnabled()) { + log.debug(String.format("Deleting existing consent mapping resources for consent ID: %s", + consentId.replaceAll("[\r\n]", ""))); + } + List mappingIdsToDelete = previousConsent.getConsentMappingResources().stream() + .map(ConsentMappingResource::getMappingID).collect(ArrayList::new, ArrayList::add, + ArrayList::addAll); + consentCoreDAO.deleteConsentMappingResources(connection, mappingIdsToDelete); + } + } + + /** + * Method to add the consent mapping resources of a consent. + * + * @param consentCoreDAO Consent core DAO + * @param connection Database connection + * @param mappingResources List of consent mapping resources to be added + * @param consentId Consent ID + * @throws ConsentDataInsertionException If an error occurs when inserting the new consent mapping resources + */ + public static void addConsentMappingResources(ConsentCoreDAO consentCoreDAO, Connection connection, + List mappingResources, String consentId) + throws ConsentDataInsertionException { + + if (log.isDebugEnabled()) { + log.debug(String.format("Adding new consent mapping resources for consent ID: %s", + consentId.replaceAll("[\r\n]", ""))); + } + consentCoreDAO.storeConsentMappingResources(connection, mappingResources); + } } diff --git a/financial-services-accelerator/components/org.wso2.financial.services.accelerator.consent.mgt.service/src/test/java/org/wso2/financial/services/accelerator/consent/mgt/service/impl/ConsentMgtCoreServiceTests.java b/financial-services-accelerator/components/org.wso2.financial.services.accelerator.consent.mgt.service/src/test/java/org/wso2/financial/services/accelerator/consent/mgt/service/impl/ConsentMgtCoreServiceTests.java index 781425cea..b7747eb94 100644 --- a/financial-services-accelerator/components/org.wso2.financial.services.accelerator.consent.mgt.service/src/test/java/org/wso2/financial/services/accelerator/consent/mgt/service/impl/ConsentMgtCoreServiceTests.java +++ b/financial-services-accelerator/components/org.wso2.financial.services.accelerator.consent.mgt.service/src/test/java/org/wso2/financial/services/accelerator/consent/mgt/service/impl/ConsentMgtCoreServiceTests.java @@ -536,6 +536,68 @@ public void testStoreDetailedConsentResourceWithMissingConsentID() throws Consen consentCoreServiceImpl.storeDetailedConsentResource(detailedConsentResource); } + @Test + public void testUpdateDetailedConsent() throws ConsentManagementException, + ConsentDataRetrievalException, ConsentDataUpdationException, ConsentDataInsertionException { + + doReturn(ConsentMgtServiceTestData.getSampleDetailedStoredTestConsentResource()).when(mockedConsentCoreDAO) + .getDetailedConsentResource(any(), anyString()); + doNothing().when(mockedConsentCoreDAO).updateConsentResource(any(), any()); + doReturn(ConsentMgtServiceTestData + .getSampleTestConsentStatusAuditRecord(ConsentMgtServiceTestData.UNMATCHED_CONSENT_ID, + ConsentMgtServiceTestData.SAMPLE_CURRENT_STATUS)) + .when(mockedConsentCoreDAO).storeConsentStatusAuditRecord(any(), any()); + + DetailedConsentResource result = consentCoreServiceImpl.updateDetailedConsent( + ConsentMgtServiceTestData.getSampleDetailedStoredTestConsentResource()); + Assert.assertNotNull(result); + } + + @Test + public void testUpdateDetailedConsentWithEmptyObjects() throws ConsentManagementException, + ConsentDataRetrievalException, ConsentDataUpdationException, ConsentDataInsertionException { + + doReturn(ConsentMgtServiceTestData.getSampleDetailedStoredTestConsentResource()) + .when(mockedConsentCoreDAO).getDetailedConsentResource(any(), anyString()); + doNothing().when(mockedConsentCoreDAO).updateConsentResource(any(), any()); + doReturn(ConsentMgtServiceTestData + .getSampleTestConsentStatusAuditRecord(ConsentMgtServiceTestData.UNMATCHED_CONSENT_ID, + ConsentMgtServiceTestData.SAMPLE_CURRENT_STATUS)) + .when(mockedConsentCoreDAO).storeConsentStatusAuditRecord(any(), any()); + + DetailedConsentResource detailedConsentResource = new DetailedConsentResource( + ConsentMgtServiceTestData.UNMATCHED_CONSENT_ID, UUID.randomUUID().toString(), + ConsentMgtServiceTestData.SAMPLE_CONSENT_RECEIPT, ConsentMgtServiceTestData.SAMPLE_CONSENT_TYPE, + ConsentMgtServiceTestData.SAMPLE_CURRENT_STATUS, ConsentMgtServiceTestData.SAMPLE_CONSENT_FREQUENCY, + ConsentMgtServiceTestData.SAMPLE_CONSENT_VALIDITY_PERIOD, System.currentTimeMillis() / 1000, + System.currentTimeMillis() / 1000, ConsentMgtServiceTestData.SAMPLE_RECURRING_INDICATOR, + new HashMap<>(), new ArrayList<>(), new ArrayList<>()); + + DetailedConsentResource result = consentCoreServiceImpl.updateDetailedConsent(detailedConsentResource); + Assert.assertNotNull(result); + } + + @Test(expectedExceptions = ConsentManagementException.class) + public void testUpdateConsentWithoutConsentId() throws ConsentManagementException { + + DetailedConsentResource consentResource = new DetailedConsentResource(); + consentResource.setConsentID(null); + + consentCoreServiceImpl.updateDetailedConsent(consentResource); + } + + @Test(expectedExceptions = ConsentManagementException.class) + public void testUpdateConsentWithConsentUpdateError() throws ConsentManagementException, + ConsentDataUpdationException, ConsentDataRetrievalException { + + doReturn(ConsentMgtServiceTestData.getSampleDetailedStoredTestConsentResource()).when(mockedConsentCoreDAO) + .getDetailedConsentResource(any(), anyString()); + doThrow(ConsentDataUpdationException.class).when(mockedConsentCoreDAO).updateConsentResource(any(), any()); + + consentCoreServiceImpl.updateDetailedConsent( + ConsentMgtServiceTestData.getSampleDetailedStoredTestConsentResource()); + } + @Test public void testUpdateConsentAndCreateAuthResources() throws ConsentManagementException, ConsentDataRetrievalException, ConsentDataInsertionException {