From e4f260bd691aa0c44ed1f9e226bcdfda2d605449 Mon Sep 17 00:00:00 2001 From: shahrahul1985 Date: Fri, 14 Aug 2015 12:27:22 +0530 Subject: [PATCH] MIFOSX-2135: Create new endpoints and the User interface for managing credentials to external services. --- api-docs/apiLive.htm | 98 +++++++++++++ .../ExternalServicesConfigurationTest.java | 96 ++++++++++++ .../ExternalServicesConfigurationHelper.java | 51 +++++++ .../service/CommandWrapperBuilder.java | 16 +- ...ternalServiceConfigurationApiConstant.java | 19 +++ ...ernalServicesConfigurationApiResource.java | 93 ++++++++++++ .../data/ExternalServicesData.java | 26 ++++ .../data/ExternalServicesPropertiesData.java | 28 ++++ .../data/SMTPCredentialsData.java | 44 ++++++ .../configuration/domain/ExternalService.java | 32 +++- .../domain/ExternalServicePropertiesPK.java | 43 ++++++ .../domain/ExternalServicesProperties.java | 76 ++++++++++ ...ExternalServicesPropertiesRepository.java} | 5 +- ...alServicesPropertiesRepositoryWrapper.java | 28 ++++ ...ServiceConfigurationNotFoundException.java | 20 +++ ...nalServiceConfigurationCommandHandler.java | 34 +++++ ...pertiesCommandFromApiJsonDeserializer.java | 72 +++++++++ .../ExternalServiceWritePlatformService.java | 15 ++ ...WritePlatformServiceJpaRepositoryImpl.java | 79 ++++++++++ .../service/ExternalServicesConstants.java | 106 ++++++++++++++ ...ServicesPropertiesReadPlatformService.java | 22 +++ ...icesPropertiesReadPlatformServiceImpl.java | 137 ++++++++++++++++++ .../ExternalServicesReadPlatformService.java | 6 +- ...ternalServicesReadPlatformServiceImpl.java | 55 ++++--- .../GmailBackedPlatformEmailService.java | 27 +++- .../ContentRepositoryFactory.java | 6 +- .../V265__modify_external_service_schema.sql | 48 ++++++ 27 files changed, 1235 insertions(+), 47 deletions(-) create mode 100644 mifosng-provider/src/integrationTest/java/org/mifosplatform/integrationtests/ExternalServicesConfigurationTest.java create mode 100644 mifosng-provider/src/integrationTest/java/org/mifosplatform/integrationtests/common/ExternalServicesConfigurationHelper.java create mode 100644 mifosng-provider/src/main/java/org/mifosplatform/infrastructure/configuration/api/ExternalServiceConfigurationApiConstant.java create mode 100644 mifosng-provider/src/main/java/org/mifosplatform/infrastructure/configuration/api/ExternalServicesConfigurationApiResource.java create mode 100644 mifosng-provider/src/main/java/org/mifosplatform/infrastructure/configuration/data/ExternalServicesData.java create mode 100644 mifosng-provider/src/main/java/org/mifosplatform/infrastructure/configuration/data/ExternalServicesPropertiesData.java create mode 100644 mifosng-provider/src/main/java/org/mifosplatform/infrastructure/configuration/data/SMTPCredentialsData.java create mode 100644 mifosng-provider/src/main/java/org/mifosplatform/infrastructure/configuration/domain/ExternalServicePropertiesPK.java create mode 100644 mifosng-provider/src/main/java/org/mifosplatform/infrastructure/configuration/domain/ExternalServicesProperties.java rename mifosng-provider/src/main/java/org/mifosplatform/infrastructure/configuration/domain/{ExternalServiceRepository.java => ExternalServicesPropertiesRepository.java} (56%) create mode 100644 mifosng-provider/src/main/java/org/mifosplatform/infrastructure/configuration/domain/ExternalServicesPropertiesRepositoryWrapper.java create mode 100644 mifosng-provider/src/main/java/org/mifosplatform/infrastructure/configuration/exception/ExternalServiceConfigurationNotFoundException.java create mode 100644 mifosng-provider/src/main/java/org/mifosplatform/infrastructure/configuration/handler/UpdateExternalServiceConfigurationCommandHandler.java create mode 100644 mifosng-provider/src/main/java/org/mifosplatform/infrastructure/configuration/serialization/ExternalServicesPropertiesCommandFromApiJsonDeserializer.java create mode 100644 mifosng-provider/src/main/java/org/mifosplatform/infrastructure/configuration/service/ExternalServiceWritePlatformService.java create mode 100644 mifosng-provider/src/main/java/org/mifosplatform/infrastructure/configuration/service/ExternalServiceWritePlatformServiceJpaRepositoryImpl.java create mode 100644 mifosng-provider/src/main/java/org/mifosplatform/infrastructure/configuration/service/ExternalServicesPropertiesReadPlatformService.java create mode 100644 mifosng-provider/src/main/java/org/mifosplatform/infrastructure/configuration/service/ExternalServicesPropertiesReadPlatformServiceImpl.java create mode 100644 mifosng-provider/src/main/resources/sql/migrations/core_db/V265__modify_external_service_schema.sql diff --git a/api-docs/apiLive.htm b/api-docs/apiLive.htm index 937452473..d8daeaacc 100644 --- a/api-docs/apiLive.htm +++ b/api-docs/apiLive.htm @@ -2395,6 +2395,16 @@ + + External Services + externalservice/{servicename} + + Retrieve + a external service configuration + Update + external service Configuration + + @@ -16556,6 +16566,94 @@ POST scheduler?command=stop + +   +
+
+

External Services

+

External Services Configuration related to set of supported configurations for third party services like Amazon S3 and SMTP:

+
    +
  1. S3 (Amazon S3):
  2. +
  3. s3_access_key -
  4. +
  5. s3_bucket_name -
  6. +
  7. s3_secret_key -
  8. +

    +
  9. SMTP (Email Service):
  10. +
  11. username -
  12. +
  13. password -
  14. +
  15. host -
  16. +
  17. port -
  18. +
  19. useTLS -
  20. + +
+
+
+ +   +
+
+

Retrieve External Services Configuration

+

Returns a external Service configurations based on the Service Name.

+

Service Names supported are S3 and SMTP.

+

Example Requests:

+
externalservice/SMTP
+
+
+ +GET https://DomainName/api/v1/externalservice/{serviceName} + + + + + [ + { + "name": "username", + "value": "test@mifos.com" + }, + { + "name": "password", + "value": "XXXX" + }, + { + "name": "host", + "value": "smtp.gmail.com" + }, + { + "name": "port", + "value": "25" + }, + { + "name": "useTLS", + "value": "true" + } + ] + + + +
+
+ +   +
+
+

Update External Service

+

Updates the external Service Configuration for a Service Name.

+
+
+ +PUT https://DomainName/api/v1/externalservice/{serviceName} + + +PUT externalservice/S3 +Content-Type: application/json +{ + "username" : "test@mifos.org" + "password" : "XXXX" +} + +
+
  diff --git a/mifosng-provider/src/integrationTest/java/org/mifosplatform/integrationtests/ExternalServicesConfigurationTest.java b/mifosng-provider/src/integrationTest/java/org/mifosplatform/integrationtests/ExternalServicesConfigurationTest.java new file mode 100644 index 000000000..55d950580 --- /dev/null +++ b/mifosng-provider/src/integrationTest/java/org/mifosplatform/integrationtests/ExternalServicesConfigurationTest.java @@ -0,0 +1,96 @@ +/** + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. + */ +package org.mifosplatform.integrationtests; + +import java.util.ArrayList; +import java.util.HashMap; + +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.mifosplatform.integrationtests.common.ExternalServicesConfigurationHelper; +import org.mifosplatform.integrationtests.common.Utils; + +import com.jayway.restassured.builder.RequestSpecBuilder; +import com.jayway.restassured.builder.ResponseSpecBuilder; +import com.jayway.restassured.http.ContentType; +import com.jayway.restassured.specification.RequestSpecification; +import com.jayway.restassured.specification.ResponseSpecification; + +@SuppressWarnings({ "rawtypes", "unchecked", "static-access" }) +public class ExternalServicesConfigurationTest { + + private ResponseSpecification responseSpec; + private RequestSpecification requestSpec; + private ExternalServicesConfigurationHelper externalServicesConfigurationHelper; + private ResponseSpecification httpStatusForidden; + + @Before + public void setup() { + Utils.initializeRESTAssured(); + this.requestSpec = new RequestSpecBuilder().setContentType(ContentType.JSON).build(); + this.requestSpec.header("Authorization", "Basic " + Utils.loginIntoServerAndGetBase64EncodedAuthenticationKey()); + this.responseSpec = new ResponseSpecBuilder().expectStatusCode(200).build(); + this.httpStatusForidden = new ResponseSpecBuilder().expectStatusCode(403).build(); + + } + + @Test + public void testExternalServicesConfiguration() { + this.externalServicesConfigurationHelper = new ExternalServicesConfigurationHelper(this.requestSpec, this.responseSpec); + + // Checking for S3 + String configName = "s3_access_key"; + ArrayList externalServicesConfig = this.externalServicesConfigurationHelper + .getExternalServicesConfigurationByServiceName(requestSpec, responseSpec, "S3"); + Assert.assertNotNull(externalServicesConfig); + for (Integer configIndex = 0; configIndex < (externalServicesConfig.size()); configIndex++) { + String name = (String) externalServicesConfig.get(configIndex).get("name"); + String value = null; + if (name.equals(configName)) { + value = (String) externalServicesConfig.get(configIndex).get("value"); + String newValue = "test"; + System.out.println(name + ":" + value); + HashMap arrayListValue = this.externalServicesConfigurationHelper.updateValueForExternaServicesConfiguration(requestSpec, + responseSpec, "S3", name, newValue); + Assert.assertNotNull(arrayListValue.get("value")); + Assert.assertEquals(arrayListValue.get("value"), newValue); + HashMap arrayListValue1 = this.externalServicesConfigurationHelper.updateValueForExternaServicesConfiguration(requestSpec, + responseSpec, "S3", name, value); + Assert.assertNotNull(arrayListValue1.get("value")); + Assert.assertEquals(arrayListValue1.get("value"), value); + } + + } + + // Checking for SMTP: + + configName = "username"; + externalServicesConfig = this.externalServicesConfigurationHelper.getExternalServicesConfigurationByServiceName(requestSpec, + responseSpec, "SMTP"); + Assert.assertNotNull(externalServicesConfig); + for (Integer configIndex = 0; configIndex < (externalServicesConfig.size()); configIndex++) { + String name = (String) externalServicesConfig.get(configIndex).get("name"); + String value = null; + if (name.equals(configName)) { + value = (String) externalServicesConfig.get(configIndex).get("value"); + String newValue = "test"; + System.out.println(name + ":" + value); + HashMap arrayListValue = this.externalServicesConfigurationHelper.updateValueForExternaServicesConfiguration(requestSpec, + responseSpec, "SMTP", name, newValue); + Assert.assertNotNull(arrayListValue.get("value")); + Assert.assertEquals(arrayListValue.get("value"), newValue); + HashMap arrayListValue1 = this.externalServicesConfigurationHelper.updateValueForExternaServicesConfiguration(requestSpec, + responseSpec, "SMTP", name, value); + Assert.assertNotNull(arrayListValue1.get("value")); + Assert.assertEquals(arrayListValue1.get("value"), value); + } + + } + + } + +} diff --git a/mifosng-provider/src/integrationTest/java/org/mifosplatform/integrationtests/common/ExternalServicesConfigurationHelper.java b/mifosng-provider/src/integrationTest/java/org/mifosplatform/integrationtests/common/ExternalServicesConfigurationHelper.java new file mode 100644 index 000000000..c82f85e99 --- /dev/null +++ b/mifosng-provider/src/integrationTest/java/org/mifosplatform/integrationtests/common/ExternalServicesConfigurationHelper.java @@ -0,0 +1,51 @@ +/** + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. + */ +package org.mifosplatform.integrationtests.common; + +import java.util.ArrayList; +import java.util.HashMap; + +import com.google.gson.Gson; +import com.jayway.restassured.specification.RequestSpecification; +import com.jayway.restassured.specification.ResponseSpecification; + +public class ExternalServicesConfigurationHelper { + + private final RequestSpecification requestSpec; + private final ResponseSpecification responseSpec; + + public ExternalServicesConfigurationHelper(final RequestSpecification requestSpec, final ResponseSpecification responseSpec) { + this.requestSpec = requestSpec; + this.responseSpec = responseSpec; + } + + public static ArrayList getExternalServicesConfigurationByServiceName(final RequestSpecification requestSpec, + final ResponseSpecification responseSpec, final String serviceName) { + final String GET_EXTERNAL_SERVICES_CONFIG_BY_SERVICE_NAME_URL = "/mifosng-provider/api/v1/externalservice/" + serviceName + "?" + + Utils.TENANT_IDENTIFIER; + System.out.println("------------------------ RETRIEVING GLOBAL CONFIGURATION BY ID -------------------------"); + return Utils.performServerGet(requestSpec, responseSpec, GET_EXTERNAL_SERVICES_CONFIG_BY_SERVICE_NAME_URL, ""); + } + + public static HashMap updateValueForExternaServicesConfiguration(final RequestSpecification requestSpec, + final ResponseSpecification responseSpec, final String serviceName, final String name, final String value) { + final String EXTERNAL_SERVICES_CONFIG_UPDATE_URL = "/mifosng-provider/api/v1/externalservice/" + serviceName + "?" + + Utils.TENANT_IDENTIFIER; + System.out.println("---------------------------------UPDATE VALUE FOR GLOBAL CONFIG---------------------------------------------"); + HashMap map = Utils.performServerPut(requestSpec, responseSpec, EXTERNAL_SERVICES_CONFIG_UPDATE_URL, + updateExternalServicesConfigUpdateValueAsJSON(name, value), ""); + + return (HashMap) map.get("changes"); + } + + public static String updateExternalServicesConfigUpdateValueAsJSON(final String name, final String value) { + final HashMap map = new HashMap<>(); + map.put(name, value); + System.out.println("map : " + map); + return new Gson().toJson(map); + } + +} diff --git a/mifosng-provider/src/main/java/org/mifosplatform/commands/service/CommandWrapperBuilder.java b/mifosng-provider/src/main/java/org/mifosplatform/commands/service/CommandWrapperBuilder.java index af23d3d99..c0e24ec2b 100755 --- a/mifosng-provider/src/main/java/org/mifosplatform/commands/service/CommandWrapperBuilder.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/commands/service/CommandWrapperBuilder.java @@ -29,8 +29,8 @@ public class CommandWrapperBuilder { private Long templateId; public CommandWrapper build() { - return new CommandWrapper(this.officeId, this.groupId, this.clientId, this.loanId, this.savingsId, this.actionName, - this.entityName, this.entityId, this.subentityId, this.href, this.json, this.transactionId, this.productId, this.templateId); + return new CommandWrapper(this.officeId, this.groupId, this.clientId, this.loanId, this.savingsId, this.actionName, this.entityName, + this.entityId, this.subentityId, this.href, this.json, this.transactionId, this.productId, this.templateId); } public CommandWrapperBuilder withLoanId(final Long withLoanId) { @@ -1813,7 +1813,8 @@ public class CommandWrapperBuilder { return this; } - public CommandWrapperBuilder saveOrUpdateAttendance(final Long entityId, final String supportedEntityType, final Long supportedEntityId) { + public CommandWrapperBuilder saveOrUpdateAttendance(final Long entityId, final String supportedEntityType, + final Long supportedEntityId) { this.actionName = "SAVEORUPDATEATTENDANCE"; this.entityName = "MEETING"; this.entityId = entityId; @@ -2394,4 +2395,13 @@ public class CommandWrapperBuilder { return this; } + public CommandWrapperBuilder updateExternalServiceProperties(final String externalServiceName) { + this.actionName = "UPDATE"; + this.entityName = "EXTERNALSERVICES"; + this.transactionId = externalServiceName; + + this.href = "/externalservices/" + externalServiceName; + return this; + } + } \ No newline at end of file diff --git a/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/configuration/api/ExternalServiceConfigurationApiConstant.java b/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/configuration/api/ExternalServiceConfigurationApiConstant.java new file mode 100644 index 000000000..7f8195fb8 --- /dev/null +++ b/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/configuration/api/ExternalServiceConfigurationApiConstant.java @@ -0,0 +1,19 @@ +/** + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. + */ +package org.mifosplatform.infrastructure.configuration.api; + +import java.util.Arrays; +import java.util.HashSet; +import java.util.Set; + +public class ExternalServiceConfigurationApiConstant { + + public static final String NAME = "name"; + public static final String VALUE = "value"; + public static final String EXTERNAL_SERVICE_RESOURCE_NAME = "externalServiceConfiguration"; + + public static final Set EXTERNAL_SERVICE_CONFIGURATION_DATA_PARAMETERS = new HashSet<>(Arrays.asList(NAME, VALUE)); +} diff --git a/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/configuration/api/ExternalServicesConfigurationApiResource.java b/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/configuration/api/ExternalServicesConfigurationApiResource.java new file mode 100644 index 000000000..9affe1005 --- /dev/null +++ b/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/configuration/api/ExternalServicesConfigurationApiResource.java @@ -0,0 +1,93 @@ +/** + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. + */ +package org.mifosplatform.infrastructure.configuration.api; + +import java.util.Collection; + +import javax.ws.rs.Consumes; +import javax.ws.rs.GET; +import javax.ws.rs.PUT; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.Produces; +import javax.ws.rs.core.Context; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.UriInfo; + +import org.mifosplatform.commands.domain.CommandWrapper; +import org.mifosplatform.commands.service.CommandWrapperBuilder; +import org.mifosplatform.commands.service.PortfolioCommandSourceWritePlatformService; +import org.mifosplatform.infrastructure.configuration.data.ExternalServicesData; +import org.mifosplatform.infrastructure.configuration.data.ExternalServicesPropertiesData; +import org.mifosplatform.infrastructure.configuration.service.ExternalServicesPropertiesReadPlatformService; +import org.mifosplatform.infrastructure.configuration.service.ExternalServicesReadPlatformService; +import org.mifosplatform.infrastructure.core.api.ApiRequestParameterHelper; +import org.mifosplatform.infrastructure.core.data.CommandProcessingResult; +import org.mifosplatform.infrastructure.core.serialization.ApiRequestJsonSerializationSettings; +import org.mifosplatform.infrastructure.core.serialization.ToApiJsonSerializer; +import org.mifosplatform.infrastructure.security.service.PlatformSecurityContext; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Scope; +import org.springframework.stereotype.Component; + +@Path("/externalservice") +@Component +@Scope("singleton") +public class ExternalServicesConfigurationApiResource { + + private final PlatformSecurityContext context; + private final ExternalServicesPropertiesReadPlatformService externalServicePropertiesReadPlatformService; + private final ExternalServicesReadPlatformService externalServiceReadPlatformService; + private final ToApiJsonSerializer toApiJsonSerializer; + // private final ToApiJsonSerializer + // s3ToApiJsonSerializer; + private final ApiRequestParameterHelper apiRequestParameterHelper; + private final PortfolioCommandSourceWritePlatformService commandsSourceWritePlatformService; + + @Autowired + public ExternalServicesConfigurationApiResource(final PlatformSecurityContext context, + final ExternalServicesPropertiesReadPlatformService readPlatformService, + final ExternalServicesReadPlatformService externalServicesReadPlatformService, + final ToApiJsonSerializer toApiJsonSerializer, + final ApiRequestParameterHelper apiRequestParameterHelper, + final PortfolioCommandSourceWritePlatformService commandsSourceWritePlatformService) { + this.context = context; + this.externalServicePropertiesReadPlatformService = readPlatformService; + this.toApiJsonSerializer = toApiJsonSerializer; + this.externalServiceReadPlatformService = externalServicesReadPlatformService; + // this.s3ToApiJsonSerializer = s3ToApiJsonSerializer; + this.apiRequestParameterHelper = apiRequestParameterHelper; + this.commandsSourceWritePlatformService = commandsSourceWritePlatformService; + } + + @GET + @Path("{servicename}") + @Consumes({ MediaType.APPLICATION_JSON }) + @Produces({ MediaType.APPLICATION_JSON }) + public String retrieveOne(@PathParam("servicename") final String serviceName, @Context final UriInfo uriInfo) { + this.context.authenticatedUser().validateHasReadPermission(ExternalServiceConfigurationApiConstant.EXTERNAL_SERVICE_RESOURCE_NAME); + final ApiRequestJsonSerializationSettings settings = this.apiRequestParameterHelper.process(uriInfo.getQueryParameters()); + final Collection externalServiceNVPs = this.externalServicePropertiesReadPlatformService + .retrieveOne(serviceName); + return this.toApiJsonSerializer.serialize(settings, externalServiceNVPs, + ExternalServiceConfigurationApiConstant.EXTERNAL_SERVICE_CONFIGURATION_DATA_PARAMETERS); + } + + @PUT + @Path("{servicename}") + @Consumes({ MediaType.APPLICATION_JSON }) + @Produces({ MediaType.APPLICATION_JSON }) + public String updateExternalServiceProperties(@PathParam("servicename") final String serviceName, final String apiRequestBodyAsJson) { + // ExternalServicesData external = + // this.externalServiceReadPlatformService.getExternalServiceDetailsByServiceName(serviceName); + final CommandWrapper commandRequest = new CommandWrapperBuilder().updateExternalServiceProperties(serviceName) + .withJson(apiRequestBodyAsJson).build(); + final CommandProcessingResult result = this.commandsSourceWritePlatformService.logCommandSource(commandRequest); + return this.toApiJsonSerializer.serialize(result); + + } +} diff --git a/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/configuration/data/ExternalServicesData.java b/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/configuration/data/ExternalServicesData.java new file mode 100644 index 000000000..721153a8f --- /dev/null +++ b/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/configuration/data/ExternalServicesData.java @@ -0,0 +1,26 @@ +/** + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. + */ +package org.mifosplatform.infrastructure.configuration.data; + +public class ExternalServicesData { + + private final Long id; + private final String name; + + public ExternalServicesData(final Long id, final String name) { + this.id = id; + this.name = name; + } + + public Long getId() { + return id; + } + + public String getName() { + return name; + } + +} diff --git a/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/configuration/data/ExternalServicesPropertiesData.java b/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/configuration/data/ExternalServicesPropertiesData.java new file mode 100644 index 000000000..fd9e583c3 --- /dev/null +++ b/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/configuration/data/ExternalServicesPropertiesData.java @@ -0,0 +1,28 @@ +/** + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. + */ +package org.mifosplatform.infrastructure.configuration.data; + +import java.io.Serializable; + +public class ExternalServicesPropertiesData implements Serializable { + + private final String name; + private final String value; + + public ExternalServicesPropertiesData(final String name, final String value) { + this.name = name; + this.value = value; + } + + public String getName() { + return name; + } + + public String getValue() { + return value; + } + +} diff --git a/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/configuration/data/SMTPCredentialsData.java b/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/configuration/data/SMTPCredentialsData.java new file mode 100644 index 000000000..75aa59934 --- /dev/null +++ b/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/configuration/data/SMTPCredentialsData.java @@ -0,0 +1,44 @@ +/** + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. + */ +package org.mifosplatform.infrastructure.configuration.data; + +public class SMTPCredentialsData { + + private final String username; + private final String password; + private final String host; + private final String port; + private final boolean useTLS; + + public SMTPCredentialsData(final String username, final String password, final String host, final String port, final boolean useTLS) { + this.username = username; + this.password = password; + this.host = host; + this.port = port; + this.useTLS = useTLS; + } + + public String getUsername() { + return username; + } + + public String getPassword() { + return password; + } + + public String getHost() { + return host; + } + + public String getPort() { + return port; + } + + public boolean isUseTLS() { + return useTLS; + } + +} diff --git a/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/configuration/domain/ExternalService.java b/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/configuration/domain/ExternalService.java index ec8b30055..bb55326df 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/configuration/domain/ExternalService.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/configuration/domain/ExternalService.java @@ -1,5 +1,11 @@ package org.mifosplatform.infrastructure.configuration.domain; +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.Set; + +import javax.persistence.CascadeType; + /** * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this file, @@ -8,29 +14,39 @@ package org.mifosplatform.infrastructure.configuration.domain; import javax.persistence.Column; import javax.persistence.Entity; +import javax.persistence.FetchType; +import javax.persistence.OneToMany; import javax.persistence.Table; import javax.persistence.UniqueConstraint; +import org.apache.commons.lang.StringUtils; +import org.mifosplatform.infrastructure.core.api.JsonCommand; import org.springframework.data.jpa.domain.AbstractPersistable; @Entity -@Table(name = "c_external_service", uniqueConstraints = { @UniqueConstraint(columnNames = "name") }) +@Table(name = "c_external_service", uniqueConstraints = { @UniqueConstraint(columnNames = { "name" }, name = "name_UNIQUE") }) public class ExternalService extends AbstractPersistable { - @Column(name = "name", nullable = false) + @Column(name = "name", length = 50) private String name; - @Column(name = "value", nullable = false) - private String value; + // @OneToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL, mappedBy = + // "externalServicePropertiesPK.externalService", orphanRemoval = true) + // private Set values; - public ExternalService(final String name, final String value) { + public static ExternalService fromJson(final JsonCommand command) { + final String name = command.stringValueOfParameterNamed("name"); + return new ExternalService(name); + } + + private ExternalService(final String name) { this.name = name; - this.value = value; } protected ExternalService() {} - public String getValue() { - return this.value; + public String name() { + return this.name; } + } \ No newline at end of file diff --git a/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/configuration/domain/ExternalServicePropertiesPK.java b/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/configuration/domain/ExternalServicePropertiesPK.java new file mode 100644 index 000000000..11fb959c1 --- /dev/null +++ b/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/configuration/domain/ExternalServicePropertiesPK.java @@ -0,0 +1,43 @@ +/** + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. + */ +package org.mifosplatform.infrastructure.configuration.domain; + +import java.io.Serializable; + +import javax.persistence.Column; +import javax.persistence.Embeddable; +import javax.persistence.JoinColumn; +import javax.persistence.ManyToOne; + +import org.springframework.data.annotation.Id; + +@Embeddable +public class ExternalServicePropertiesPK implements Serializable { + + @Column(name = "name", length = 150) + private String name; + + @Column(name = "external_service_id") + private Long externalServiceId; + + public ExternalServicePropertiesPK() { + + } + + public ExternalServicePropertiesPK(Long externalServiceId, String name) { + this.externalServiceId = externalServiceId; + this.name = name; + } + + public String getName() { + return name; + } + + public Long getExternalService() { + return externalServiceId; + } + +} diff --git a/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/configuration/domain/ExternalServicesProperties.java b/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/configuration/domain/ExternalServicesProperties.java new file mode 100644 index 000000000..582a3b090 --- /dev/null +++ b/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/configuration/domain/ExternalServicesProperties.java @@ -0,0 +1,76 @@ +/** + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. + */ +package org.mifosplatform.infrastructure.configuration.domain; + +import java.util.LinkedHashMap; +import java.util.Map; + +import javax.persistence.Column; +import javax.persistence.Embeddable; +import javax.persistence.Embedded; +import javax.persistence.EmbeddedId; +import javax.persistence.Entity; +import javax.persistence.JoinColumn; +import javax.persistence.ManyToOne; +import javax.persistence.Table; + +import org.apache.commons.lang.StringUtils; +import org.mifosplatform.infrastructure.configuration.data.ExternalServicesPropertiesData; +import org.mifosplatform.infrastructure.configuration.service.ExternalServicesConstants.EXTERNALSERVICEPROPERTIES_JSON_INPUT_PARAMS; +import org.mifosplatform.infrastructure.configuration.service.ExternalServicesConstants.SMTP_JSON_INPUT_PARAMS; +import org.mifosplatform.infrastructure.core.api.JsonCommand; +import org.springframework.data.annotation.Id; + +@Entity +@Table(name = "c_external_service_properties") +public class ExternalServicesProperties { + + @EmbeddedId + ExternalServicePropertiesPK externalServicePropertiesPK; + + @Column(name = "value", length = 250) + private String value; + + protected ExternalServicesProperties() { + + } + + private ExternalServicesProperties(final ExternalServicePropertiesPK externalServicePropertiesPK, final String value) { + this.externalServicePropertiesPK = externalServicePropertiesPK; + + this.value = value; + + } + + public static ExternalServicesProperties fromJson(final ExternalService externalService, final JsonCommand command) { + final String name = command.stringValueOfParameterNamed(EXTERNALSERVICEPROPERTIES_JSON_INPUT_PARAMS.NAME.getValue()); + final String value = command.stringValueOfParameterNamed(EXTERNALSERVICEPROPERTIES_JSON_INPUT_PARAMS.VALUE.getValue()); + return new ExternalServicesProperties(new ExternalServicePropertiesPK(externalService.getId(), name), value); + } + + public Map update(final JsonCommand command, String paramName) { + final Map actualChanges = new LinkedHashMap<>(2); + + final String valueParamName = EXTERNALSERVICEPROPERTIES_JSON_INPUT_PARAMS.VALUE.getValue(); + if (command.isChangeInStringParameterNamed(paramName, this.value)) { + final String newValue = command.stringValueOfParameterNamed(paramName); + if (paramName.equals(SMTP_JSON_INPUT_PARAMS.PASSWORD.getValue()) && newValue.equals("XXXX")) { + // If Param Name is Password and ParamValue is XXXX that means + // the password has not been changed. + } else { + actualChanges.put(valueParamName, newValue); + } + this.value = StringUtils.defaultIfEmpty(newValue, null); + } + + return actualChanges; + } + + public ExternalServicesPropertiesData toData() { + return new ExternalServicesPropertiesData(this.externalServicePropertiesPK.getName(), this.value); + } + +} diff --git a/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/configuration/domain/ExternalServiceRepository.java b/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/configuration/domain/ExternalServicesPropertiesRepository.java similarity index 56% rename from mifosng-provider/src/main/java/org/mifosplatform/infrastructure/configuration/domain/ExternalServiceRepository.java rename to mifosng-provider/src/main/java/org/mifosplatform/infrastructure/configuration/domain/ExternalServicesPropertiesRepository.java index baf42651d..48ee6b69d 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/configuration/domain/ExternalServiceRepository.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/configuration/domain/ExternalServicesPropertiesRepository.java @@ -8,7 +8,8 @@ package org.mifosplatform.infrastructure.configuration.domain; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.JpaSpecificationExecutor; -public interface ExternalServiceRepository extends JpaRepository, JpaSpecificationExecutor { +public interface ExternalServicesPropertiesRepository extends JpaRepository, + JpaSpecificationExecutor { - ExternalService findOneByName(String name); + ExternalServicesProperties findOneByExternalServicePropertiesPK(ExternalServicePropertiesPK externalServicesProptiesPK); } \ No newline at end of file diff --git a/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/configuration/domain/ExternalServicesPropertiesRepositoryWrapper.java b/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/configuration/domain/ExternalServicesPropertiesRepositoryWrapper.java new file mode 100644 index 000000000..4895f2f74 --- /dev/null +++ b/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/configuration/domain/ExternalServicesPropertiesRepositoryWrapper.java @@ -0,0 +1,28 @@ +/** + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. + */ +package org.mifosplatform.infrastructure.configuration.domain; + +import org.mifosplatform.infrastructure.configuration.exception.ExternalServiceConfigurationNotFoundException; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +@Service +public class ExternalServicesPropertiesRepositoryWrapper { + + private final ExternalServicesPropertiesRepository repository; + + @Autowired + public ExternalServicesPropertiesRepositoryWrapper(final ExternalServicesPropertiesRepository repository) { + this.repository = repository; + } + + public ExternalServicesProperties findOneByIdAndName(Long id, String name, String externalServiceName) { + final ExternalServicesProperties externalServicesProperties = this.repository + .findOneByExternalServicePropertiesPK(new ExternalServicePropertiesPK(id, name)); + if (externalServicesProperties == null) throw new ExternalServiceConfigurationNotFoundException(externalServiceName, name); + return externalServicesProperties; + } +} diff --git a/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/configuration/exception/ExternalServiceConfigurationNotFoundException.java b/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/configuration/exception/ExternalServiceConfigurationNotFoundException.java new file mode 100644 index 000000000..46233d200 --- /dev/null +++ b/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/configuration/exception/ExternalServiceConfigurationNotFoundException.java @@ -0,0 +1,20 @@ +/** + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. + */ +package org.mifosplatform.infrastructure.configuration.exception; + +import org.mifosplatform.infrastructure.core.exception.AbstractPlatformResourceNotFoundException; + +public class ExternalServiceConfigurationNotFoundException extends AbstractPlatformResourceNotFoundException { + + public ExternalServiceConfigurationNotFoundException(final String serviceName) { + super("error.msg.externalservice.servicename.invalid", "Service Name`" + serviceName + "` does not exist", serviceName); + } + + public ExternalServiceConfigurationNotFoundException(final String externalServiceName, final String name) { + super("error.msg.externalservice.property.invalid", + "Parameter`" + name + "` does not exist for the ServiceName `" + externalServiceName + "`", name, externalServiceName); + } +} diff --git a/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/configuration/handler/UpdateExternalServiceConfigurationCommandHandler.java b/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/configuration/handler/UpdateExternalServiceConfigurationCommandHandler.java new file mode 100644 index 000000000..2ff4df255 --- /dev/null +++ b/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/configuration/handler/UpdateExternalServiceConfigurationCommandHandler.java @@ -0,0 +1,34 @@ +/** + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. + */ +package org.mifosplatform.infrastructure.configuration.handler; + +import org.mifosplatform.commands.annotation.CommandType; +import org.mifosplatform.commands.handler.NewCommandSourceHandler; +import org.mifosplatform.infrastructure.configuration.service.ExternalServiceWritePlatformService; +import org.mifosplatform.infrastructure.core.api.JsonCommand; +import org.mifosplatform.infrastructure.core.data.CommandProcessingResult; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +@CommandType(entity = "EXTERNALSERVICES", action = "UPDATE") +public class UpdateExternalServiceConfigurationCommandHandler implements NewCommandSourceHandler { + + private final ExternalServiceWritePlatformService writePlatformService; + + @Autowired + public UpdateExternalServiceConfigurationCommandHandler(final ExternalServiceWritePlatformService writePlatformService) { + this.writePlatformService = writePlatformService; + } + + @Transactional + @Override + public CommandProcessingResult processCommand(final JsonCommand command) { + return this.writePlatformService.updateExternalServicesProperties(command.getTransactionId(), command); + } + +} diff --git a/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/configuration/serialization/ExternalServicesPropertiesCommandFromApiJsonDeserializer.java b/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/configuration/serialization/ExternalServicesPropertiesCommandFromApiJsonDeserializer.java new file mode 100644 index 000000000..ce60be3d6 --- /dev/null +++ b/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/configuration/serialization/ExternalServicesPropertiesCommandFromApiJsonDeserializer.java @@ -0,0 +1,72 @@ +/** + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. + */ +package org.mifosplatform.infrastructure.configuration.serialization; + +import java.lang.reflect.Type; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.apache.commons.lang.StringUtils; +import org.mifosplatform.infrastructure.configuration.exception.ExternalServiceConfigurationNotFoundException; +import org.mifosplatform.infrastructure.configuration.service.ExternalServicesConstants; +import org.mifosplatform.infrastructure.configuration.service.ExternalServicesConstants.EXTERNALSERVICEPROPERTIES_JSON_INPUT_PARAMS; +import org.mifosplatform.infrastructure.configuration.service.ExternalServicesConstants.S3_JSON_INPUT_PARAMS; +import org.mifosplatform.infrastructure.configuration.service.ExternalServicesConstants.SMTP_JSON_INPUT_PARAMS; +import org.mifosplatform.infrastructure.core.data.ApiParameterError; +import org.mifosplatform.infrastructure.core.data.DataValidatorBuilder; +import org.mifosplatform.infrastructure.core.exception.InvalidJsonException; +import org.mifosplatform.infrastructure.core.serialization.FromJsonHelper; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import com.google.gson.JsonElement; +import com.google.gson.reflect.TypeToken; + +@Component +public class ExternalServicesPropertiesCommandFromApiJsonDeserializer { + + private final Set supportedParameters = EXTERNALSERVICEPROPERTIES_JSON_INPUT_PARAMS.getAllValues(); + private final Set S3SupportedParameters = S3_JSON_INPUT_PARAMS.getAllValues(); + private final Set SMTPSupportedParameters = SMTP_JSON_INPUT_PARAMS.getAllValues(); + private final FromJsonHelper fromApiJsonHelper; + + @Autowired + public ExternalServicesPropertiesCommandFromApiJsonDeserializer(final FromJsonHelper fromApiJsonHelper) { + this.fromApiJsonHelper = fromApiJsonHelper; + } + + public void validateForUpdate(final String json, final String externalServiceName) { + if (StringUtils.isBlank(json)) { throw new InvalidJsonException(); } + + final Type typeOfMap = new TypeToken>() {}.getType(); + switch (externalServiceName) { + case "S3": + this.fromApiJsonHelper.checkForUnsupportedParameters(typeOfMap, json, this.S3SupportedParameters); + break; + + case "SMTP": + this.fromApiJsonHelper.checkForUnsupportedParameters(typeOfMap, json, this.SMTPSupportedParameters); + break; + + default: + throw new ExternalServiceConfigurationNotFoundException(externalServiceName); + } + + final List dataValidationErrors = new ArrayList<>(); + final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors).resource("external.service"); + final JsonElement element = this.fromApiJsonHelper.parse(json); + + } + + public Set getNameKeys(final String json) { + final Type typeOfMap = new TypeToken>() {}.getType(); + Map jsonMap = this.fromApiJsonHelper.extractDataMap(typeOfMap, json); + Set keyNames = jsonMap.keySet(); + return keyNames; + } +} diff --git a/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/configuration/service/ExternalServiceWritePlatformService.java b/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/configuration/service/ExternalServiceWritePlatformService.java new file mode 100644 index 000000000..a5462d43f --- /dev/null +++ b/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/configuration/service/ExternalServiceWritePlatformService.java @@ -0,0 +1,15 @@ +/** + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. + */ +package org.mifosplatform.infrastructure.configuration.service; + +import org.mifosplatform.infrastructure.core.api.JsonCommand; +import org.mifosplatform.infrastructure.core.data.CommandProcessingResult; + +public interface ExternalServiceWritePlatformService { + + CommandProcessingResult updateExternalServicesProperties(String externalServiceName, JsonCommand command); + +} diff --git a/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/configuration/service/ExternalServiceWritePlatformServiceJpaRepositoryImpl.java b/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/configuration/service/ExternalServiceWritePlatformServiceJpaRepositoryImpl.java new file mode 100644 index 000000000..f8735d7d7 --- /dev/null +++ b/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/configuration/service/ExternalServiceWritePlatformServiceJpaRepositoryImpl.java @@ -0,0 +1,79 @@ +/** + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. + */ +package org.mifosplatform.infrastructure.configuration.service; + +import java.util.Iterator; +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.Set; + +import org.mifosplatform.infrastructure.configuration.data.ExternalServicesData; +import org.mifosplatform.infrastructure.configuration.domain.ExternalServicesProperties; +import org.mifosplatform.infrastructure.configuration.domain.ExternalServicesPropertiesRepository; +import org.mifosplatform.infrastructure.configuration.domain.ExternalServicesPropertiesRepositoryWrapper; +import org.mifosplatform.infrastructure.configuration.serialization.ExternalServicesPropertiesCommandFromApiJsonDeserializer; +import org.mifosplatform.infrastructure.core.api.JsonCommand; +import org.mifosplatform.infrastructure.core.data.CommandProcessingResult; +import org.mifosplatform.infrastructure.core.data.CommandProcessingResultBuilder; +import org.mifosplatform.infrastructure.security.service.PlatformSecurityContext; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +public class ExternalServiceWritePlatformServiceJpaRepositoryImpl implements ExternalServiceWritePlatformService { + + private final static Logger logger = LoggerFactory.getLogger(ExternalServiceWritePlatformServiceJpaRepositoryImpl.class); + + private final PlatformSecurityContext context; + private final ExternalServicesPropertiesRepositoryWrapper repositoryWrapper; + private final ExternalServicesPropertiesRepository repository; + private final ExternalServicesPropertiesCommandFromApiJsonDeserializer fromApiJsonDeserializer; + private final ExternalServicesReadPlatformService readPlatformService; + + @Autowired + public ExternalServiceWritePlatformServiceJpaRepositoryImpl(final PlatformSecurityContext context, + final ExternalServicesPropertiesRepositoryWrapper repositoryWrapper, final ExternalServicesPropertiesRepository repository, + final ExternalServicesPropertiesCommandFromApiJsonDeserializer fromApiJsonDeserializer, + final ExternalServicesReadPlatformService readPlatformService) { + + this.context = context; + this.repositoryWrapper = repositoryWrapper; + this.repository = repository; + this.fromApiJsonDeserializer = fromApiJsonDeserializer; + this.readPlatformService = readPlatformService; + } + + @Transactional + @Override + public CommandProcessingResult updateExternalServicesProperties(String externalServiceName, JsonCommand command) { + // TODO Auto-generated method stub + this.context.authenticatedUser(); + this.fromApiJsonDeserializer.validateForUpdate(command.json(), externalServiceName); + Set keyName = this.fromApiJsonDeserializer.getNameKeys(command.json()); + ExternalServicesData external = this.readPlatformService.getExternalServiceDetailsByServiceName(externalServiceName); + Long externalServiceId = external.getId(); + Iterator it = keyName.iterator(); + Map changesList = new LinkedHashMap<>(); + while (it.hasNext()) { + String name = it.next(); + final ExternalServicesProperties externalServicesProperties = this.repositoryWrapper.findOneByIdAndName(externalServiceId, name, + externalServiceName); + final Map changes = externalServicesProperties.update(command, name); + changesList.putAll(changes); + if (!changes.isEmpty()) { + this.repository.saveAndFlush(externalServicesProperties); + } + } + return new CommandProcessingResultBuilder() // + .withCommandId(command.commandId()).withEntityId(externalServiceId).with(changesList).build(); + // + + } + +} diff --git a/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/configuration/service/ExternalServicesConstants.java b/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/configuration/service/ExternalServicesConstants.java index 886e8b45b..57b19b72a 100755 --- a/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/configuration/service/ExternalServicesConstants.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/configuration/service/ExternalServicesConstants.java @@ -5,10 +5,116 @@ */ package org.mifosplatform.infrastructure.configuration.service; +import java.util.HashSet; +import java.util.Set; + +import org.mifosplatform.infrastructure.codes.CodeConstants.CODEVALUE_JSON_INPUT_PARAMS; + public class ExternalServicesConstants { + public static final String S3_SERVICE_NAME = "S3"; public static final String S3_BUCKET_NAME = "s3_bucket_name"; public static final String S3_ACCESS_KEY = "s3_access_key"; public static final String S3_SECRET_KEY = "s3_secret_key"; + public static final String SMTP_SERVICE_NAME = "SMTP_Email_Account"; + public static final String SMTP_USERNAME = "username"; + public static final String SMTP_PASSWORD = "password"; + public static final String SMTP_HOST = "host"; + public static final String SMTP_PORT = "port"; + public static final String SMTP_USE_TLS = "useTLS"; + + public static enum EXTERNALSERVICEPROPERTIES_JSON_INPUT_PARAMS { + EXTERNAL_SERVICE_ID("external_service_id"), NAME("name"), VALUE("value"); + + private final String value; + + private EXTERNALSERVICEPROPERTIES_JSON_INPUT_PARAMS(final String value) { + this.value = value; + } + + private static final Set values = new HashSet<>(); + + static { + for (final EXTERNALSERVICEPROPERTIES_JSON_INPUT_PARAMS type : EXTERNALSERVICEPROPERTIES_JSON_INPUT_PARAMS.values()) { + values.add(type.value); + } + } + + public static Set getAllValues() { + return values; + } + + @Override + public String toString() { + return name().toString().replaceAll("_", " "); + } + + public String getValue() { + return this.value; + } + } + + public static enum SMTP_JSON_INPUT_PARAMS { + USERNAME("username"), PASSWORD("password"), HOST("host"), PORT("port"), USETLS("useTLS"); + + private final String value; + + private SMTP_JSON_INPUT_PARAMS(final String value) { + this.value = value; + } + + private static final Set values = new HashSet<>(); + + static { + for (final SMTP_JSON_INPUT_PARAMS type : SMTP_JSON_INPUT_PARAMS.values()) { + values.add(type.value); + } + } + + public static Set getAllValues() { + return values; + } + + @Override + public String toString() { + return name().toString().replaceAll("_", " "); + } + + public String getValue() { + return this.value; + } + } + + public static enum S3_JSON_INPUT_PARAMS { + S3_ACCESS_KEY("s3_access_key"), S3_BUCKET_NAME("s3_bucket_name"), S3_SECRET_KEY("s3_secret_key"); + + private final String value; + + private S3_JSON_INPUT_PARAMS(final String value) { + this.value = value; + } + + private static final Set values = new HashSet<>(); + + static { + for (final S3_JSON_INPUT_PARAMS type : S3_JSON_INPUT_PARAMS.values()) { + values.add(type.value); + } + } + + public static Set getAllValues() { + return values; + } + + @Override + public String toString() { + return name().toString().replaceAll("_", " "); + } + + public String getValue() { + return this.value; + } + } + } diff --git a/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/configuration/service/ExternalServicesPropertiesReadPlatformService.java b/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/configuration/service/ExternalServicesPropertiesReadPlatformService.java new file mode 100644 index 000000000..9f43bb0d3 --- /dev/null +++ b/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/configuration/service/ExternalServicesPropertiesReadPlatformService.java @@ -0,0 +1,22 @@ +/** + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. + */ +package org.mifosplatform.infrastructure.configuration.service; + +import java.util.Collection; + +import org.mifosplatform.infrastructure.configuration.data.ExternalServicesPropertiesData; +import org.mifosplatform.infrastructure.configuration.data.S3CredentialsData; +import org.mifosplatform.infrastructure.configuration.data.SMTPCredentialsData; + +public interface ExternalServicesPropertiesReadPlatformService { + + S3CredentialsData getS3Credentials(); + + SMTPCredentialsData getSMTPCredentials(); + + Collection retrieveOne(String serviceName); + +} \ No newline at end of file diff --git a/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/configuration/service/ExternalServicesPropertiesReadPlatformServiceImpl.java b/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/configuration/service/ExternalServicesPropertiesReadPlatformServiceImpl.java new file mode 100644 index 000000000..b2395a561 --- /dev/null +++ b/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/configuration/service/ExternalServicesPropertiesReadPlatformServiceImpl.java @@ -0,0 +1,137 @@ +/** + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. + */ +package org.mifosplatform.infrastructure.configuration.service; + +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.Collection; + +import org.mifosplatform.infrastructure.configuration.data.ExternalServicesPropertiesData; +import org.mifosplatform.infrastructure.configuration.data.S3CredentialsData; +import org.mifosplatform.infrastructure.configuration.data.SMTPCredentialsData; +import org.mifosplatform.infrastructure.configuration.exception.ExternalServiceConfigurationNotFoundException; +import org.mifosplatform.infrastructure.core.service.RoutingDataSource; +import org.mifosplatform.infrastructure.documentmanagement.data.DocumentData; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.dao.DataAccessException; +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.jdbc.core.ResultSetExtractor; +import org.springframework.jdbc.core.RowMapper; +import org.springframework.stereotype.Service; + +@Service +public class ExternalServicesPropertiesReadPlatformServiceImpl implements ExternalServicesPropertiesReadPlatformService { + + private final JdbcTemplate jdbcTemplate; + + @Autowired + public ExternalServicesPropertiesReadPlatformServiceImpl(final RoutingDataSource dataSource) { + this.jdbcTemplate = new JdbcTemplate(dataSource); + } + + private static final class S3CredentialsDataExtractor implements ResultSetExtractor { + + @Override + public S3CredentialsData extractData(final ResultSet rs) throws SQLException, DataAccessException { + String accessKey = null; + String bucketName = null; + String secretKey = null; + while (rs.next()) { + if (rs.getString("name").equalsIgnoreCase(ExternalServicesConstants.S3_ACCESS_KEY)) { + accessKey = rs.getString("value"); + } else if (rs.getString("name").equalsIgnoreCase(ExternalServicesConstants.S3_BUCKET_NAME)) { + bucketName = rs.getString("value"); + } else if (rs.getString("name").equalsIgnoreCase(ExternalServicesConstants.S3_SECRET_KEY)) { + secretKey = rs.getString("value"); + } + } + return new S3CredentialsData(bucketName, accessKey, secretKey); + } + } + + private static final class SMTPCredentialsDataExtractor implements ResultSetExtractor { + + @Override + public SMTPCredentialsData extractData(final ResultSet rs) throws SQLException, DataAccessException { + String username = null; + String password = null; + String host = null; + String port = "25"; + boolean useTLS = false; + + while (rs.next()) { + if (rs.getString("name").equalsIgnoreCase(ExternalServicesConstants.SMTP_USERNAME)) { + username = rs.getString("value"); + } else if (rs.getString("name").equalsIgnoreCase(ExternalServicesConstants.SMTP_PASSWORD)) { + password = rs.getString("value"); + } else if (rs.getString("name").equalsIgnoreCase(ExternalServicesConstants.SMTP_HOST)) { + host = rs.getString("value"); + } else if (rs.getString("name").equalsIgnoreCase(ExternalServicesConstants.SMTP_PORT)) { + port = rs.getString("value"); + } else if (rs.getString("name").equalsIgnoreCase(ExternalServicesConstants.SMTP_USE_TLS)) { + useTLS = Boolean.parseBoolean(rs.getString("value")); + } + } + return new SMTPCredentialsData(username, password, host, port, useTLS); + } + } + + private static final class ExternalServiceMapper implements RowMapper { + + @Override + public ExternalServicesPropertiesData mapRow(ResultSet rs, int rowNum) throws SQLException { + // TODO Auto-generated method stub + final String name = rs.getString("name"); + String value = rs.getString("value"); + // Masking the password as we should not send the password back + if (name != null && "password".equalsIgnoreCase(name)) { + value = "XXXX"; + } + return new ExternalServicesPropertiesData(name, value); + } + + } + + @Override + public S3CredentialsData getS3Credentials() { + final ResultSetExtractor resultSetExtractor = new S3CredentialsDataExtractor(); + final String sql = "SELECT esp.name, esp.value FROM c_external_service_properties esp inner join c_external_service es on esp.external_service_id = es.id where es.name = '" + + ExternalServicesConstants.S3_SERVICE_NAME + "'"; + final S3CredentialsData s3CredentialsData = this.jdbcTemplate.query(sql, resultSetExtractor, new Object[] {}); + return s3CredentialsData; + } + + @Override + public SMTPCredentialsData getSMTPCredentials() { + // TODO Auto-generated method stub + final ResultSetExtractor resultSetExtractor = new SMTPCredentialsDataExtractor(); + final String sql = "SELECT esp.name, esp.value FROM c_external_service_properties esp inner join c_external_service es on esp.external_service_id = es.id where es.name = '" + + ExternalServicesConstants.SMTP_SERVICE_NAME + "'"; + final SMTPCredentialsData smtpCredentialsData = this.jdbcTemplate.query(sql, resultSetExtractor, new Object[] {}); + return smtpCredentialsData; + } + + public Collection retrieveOne(String serviceName) { + String serviceNameToUse = null; + switch (serviceName) { + case "S3": + serviceNameToUse = ExternalServicesConstants.S3_SERVICE_NAME; + break; + + case "SMTP": + serviceNameToUse = ExternalServicesConstants.SMTP_SERVICE_NAME; + break; + + default: + throw new ExternalServiceConfigurationNotFoundException(serviceName); + } + final ExternalServiceMapper mapper = new ExternalServiceMapper(); + final String sql = "SELECT esp.name, esp.value FROM c_external_service_properties esp inner join c_external_service es on esp.external_service_id = es.id where es.name = '" + + serviceNameToUse + "'"; + return this.jdbcTemplate.query(sql, mapper, new Object[] {}); + + } +} diff --git a/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/configuration/service/ExternalServicesReadPlatformService.java b/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/configuration/service/ExternalServicesReadPlatformService.java index c30152d03..398d8a45a 100755 --- a/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/configuration/service/ExternalServicesReadPlatformService.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/configuration/service/ExternalServicesReadPlatformService.java @@ -5,10 +5,10 @@ */ package org.mifosplatform.infrastructure.configuration.service; -import org.mifosplatform.infrastructure.configuration.data.S3CredentialsData; +import org.mifosplatform.infrastructure.configuration.data.ExternalServicesData; public interface ExternalServicesReadPlatformService { - S3CredentialsData getS3Credentials(); + ExternalServicesData getExternalServiceDetailsByServiceName(String serviceName); -} \ No newline at end of file +} diff --git a/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/configuration/service/ExternalServicesReadPlatformServiceImpl.java b/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/configuration/service/ExternalServicesReadPlatformServiceImpl.java index 90099c370..4a069bc71 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/configuration/service/ExternalServicesReadPlatformServiceImpl.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/configuration/service/ExternalServicesReadPlatformServiceImpl.java @@ -8,7 +8,8 @@ package org.mifosplatform.infrastructure.configuration.service; import java.sql.ResultSet; import java.sql.SQLException; -import org.mifosplatform.infrastructure.configuration.data.S3CredentialsData; +import org.mifosplatform.infrastructure.configuration.data.ExternalServicesData; +import org.mifosplatform.infrastructure.configuration.exception.ExternalServiceConfigurationNotFoundException; import org.mifosplatform.infrastructure.core.service.RoutingDataSource; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.dao.DataAccessException; @@ -26,31 +27,43 @@ public class ExternalServicesReadPlatformServiceImpl implements ExternalServices this.jdbcTemplate = new JdbcTemplate(dataSource); } - private static final class S3CredentialsDataExtractor implements ResultSetExtractor { + @Override + public ExternalServicesData getExternalServiceDetailsByServiceName(String serviceName) { + // TODO Auto-generated method stub + final ResultSetExtractor resultSetExtractor = new ExternalServicesDetailsDataExtractor(); + String serviceNameToUse = null; + switch (serviceName) { + case "S3": + serviceNameToUse = ExternalServicesConstants.S3_SERVICE_NAME; + break; + + case "SMTP": + serviceNameToUse = ExternalServicesConstants.SMTP_SERVICE_NAME; + break; + + default: + throw new ExternalServiceConfigurationNotFoundException(serviceName); + } + final String sql = "SELECT es.name as name, es.id as id FROM c_external_service es where es.name='" + serviceNameToUse + "'"; + final ExternalServicesData externalServicesData = this.jdbcTemplate.query(sql, resultSetExtractor, new Object[] {}); + return externalServicesData; + } + + private static final class ExternalServicesDetailsDataExtractor implements ResultSetExtractor { @Override - public S3CredentialsData extractData(final ResultSet rs) throws SQLException, DataAccessException { - String accessKey = null; - String bucketName = null; - String secretKey = null; + public ExternalServicesData extractData(ResultSet rs) throws SQLException, DataAccessException { + // TODO Auto-generated method stub + Long id = (long) 0; + String name = null; while (rs.next()) { - if (rs.getString("name").equalsIgnoreCase(ExternalServicesConstants.S3_ACCESS_KEY)) { - accessKey = rs.getString("value"); - } else if (rs.getString("name").equalsIgnoreCase(ExternalServicesConstants.S3_BUCKET_NAME)) { - bucketName = rs.getString("value"); - } else if (rs.getString("name").equalsIgnoreCase(ExternalServicesConstants.S3_SECRET_KEY)) { - secretKey = rs.getString("value"); - } + name = rs.getString("name"); + id = rs.getLong("id"); } - return new S3CredentialsData(bucketName, accessKey, secretKey); + + return new ExternalServicesData(id, name); } + } - @Override - public S3CredentialsData getS3Credentials() { - final ResultSetExtractor resultSetExtractor = new S3CredentialsDataExtractor(); - final String sql = "SELECT es.name, es.value FROM c_external_service es where es.name in('s3_bucket_name','s3_access_key','s3_secret_key')"; - final S3CredentialsData s3CredentialsData = this.jdbcTemplate.query(sql, resultSetExtractor, new Object[] {}); - return s3CredentialsData; - } } diff --git a/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/core/service/GmailBackedPlatformEmailService.java b/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/core/service/GmailBackedPlatformEmailService.java index 64a452bc7..f1b19a6fb 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/core/service/GmailBackedPlatformEmailService.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/core/service/GmailBackedPlatformEmailService.java @@ -9,28 +9,41 @@ import org.apache.commons.mail.DefaultAuthenticator; import org.apache.commons.mail.Email; import org.apache.commons.mail.EmailException; import org.apache.commons.mail.SimpleEmail; +import org.mifosplatform.infrastructure.configuration.data.S3CredentialsData; +import org.mifosplatform.infrastructure.configuration.data.SMTPCredentialsData; +import org.mifosplatform.infrastructure.configuration.service.ExternalServicesPropertiesReadPlatformService; import org.mifosplatform.infrastructure.core.domain.EmailDetail; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; @Service public class GmailBackedPlatformEmailService implements PlatformEmailService { + + private final ExternalServicesPropertiesReadPlatformService externalServicesReadPlatformService; + + @Autowired + public GmailBackedPlatformEmailService(final ExternalServicesPropertiesReadPlatformService externalServicesReadPlatformService){ + this.externalServicesReadPlatformService = externalServicesReadPlatformService; + } @Override public void sendToUserAccount(final EmailDetail emailDetail, final String unencodedPassword) { final Email email = new SimpleEmail(); + final SMTPCredentialsData smtpCredentialsData = this.externalServicesReadPlatformService.getSMTPCredentials(); + final String authuserName = smtpCredentialsData.getUsername(); - final String authuserName = "support@cloudmicrofinance.com"; - - final String authuser = "support@cloudmicrofinance.com"; - final String authpwd = "support80"; + final String authuser = smtpCredentialsData.getUsername(); + final String authpwd = smtpCredentialsData.getPassword(); // Very Important, Don't use email.setAuthentication() email.setAuthenticator(new DefaultAuthenticator(authuser, authpwd)); email.setDebug(false); // true if you want to debug - email.setHostName("smtp.gmail.com"); + email.setHostName(smtpCredentialsData.getHost()); try { - email.getMailSession().getProperties().put("mail.smtp.starttls.enable", "true"); - email.setFrom(authuser, authuserName); + if(smtpCredentialsData.isUseTLS()){ + email.getMailSession().getProperties().put("mail.smtp.starttls.enable", "true"); + } + email.setFrom(authuser, authuserName); final StringBuilder subjectBuilder = new StringBuilder().append("MifosX Prototype Demo: ").append(emailDetail.getContactName()) .append(" user account creation."); diff --git a/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/documentmanagement/contentrepository/ContentRepositoryFactory.java b/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/documentmanagement/contentrepository/ContentRepositoryFactory.java index a0fea898c..fadb72365 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/documentmanagement/contentrepository/ContentRepositoryFactory.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/documentmanagement/contentrepository/ContentRepositoryFactory.java @@ -7,7 +7,7 @@ package org.mifosplatform.infrastructure.documentmanagement.contentrepository; import org.mifosplatform.infrastructure.configuration.data.S3CredentialsData; import org.mifosplatform.infrastructure.configuration.domain.ConfigurationDomainService; -import org.mifosplatform.infrastructure.configuration.service.ExternalServicesReadPlatformService; +import org.mifosplatform.infrastructure.configuration.service.ExternalServicesPropertiesReadPlatformService; import org.mifosplatform.infrastructure.documentmanagement.domain.StorageType; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.ApplicationContext; @@ -17,11 +17,11 @@ import org.springframework.stereotype.Component; public class ContentRepositoryFactory { private final ApplicationContext applicationContext; - private final ExternalServicesReadPlatformService externalServicesReadPlatformService; + private final ExternalServicesPropertiesReadPlatformService externalServicesReadPlatformService; @Autowired public ContentRepositoryFactory(final ApplicationContext applicationContext, - final ExternalServicesReadPlatformService externalServicesReadPlatformService) { + final ExternalServicesPropertiesReadPlatformService externalServicesReadPlatformService) { this.applicationContext = applicationContext; this.externalServicesReadPlatformService = externalServicesReadPlatformService; } diff --git a/mifosng-provider/src/main/resources/sql/migrations/core_db/V265__modify_external_service_schema.sql b/mifosng-provider/src/main/resources/sql/migrations/core_db/V265__modify_external_service_schema.sql new file mode 100644 index 000000000..e264d424e --- /dev/null +++ b/mifosng-provider/src/main/resources/sql/migrations/core_db/V265__modify_external_service_schema.sql @@ -0,0 +1,48 @@ + + + +alter table c_external_service drop index name; + +Rename table c_external_service to c_external_service_properties; + +CREATE TABLE `c_external_service` ( + `id` BIGINT(20) NOT NULL AUTO_INCREMENT, + `name` VARCHAR(100) NULL DEFAULT NULL, + PRIMARY KEY (`id`), + UNIQUE KEY `name_UNIQUE` (`name`) +) +COLLATE='utf8_general_ci' +ENGINE=InnoDB; + +insert into `c_external_service` ( `name`) values( 'S3'); + +Alter table c_external_service_properties + ADD COLUMN `external_service_id` BIGINT(20) NULL DEFAULT NULL; + +update c_external_service_properties set external_service_id = (select id from c_external_service where name = 'S3'); + +ALTER TABLE `c_external_service_properties` + CHANGE COLUMN `external_service_id` `external_service_id` BIGINT(20) NOT NULL; + +ALTER TABLE `c_external_service_properties` + ADD CONSTRAINT `FK_c_external_service_properties_c_external_service` FOREIGN KEY (`external_service_id`) REFERENCES `c_external_service` (`id`); + + +insert into `c_external_service` ( `name`) values( 'SMTP_Email_Account'); + +insert into c_external_service_properties (`name`, `value`, `external_service_id`) values('username', 'support@cloudmicrofinance.com', (select id from c_external_service where name = 'Gmail_Email_Account')); + +insert into c_external_service_properties (`name`, `value`, `external_service_id`) values('password', 'support80', (select id from c_external_service where name = 'Gmail_Email_Account')); + +insert into c_external_service_properties (`name`, `value`, `external_service_id`) values('host', 'smtp.gmail.com', (select id from c_external_service where name = 'Gmail_Email_Account')); + +insert into c_external_service_properties (`name`, `value`, `external_service_id`) values('port', '25', (select id from c_external_service where name = 'Gmail_Email_Account')); + +insert into c_external_service_properties (`name`, `value`, `external_service_id`) values('useTLS', 'true', (select id from c_external_service where name = 'Gmail_Email_Account')); + +insert into m_permission(grouping, code, entity_name, action_name, can_maker_checker) values('externalservices', 'UPDATE_EXTERNALSERVICES', 'EXTERNALSERVICES', 'UPDATE', 0); + + + +commit; +