MIFOSX-97: detect changes on update of role. split out image part of clients api into its own resource class.

This commit is contained in:
Keith Woodlock
2012-12-07 00:10:46 +00:00
parent c966892b37
commit f5c1225dfa
9 changed files with 262 additions and 315 deletions
@@ -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<String> 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<String> 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<String> 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()); }
@@ -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<ClientData> toApiJsonSerializer;
@Autowired
public ClientImagesApiResource(final PlatformSecurityContext context, final ClientReadPlatformService readPlatformService,
final ClientWritePlatformService clientWritePlatformService, final DefaultToApiJsonSerializer<ClientData> 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);
}
}
@@ -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<ClientData> 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<ClientData> toApiJsonSerializer, final ApiRequestParameterHelper apiRequestParameterHelper,
final PortfolioApiDataConversionService apiDataConversionService,
final OfficeReadPlatformService officeReadPlatformService, final DefaultToApiJsonSerializer<ClientData> 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<String> 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);
}
}
@@ -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.
*
* <p>Fields that are transient are intended not to be serialized into JSON.</p>
*/
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<String> modifiedParameters;
public RoleCommand(
final Set<String> 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<ApiParameterError> dataValidationErrors = new ArrayList<ApiParameterError>();
@@ -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); }
}
}
@@ -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<AppUser, Long> {
@JoinTable(name = "m_role_permission", joinColumns = @JoinColumn(name = "role_id"), inverseJoinColumns = @JoinColumn(name = "permission_id"))
private Set<Permission> permissions = new HashSet<Permission>();
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<AppUser, Long> {
this.description = description.trim();
}
public void update(final RoleCommand command) {
if (command.isNameChanged()) {
this.name = command.getName();
public Map<String, Object> update(final JsonCommand command) {
final Map<String, Object> actualChanges = new LinkedHashMap<String, Object>(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<AppUser, Long> {
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;
}
}
@@ -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<RoleCommand> {
public final class RoleCommandFromApiJsonDeserializer extends AbstractFromApiJsonDeserializer<RoleCommand> {
/**
* The parameters supported for this command.
@@ -27,41 +31,25 @@ public final class RoleCommandFromApiJsonDeserializer implements FromApiJsonDese
private final Set<String> supportedParameters = new HashSet<String>(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<Map<String, Object>>() {}.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);
}
}
@@ -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<RoleCommand> {
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<String> parametersPassedInRequest = new HashSet<String>();
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);
}
}
@@ -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);
}
@@ -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<String, Object> 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<Permission> allPermissions = this.permissionRepository.findAll();
final PermissionsCommand permissionsCommand = this.fromApiJsonDeserializer.commandFromApiJson(command.json());
final PermissionsCommand permissionsCommand = this.permissionsFromApiJsonDeserializer.commandFromApiJson(command.json());
final Map<String, Boolean> commandPermissions = permissionsCommand.getPermissions();
final Map<String, Object> changes = new HashMap<String, Object>();
final Map<String, Boolean> changedPermissions = new HashMap<String, Boolean>();
@@ -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; }
}
}