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 041553a62..00ec71274 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 @@ -28,7 +28,8 @@ public class RoleCommandHandler implements CommandSourceHandler { private final ExcludeNothingWithPrettyPrintingOffJsonSerializerGoogleGson toApiJsonSerializer; @Autowired - public RoleCommandHandler(final PlatformSecurityContext context, final FromJsonHelper fromApiJsonHelper, + public RoleCommandHandler(final PlatformSecurityContext context, + final FromJsonHelper fromApiJsonHelper, final ExcludeNothingWithPrettyPrintingOffJsonSerializerGoogleGson toApiJsonSerializer, final RoleWritePlatformService writePlatformService) { this.context = context; @@ -45,11 +46,11 @@ public class RoleCommandHandler implements CommandSourceHandler { CommandSource commandSourceResult = commandSource.copy(); + final JsonElement parsedCommand = this.fromApiJsonHelper.parse(commandSource.json()); + final JsonCommand command = JsonCommand.from(commandSource.json(), parsedCommand, this.fromApiJsonHelper); final Long resourceId = commandSource.resourceId(); if (commandSource.isCreate()) { try { - final JsonElement parsedCommand = this.fromApiJsonHelper.parse(commandSource.json()); - final JsonCommand command = JsonCommand.from(commandSource.json(), parsedCommand, this.fromApiJsonHelper); final Long newResourceId = this.writePlatformService.createRole(command); @@ -60,24 +61,16 @@ public class RoleCommandHandler implements CommandSourceHandler { } } else if (commandSource.isUpdate()) { try { - final JsonElement parsedCommand = this.fromApiJsonHelper.parse(commandSource.json()); - final JsonCommand command = JsonCommand.from(commandSource.json(), parsedCommand, this.fromApiJsonHelper); - 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) { // swallow this rollback transaction by design } } else if (commandSource.isUpdateRolePermissions()) { try { - - final JsonElement parsedCommand = this.fromApiJsonHelper.parse(commandSource.json()); - final JsonCommand command = JsonCommand.from(commandSource.json(), parsedCommand, this.fromApiJsonHelper); - final EntityIdentifier result = this.writePlatformService.updateRolePermissions(resourceId, command); final String jsonOfChangesOnly = toApiJsonSerializer.serialize(result.getChanges()); diff --git a/mifosng-provider/src/main/java/org/mifosplatform/commands/handler/UserCommandHandler.java b/mifosng-provider/src/main/java/org/mifosplatform/commands/handler/UserCommandHandler.java index c9262a8b7..8eea8953e 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/commands/handler/UserCommandHandler.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/commands/handler/UserCommandHandler.java @@ -5,27 +5,34 @@ import java.util.List; import org.joda.time.LocalDate; import org.mifosplatform.commands.domain.CommandSource; +import org.mifosplatform.infrastructure.core.api.JsonCommand; +import org.mifosplatform.infrastructure.core.data.EntityIdentifier; +import org.mifosplatform.infrastructure.core.serialization.ExcludeNothingWithPrettyPrintingOffJsonSerializerGoogleGson; +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.UserCommand; import org.mifosplatform.useradministration.domain.AppUser; -import org.mifosplatform.useradministration.serialization.UserCommandFromCommandJsonDeserializer; import org.mifosplatform.useradministration.service.AppUserWritePlatformService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; +import com.google.gson.JsonElement; + @Service public class UserCommandHandler implements CommandSourceHandler { private final PlatformSecurityContext context; - private final UserCommandFromCommandJsonDeserializer fromCommandJsonDeserializer; + private final FromJsonHelper fromApiJsonHelper; + private final ExcludeNothingWithPrettyPrintingOffJsonSerializerGoogleGson toApiJsonSerializer; private final AppUserWritePlatformService writePlatformService; @Autowired - public UserCommandHandler(final PlatformSecurityContext context, - final UserCommandFromCommandJsonDeserializer fromCommandJsonDeserializer, final AppUserWritePlatformService writePlatformService) { + public UserCommandHandler(final PlatformSecurityContext context, final FromJsonHelper fromApiJsonHelper, + final ExcludeNothingWithPrettyPrintingOffJsonSerializerGoogleGson toApiJsonSerializer, + final AppUserWritePlatformService writePlatformService) { this.context = context; - this.fromCommandJsonDeserializer = fromCommandJsonDeserializer; + this.fromApiJsonHelper = fromApiJsonHelper; + this.toApiJsonSerializer = toApiJsonSerializer; this.writePlatformService = writePlatformService; } @@ -36,11 +43,13 @@ public class UserCommandHandler implements CommandSourceHandler { final LocalDate asToday = new LocalDate(); final Long resourceId = commandSource.resourceId(); - final UserCommand command = this.fromCommandJsonDeserializer.commandFromCommandJson(resourceId, commandSource.json()); + final JsonElement parsedCommand = this.fromApiJsonHelper.parse(commandSource.json()); + final JsonCommand command = JsonCommand.from(commandSource.json(), parsedCommand, this.fromApiJsonHelper); + CommandSource commandSourceResult = commandSource.copy(); if (commandSource.isCreate()) { try { - Long newResourceId = this.writePlatformService.createUser(command); + final Long newResourceId = this.writePlatformService.createUser(command); commandSourceResult.markAsChecked(maker, asToday); commandSourceResult.updateResourceId(newResourceId); @@ -49,19 +58,22 @@ public class UserCommandHandler implements CommandSourceHandler { } } else if (commandSource.isUpdate()) { try { - if (maker.hasIdOf(command.getId())) { - this.writePlatformService.updateUsersOwnAccountDetails(command); + EntityIdentifier result = null; + if (maker.hasIdOf(resourceId)) { + result = this.writePlatformService.updateUsersOwnAccountDetails(resourceId, command); } else { - this.writePlatformService.updateUser(command); + result = this.writePlatformService.updateUser(resourceId, command); } + final String jsonOfChangesOnly = toApiJsonSerializer.serialize(result.getChanges()); + commandSourceResult.updateJsonTo(jsonOfChangesOnly); commandSourceResult.markAsChecked(maker, asToday); } catch (RollbackTransactionAsCommandIsNotApprovedByCheckerException e) { // swallow this rollback transaction by design } } else if (commandSource.isDelete()) { try { - this.writePlatformService.deleteUser(command); + this.writePlatformService.deleteUser(resourceId, command); commandSourceResult.markAsChecked(maker, asToday); } catch (RollbackTransactionAsCommandIsNotApprovedByCheckerException e) { // swallow this rollback transaction by design @@ -76,35 +88,40 @@ public class UserCommandHandler implements CommandSourceHandler { final AppUser checker = context.authenticatedUser(); - Long resourceId = commandSourceResult.resourceId(); - final UserCommand command = this.fromCommandJsonDeserializer.commandFromCommandJson(resourceId, commandSourceResult.json(), true); + final Long resourceId = commandSourceResult.resourceId(); + final JsonElement parsedCommand = this.fromApiJsonHelper.parse(commandSourceResult.json()); + final JsonCommand command = JsonCommand.withMakerCheckerApproval(commandSourceResult.json(), parsedCommand, this.fromApiJsonHelper); + if (commandSourceResult.isUserResource()) { if (commandSourceResult.isCreate()) { final List allowedPermissions = Arrays.asList("ALL_FUNCTIONS", "USER_ADMINISTRATION_SUPER_USER", "CREATE_USER_MAKER"); context.authenticatedUser().validateHasPermissionTo("CREATE_USER_MAKER", allowedPermissions); - resourceId = this.writePlatformService.createUser(command); - commandSourceResult.updateResourceId(resourceId); + final Long newResourceId = this.writePlatformService.createUser(command); + commandSourceResult.updateResourceId(newResourceId); commandSourceResult.markAsChecked(checker, new LocalDate()); } else if (commandSourceResult.isUpdate()) { - if (checker.hasIdOf(command.getId())) { - this.writePlatformService.updateUsersOwnAccountDetails(command); + EntityIdentifier result = null; + if (checker.hasIdOf(resourceId)) { + result = this.writePlatformService.updateUsersOwnAccountDetails(resourceId, command); } else { final List allowedPermissions = Arrays.asList("ALL_FUNCTIONS", "USER_ADMINISTRATION_SUPER_USER", "UPDATE_USER_MAKER"); context.authenticatedUser().validateHasPermissionTo("UPDATE_USER_MAKER", allowedPermissions); - this.writePlatformService.updateUser(command); + result = this.writePlatformService.updateUser(resourceId, command); } - + + final String jsonOfChangesOnly = toApiJsonSerializer.serialize(result.getChanges()); + commandSourceResult.updateJsonTo(jsonOfChangesOnly); commandSourceResult.markAsChecked(checker, new LocalDate()); } else if (commandSourceResult.isDelete()) { final List allowedPermissions = Arrays.asList("ALL_FUNCTIONS", "USER_ADMINISTRATION_SUPER_USER", "DELETE_USER_MAKER"); context.authenticatedUser().validateHasPermissionTo("DELETE_USER_MAKER", allowedPermissions); - this.writePlatformService.deleteUser(command); + this.writePlatformService.deleteUser(resourceId, command); commandSourceResult.markAsChecked(checker, new LocalDate()); } } diff --git a/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/core/api/JsonCommand.java b/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/core/api/JsonCommand.java index 93427005d..11e68a850 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/core/api/JsonCommand.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/core/api/JsonCommand.java @@ -1,11 +1,15 @@ package org.mifosplatform.infrastructure.core.api; import java.lang.reflect.Type; +import java.util.Arrays; import java.util.Map; import org.apache.commons.lang.StringUtils; import org.joda.time.LocalDate; import org.mifosplatform.infrastructure.core.serialization.FromJsonHelper; +import org.mifosplatform.infrastructure.security.domain.BasicPasswordEncodablePlatformUser; +import org.mifosplatform.infrastructure.security.domain.PlatformUser; +import org.mifosplatform.infrastructure.security.service.PlatformPasswordEncoder; import com.google.gson.JsonElement; import com.google.gson.reflect.TypeToken; @@ -72,6 +76,12 @@ public final class JsonCommand { return differenceExists; } + private boolean differenceExists(final String[] baseValue, final String[] workingCopyValue) { + Arrays.sort(baseValue); + Arrays.sort(workingCopyValue); + return !Arrays.equals(baseValue, workingCopyValue); + } + private boolean differenceExists(final Long baseValue, final Long workingCopyValue) { boolean differenceExists = false; @@ -87,6 +97,10 @@ public final class JsonCommand { private boolean parameterExists(final String parameterName) { return this.fromApiJsonHelper.parameterExists(parameterName, parsedCommand); } + + public boolean hasParameter(final String parameterName) { + return parameterExists(parameterName); + } public String dateFormat() { return stringValueOfParameterNamed("dateFormat"); @@ -95,14 +109,14 @@ public final class JsonCommand { public String locale() { return stringValueOfParameterNamed("locale"); } - + public Map mapValueOfParameterNamed(final String parameterName) { final Type typeOfMap = new TypeToken>() {}.getType(); - + if (parsedCommand.getAsJsonObject().has(parameterName)) { parsedCommand.getAsJsonObject().get(parameterName); } - + return this.fromApiJsonHelper.extractMap(typeOfMap, jsonCommand); } @@ -145,4 +159,33 @@ public final class JsonCommand { final String value = this.fromApiJsonHelper.extractStringNamed(parameterName, parsedCommand); return StringUtils.defaultIfEmpty(value, ""); } + + public boolean isChangeInArrayParameterNamed(final String parameterName, final String[] existingValue) { + boolean isChanged = false; + if (parameterExists(parameterName)) { + final String[] workingValue = arrayValueOfParameterNamed(parameterName); + isChanged = differenceExists(existingValue, workingValue); + } + return isChanged; + } + + public String[] arrayValueOfParameterNamed(final String parameterName) { + return this.fromApiJsonHelper.extractArrayNamed(parameterName, parsedCommand); + } + + public boolean isChangeInPasswordParameterNamed(final String parameterName, final String existingValue, final PlatformPasswordEncoder platformPasswordEncoder, final Long saltValue) { + boolean isChanged = false; + if (parameterExists(parameterName)) { + final String workingValue = passwordValueOfParameterNamed(parameterName, platformPasswordEncoder, saltValue); + isChanged = differenceExists(existingValue, workingValue); + } + return isChanged; + } + + public String passwordValueOfParameterNamed(final String parameterName, final PlatformPasswordEncoder platformPasswordEncoder, final Long saltValue) { + final String passwordPlainText = stringValueOfParameterNamed(parameterName); + + final PlatformUser dummyPlatformUser = new BasicPasswordEncodablePlatformUser(saltValue, "", passwordPlainText); + return platformPasswordEncoder.encode(dummyPlatformUser); + } } \ No newline at end of file diff --git a/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/core/data/EntityIdentifier.java b/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/core/data/EntityIdentifier.java index 44781d669..0c30c396b 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/core/data/EntityIdentifier.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/core/data/EntityIdentifier.java @@ -27,6 +27,10 @@ public class EntityIdentifier { public static EntityIdentifier withChanges(final Long resourceId, final Map changes) { return new EntityIdentifier(resourceId, null, changes); } + + public static EntityIdentifier empty() { + return new EntityIdentifier(Long.valueOf(-1), null, null); + } public EntityIdentifier() { // diff --git a/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/core/serialization/FromJsonHelper.java b/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/core/serialization/FromJsonHelper.java index 606ced0ac..63dbd5565 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/core/serialization/FromJsonHelper.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/core/serialization/FromJsonHelper.java @@ -78,6 +78,10 @@ public class FromJsonHelper { public Long extractLongNamed(final String parameterName, final JsonElement element, final Set parametersPassedInRequest) { return helperDelegator.extractLongNamed(parameterName, element, parametersPassedInRequest); } + + public String[] extractArrayNamed(final String parameterName, final JsonElement element) { + return helperDelegator.extractArrayNamed(parameterName, element, new HashSet()); + } public String[] extractArrayNamed(final String parameterName, final JsonElement element, final Set parametersPassedInRequest) { return helperDelegator.extractArrayNamed(parameterName, element, parametersPassedInRequest); diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/client/service/ClientWritePlatformServiceJpaRepositoryImpl.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/client/service/ClientWritePlatformServiceJpaRepositoryImpl.java index 72daed081..d73351577 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/client/service/ClientWritePlatformServiceJpaRepositoryImpl.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/client/service/ClientWritePlatformServiceJpaRepositoryImpl.java @@ -145,6 +145,7 @@ public class ClientWritePlatformServiceJpaRepositoryImpl implements ClientWriteP final Client clientForUpdate = this.clientRepository.findOne(clientId); if (clientForUpdate == null || clientForUpdate.isDeleted()) { throw new ClientNotFoundException(clientId); } + final Map changesOnly = clientForUpdate.update(command); if (changesOnly.containsKey("officeId")) { diff --git a/mifosng-provider/src/main/java/org/mifosplatform/useradministration/api/UsersApiResource.java b/mifosng-provider/src/main/java/org/mifosplatform/useradministration/api/UsersApiResource.java index d7d4ca278..cdeeb9709 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/useradministration/api/UsersApiResource.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/useradministration/api/UsersApiResource.java @@ -20,7 +20,6 @@ import javax.ws.rs.core.MediaType; import javax.ws.rs.core.UriInfo; import org.mifosplatform.commands.service.PortfolioCommandSourceWritePlatformService; -import org.mifosplatform.infrastructure.codes.data.CodeData; import org.mifosplatform.infrastructure.core.api.ApiRequestParameterHelper; import org.mifosplatform.infrastructure.core.data.EntityIdentifier; import org.mifosplatform.infrastructure.core.serialization.ApiRequestJsonSerializationSettings; @@ -29,7 +28,6 @@ import org.mifosplatform.infrastructure.security.service.PlatformSecurityContext import org.mifosplatform.organisation.office.data.OfficeLookup; import org.mifosplatform.organisation.office.service.OfficeReadPlatformService; import org.mifosplatform.useradministration.data.AppUserData; -import org.mifosplatform.useradministration.serialization.UserCommandFromApiJsonDeserializer; import org.mifosplatform.useradministration.service.AppUserReadPlatformService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Scope; @@ -41,7 +39,7 @@ import org.springframework.stereotype.Component; public class UsersApiResource { /** - * The set of parameters that are supported in response for {@link CodeData} + * The set of parameters that are supported in response for {@link AppUserData}. */ private final Set RESPONSE_DATA_PARAMETERS = new HashSet(Arrays.asList("id", "officeId", "officeName", "username", "firstname", "lastname", "email", "allowedOffices", "availableRoles", "selectedRoles")); @@ -51,20 +49,18 @@ public class UsersApiResource { private final PlatformSecurityContext context; private final AppUserReadPlatformService readPlatformService; private final OfficeReadPlatformService officeReadPlatformService; - private final UserCommandFromApiJsonDeserializer fromApiJsonDeserializer; private final DefaultToApiJsonSerializer toApiJsonSerializer; private final ApiRequestParameterHelper apiRequestParameterHelper; private final PortfolioCommandSourceWritePlatformService commandsSourceWritePlatformService; @Autowired public UsersApiResource(final PlatformSecurityContext context, final AppUserReadPlatformService readPlatformService, - final OfficeReadPlatformService officeReadPlatformService, final UserCommandFromApiJsonDeserializer fromApiJsonDeserializer, + final OfficeReadPlatformService officeReadPlatformService, final DefaultToApiJsonSerializer toApiJsonSerializer, final ApiRequestParameterHelper apiRequestParameterHelper, final PortfolioCommandSourceWritePlatformService commandsSourceWritePlatformService) { this.context = context; this.readPlatformService = readPlatformService; this.officeReadPlatformService = officeReadPlatformService; - this.fromApiJsonDeserializer = fromApiJsonDeserializer; this.toApiJsonSerializer = toApiJsonSerializer; this.apiRequestParameterHelper = apiRequestParameterHelper; this.commandsSourceWritePlatformService = commandsSourceWritePlatformService; @@ -124,10 +120,8 @@ public class UsersApiResource { final List allowedPermissions = Arrays.asList("ALL_FUNCTIONS", "USER_ADMINISTRATION_SUPER_USER", "CREATE_USER"); context.authenticatedUser().validateHasPermissionTo("CREATE_USER", allowedPermissions); - final String commandSerializedAsJson = this.fromApiJsonDeserializer.serializedCommandJsonFromApiJson(apiRequestBodyAsJson); - final EntityIdentifier result = this.commandsSourceWritePlatformService.logCommandSource("CREATE", "users", null, - commandSerializedAsJson); + apiRequestBodyAsJson); return this.toApiJsonSerializer.serialize(result); } @@ -141,10 +135,8 @@ public class UsersApiResource { final List allowedPermissions = Arrays.asList("ALL_FUNCTIONS", "USER_ADMINISTRATION_SUPER_USER", "UPDATE_USER"); context.authenticatedUser().validateHasPermissionTo("UPDATE_USER", allowedPermissions); - final String commandSerializedAsJson = this.fromApiJsonDeserializer.serializedCommandJsonFromApiJson(apiRequestBodyAsJson); - final EntityIdentifier result = this.commandsSourceWritePlatformService.logCommandSource("UPDATE", "users", userId, - commandSerializedAsJson); + apiRequestBodyAsJson); return this.toApiJsonSerializer.serialize(result); } diff --git a/mifosng-provider/src/main/java/org/mifosplatform/useradministration/command/UserCommand.java b/mifosng-provider/src/main/java/org/mifosplatform/useradministration/command/UserCommand.java index 98583878d..c74994183 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/useradministration/command/UserCommand.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/useradministration/command/UserCommand.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; @@ -18,37 +17,26 @@ public class UserCommand { private final String lastname; private final String password; private final String repeatPassword; + private final String passwordEncoded; private final String email; private final Long officeId; - private final String[] notSelectedRoles; private final String[] roles; - private transient final boolean makerCheckerApproval; - private transient final Long id; - private transient final Set modifiedParameters; - - public UserCommand(final Set modifiedParameters, final boolean makerCheckerApproval, final Long id, final String username, - final String firstname, final String lastname, final String password, final String repeatPassword, final String email, - final Long officeId, final String[] notSelectedRoles, final String[] roles) { - this.modifiedParameters = modifiedParameters; - this.makerCheckerApproval = makerCheckerApproval; - this.id = id; + public UserCommand(final String username, final String firstname, final String lastname, final String password, + final String repeatPassword, final String passwordEncoded, final String email, final Long officeId, final String[] notSelectedRoles, final String[] roles) { this.username = username; this.firstname = firstname; this.lastname = lastname; this.password = password; this.repeatPassword = repeatPassword; + this.passwordEncoded = passwordEncoded; this.email = email; this.officeId = officeId; this.notSelectedRoles = notSelectedRoles; this.roles = roles; } - public Long getId() { - return id; - } - public String getUsername() { return username; } @@ -85,38 +73,6 @@ public class UserCommand { return roles; } - public boolean isUsernameChanged() { - return this.modifiedParameters.contains("username"); - } - - public boolean isFirstnameChanged() { - return this.modifiedParameters.contains("firstname"); - } - - public boolean isLastnameChanged() { - return this.modifiedParameters.contains("lastname"); - } - - public boolean isEmailChanged() { - return this.modifiedParameters.contains("email"); - } - - public boolean isPasswordChanged() { - return this.modifiedParameters.contains("password") && this.modifiedParameters.contains("repeatPassword"); - } - - public boolean isOfficeChanged() { - return this.modifiedParameters.contains("officeId"); - } - - public boolean isRolesChanged() { - return this.modifiedParameters.contains("roles"); - } - - public boolean isApprovedByChecker() { - return this.makerCheckerApproval; - } - public void validateForCreate() { List dataValidationErrors = new ArrayList(); @@ -130,7 +86,7 @@ public class UserCommand { baseDataValidator.reset().parameter("roles").value(this.roles).arrayNotEmpty(); if (!dataValidationErrors.isEmpty()) { throw new PlatformApiDataValidationException("validation.msg.validation.errors.exist", - "Validation errors exist.", dataValidationErrors); } + "Validation errors exist.", dataValidationErrors); } } public void validateForUpdate() { @@ -138,7 +94,6 @@ public class UserCommand { DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors).resource("user"); - baseDataValidator.reset().parameter("id").value(this.id).notNull(); baseDataValidator.reset().parameter("username").value(this.username).ignoreIfNull().notBlank(); baseDataValidator.reset().parameter("firstname").value(this.firstname).ignoreIfNull().notBlank(); baseDataValidator.reset().parameter("lastname").value(this.lastname).ignoreIfNull().notBlank(); @@ -151,8 +106,8 @@ public class UserCommand { baseDataValidator.reset().parameter("password").value(this.password).ignoreIfNull() .equalToParameter("repeatPassword", this.repeatPassword); - baseDataValidator.reset().anyOfNotNull(this.username, this.firstname, this.lastname, this.email, this.officeId, - this.roles, this.password, this.repeatPassword); + baseDataValidator.reset().anyOfNotNull(this.username, this.firstname, this.lastname, this.email, this.officeId, this.roles, + this.password, this.repeatPassword); if (!dataValidationErrors.isEmpty()) { throw new PlatformApiDataValidationException("validation.msg.validation.errors.exist", "Validation errors exist.", dataValidationErrors); } diff --git a/mifosng-provider/src/main/java/org/mifosplatform/useradministration/domain/AppUser.java b/mifosng-provider/src/main/java/org/mifosplatform/useradministration/domain/AppUser.java index 40d7e2cdd..b8baf1840 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/useradministration/domain/AppUser.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/useradministration/domain/AppUser.java @@ -3,7 +3,9 @@ package org.mifosplatform.useradministration.domain; import java.util.ArrayList; import java.util.Collection; import java.util.HashSet; +import java.util.LinkedHashMap; import java.util.List; +import java.util.Map; import java.util.Set; import javax.persistence.Column; @@ -16,11 +18,13 @@ import javax.persistence.ManyToOne; import javax.persistence.Table; import javax.persistence.UniqueConstraint; +import org.apache.commons.lang.StringUtils; +import org.mifosplatform.infrastructure.core.api.JsonCommand; import org.mifosplatform.infrastructure.core.domain.AbstractAuditableCustom; import org.mifosplatform.infrastructure.security.domain.PlatformUser; import org.mifosplatform.infrastructure.security.exception.NoAuthorizationException; +import org.mifosplatform.infrastructure.security.service.PlatformPasswordEncoder; import org.mifosplatform.organisation.office.domain.Office; -import org.mifosplatform.useradministration.command.UserCommand; import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.authority.SimpleGrantedAuthority; import org.springframework.security.core.userdetails.User; @@ -71,8 +75,13 @@ public class AppUser extends AbstractAuditableCustom implements P @JoinTable(name = "m_appuser_role", joinColumns = @JoinColumn(name = "appuser_id"), inverseJoinColumns = @JoinColumn(name = "role_id")) private Set roles; - public static AppUser createNew(final Office office, final Set allRoles, final String username, final String email, - final String firstname, final String lastname, final String password) { + public static AppUser fromJson(final Office userOffice, final Set allRoles, final JsonCommand command) { + + final String username = command.stringValueOfParameterNamed("username"); + String password = command.stringValueOfParameterNamed("password"); + if (StringUtils.isBlank(password)) { + password = "autogenerate"; + } boolean userEnabled = true; boolean userAccountNonExpired = true; @@ -84,20 +93,18 @@ public class AppUser extends AbstractAuditableCustom implements P User user = new User(username, password, userEnabled, userAccountNonExpired, userCredentialsNonExpired, userAccountNonLocked, authorities); - return new AppUser(office, user, allRoles, email, firstname, lastname); + + final String email = command.stringValueOfParameterNamed("email"); + final String firstname = command.stringValueOfParameterNamed("firstname"); + final String lastname = command.stringValueOfParameterNamed("lastname"); + + return new AppUser(userOffice, user, allRoles, email, firstname, lastname); } protected AppUser() { - this.office = null; - this.email = null; - this.username = null; - this.password = null; - this.accountNonExpired = false; this.accountNonLocked = false; this.credentialsNonExpired = false; - this.enabled = false; this.roles = new HashSet(); - this.firstTimeLoginRemaining = true; } public AppUser(final Office office, final User user, final Set roles, final String email, final String firstname, @@ -121,27 +128,92 @@ public class AppUser extends AbstractAuditableCustom implements P this.firstTimeLoginRemaining = false; } - public void update(final Set allRoles, final Office office, final UserCommand userCommand) { + public void changeOffice(final Office differentOffice) { + this.office = differentOffice; + } - if (userCommand.isRolesChanged() && !allRoles.isEmpty()) { + public void updateRoles(final Set allRoles) { + if (!allRoles.isEmpty()) { this.roles.clear(); this.roles = allRoles; } - if (userCommand.isOfficeChanged()) { - this.office = office; + } + + public Map update(final JsonCommand command, final PlatformPasswordEncoder platformPasswordEncoder) { + + final Map actualChanges = new LinkedHashMap(7); + + // unencoded password provided + final String passwordParamName = "password"; + final String passwordEncodedParamName = "passwordEncoded"; + if (command.hasParameter(passwordParamName)) { + if (command.isChangeInPasswordParameterNamed(passwordParamName, this.password, platformPasswordEncoder, this.getId())) { + final String passwordEncodedValue = command.passwordValueOfParameterNamed(passwordParamName, platformPasswordEncoder, + this.getId()); + actualChanges.put(passwordEncodedParamName, passwordEncodedValue); + updatePassword(passwordEncodedValue); + } } - if (userCommand.isUsernameChanged()) { - this.username = userCommand.getUsername(); + + if (command.hasParameter(passwordEncodedParamName)) { + if (command.isChangeInStringParameterNamed(passwordEncodedParamName, this.password)) { + final String newValue = command.stringValueOfParameterNamed(passwordEncodedParamName); + actualChanges.put(passwordEncodedParamName, newValue); + updatePassword(newValue); + } } - if (userCommand.isFirstnameChanged()) { - this.firstname = userCommand.getFirstname(); + + final String officeIdParamName = "officeId"; + if (command.isChangeInLongParameterNamed(officeIdParamName, this.office.getId())) { + final Long newValue = command.longValueOfParameterNamed(officeIdParamName); + actualChanges.put(officeIdParamName, newValue); } - if (userCommand.isLastnameChanged()) { - this.lastname = userCommand.getLastname(); + + final String rolesParamName = "roles"; + if (command.isChangeInArrayParameterNamed(rolesParamName, getRolesAsIdStringArray())) { + final String[] newValue = command.arrayValueOfParameterNamed(rolesParamName); + actualChanges.put(rolesParamName, newValue); } - if (userCommand.isEmailChanged()) { - this.email = userCommand.getEmail(); + + final String usernameParamName = "username"; + if (command.isChangeInStringParameterNamed(usernameParamName, this.username)) { + final String newValue = command.stringValueOfParameterNamed(usernameParamName); + actualChanges.put(usernameParamName, newValue); + this.username = newValue; } + + final String firstnameParamName = "firstname"; + if (command.isChangeInStringParameterNamed(firstnameParamName, this.firstname)) { + final String newValue = command.stringValueOfParameterNamed(firstnameParamName); + actualChanges.put(firstnameParamName, newValue); + this.firstname = newValue; + } + + final String lastnameParamName = "lastname"; + if (command.isChangeInStringParameterNamed(lastnameParamName, this.lastname)) { + final String newValue = command.stringValueOfParameterNamed(lastnameParamName); + actualChanges.put(lastnameParamName, newValue); + this.lastname = newValue; + } + + final String emailParamName = "email"; + if (command.isChangeInStringParameterNamed(emailParamName, this.email)) { + final String newValue = command.stringValueOfParameterNamed(emailParamName); + actualChanges.put(emailParamName, newValue); + this.email = newValue; + } + + return actualChanges; + } + + private String[] getRolesAsIdStringArray() { + List roleIds = new ArrayList(); + + for (Role role : this.roles) { + roleIds.add(role.getId().toString()); + } + + return roleIds.toArray(new String[roleIds.size()]); } /** @@ -352,7 +424,7 @@ public class AppUser extends AbstractAuditableCustom implements P } return match; } - + public boolean hasIdOf(final Long userId) { return getId().equals(userId); } @@ -360,7 +432,7 @@ public class AppUser extends AbstractAuditableCustom implements P private boolean hasNotAnyPermission(final List permissions) { return !hasAnyPermission(permissions); } - + private boolean hasAnyPermission(final List permissions) { boolean hasAtLeastOneOf = false; @@ -370,7 +442,7 @@ public class AppUser extends AbstractAuditableCustom implements P break; } } - + return hasAtLeastOneOf; } diff --git a/mifosng-provider/src/main/java/org/mifosplatform/useradministration/serialization/UserCommandFromApiJsonDeserializer.java b/mifosng-provider/src/main/java/org/mifosplatform/useradministration/serialization/UserCommandFromApiJsonDeserializer.java index ff3cf9e8a..819fa5253 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/useradministration/serialization/UserCommandFromApiJsonDeserializer.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/useradministration/serialization/UserCommandFromApiJsonDeserializer.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.UserCommand; 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 UserCommand}'s. */ @Component -public final class UserCommandFromApiJsonDeserializer implements FromApiJsonDeserializer { +public final class UserCommandFromApiJsonDeserializer extends AbstractFromApiJsonDeserializer { /** * The parameters supported for this command. @@ -28,41 +32,36 @@ public final class UserCommandFromApiJsonDeserializer implements FromApiJsonDese "repeatPassword", "email", "officeId", "notSelectedRoles", "roles")); private final FromJsonHelper fromApiJsonHelper; - private final UserCommandFromCommandJsonDeserializer fromCommandJsonDeserializer; - private final CommandSerializer commandSerializerService; @Autowired - public UserCommandFromApiJsonDeserializer(final FromJsonHelper fromApiJsonHelper, - final UserCommandFromCommandJsonDeserializer fromCommandJsonDeserializer, final CommandSerializer commandSerializerService) { + public UserCommandFromApiJsonDeserializer(final FromJsonHelper fromApiJsonHelper, final CommandSerializer commandSerializerService) { + super(commandSerializerService); this.fromApiJsonHelper = fromApiJsonHelper; - this.fromCommandJsonDeserializer = fromCommandJsonDeserializer; - this.commandSerializerService = commandSerializerService; } @Override - public UserCommand commandFromApiJson(final String json) { - return commandFromApiJson(null, json); - } + public UserCommand commandFromApiJson(@SuppressWarnings("unused") final Long userId, final String json) { - @Override - public UserCommand commandFromApiJson(final Long userId, 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(userId, json); - } + final JsonElement element = fromApiJsonHelper.parse(json); - @Override - public String serializedCommandJsonFromApiJson(final String json) { - final UserCommand command = commandFromApiJson(json); - return this.commandSerializerService.serializeCommandToJson(command); - } + final String username = fromApiJsonHelper.extractStringNamed("username", element); + final String firstname = fromApiJsonHelper.extractStringNamed("firstname", element); + final String lastname = fromApiJsonHelper.extractStringNamed("lastname", element); + final String password = fromApiJsonHelper.extractStringNamed("password", element); + final String repeatPassword = fromApiJsonHelper.extractStringNamed("repeatPassword", element); + final String passwordEncoded = fromApiJsonHelper.extractStringNamed("passwordEncoded", element); + final String email = fromApiJsonHelper.extractStringNamed("email", element); + final Long officeId = fromApiJsonHelper.extractLongNamed("officeId", element); - @Override - public String serializedCommandJsonFromApiJson(final Long userId, final String json) { - final UserCommand command = commandFromApiJson(userId, json); - return this.commandSerializerService.serializeCommandToJson(command); + final String[] notSelectedRoles = fromApiJsonHelper.extractArrayNamed("notSelectedRoles", element); + final String[] roles = fromApiJsonHelper.extractArrayNamed("roles", element); + + return new UserCommand(username, firstname, lastname, password, repeatPassword, passwordEncoded, email, officeId, notSelectedRoles, roles); } } \ No newline at end of file diff --git a/mifosng-provider/src/main/java/org/mifosplatform/useradministration/serialization/UserCommandFromCommandJsonDeserializer.java b/mifosng-provider/src/main/java/org/mifosplatform/useradministration/serialization/UserCommandFromCommandJsonDeserializer.java deleted file mode 100644 index e9fdb97d3..000000000 --- a/mifosng-provider/src/main/java/org/mifosplatform/useradministration/serialization/UserCommandFromCommandJsonDeserializer.java +++ /dev/null @@ -1,61 +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.UserCommand; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Component; - -import com.google.gson.JsonElement; - -/** - * - */ -@Component -public final class UserCommandFromCommandJsonDeserializer implements FromCommandJsonDeserializer { - - private final FromJsonHelper fromJsonHelper; - - @Autowired - public UserCommandFromCommandJsonDeserializer(final FromJsonHelper fromApiJsonHelper) { - this.fromJsonHelper = fromApiJsonHelper; - } - - @Override - public UserCommand commandFromCommandJson(final String commandAsJson) { - return commandFromCommandJson(null, commandAsJson); - } - - @Override - public UserCommand commandFromCommandJson(final Long userId, final String commandAsJson) { - return commandFromCommandJson(userId, commandAsJson, false); - } - - @Override - public UserCommand commandFromCommandJson(final Long userId, 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 username = fromJsonHelper.extractStringNamed("username", element, parametersPassedInRequest); - final String firstname = fromJsonHelper.extractStringNamed("firstname", element, parametersPassedInRequest); - final String lastname = fromJsonHelper.extractStringNamed("lastname", element, parametersPassedInRequest); - final String password = fromJsonHelper.extractStringNamed("password", element, parametersPassedInRequest); - final String repeatPassword = fromJsonHelper.extractStringNamed("repeatPassword", element, parametersPassedInRequest); - final String email = fromJsonHelper.extractStringNamed("email", element, parametersPassedInRequest); - final Long officeId = fromJsonHelper.extractLongNamed("officeId", element, parametersPassedInRequest); - - final String[] notSelectedRoles = fromJsonHelper.extractArrayNamed("notSelectedRoles", element, parametersPassedInRequest); - final String[] roles = fromJsonHelper.extractArrayNamed("roles", element, parametersPassedInRequest); - - return new UserCommand(parametersPassedInRequest, makerCheckerApproval, userId, username, firstname, lastname, password, - repeatPassword, email, officeId, notSelectedRoles, roles); - } -} \ No newline at end of file diff --git a/mifosng-provider/src/main/java/org/mifosplatform/useradministration/service/AppUserWritePlatformService.java b/mifosng-provider/src/main/java/org/mifosplatform/useradministration/service/AppUserWritePlatformService.java index e2e59e1cf..430d5e839 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/useradministration/service/AppUserWritePlatformService.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/useradministration/service/AppUserWritePlatformService.java @@ -1,16 +1,17 @@ package org.mifosplatform.useradministration.service; -import org.mifosplatform.useradministration.command.UserCommand; +import org.mifosplatform.infrastructure.core.api.JsonCommand; +import org.mifosplatform.infrastructure.core.data.EntityIdentifier; public interface AppUserWritePlatformService { - Long createUser(UserCommand command); + Long createUser(JsonCommand command); - Long updateUser(UserCommand command); + EntityIdentifier updateUser(Long userId, JsonCommand command); - void deleteUser(UserCommand command); + void deleteUser(Long userId, JsonCommand command); // we dont put any permissions on this e.g. a user with no admin rights can // change their own details (email, username, password etc). - Long updateUsersOwnAccountDetails(UserCommand command); + EntityIdentifier updateUsersOwnAccountDetails(Long userId, JsonCommand command); } \ No newline at end of file diff --git a/mifosng-provider/src/main/java/org/mifosplatform/useradministration/service/AppUserWritePlatformServiceJpaRepositoryImpl.java b/mifosng-provider/src/main/java/org/mifosplatform/useradministration/service/AppUserWritePlatformServiceJpaRepositoryImpl.java index 14fa8179e..e670dde2f 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/useradministration/service/AppUserWritePlatformServiceJpaRepositoryImpl.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/useradministration/service/AppUserWritePlatformServiceJpaRepositoryImpl.java @@ -3,15 +3,15 @@ package org.mifosplatform.useradministration.service; import java.util.ArrayList; import java.util.HashSet; import java.util.List; +import java.util.Map; import java.util.Set; -import org.apache.commons.lang.StringUtils; +import org.mifosplatform.infrastructure.core.api.JsonCommand; import org.mifosplatform.infrastructure.core.data.ApiParameterError; +import org.mifosplatform.infrastructure.core.data.EntityIdentifier; import org.mifosplatform.infrastructure.core.exception.PlatformApiDataValidationException; import org.mifosplatform.infrastructure.core.exception.PlatformDataIntegrityException; import org.mifosplatform.infrastructure.core.service.PlatformEmailSendException; -import org.mifosplatform.infrastructure.security.domain.BasicPasswordEncodablePlatformUser; -import org.mifosplatform.infrastructure.security.domain.PlatformUser; import org.mifosplatform.infrastructure.security.service.PlatformPasswordEncoder; import org.mifosplatform.infrastructure.security.service.PlatformSecurityContext; import org.mifosplatform.organisation.monetary.service.ConfigurationDomainService; @@ -27,6 +27,7 @@ import org.mifosplatform.useradministration.domain.RoleRepository; import org.mifosplatform.useradministration.domain.UserDomainService; import org.mifosplatform.useradministration.exception.RoleNotFoundException; import org.mifosplatform.useradministration.exception.UserNotFoundException; +import org.mifosplatform.useradministration.serialization.UserCommandFromApiJsonDeserializer; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -47,11 +48,13 @@ public class AppUserWritePlatformServiceJpaRepositoryImpl implements AppUserWrit private final OfficeRepository officeRepository; private final RoleRepository roleRepository; private final ConfigurationDomainService configurationDomainService; + private final UserCommandFromApiJsonDeserializer fromApiJsonDeserializer; @Autowired public AppUserWritePlatformServiceJpaRepositoryImpl(final PlatformSecurityContext context, final AppUserRepository appUserRepository, final UserDomainService userDomainService, final OfficeRepository officeRepository, final RoleRepository roleRepository, - final PlatformPasswordEncoder platformPasswordEncoder, final ConfigurationDomainService configurationDomainService) { + final PlatformPasswordEncoder platformPasswordEncoder, final ConfigurationDomainService configurationDomainService, + final UserCommandFromApiJsonDeserializer fromApiJsonDeserializer) { this.context = context; this.appUserRepository = appUserRepository; this.userDomainService = userDomainService; @@ -59,29 +62,29 @@ public class AppUserWritePlatformServiceJpaRepositoryImpl implements AppUserWrit this.roleRepository = roleRepository; this.platformPasswordEncoder = platformPasswordEncoder; this.configurationDomainService = configurationDomainService; + this.fromApiJsonDeserializer = fromApiJsonDeserializer; } @Transactional @Override - public Long createUser(final UserCommand command) { + public Long createUser(final JsonCommand command) { try { context.authenticatedUser(); - command.validateForCreate(); - final Set allRoles = assembleSetOfRoles(command); + final UserCommand userCommand = this.fromApiJsonDeserializer.commandFromApiJson(command.json()); + userCommand.validateForCreate(); - final Office office = this.officeRepository.findOne(command.getOfficeId()); - if (office == null) { throw new OfficeNotFoundException(command.getOfficeId()); } + final String officeIdParamName = "officeId"; + final Long officeId = command.longValueOfParameterNamed(officeIdParamName); - String password = command.getPassword(); - if (StringUtils.isBlank(password)) { - password = "autogenerate"; - } + final Office userOffice = this.officeRepository.findOne(officeId); + if (userOffice == null) { throw new OfficeNotFoundException(officeId); } - final AppUser appUser = AppUser.createNew(office, allRoles, command.getUsername(), command.getEmail(), command.getFirstname(), - command.getLastname(), password); + final String[] roles = command.arrayValueOfParameterNamed("roles"); + final Set allRoles = assembleSetOfRoles(roles); + final AppUser appUser = AppUser.fromJson(userOffice, allRoles, command); this.userDomainService.create(appUser, command.isApprovedByChecker()); return appUser.getId(); @@ -90,8 +93,10 @@ public class AppUserWritePlatformServiceJpaRepositoryImpl implements AppUserWrit return Long.valueOf(-1); } catch (PlatformEmailSendException e) { final List dataValidationErrors = new ArrayList(); + + final String email = command.stringValueOfParameterNamed("email"); ApiParameterError error = ApiParameterError.parameterError("error.msg.user.email.invalid", "The parameter email is invalid.", - "email", command.getEmail()); + "email", email); dataValidationErrors.add(error); throw new PlatformApiDataValidationException("validation.msg.validation.errors.exist", "Validation errors exist.", @@ -101,42 +106,44 @@ public class AppUserWritePlatformServiceJpaRepositoryImpl implements AppUserWrit @Transactional @Override - public Long updateUser(final UserCommand command) { + public EntityIdentifier updateUser(final Long userId, final JsonCommand command) { try { context.authenticatedUser(); - command.validateForUpdate(); - final Set allRoles = assembleSetOfRoles(command); + final UserCommand userCommand = this.fromApiJsonDeserializer.commandFromApiJson(command.json()); + userCommand.validateForUpdate(); - Office office = null; - if (command.isOfficeChanged()) { - office = this.officeRepository.findOne(command.getOfficeId()); - if (office == null) { throw new OfficeNotFoundException(command.getOfficeId()); } + final AppUser userToUpdate = this.appUserRepository.findOne(userId); + if (userToUpdate == null) { throw new UserNotFoundException(userId); } + + final Map changes = userToUpdate.update(command, this.platformPasswordEncoder); + + if (changes.containsKey("officeId")) { + final Long officeId = (Long) changes.get("officeId"); + final Office office = this.officeRepository.findOne(officeId); + if (office == null) { throw new OfficeNotFoundException(officeId); } + + userToUpdate.changeOffice(office); } - final AppUser userToUpdate = this.appUserRepository.findOne(command.getId()); - if (userToUpdate == null) { throw new UserNotFoundException(command.getId()); } + if (changes.containsKey("roles")) { + final String[] roleIds = (String[]) changes.get("roles"); + final Set allRoles = assembleSetOfRoles(roleIds); - userToUpdate.update(allRoles, office, command); - this.appUserRepository.saveAndFlush(userToUpdate); + userToUpdate.updateRoles(allRoles); + } - if (command.isPasswordChanged()) { - PlatformUser dummyPlatformUser = new BasicPasswordEncodablePlatformUser(userToUpdate.getId(), userToUpdate.getUsername(), - command.getPassword()); - - String newPasswordEncoded = this.platformPasswordEncoder.encode(dummyPlatformUser); - - userToUpdate.updatePassword(newPasswordEncoded); - this.appUserRepository.saveAndFlush(userToUpdate); + if (!changes.isEmpty()) { + this.appUserRepository.save(userToUpdate); } if (this.configurationDomainService.isMakerCheckerEnabledForTask("UPDATE_USER") && !command.isApprovedByChecker()) { throw new RollbackTransactionAsCommandIsNotApprovedByCheckerException(); } - return userToUpdate.getId(); + return EntityIdentifier.withChanges(userId, changes); } catch (DataIntegrityViolationException dve) { handleDataIntegrityIssues(command, dve); - return Long.valueOf(-1); + return EntityIdentifier.empty(); } } @@ -147,52 +154,53 @@ public class AppUserWritePlatformServiceJpaRepositoryImpl implements AppUserWrit */ @Transactional @Override - public Long updateUsersOwnAccountDetails(final UserCommand command) { + public EntityIdentifier updateUsersOwnAccountDetails(final Long userId, final JsonCommand command) { try { context.authenticatedUser(); - command.validateForUpdate(); - final Set allRoles = assembleSetOfRoles(command); + final UserCommand userCommand = this.fromApiJsonDeserializer.commandFromApiJson(command.json()); + userCommand.validateForUpdate(); - Office office = null; - if (command.isOfficeChanged()) { - office = this.officeRepository.findOne(command.getOfficeId()); - if (office == null) { throw new OfficeNotFoundException(command.getOfficeId()); } + final AppUser userToUpdate = this.appUserRepository.findOne(userId); + if (userToUpdate == null) { throw new UserNotFoundException(userId); } + + final Map changes = userToUpdate.update(command, this.platformPasswordEncoder); + + if (changes.containsKey("officeId")) { + final Long officeId = (Long) changes.get("officeId"); + final Office office = this.officeRepository.findOne(officeId); + if (office == null) { throw new OfficeNotFoundException(officeId); } + + userToUpdate.changeOffice(office); } - final AppUser userToUpdate = this.appUserRepository.findOne(command.getId()); - if (userToUpdate == null) { throw new UserNotFoundException(command.getId()); } + if (changes.containsKey("roles")) { + final String[] roleIds = (String[]) changes.get("roles"); + final Set allRoles = assembleSetOfRoles(roleIds); - userToUpdate.update(allRoles, office, command); - this.appUserRepository.saveAndFlush(userToUpdate); + userToUpdate.updateRoles(allRoles); + } - if (command.isPasswordChanged()) { - PlatformUser dummyPlatformUser = new BasicPasswordEncodablePlatformUser(userToUpdate.getId(), userToUpdate.getUsername(), - command.getPassword()); - - String newPasswordEncoded = this.platformPasswordEncoder.encode(dummyPlatformUser); - - userToUpdate.updatePassword(newPasswordEncoded); + if (!changes.isEmpty()) { this.appUserRepository.saveAndFlush(userToUpdate); } - return userToUpdate.getId(); + return EntityIdentifier.withChanges(userId, changes); } catch (DataIntegrityViolationException dve) { handleDataIntegrityIssues(command, dve); - return Long.valueOf(-1); + return EntityIdentifier.empty(); } } - private Set assembleSetOfRoles(final UserCommand command) { + private Set assembleSetOfRoles(final String[] rolesArray) { final Set allRoles = new HashSet(); - String[] rolesArray = command.getRoles(); - if (command.isRolesChanged() && !ObjectUtils.isEmpty(rolesArray)) { + if (!ObjectUtils.isEmpty(rolesArray)) { for (String roleId : rolesArray) { - Long id = Long.valueOf(roleId); - Role role = this.roleRepository.findOne(id); + final Long id = Long.valueOf(roleId); + final Role role = this.roleRepository.findOne(id); if (role == null) { throw new RoleNotFoundException(id); } allRoles.add(role); } @@ -203,10 +211,9 @@ public class AppUserWritePlatformServiceJpaRepositoryImpl implements AppUserWrit @Transactional @Override - public void deleteUser(final UserCommand command) { + public void deleteUser(final Long userId, final JsonCommand command) { - final Long userId = command.getId(); - AppUser user = this.appUserRepository.findOne(userId); + final AppUser user = this.appUserRepository.findOne(userId); if (user == null || user.isDeleted()) { throw new UserNotFoundException(userId); } user.delete(); @@ -219,14 +226,14 @@ public class AppUserWritePlatformServiceJpaRepositoryImpl implements AppUserWrit * Guaranteed to throw an exception no matter what the data integrity issue * is. */ - private void handleDataIntegrityIssues(final UserCommand command, final DataIntegrityViolationException dve) { + private void handleDataIntegrityIssues(final JsonCommand command, final DataIntegrityViolationException dve) { Throwable realCause = dve.getMostSpecificCause(); if (realCause.getMessage().contains("username_org")) { - StringBuilder defaultMessageBuilder = new StringBuilder("User with username ").append(command.getUsername()).append( - " already exists."); + final String username = command.stringValueOfParameterNamed("username"); + StringBuilder defaultMessageBuilder = new StringBuilder("User with username ").append(username).append(" already exists."); throw new PlatformDataIntegrityException("error.msg.user.duplicate.username", defaultMessageBuilder.toString(), "username", - command.getUsername()); + username); } logger.error(dve.getMessage(), dve);