diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/api/commands/UserCommand.java b/mifosng-provider/src/main/java/org/mifosng/platform/api/commands/UserCommand.java index 8bf02eb94..9b7571e53 100644 --- a/mifosng-provider/src/main/java/org/mifosng/platform/api/commands/UserCommand.java +++ b/mifosng-provider/src/main/java/org/mifosng/platform/api/commands/UserCommand.java @@ -86,4 +86,28 @@ public class UserCommand implements Serializable { 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"); + } + + public boolean isOfficeChanged() { + return this.modifiedParameters.contains("officeId"); + } + + public boolean isRolesChanged() { + return this.modifiedParameters.contains("roles"); + } } \ No newline at end of file diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/api/errorhandling/JsonSyntaxExceptionMapper.java b/mifosng-provider/src/main/java/org/mifosng/platform/api/errorhandling/JsonSyntaxExceptionMapper.java new file mode 100644 index 000000000..0d372ac3f --- /dev/null +++ b/mifosng-provider/src/main/java/org/mifosng/platform/api/errorhandling/JsonSyntaxExceptionMapper.java @@ -0,0 +1,33 @@ +package org.mifosng.platform.api.errorhandling; + +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.Response.Status; +import javax.ws.rs.ext.ExceptionMapper; +import javax.ws.rs.ext.Provider; + +import org.mifosng.platform.api.data.ApiParameterError; +import org.springframework.context.annotation.Scope; +import org.springframework.stereotype.Component; + +import com.google.gson.JsonSyntaxException; + +/** + * An {@link ExceptionMapper} to map {@link JsonSyntaxException} thrown by platform into a HTTP API friendly format. + */ +@Provider +@Component +@Scope("singleton") +public class JsonSyntaxExceptionMapper implements ExceptionMapper { + + @Override + public Response toResponse(final JsonSyntaxException exception) { + + String globalisationMessageCode = "error.msg.invalid.request.body"; + String defaultUserMessage = "The JSON syntax provided in the body of the request is invalid: " + exception.getMessage(); + + ApiParameterError error = ApiParameterError.generalError(globalisationMessageCode, defaultUserMessage); + + return Response.status(Status.BAD_REQUEST).entity(error).type(MediaType.APPLICATION_JSON).build(); + } +} \ No newline at end of file diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/organisation/domain/Office.java b/mifosng-provider/src/main/java/org/mifosng/platform/organisation/domain/Office.java index 84a1fe300..537348250 100644 --- a/mifosng-provider/src/main/java/org/mifosng/platform/organisation/domain/Office.java +++ b/mifosng-provider/src/main/java/org/mifosng/platform/organisation/domain/Office.java @@ -49,7 +49,8 @@ public class Office extends AbstractAuditableCustom { @Temporal(TemporalType.DATE) private Date openingDate; - @Column(name = "external_id", length=100) + @SuppressWarnings("unused") + @Column(name = "external_id", length=100) private String externalId; public static Office headOffice(final String name, final LocalDate openingDate, final String externalId) { @@ -67,7 +68,7 @@ public class Office extends AbstractAuditableCustom { this.externalId = null; } - public Office(final Office parent, final String name, final LocalDate openingDate, final String externalId) { + private Office(final Office parent, final String name, final LocalDate openingDate, final String externalId) { this.parent = parent; this.openingDate = openingDate.toDateMidnight().toDate(); if (parent != null) { @@ -90,14 +91,6 @@ public class Office extends AbstractAuditableCustom { this.children.add(office); } - public String getName() { - return this.name; - } - - public boolean isHeadOffice() { - return this.parent == null; - } - public void update(final OfficeCommand command) { if (command.isNameChanged()) { @@ -131,15 +124,44 @@ public class Office extends AbstractAuditableCustom { generateHierarchy(); } - public boolean identifiedBy(String identifier) { - return identifier.equalsIgnoreCase(this.name) || identifier.equalsIgnoreCase(this.externalId); - } - public boolean identifiedBy(final Long id) { return getId().equals(id); } - public boolean hasAnOfficeInHierarchyWithId(Long officeId) { + public void generateHierarchy() { + + if (parent != null) { + this.hierarchy = this.parent.hierarchyOf(this.getId()); + } else { + this.hierarchy = "."; + } + } + + private String hierarchyOf(Long id) { + return this.hierarchy + id.toString() + "."; + } + + public String getName() { + return this.name; + } + + public String getHierarchy() { + return hierarchy; + } + + public boolean hasParentOf(final Office office) { + boolean isParent = false; + if (this.parent != null) { + isParent = this.parent.equals(office); + } + return isParent; + } + + public boolean doesNotHaveAnOfficeInHierarchyWithId(Long officeId) { + return !this.hasAnOfficeInHierarchyWithId(officeId); + } + + private boolean hasAnOfficeInHierarchyWithId(Long officeId) { boolean match = false; @@ -160,33 +182,4 @@ public class Office extends AbstractAuditableCustom { return match; } - - public boolean doesNotHaveAnOfficeInHierarchyWithId(Long officeId) { - return !this.hasAnOfficeInHierarchyWithId(officeId); - } - - public void generateHierarchy() { - - if (parent != null) { - this.hierarchy = this.parent.hierarchyOf(this.getId()); - } else { - this.hierarchy = "."; - } - } - - private String hierarchyOf(Long id) { - return this.hierarchy + id.toString() + "."; - } - - public String getHierarchy() { - return hierarchy; - } - - public boolean hasParentOf(final Office office) { - boolean isParent = false; - if (this.parent != null) { - isParent = this.parent.equals(office); - } - return isParent; - } } \ No newline at end of file diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/user/domain/AppUser.java b/mifosng-provider/src/main/java/org/mifosng/platform/user/domain/AppUser.java index b6087cfb7..a81ed2b5e 100644 --- a/mifosng-provider/src/main/java/org/mifosng/platform/user/domain/AppUser.java +++ b/mifosng-provider/src/main/java/org/mifosng/platform/user/domain/AppUser.java @@ -16,6 +16,7 @@ import javax.persistence.ManyToOne; import javax.persistence.Table; import javax.persistence.UniqueConstraint; +import org.mifosng.platform.api.commands.UserCommand; import org.mifosng.platform.infrastructure.AbstractAuditableCustom; import org.mifosng.platform.infrastructure.PlatformUser; import org.mifosng.platform.organisation.domain.Office; @@ -138,6 +139,29 @@ public class AppUser extends AbstractAuditableCustom implements P public void updatePassword(final String encodePassword) { this.password = encodePassword; } + + public void update(final Set allRoles, final Office office, final UserCommand userCommand) { + + if (userCommand.isRolesChanged() && !allRoles.isEmpty()) { + this.roles.clear(); + this.roles = allRoles; + } + if (userCommand.isOfficeChanged()) { + this.office = office; + } + if (userCommand.isUsernameChanged()) { + this.username = userCommand.getUsername(); + } + if (userCommand.isFirstnameChanged()) { + this.firstname = userCommand.getFirstname(); + } + if (userCommand.isLastnameChanged()) { + this.lastname = userCommand.getLastname(); + } + if (userCommand.isEmailChanged()) { + this.email = userCommand.getEmail(); + } + } @Override public Collection getAuthorities() { @@ -184,6 +208,14 @@ public class AppUser extends AbstractAuditableCustom implements P public boolean isEnabled() { return this.enabled; } + + public String getFirstname() { + return firstname; + } + + public String getLastname() { + return lastname; + } public String getEmail() { return this.email; @@ -193,97 +225,10 @@ public class AppUser extends AbstractAuditableCustom implements P return this.roles; } - public String getRoleNames() { - StringBuilder roleNames = new StringBuilder(); - - for (Role role : this.roles) { - roleNames.append(role.toData().getName()).append(' '); - } - - return roleNames.toString(); - } - - public void setUserIdAs(final Long id) { - this.setId(id); - } - public Office getOffice() { return this.office; } - public boolean isHeadOfficeUser() { - boolean headOfficeUser = false; - if (this.office != null) { - headOfficeUser = this.office.isHeadOffice(); - } - return headOfficeUser; - } - - public boolean hasPermissionTo(final String permissionCode) { - boolean match = false; - for (Role role : this.roles) { - if (role.hasPermissionTo(permissionCode)) { - match = true; - break; - } - } - - return match; - } - - public boolean hasNotPermissionForAnyOf(final String... permissionCodes) { - boolean hasNotPermission = true; - for (String permissionCode : permissionCodes) { - boolean checkPermission = this.hasPermissionTo(permissionCode); - if (checkPermission) { - hasNotPermission = false; - break; - } - } - return hasNotPermission; - } - - public boolean hasNotPermissionTo(final String permissionCode) { - return !this.hasPermissionTo(permissionCode); - } - - public boolean canAccess(Long officeId) { - return this.office.hasAnOfficeInHierarchyWithId(officeId); - } - - public String getFirstname() { - return firstname; - } - - public String getLastname() { - return lastname; - } - - /** - * When updating details, any parameters with null values are ignored. - */ - public void update(Set allRoles, Office office, String username, String firstname, String lastname, String email) { - if (!allRoles.isEmpty()) { - this.roles.clear(); - this.roles = allRoles; - } - if (office != null) { - this.office = office; - } - if (username != null) { - this.username = username; - } - if (firstname != null) { - this.firstname = firstname; - } - if (lastname != null) { - this.lastname = lastname; - } - if (email != null) { - this.email = email; - } - } - public boolean canNotApproveLoanInPast() { return hasNotPermissionForAnyOf("CAN_APPROVE_LOAN_IN_THE_PAST_ROLE", "PORTFOLIO_MANAGEMENT_SUPER_USER_ROLE"); } @@ -303,4 +248,28 @@ public class AppUser extends AbstractAuditableCustom implements P public boolean canNotMakeRepaymentOnLoanInPast() { return hasNotPermissionForAnyOf("CAN_MAKE_LOAN_REPAYMENT_IN_THE_PAST_ROLE", "PORTFOLIO_MANAGEMENT_SUPER_USER_ROLE"); } + + public boolean hasNotPermissionForAnyOf(final String... permissionCodes) { + boolean hasNotPermission = true; + for (String permissionCode : permissionCodes) { + boolean checkPermission = this.hasPermissionTo(permissionCode); + if (checkPermission) { + hasNotPermission = false; + break; + } + } + return hasNotPermission; + } + + private boolean hasPermissionTo(final String permissionCode) { + boolean match = false; + for (Role role : this.roles) { + if (role.hasPermissionTo(permissionCode)) { + match = true; + break; + } + } + + return match; + } } \ No newline at end of file diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/user/domain/Role.java b/mifosng-provider/src/main/java/org/mifosng/platform/user/domain/Role.java index 177efddd7..4556a9719 100644 --- a/mifosng-provider/src/main/java/org/mifosng/platform/user/domain/Role.java +++ b/mifosng-provider/src/main/java/org/mifosng/platform/user/domain/Role.java @@ -74,7 +74,7 @@ public class Role extends AbstractAuditableCustom { return data; } - public void update(final RoleCommand command, List selectedPermissions) { + public void update(final RoleCommand command, final List selectedPermissions) { if (command.isNameChanged()) { this.name = command.getName(); } diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/user/service/AppUserWritePlatformServiceJpaRepositoryImpl.java b/mifosng-provider/src/main/java/org/mifosng/platform/user/service/AppUserWritePlatformServiceJpaRepositoryImpl.java index 3dbe45ba8..fc755dec6 100644 --- a/mifosng-provider/src/main/java/org/mifosng/platform/user/service/AppUserWritePlatformServiceJpaRepositoryImpl.java +++ b/mifosng-provider/src/main/java/org/mifosng/platform/user/service/AppUserWritePlatformServiceJpaRepositoryImpl.java @@ -67,7 +67,7 @@ public class AppUserWritePlatformServiceJpaRepositoryImpl implements AppUserWrit UserCommandValidator validator = new UserCommandValidator(command); validator.validateForCreate(); - Set allRoles = assembleSetOfRoles(command.getRoles()); + final Set allRoles = assembleSetOfRoles(command); Office office = this.officeRepository.findOne(command.getOfficeId()); if (office == null) { @@ -101,7 +101,7 @@ public class AppUserWritePlatformServiceJpaRepositoryImpl implements AppUserWrit @Transactional @Override - public Long updateUser(UserCommand command) { + public Long updateUser(final UserCommand command) { try { context.authenticatedUser(); @@ -109,10 +109,10 @@ public class AppUserWritePlatformServiceJpaRepositoryImpl implements AppUserWrit UserCommandValidator validator = new UserCommandValidator(command); validator.validateForUpdate(); - Set allRoles = assembleSetOfRoles(command.getRoles()); + final Set allRoles = assembleSetOfRoles(command); Office office = null; - if (command.getOfficeId() != null) { + if (command.isOfficeChanged()) { office = this.officeRepository.findOne(command.getOfficeId()); if (office == null) { throw new OfficeNotFoundException(command.getOfficeId()); @@ -124,7 +124,7 @@ public class AppUserWritePlatformServiceJpaRepositoryImpl implements AppUserWrit throw new UserNotFoundException(command.getId()); } - userToUpdate.update(allRoles, office, command.getUsername(), command.getFirstname(), command.getLastname(), command.getEmail()); + userToUpdate.update(allRoles, office, command); this.appUserRepository.saveAndFlush(userToUpdate); if (command.getPassword() != null || command.getRepeatPassword() != null) { @@ -145,9 +145,12 @@ public class AppUserWritePlatformServiceJpaRepositoryImpl implements AppUserWrit } } - private Set assembleSetOfRoles(final String[] rolesArray) { - Set allRoles = new HashSet(); - if (!ObjectUtils.isEmpty(rolesArray)) { + private Set assembleSetOfRoles(final UserCommand command) { + + final Set allRoles = new HashSet(); + + String[] rolesArray = command.getRoles(); + if (command.isRolesChanged() && !ObjectUtils.isEmpty(rolesArray)) { for (String roleId : rolesArray) { Long id = Long.valueOf(roleId); Role role = this.roleRepository.findOne(id); @@ -157,6 +160,7 @@ public class AppUserWritePlatformServiceJpaRepositoryImpl implements AppUserWrit allRoles.add(role); } } + return allRoles; }