diff --git a/mifosng-provider/src/main/java/org/mifosplatform/commands/handler/RoleCommandHandler.java b/mifosng-provider/src/main/java/org/mifosplatform/commands/handler/RoleCommandHandler.java index 5e6bf539e..041553a62 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/commands/handler/RoleCommandHandler.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/commands/handler/RoleCommandHandler.java @@ -12,9 +12,7 @@ import org.mifosplatform.infrastructure.core.serialization.ExcludeNothingWithPre import org.mifosplatform.infrastructure.core.serialization.FromJsonHelper; import org.mifosplatform.infrastructure.security.service.PlatformSecurityContext; import org.mifosplatform.portfolio.client.service.RollbackTransactionAsCommandIsNotApprovedByCheckerException; -import org.mifosplatform.useradministration.command.RoleCommand; import org.mifosplatform.useradministration.domain.AppUser; -import org.mifosplatform.useradministration.serialization.RoleCommandFromCommandJsonDeserializer; import org.mifosplatform.useradministration.service.RoleWritePlatformService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; @@ -26,18 +24,14 @@ public class RoleCommandHandler implements CommandSourceHandler { private final PlatformSecurityContext context; private final RoleWritePlatformService writePlatformService; - private final RoleCommandFromCommandJsonDeserializer commandFromCommandJsonDeserializer; private final FromJsonHelper fromApiJsonHelper; private final ExcludeNothingWithPrettyPrintingOffJsonSerializerGoogleGson toApiJsonSerializer; - + @Autowired - public RoleCommandHandler(final PlatformSecurityContext context, - final RoleCommandFromCommandJsonDeserializer commandFromCommandJsonDeserializer, - final FromJsonHelper fromApiJsonHelper, + public RoleCommandHandler(final PlatformSecurityContext context, final FromJsonHelper fromApiJsonHelper, final ExcludeNothingWithPrettyPrintingOffJsonSerializerGoogleGson toApiJsonSerializer, final RoleWritePlatformService writePlatformService) { this.context = context; - this.commandFromCommandJsonDeserializer = commandFromCommandJsonDeserializer; this.fromApiJsonHelper = fromApiJsonHelper; this.toApiJsonSerializer = toApiJsonSerializer; this.writePlatformService = writePlatformService; @@ -52,14 +46,12 @@ public class RoleCommandHandler implements CommandSourceHandler { CommandSource commandSourceResult = commandSource.copy(); final Long resourceId = commandSource.resourceId(); - Long newResourceId = null; - if (commandSource.isCreate()) { try { - final RoleCommand command = this.commandFromCommandJsonDeserializer - .commandFromCommandJson(resourceId, commandSource.json()); + final JsonElement parsedCommand = this.fromApiJsonHelper.parse(commandSource.json()); + final JsonCommand command = JsonCommand.from(commandSource.json(), parsedCommand, this.fromApiJsonHelper); - newResourceId = this.writePlatformService.createRole(command); + final Long newResourceId = this.writePlatformService.createRole(command); commandSourceResult.markAsChecked(maker, asToday); commandSourceResult.updateResourceId(newResourceId); @@ -68,10 +60,13 @@ public class RoleCommandHandler implements CommandSourceHandler { } } else if (commandSource.isUpdate()) { try { - final RoleCommand command = this.commandFromCommandJsonDeserializer.commandFromCommandJson(resourceId, - commandSource.json()); + final JsonElement parsedCommand = this.fromApiJsonHelper.parse(commandSource.json()); + final JsonCommand command = JsonCommand.from(commandSource.json(), parsedCommand, this.fromApiJsonHelper); - newResourceId = this.writePlatformService.updateRole(command); + final EntityIdentifier result = this.writePlatformService.updateRole(resourceId, command); + + final String jsonOfChangesOnly = toApiJsonSerializer.serialize(result.getChanges()); + commandSourceResult.updateJsonTo(jsonOfChangesOnly); commandSourceResult.markAsChecked(maker, asToday); } catch (RollbackTransactionAsCommandIsNotApprovedByCheckerException e) { @@ -79,12 +74,12 @@ public class RoleCommandHandler implements CommandSourceHandler { } } else if (commandSource.isUpdateRolePermissions()) { try { - + final JsonElement parsedCommand = this.fromApiJsonHelper.parse(commandSource.json()); final JsonCommand command = JsonCommand.from(commandSource.json(), parsedCommand, this.fromApiJsonHelper); - - EntityIdentifier result = this.writePlatformService.updateRolePermissions(resourceId, command); - + + final EntityIdentifier result = this.writePlatformService.updateRolePermissions(resourceId, command); + final String jsonOfChangesOnly = toApiJsonSerializer.serialize(result.getChanges()); commandSourceResult.updateJsonTo(jsonOfChangesOnly); @@ -102,40 +97,37 @@ public class RoleCommandHandler implements CommandSourceHandler { final AppUser checker = context.authenticatedUser(); - Long resourceId = commandSourceResult.resourceId(); + final JsonElement parsedCommand = this.fromApiJsonHelper.parse(commandSourceResult.json()); + final JsonCommand command = JsonCommand.withMakerCheckerApproval(commandSourceResult.json(), parsedCommand, this.fromApiJsonHelper); + final Long resourceId = commandSourceResult.resourceId(); + if (commandSourceResult.isCreate()) { final List allowedPermissions = Arrays.asList("ALL_FUNCTIONS", "USER_ADMINISTRATION_SUPER_USER", "CREATE_ROLE_CHECKER"); context.authenticatedUser().validateHasPermissionTo("CREATE_ROLE_CHECKER", allowedPermissions); - final RoleCommand command = this.commandFromCommandJsonDeserializer.commandFromCommandJson(resourceId, - commandSourceResult.json(), true); + final Long newResourceId = this.writePlatformService.createRole(command); - resourceId = this.writePlatformService.createRole(command); - commandSourceResult.updateResourceId(resourceId); + commandSourceResult.updateResourceId(newResourceId); commandSourceResult.markAsChecked(checker, new LocalDate()); } else if (commandSourceResult.isUpdate()) { final List allowedPermissions = Arrays.asList("ALL_FUNCTIONS", "USER_ADMINISTRATION_SUPER_USER", "UPDATE_ROLE_CHECKER"); context.authenticatedUser().validateHasPermissionTo("UPDATE_ROLE_CHECKER", allowedPermissions); - final RoleCommand command = this.commandFromCommandJsonDeserializer.commandFromCommandJson(resourceId, - commandSourceResult.json(), true); + final EntityIdentifier result = this.writePlatformService.updateRole(resourceId, command); - resourceId = this.writePlatformService.updateRole(command); + final String jsonOfChangesOnly = toApiJsonSerializer.serialize(result.getChanges()); + commandSourceResult.updateJsonTo(jsonOfChangesOnly); commandSourceResult.markAsChecked(checker, new LocalDate()); } else if (commandSourceResult.isUpdateRolePermissions()) { final List allowedPermissions = Arrays.asList("ALL_FUNCTIONS", "USER_ADMINISTRATION_SUPER_USER", "PERMISSIONS_ROLE_CHECKER"); context.authenticatedUser().validateHasPermissionTo("PERMISSIONS_ROLE_CHECKER", allowedPermissions); - final JsonElement parsedCommand = this.fromApiJsonHelper.parse(commandSourceResult.json()); - final JsonCommand command = JsonCommand.from(commandSourceResult.json(), parsedCommand, this.fromApiJsonHelper); - EntityIdentifier result = this.writePlatformService.updateRolePermissions(resourceId, command); - + final String jsonOfChangesOnly = toApiJsonSerializer.serialize(result.getChanges()); commandSourceResult.updateJsonTo(jsonOfChangesOnly); - commandSourceResult.markAsChecked(checker, new LocalDate()); } else if (commandSourceResult.isDelete()) { throw new UnsupportedCommandException(commandSourceResult.commandName()); } diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/client/api/ClientImagesApiResource.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/client/api/ClientImagesApiResource.java new file mode 100644 index 000000000..970e9ab22 --- /dev/null +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/client/api/ClientImagesApiResource.java @@ -0,0 +1,145 @@ +package org.mifosplatform.portfolio.client.api; + +import java.io.InputStream; + +import javax.ws.rs.Consumes; +import javax.ws.rs.DELETE; +import javax.ws.rs.GET; +import javax.ws.rs.HeaderParam; +import javax.ws.rs.POST; +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.MediaType; + +import org.mifosplatform.infrastructure.core.api.ApiConstants; +import org.mifosplatform.infrastructure.core.data.EntityIdentifier; +import org.mifosplatform.infrastructure.core.domain.Base64EncodedImage; +import org.mifosplatform.infrastructure.core.serialization.DefaultToApiJsonSerializer; +import org.mifosplatform.infrastructure.core.service.FileUtils; +import org.mifosplatform.infrastructure.security.service.PlatformSecurityContext; +import org.mifosplatform.portfolio.client.data.ClientData; +import org.mifosplatform.portfolio.client.exception.ImageNotFoundException; +import org.mifosplatform.portfolio.client.service.ClientReadPlatformService; +import org.mifosplatform.portfolio.client.service.ClientWritePlatformService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Scope; +import org.springframework.stereotype.Component; + +import com.lowagie.text.pdf.codec.Base64; +import com.sun.jersey.core.header.FormDataContentDisposition; +import com.sun.jersey.multipart.FormDataBodyPart; +import com.sun.jersey.multipart.FormDataParam; + +// FIXME - kw- image should be images to keep consitent with rest of API - even if we only support one image per client. +@Path("/clients/{clientId}/image") +@Component +@Scope("singleton") +public class ClientImagesApiResource { + + private final PlatformSecurityContext context; + private final ClientReadPlatformService clientReadPlatformService; + private final ClientWritePlatformService clientWritePlatformService; + private final DefaultToApiJsonSerializer toApiJsonSerializer; + + @Autowired + public ClientImagesApiResource(final PlatformSecurityContext context, final ClientReadPlatformService readPlatformService, + final ClientWritePlatformService clientWritePlatformService, final DefaultToApiJsonSerializer toApiJsonSerializer) { + this.context = context; + this.clientReadPlatformService = readPlatformService; + this.clientWritePlatformService = clientWritePlatformService; + this.toApiJsonSerializer = toApiJsonSerializer; + } + + /** + * Upload images through multi-part form upload + */ + @POST + @Consumes({ MediaType.MULTIPART_FORM_DATA }) + @Produces({ MediaType.APPLICATION_JSON }) + public String addNewClientImage(@PathParam("clientId") final Long clientId, @HeaderParam("Content-Length") Long fileSize, + @FormDataParam("file") InputStream inputStream, @FormDataParam("file") FormDataContentDisposition fileDetails, + @FormDataParam("file") FormDataBodyPart bodyPart) { + + // TODO: vishwas might need more advances validation (like reading magic + // number) for handling malicious clients + // and clients not setting mime type + FileUtils.validateClientImageNotEmpty(fileDetails.getFileName()); + FileUtils.validateImageMimeType(bodyPart.getMediaType().toString()); + FileUtils.validateFileSizeWithinPermissibleRange(fileSize, fileDetails.getFileName(), ApiConstants.MAX_FILE_UPLOAD_SIZE_IN_MB); + + final EntityIdentifier result = this.clientWritePlatformService.saveOrUpdateClientImage(clientId, fileDetails.getFileName(), + inputStream); + + return this.toApiJsonSerializer.serialize(result); + } + + /** + * Upload image as a Data URL (essentially a base64 encoded stream) + */ + @POST + @Consumes({ MediaType.APPLICATION_JSON }) + @Produces({ MediaType.APPLICATION_JSON }) + public String addNewClientImage(@PathParam("clientId") final Long clientId, final String jsonRequestBody) { + + final Base64EncodedImage base64EncodedImage = FileUtils.extractImageFromDataURL(jsonRequestBody); + + final EntityIdentifier result = this.clientWritePlatformService.saveOrUpdateClientImage(clientId, base64EncodedImage); + + return this.toApiJsonSerializer.serialize(result); + } + + /** + * Returns a base 64 encoded client image + */ + @GET + @Consumes({ MediaType.APPLICATION_JSON }) + @Produces({ MediaType.APPLICATION_JSON }) + public String retrieveClientImage(@PathParam("clientId") final Long clientId) { + + context.authenticatedUser().validateHasReadPermission("CLIENTIMAGE"); + + final ClientData clientData = this.clientReadPlatformService.retrieveIndividualClient(clientId); + + if (clientData.imageKeyDoesNotExist()) { throw new ImageNotFoundException("clients", clientId); } + + return Base64.encodeFromFile(clientData.imageKey()); + } + + /** + * This method is added only for consistency with other URL patterns and for + * maintaining consistency of usage of the HTTP "verb" at the client side + */ + @PUT + @Consumes({ MediaType.MULTIPART_FORM_DATA }) + @Produces({ MediaType.APPLICATION_JSON }) + public String updateClientImage(@PathParam("clientId") final Long clientId, @HeaderParam("Content-Length") Long fileSize, + @FormDataParam("file") InputStream inputStream, @FormDataParam("file") FormDataContentDisposition fileDetails, + @FormDataParam("file") FormDataBodyPart bodyPart) { + + return addNewClientImage(clientId, fileSize, inputStream, fileDetails, bodyPart); + } + + @DELETE + @Consumes({ MediaType.APPLICATION_JSON }) + @Produces({ MediaType.APPLICATION_JSON }) + public String deleteClientImage(@PathParam("clientId") final Long clientId) { + this.clientWritePlatformService.deleteClientImage(clientId); + + return this.toApiJsonSerializer.serialize(new EntityIdentifier(clientId)); + } + + /** + * This method is added only for consistency with other URL patterns and for + * maintaining consistency of usage of the HTTP "verb" at the client side + * + * Upload image as a Data URL (essentially a base64 encoded stream) + */ + @PUT + @Consumes({ MediaType.APPLICATION_JSON }) + @Produces({ MediaType.APPLICATION_JSON }) + public String updateClientImage(@PathParam("clientId") final Long clientId, final String jsonRequestBody) { + return addNewClientImage(clientId, jsonRequestBody); + } +} \ No newline at end of file diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/client/api/ClientsApiResource.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/client/api/ClientsApiResource.java index 837e4d1d5..32bd92de3 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/client/api/ClientsApiResource.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/client/api/ClientsApiResource.java @@ -1,6 +1,5 @@ package org.mifosplatform.portfolio.client.api; -import java.io.InputStream; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; @@ -11,7 +10,6 @@ import java.util.Set; import javax.ws.rs.Consumes; import javax.ws.rs.DELETE; import javax.ws.rs.GET; -import javax.ws.rs.HeaderParam; import javax.ws.rs.POST; import javax.ws.rs.PUT; import javax.ws.rs.Path; @@ -26,33 +24,23 @@ import org.apache.commons.lang.StringUtils; import org.mifosplatform.commands.data.CommandSourceData; import org.mifosplatform.commands.service.PortfolioCommandSourceWritePlatformService; import org.mifosplatform.commands.service.PortfolioCommandsReadPlatformService; -import org.mifosplatform.infrastructure.core.api.ApiConstants; import org.mifosplatform.infrastructure.core.api.ApiParameterHelper; import org.mifosplatform.infrastructure.core.api.ApiRequestParameterHelper; import org.mifosplatform.infrastructure.core.api.PortfolioApiDataConversionService; import org.mifosplatform.infrastructure.core.api.PortfolioApiJsonSerializerService; import org.mifosplatform.infrastructure.core.data.EntityIdentifier; -import org.mifosplatform.infrastructure.core.domain.Base64EncodedImage; import org.mifosplatform.infrastructure.core.serialization.ApiRequestJsonSerializationSettings; import org.mifosplatform.infrastructure.core.serialization.DefaultToApiJsonSerializer; -import org.mifosplatform.infrastructure.core.service.FileUtils; import org.mifosplatform.infrastructure.security.service.PlatformSecurityContext; import org.mifosplatform.organisation.office.data.OfficeLookup; import org.mifosplatform.organisation.office.service.OfficeReadPlatformService; import org.mifosplatform.portfolio.client.data.ClientAccountSummaryCollectionData; import org.mifosplatform.portfolio.client.data.ClientData; -import org.mifosplatform.portfolio.client.exception.ImageNotFoundException; import org.mifosplatform.portfolio.client.service.ClientReadPlatformService; -import org.mifosplatform.portfolio.client.service.ClientWritePlatformService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Scope; import org.springframework.stereotype.Component; -import com.lowagie.text.pdf.codec.Base64; -import com.sun.jersey.core.header.FormDataContentDisposition; -import com.sun.jersey.multipart.FormDataBodyPart; -import com.sun.jersey.multipart.FormDataParam; - @Path("/clients") @Component @Scope("singleton") @@ -63,7 +51,6 @@ public class ClientsApiResource { private final PlatformSecurityContext context; private final ClientReadPlatformService clientReadPlatformService; - private final ClientWritePlatformService clientWritePlatformService; private final OfficeReadPlatformService officeReadPlatformService; private final DefaultToApiJsonSerializer toApiJsonSerializer; private final ApiRequestParameterHelper apiRequestParameterHelper; @@ -74,15 +61,13 @@ public class ClientsApiResource { @Autowired public ClientsApiResource(final PlatformSecurityContext context, final ClientReadPlatformService readPlatformService, - final ClientWritePlatformService clientWritePlatformService, final OfficeReadPlatformService officeReadPlatformService, - final DefaultToApiJsonSerializer toApiJsonSerializer, final ApiRequestParameterHelper apiRequestParameterHelper, - final PortfolioApiDataConversionService apiDataConversionService, + final OfficeReadPlatformService officeReadPlatformService, final DefaultToApiJsonSerializer toApiJsonSerializer, + final ApiRequestParameterHelper apiRequestParameterHelper, final PortfolioApiDataConversionService apiDataConversionService, final PortfolioApiJsonSerializerService apiJsonSerializerService, final PortfolioCommandsReadPlatformService commandsReadPlatformService, final PortfolioCommandSourceWritePlatformService commandsSourceWritePlatformService) { this.context = context; this.clientReadPlatformService = readPlatformService; - this.clientWritePlatformService = clientWritePlatformService; this.officeReadPlatformService = officeReadPlatformService; this.toApiJsonSerializer = toApiJsonSerializer; this.apiRequestParameterHelper = apiRequestParameterHelper; @@ -246,11 +231,6 @@ public class ClientsApiResource { final List allowedPermissions = Arrays.asList("ALL_FUNCTIONS", "PORTFOLIO_MANAGEMENT_SUPER_USER", "UPDATE_CLIENT"); context.authenticatedUser().validateHasPermissionTo("UPDATE_CLIENT", allowedPermissions); - // 1. check json request body for create client - -// final String commandSerializedAsJson = this.fromApiJsonDeserializer -// .serializedCommandJsonFromApiJson(clientId, apiRequestBodyAsJson); - final EntityIdentifier result = this.commandsSourceWritePlatformService.logCommandSource("UPDATE", "clients", clientId, apiRequestBodyAsJson); @@ -287,103 +267,4 @@ public class ClientsApiResource { return this.apiJsonSerializerService.serializeClientAccountSummaryCollectionDataToJson(prettyPrint, responseParameters, clientAccount); } - - /** - * Upload images through multi-part form upload - */ - @POST - @Path("{clientId}/image") - @Consumes({ MediaType.MULTIPART_FORM_DATA }) - @Produces({ MediaType.APPLICATION_JSON }) - public String addNewClientImage(@PathParam("clientId") final Long clientId, @HeaderParam("Content-Length") Long fileSize, - @FormDataParam("file") InputStream inputStream, @FormDataParam("file") FormDataContentDisposition fileDetails, - @FormDataParam("file") FormDataBodyPart bodyPart) { - - // TODO: vishwas might need more advances validation (like reading magic - // number) for handling malicious clients - // and clients not setting mime type - FileUtils.validateClientImageNotEmpty(fileDetails.getFileName()); - FileUtils.validateImageMimeType(bodyPart.getMediaType().toString()); - FileUtils.validateFileSizeWithinPermissibleRange(fileSize, fileDetails.getFileName(), ApiConstants.MAX_FILE_UPLOAD_SIZE_IN_MB); - - // logger.debug(bodyPart.getMediaType().toString()); - - final EntityIdentifier result = this.clientWritePlatformService.saveOrUpdateClientImage(clientId, fileDetails.getFileName(), - inputStream); - - return this.toApiJsonSerializer.serialize(result); - } - - /** - * Upload image as a Data URL (essentially a base64 encoded stream) - */ - @POST - @Path("{clientId}/image") - @Consumes({ MediaType.APPLICATION_JSON }) - @Produces({ MediaType.APPLICATION_JSON }) - public String addNewClientImage(@PathParam("clientId") final Long clientId, final String jsonRequestBody) { - - final Base64EncodedImage base64EncodedImage = FileUtils.extractImageFromDataURL(jsonRequestBody); - - final EntityIdentifier result = this.clientWritePlatformService.saveOrUpdateClientImage(clientId, base64EncodedImage); - - return this.toApiJsonSerializer.serialize(result); - } - - /** - * Returns a base 64 encoded client image - */ - @GET - @Path("{clientId}/image") - @Consumes({ MediaType.APPLICATION_JSON }) - @Produces({ MediaType.APPLICATION_JSON }) - public String retrieveClientImage(@PathParam("clientId") final Long clientId) { - - context.authenticatedUser().validateHasReadPermission("CLIENTIMAGE"); - - final ClientData clientData = this.clientReadPlatformService.retrieveIndividualClient(clientId); - - if (clientData.imageKeyDoesNotExist()) { throw new ImageNotFoundException("clients", clientId); } - - return Base64.encodeFromFile(clientData.imageKey()); - } - - /** - * This method is added only for consistency with other URL patterns and for - * maintaining consistency of usage of the HTTP "verb" at the client side - */ - @PUT - @Path("{clientId}/image") - @Consumes({ MediaType.MULTIPART_FORM_DATA }) - @Produces({ MediaType.APPLICATION_JSON }) - public String updateClientImage(@PathParam("clientId") final Long clientId, @HeaderParam("Content-Length") Long fileSize, - @FormDataParam("file") InputStream inputStream, @FormDataParam("file") FormDataContentDisposition fileDetails, - @FormDataParam("file") FormDataBodyPart bodyPart) { - - return addNewClientImage(clientId, fileSize, inputStream, fileDetails, bodyPart); - } - - @DELETE - @Path("{clientId}/image") - @Consumes({ MediaType.APPLICATION_JSON }) - @Produces({ MediaType.APPLICATION_JSON }) - public String deleteClientImage(@PathParam("clientId") final Long clientId) { - this.clientWritePlatformService.deleteClientImage(clientId); - - return this.toApiJsonSerializer.serialize(new EntityIdentifier(clientId)); - } - - /** - * This method is added only for consistency with other URL patterns and for - * maintaining consistency of usage of the HTTP "verb" at the client side - * - * Upload image as a Data URL (essentially a base64 encoded stream) - */ - @PUT - @Path("{clientId}/image") - @Consumes({ MediaType.APPLICATION_JSON }) - @Produces({ MediaType.APPLICATION_JSON }) - public String updateClientImage(@PathParam("clientId") final Long clientId, final String jsonRequestBody) { - return addNewClientImage(clientId, jsonRequestBody); - } } \ No newline at end of file diff --git a/mifosng-provider/src/main/java/org/mifosplatform/useradministration/command/RoleCommand.java b/mifosng-provider/src/main/java/org/mifosplatform/useradministration/command/RoleCommand.java index 85a7a722f..96e7a2550 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/useradministration/command/RoleCommand.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/useradministration/command/RoleCommand.java @@ -2,7 +2,6 @@ package org.mifosplatform.useradministration.command; import java.util.ArrayList; import java.util.List; -import java.util.Set; import org.mifosplatform.infrastructure.core.data.ApiParameterError; import org.mifosplatform.infrastructure.core.data.DataValidatorBuilder; @@ -10,35 +9,17 @@ import org.mifosplatform.infrastructure.core.exception.PlatformApiDataValidation /** * Immutable command for creating or updating details of a role. - * - *

Fields that are transient are intended not to be serialized into JSON.

*/ public class RoleCommand { - private final transient Long id; private final String name; private final String description; - private final transient boolean makerCheckerApproval; - private final transient Set modifiedParameters; - - public RoleCommand( - final Set modifiedParameters, - final boolean makerCheckerApproval, - final Long id, - final String name, - final String description) { - this.modifiedParameters = modifiedParameters; - this.makerCheckerApproval = makerCheckerApproval; - this.id = id; + public RoleCommand(final String name, final String description) { this.name = name; this.description = description; } - public Long getId() { - return id; - } - public String getName() { return name; } @@ -47,18 +28,6 @@ public class RoleCommand { return description; } - public boolean isNameChanged() { - return this.modifiedParameters.contains("name"); - } - - public boolean isDescriptionChanged() { - return this.modifiedParameters.contains("description"); - } - - public boolean isApprovedByChecker() { - return this.makerCheckerApproval; - } - public void validateForCreate() { List dataValidationErrors = new ArrayList(); @@ -68,7 +37,7 @@ public class RoleCommand { baseDataValidator.reset().parameter("description").value(this.description).notBlank().notExceedingLengthOf(500); if (!dataValidationErrors.isEmpty()) { throw new PlatformApiDataValidationException("validation.msg.validation.errors.exist", - "Validation errors exist.", dataValidationErrors); } + "Validation errors exist.", dataValidationErrors); } } public void validateForUpdate() { @@ -76,14 +45,12 @@ public class RoleCommand { DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors).resource("role"); - baseDataValidator.reset().parameter("id").value(this.id).notNull(); baseDataValidator.reset().parameter("name").value(this.name).ignoreIfNull().notBlank(); - baseDataValidator.reset().parameter("description").value(this.description).ignoreIfNull().notBlank() - .notExceedingLengthOf(500); + baseDataValidator.reset().parameter("description").value(this.description).ignoreIfNull().notBlank().notExceedingLengthOf(500); baseDataValidator.reset().anyOfNotNull(this.name, this.description); if (!dataValidationErrors.isEmpty()) { throw new PlatformApiDataValidationException("validation.msg.validation.errors.exist", - "Validation errors exist.", dataValidationErrors); } + "Validation errors exist.", dataValidationErrors); } } } \ No newline at end of file diff --git a/mifosng-provider/src/main/java/org/mifosplatform/useradministration/domain/Role.java b/mifosng-provider/src/main/java/org/mifosplatform/useradministration/domain/Role.java index ebfd671d3..15b1f1bd4 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/useradministration/domain/Role.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/useradministration/domain/Role.java @@ -2,6 +2,8 @@ package org.mifosplatform.useradministration.domain; import java.util.Collection; import java.util.HashSet; +import java.util.LinkedHashMap; +import java.util.Map; import java.util.Set; import javax.persistence.Column; @@ -12,8 +14,8 @@ import javax.persistence.JoinTable; import javax.persistence.ManyToMany; import javax.persistence.Table; +import org.mifosplatform.infrastructure.core.api.JsonCommand; import org.mifosplatform.infrastructure.core.domain.AbstractAuditableCustom; -import org.mifosplatform.useradministration.command.RoleCommand; import org.mifosplatform.useradministration.data.RoleData; @Entity @@ -30,6 +32,12 @@ public class Role extends AbstractAuditableCustom { @JoinTable(name = "m_role_permission", joinColumns = @JoinColumn(name = "role_id"), inverseJoinColumns = @JoinColumn(name = "permission_id")) private Set permissions = new HashSet(); + public static Role fromJson(final JsonCommand command) { + final String name = command.stringValueOfParameterNamed("name"); + final String description = command.stringValueOfParameterNamed("description"); + return new Role(name, description); + } + protected Role() { // } @@ -39,21 +47,43 @@ public class Role extends AbstractAuditableCustom { this.description = description.trim(); } - public void update(final RoleCommand command) { - if (command.isNameChanged()) { - this.name = command.getName(); + public Map update(final JsonCommand command) { + + final Map actualChanges = new LinkedHashMap(7); + + final String nameParamName = "name"; + if (command.isChangeInStringParameterNamed(nameParamName, this.name)) { + final String newValue = command.stringValueOfParameterNamed(nameParamName); + actualChanges.put(nameParamName, newValue); + this.name = newValue; } - if (command.isDescriptionChanged()) { - this.description = command.getDescription(); + final String descriptionParamName = "description"; + if (command.isChangeInStringParameterNamed(descriptionParamName, this.description)) { + final String newValue = command.stringValueOfParameterNamed(descriptionParamName); + actualChanges.put(descriptionParamName, newValue); + this.description = newValue; } + + return actualChanges; } - public boolean addPermission(final Permission permission) { + public boolean updatePermission(final Permission permission, final boolean isSelected) { + boolean changed = false; + if (isSelected) { + changed = addPermission(permission); + } else { + changed = removePermission(permission); + } + + return changed; + } + + private boolean addPermission(final Permission permission) { return this.permissions.add(permission); } - public boolean removePermission(final Permission permission) { + private boolean removePermission(final Permission permission) { return this.permissions.remove(permission); } @@ -75,15 +105,4 @@ public class Role extends AbstractAuditableCustom { public RoleData toData() { return new RoleData(this.getId(), this.name, this.description, null); } - - public boolean updatePermission(final Permission permission, final boolean isSelected) { - boolean changed = false; - if (isSelected) { - changed = addPermission(permission); - } else { - changed = removePermission(permission); - } - - return changed; - } } \ No newline at end of file diff --git a/mifosng-provider/src/main/java/org/mifosplatform/useradministration/serialization/RoleCommandFromApiJsonDeserializer.java b/mifosng-provider/src/main/java/org/mifosplatform/useradministration/serialization/RoleCommandFromApiJsonDeserializer.java index 5590de52e..6e5ea2945 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/useradministration/serialization/RoleCommandFromApiJsonDeserializer.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/useradministration/serialization/RoleCommandFromApiJsonDeserializer.java @@ -6,6 +6,9 @@ import java.util.HashSet; import java.util.Map; import java.util.Set; +import org.apache.commons.lang.StringUtils; +import org.mifosplatform.infrastructure.core.exception.InvalidJsonException; +import org.mifosplatform.infrastructure.core.serialization.AbstractFromApiJsonDeserializer; import org.mifosplatform.infrastructure.core.serialization.CommandSerializer; import org.mifosplatform.infrastructure.core.serialization.FromApiJsonDeserializer; import org.mifosplatform.infrastructure.core.serialization.FromJsonHelper; @@ -13,13 +16,14 @@ import org.mifosplatform.useradministration.command.RoleCommand; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; +import com.google.gson.JsonElement; import com.google.gson.reflect.TypeToken; /** * Implementation of {@link FromApiJsonDeserializer} for {@link RoleCommand}'s. */ @Component -public final class RoleCommandFromApiJsonDeserializer implements FromApiJsonDeserializer { +public final class RoleCommandFromApiJsonDeserializer extends AbstractFromApiJsonDeserializer { /** * The parameters supported for this command. @@ -27,41 +31,25 @@ public final class RoleCommandFromApiJsonDeserializer implements FromApiJsonDese private final Set supportedParameters = new HashSet(Arrays.asList("id", "name", "description")); private final FromJsonHelper fromApiJsonHelper; - private final RoleCommandFromCommandJsonDeserializer fromCommandJsonDeserializer; - private final CommandSerializer commandSerializerService; @Autowired - public RoleCommandFromApiJsonDeserializer(final FromJsonHelper fromApiJsonHelper, - final RoleCommandFromCommandJsonDeserializer fromCommandJsonDeserializer, final CommandSerializer commandSerializerService) { + public RoleCommandFromApiJsonDeserializer(final FromJsonHelper fromApiJsonHelper, final CommandSerializer commandSerializerService) { + super(commandSerializerService); this.fromApiJsonHelper = fromApiJsonHelper; - this.fromCommandJsonDeserializer = fromCommandJsonDeserializer; - this.commandSerializerService = commandSerializerService; } @Override - public RoleCommand commandFromApiJson(final String json) { - return commandFromApiJson(null, json); - } + public RoleCommand commandFromApiJson(@SuppressWarnings("unused") final Long roleId, final String json) { - @Override - public RoleCommand commandFromApiJson(final Long roleId, final String json) { + if (StringUtils.isBlank(json)) { throw new InvalidJsonException(); } final Type typeOfMap = new TypeToken>() {}.getType(); - fromApiJsonHelper.checkForUnsupportedParameters(typeOfMap, json, supportedParameters); - return this.fromCommandJsonDeserializer.commandFromCommandJson(roleId, json); - } + final JsonElement element = fromApiJsonHelper.parse(json); + final String name = fromApiJsonHelper.extractStringNamed("name", element); + final String description = fromApiJsonHelper.extractStringNamed("description", element); - @Override - public String serializedCommandJsonFromApiJson(final String json) { - final RoleCommand command = commandFromApiJson(json); - return this.commandSerializerService.serializeCommandToJson(command); - } - - @Override - public String serializedCommandJsonFromApiJson(final Long roleId, final String json) { - final RoleCommand command = commandFromApiJson(roleId, json); - return this.commandSerializerService.serializeCommandToJson(command); + return new RoleCommand(name, description); } } \ No newline at end of file diff --git a/mifosng-provider/src/main/java/org/mifosplatform/useradministration/serialization/RoleCommandFromCommandJsonDeserializer.java b/mifosng-provider/src/main/java/org/mifosplatform/useradministration/serialization/RoleCommandFromCommandJsonDeserializer.java deleted file mode 100644 index 3e5699d9c..000000000 --- a/mifosng-provider/src/main/java/org/mifosplatform/useradministration/serialization/RoleCommandFromCommandJsonDeserializer.java +++ /dev/null @@ -1,52 +0,0 @@ -package org.mifosplatform.useradministration.serialization; - -import java.util.HashSet; -import java.util.Set; - -import org.apache.commons.lang.StringUtils; -import org.mifosplatform.infrastructure.core.exception.InvalidJsonException; -import org.mifosplatform.infrastructure.core.serialization.FromCommandJsonDeserializer; -import org.mifosplatform.infrastructure.core.serialization.FromJsonHelper; -import org.mifosplatform.useradministration.command.RoleCommand; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Component; - -import com.google.gson.JsonElement; - -/** - * - */ -@Component -public final class RoleCommandFromCommandJsonDeserializer implements FromCommandJsonDeserializer { - - private final FromJsonHelper fromJsonHelper; - - @Autowired - public RoleCommandFromCommandJsonDeserializer(final FromJsonHelper fromApiJsonHelper) { - this.fromJsonHelper = fromApiJsonHelper; - } - - @Override - public RoleCommand commandFromCommandJson(final String commandAsJson) { - return commandFromCommandJson(null, commandAsJson); - } - - @Override - public RoleCommand commandFromCommandJson(final Long roleId, final String commandAsJson) { - return commandFromCommandJson(roleId, commandAsJson, false); - } - - @Override - public RoleCommand commandFromCommandJson(final Long roleId, final String commandAsJson, final boolean makerCheckerApproval) { - if (StringUtils.isBlank(commandAsJson)) { throw new InvalidJsonException(); } - - final Set parametersPassedInRequest = new HashSet(); - - final JsonElement element = fromJsonHelper.parse(commandAsJson); - - final String name = fromJsonHelper.extractStringNamed("name", element, parametersPassedInRequest); - final String description = fromJsonHelper.extractStringNamed("description", element, parametersPassedInRequest); - - return new RoleCommand(parametersPassedInRequest, makerCheckerApproval, roleId, name, description); - } -} \ No newline at end of file diff --git a/mifosng-provider/src/main/java/org/mifosplatform/useradministration/service/RoleWritePlatformService.java b/mifosng-provider/src/main/java/org/mifosplatform/useradministration/service/RoleWritePlatformService.java index 5775ad363..6abb28483 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/useradministration/service/RoleWritePlatformService.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/useradministration/service/RoleWritePlatformService.java @@ -2,13 +2,12 @@ package org.mifosplatform.useradministration.service; import org.mifosplatform.infrastructure.core.api.JsonCommand; import org.mifosplatform.infrastructure.core.data.EntityIdentifier; -import org.mifosplatform.useradministration.command.RoleCommand; public interface RoleWritePlatformService { - Long createRole(RoleCommand command); + Long createRole(JsonCommand command); - Long updateRole(RoleCommand command); + EntityIdentifier updateRole(Long roleId, JsonCommand command); EntityIdentifier updateRolePermissions(Long roleId, JsonCommand command); } \ No newline at end of file diff --git a/mifosng-provider/src/main/java/org/mifosplatform/useradministration/service/RoleWritePlatformServiceJpaRepositoryImpl.java b/mifosng-provider/src/main/java/org/mifosplatform/useradministration/service/RoleWritePlatformServiceJpaRepositoryImpl.java index 9094aeaba..3f5b88a89 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/useradministration/service/RoleWritePlatformServiceJpaRepositoryImpl.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/useradministration/service/RoleWritePlatformServiceJpaRepositoryImpl.java @@ -18,6 +18,7 @@ import org.mifosplatform.useradministration.domain.RoleRepository; import org.mifosplatform.useradministration.exception.PermissionNotFoundException; import org.mifosplatform.useradministration.exception.RoleNotFoundException; import org.mifosplatform.useradministration.serialization.PermissionsCommandFromApiJsonDeserializer; +import org.mifosplatform.useradministration.serialization.RoleCommandFromApiJsonDeserializer; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -29,52 +30,59 @@ public class RoleWritePlatformServiceJpaRepositoryImpl implements RoleWritePlatf private final RoleRepository roleRepository; private final PermissionRepository permissionRepository; private final ConfigurationDomainService configurationDomainService; - private final PermissionsCommandFromApiJsonDeserializer fromApiJsonDeserializer; + private final RoleCommandFromApiJsonDeserializer roleCommandFromApiJsonDeserializer; + private final PermissionsCommandFromApiJsonDeserializer permissionsFromApiJsonDeserializer; @Autowired public RoleWritePlatformServiceJpaRepositoryImpl(final PlatformSecurityContext context, final RoleRepository roleRepository, - final PermissionRepository permissionRepository, - final ConfigurationDomainService configurationDomainService, + final PermissionRepository permissionRepository, final ConfigurationDomainService configurationDomainService, + final RoleCommandFromApiJsonDeserializer roleCommandFromApiJsonDeserializer, final PermissionsCommandFromApiJsonDeserializer fromApiJsonDeserializer) { this.context = context; this.roleRepository = roleRepository; this.permissionRepository = permissionRepository; this.configurationDomainService = configurationDomainService; - this.fromApiJsonDeserializer = fromApiJsonDeserializer; + this.roleCommandFromApiJsonDeserializer = roleCommandFromApiJsonDeserializer; + this.permissionsFromApiJsonDeserializer = fromApiJsonDeserializer; } @Transactional @Override - public Long createRole(final RoleCommand command) { + public Long createRole(final JsonCommand command) { context.authenticatedUser(); - command.validateForCreate(); - - final Role entity = new Role(command.getName(), command.getDescription()); + final RoleCommand roleCommand = this.roleCommandFromApiJsonDeserializer.commandFromApiJson(command.json()); + roleCommand.validateForCreate(); + + final Role entity = Role.fromJson(command); this.roleRepository.save(entity); - + if (this.configurationDomainService.isMakerCheckerEnabledForTask("CREATE_ROLE") && !command.isApprovedByChecker()) { throw new RollbackTransactionAsCommandIsNotApprovedByCheckerException(); } - + return entity.getId(); } @Transactional @Override - public Long updateRole(final RoleCommand command) { + public EntityIdentifier updateRole(final Long roleId, final JsonCommand command) { context.authenticatedUser(); - command.validateForUpdate(); - - final Role role = this.roleRepository.findOne(command.getId()); - if (role == null) { throw new RoleNotFoundException(command.getId()); } - role.update(command); - this.roleRepository.save(role); - + final RoleCommand roleCommand = this.roleCommandFromApiJsonDeserializer.commandFromApiJson(command.json()); + roleCommand.validateForUpdate(); + + final Role role = this.roleRepository.findOne(roleId); + if (role == null) { throw new RoleNotFoundException(roleId); } + + final Map changes = role.update(command); + if (!changes.isEmpty()) { + this.roleRepository.save(role); + } + if (this.configurationDomainService.isMakerCheckerEnabledForTask("UPDATE_ROLE") && !command.isApprovedByChecker()) { throw new RollbackTransactionAsCommandIsNotApprovedByCheckerException(); } - - return role.getId(); + + return EntityIdentifier.withChanges(role.getId(), changes); } @Transactional @@ -87,8 +95,8 @@ public class RoleWritePlatformServiceJpaRepositoryImpl implements RoleWritePlatf final Collection allPermissions = this.permissionRepository.findAll(); - final PermissionsCommand permissionsCommand = this.fromApiJsonDeserializer.commandFromApiJson(command.json()); - + final PermissionsCommand permissionsCommand = this.permissionsFromApiJsonDeserializer.commandFromApiJson(command.json()); + final Map commandPermissions = permissionsCommand.getPermissions(); final Map changes = new HashMap(); final Map changedPermissions = new HashMap(); @@ -106,9 +114,9 @@ public class RoleWritePlatformServiceJpaRepositoryImpl implements RoleWritePlatf changes.put("permissions", changedPermissions); this.roleRepository.save(role); } - + if (this.configurationDomainService.isMakerCheckerEnabledForTask("PERMISSIONS_ROLE") && !command.isApprovedByChecker()) { throw new RollbackTransactionAsCommandIsNotApprovedByCheckerException(); } - + return EntityIdentifier.withChanges(role.getId(), changes); } @@ -116,7 +124,7 @@ public class RoleWritePlatformServiceJpaRepositoryImpl implements RoleWritePlatf if (allPermissions != null) { for (Permission permission : allPermissions) { - if (permission.hasCode(permissionCode)) {return permission;} + if (permission.hasCode(permissionCode)) { return permission; } } }