diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/domain/SavingsProduct.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/domain/SavingsProduct.java index 2f9da549c..577ce2edb 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/domain/SavingsProduct.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/domain/SavingsProduct.java @@ -73,7 +73,7 @@ public class SavingsProduct extends AbstractPersistable { /** * The interest period is the span of time at the end of which savings in a * client's account earn interest. - * + * * A value from the {@link SavingsCompoundingInterestPeriodType} * enumeration. */ @@ -119,9 +119,8 @@ public class SavingsProduct extends AbstractPersistable { @Column(name = "withdrawal_fee_type_enum", nullable = true) private Integer withdrawalFeeType; - + @Column(name = "withdrawal_fee_for_transfer") - @SuppressWarnings("unused") private boolean withdrawalFeeApplicableForTransfer; @Column(name = "annual_fee_amount", scale = 6, precision = 19, nullable = true) @@ -138,12 +137,12 @@ public class SavingsProduct extends AbstractPersistable { final SavingsPostingInterestPeriodType interestPostingPeriodType, final SavingsInterestCalculationType interestCalculationType, final SavingsInterestCalculationDaysInYearType interestCalculationDaysInYearType, final BigDecimal minRequiredOpeningBalance, final Integer lockinPeriodFrequency, final SavingsPeriodFrequencyType lockinPeriodFrequencyType, - final BigDecimal withdrawalFeeAmount, final SavingsWithdrawalFeesType withdrawalFeeType, boolean withdrawalFeeApplicableForTransfer, + final BigDecimal withdrawalFeeAmount, final SavingsWithdrawalFeesType withdrawalFeeType, final boolean withdrawalFeeApplicableForTransfer, final BigDecimal annualFeeAmount, final MonthDay annualFeeOnMonthDay, final AccountingRuleType accountingRuleType) { return new SavingsProduct(name, description, currency, interestRate, interestCompoundingPeriodType, interestPostingPeriodType, interestCalculationType, interestCalculationDaysInYearType, minRequiredOpeningBalance, lockinPeriodFrequency, - lockinPeriodFrequencyType, withdrawalFeeAmount, withdrawalFeeType,withdrawalFeeApplicableForTransfer, annualFeeAmount, + lockinPeriodFrequencyType, withdrawalFeeAmount, withdrawalFeeType,withdrawalFeeApplicableForTransfer, annualFeeAmount, annualFeeOnMonthDay, accountingRuleType); } @@ -376,7 +375,7 @@ public class SavingsProduct extends AbstractPersistable { actualChanges.put(withdrawalFeeTypeParamName, newValue); this.withdrawalFeeType = newValue != null ? SavingsWithdrawalFeesType.fromInt(newValue).getValue() : newValue; } - + if(command.isChangeInBooleanParameterNamed(withdrawalFeeForTransfersParamName, this.withdrawalFeeApplicableForTransfer)){ final boolean newValue = command.booleanPrimitiveValueOfParameterNamed(withdrawalFeeForTransfersParamName); actualChanges.put(withdrawalFeeForTransfersParamName, newValue); @@ -484,16 +483,16 @@ public class SavingsProduct extends AbstractPersistable { .resource(SAVINGS_PRODUCT_RESOURCE_NAME); if (this.lockinPeriodFrequency == null) { - baseDataValidator.reset().parameter(lockinPeriodFrequencyTypeParamName).value(lockinPeriodFrequencyType).ignoreIfNull() + baseDataValidator.reset().parameter(lockinPeriodFrequencyTypeParamName).value(this.lockinPeriodFrequencyType).ignoreIfNull() .inMinMaxRange(0, 3); if (this.lockinPeriodFrequencyType != null) { - baseDataValidator.reset().parameter(lockinPeriodFrequencyParamName).value(lockinPeriodFrequency).notNull() + baseDataValidator.reset().parameter(lockinPeriodFrequencyParamName).value(this.lockinPeriodFrequency).notNull() .integerZeroOrGreater(); } } else { - baseDataValidator.reset().parameter(lockinPeriodFrequencyParamName).value(lockinPeriodFrequencyType).integerZeroOrGreater(); - baseDataValidator.reset().parameter(lockinPeriodFrequencyTypeParamName).value(lockinPeriodFrequencyType).notNull() + baseDataValidator.reset().parameter(lockinPeriodFrequencyParamName).value(this.lockinPeriodFrequencyType).integerZeroOrGreater(); + baseDataValidator.reset().parameter(lockinPeriodFrequencyTypeParamName).value(this.lockinPeriodFrequencyType).notNull() .inMinMaxRange(0, 3); } 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 f23fa8c3a..432201399 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 @@ -75,25 +75,25 @@ public class UsersApiResource { @GET @Consumes({ MediaType.APPLICATION_JSON }) @Produces({ MediaType.APPLICATION_JSON }) - public String retrieveUsers(@Context final UriInfo uriInfo) { + public String retrieveAll(@Context final UriInfo uriInfo) { - context.authenticatedUser().validateHasReadPermission(resourceNameForPermissions); + this.context.authenticatedUser().validateHasReadPermission(this.resourceNameForPermissions); final Collection users = this.readPlatformService.retrieveAllUsers(); - final ApiRequestJsonSerializationSettings settings = apiRequestParameterHelper.process(uriInfo.getQueryParameters()); - return this.toApiJsonSerializer.serialize(settings, users, RESPONSE_DATA_PARAMETERS); + final ApiRequestJsonSerializationSettings settings = this.apiRequestParameterHelper.process(uriInfo.getQueryParameters()); + return this.toApiJsonSerializer.serialize(settings, users, this.RESPONSE_DATA_PARAMETERS); } @GET @Path("{userId}") @Consumes({ MediaType.APPLICATION_JSON }) @Produces({ MediaType.APPLICATION_JSON }) - public String retrieveUser(@PathParam("userId") final Long userId, @Context final UriInfo uriInfo) { + public String retrieveOne(@PathParam("userId") final Long userId, @Context final UriInfo uriInfo) { - context.authenticatedUser().validateHasReadPermission(resourceNameForPermissions); + this.context.authenticatedUser().validateHasReadPermission(this.resourceNameForPermissions, userId); - final ApiRequestJsonSerializationSettings settings = apiRequestParameterHelper.process(uriInfo.getQueryParameters()); + final ApiRequestJsonSerializationSettings settings = this.apiRequestParameterHelper.process(uriInfo.getQueryParameters()); AppUserData user = this.readPlatformService.retrieveUser(userId); if (settings.isTemplate()) { @@ -101,27 +101,27 @@ public class UsersApiResource { user = AppUserData.template(user, offices); } - return this.toApiJsonSerializer.serialize(settings, user, RESPONSE_DATA_PARAMETERS); + return this.toApiJsonSerializer.serialize(settings, user, this.RESPONSE_DATA_PARAMETERS); } @GET @Path("template") @Consumes({ MediaType.APPLICATION_JSON }) @Produces({ MediaType.APPLICATION_JSON }) - public String newUserDetails(@Context final UriInfo uriInfo) { + public String template(@Context final UriInfo uriInfo) { - context.authenticatedUser().validateHasReadPermission(resourceNameForPermissions); + this.context.authenticatedUser().validateHasReadPermission(this.resourceNameForPermissions); final AppUserData user = this.readPlatformService.retrieveNewUserDetails(); - final ApiRequestJsonSerializationSettings settings = apiRequestParameterHelper.process(uriInfo.getQueryParameters()); - return this.toApiJsonSerializer.serialize(settings, user, RESPONSE_DATA_PARAMETERS); + final ApiRequestJsonSerializationSettings settings = this.apiRequestParameterHelper.process(uriInfo.getQueryParameters()); + return this.toApiJsonSerializer.serialize(settings, user, this.RESPONSE_DATA_PARAMETERS); } @POST @Consumes({ MediaType.APPLICATION_JSON }) @Produces({ MediaType.APPLICATION_JSON }) - public String createUser(final String apiRequestBodyAsJson) { + public String create(final String apiRequestBodyAsJson) { final CommandWrapper commandRequest = new CommandWrapperBuilder() // .createUser() // @@ -137,7 +137,7 @@ public class UsersApiResource { @Path("{userId}") @Consumes({ MediaType.APPLICATION_JSON }) @Produces({ MediaType.APPLICATION_JSON }) - public String updateUser(@PathParam("userId") final Long userId, final String apiRequestBodyAsJson) { + public String update(@PathParam("userId") final Long userId, final String apiRequestBodyAsJson) { final CommandWrapper commandRequest = new CommandWrapperBuilder() // .updateUser(userId) // @@ -153,7 +153,7 @@ public class UsersApiResource { @Path("{userId}") @Consumes({ MediaType.APPLICATION_JSON }) @Produces({ MediaType.APPLICATION_JSON }) - public String deleteUser(@PathParam("userId") final Long userId) { + public String delete(@PathParam("userId") final Long userId) { final CommandWrapper commandRequest = new CommandWrapperBuilder() // .deleteUser(userId) // 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 26feeae57..4e1e6f55b 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 @@ -42,491 +42,452 @@ import org.springframework.security.core.userdetails.User; @Table(name = "m_appuser", uniqueConstraints = @UniqueConstraint(columnNames = { "username" }, name = "username_org")) public class AppUser extends AbstractPersistable implements PlatformUser { - private final static Logger logger = LoggerFactory.getLogger(AppUser.class); - - @Column(name = "email", nullable = false, length = 100) - private String email; - - @Column(name = "username", nullable = false, length = 100) - private String username; - - @Column(name = "firstname", nullable = false, length = 100) - private String firstname; - - @Column(name = "lastname", nullable = false, length = 100) - private String lastname; - - @Column(name = "password", nullable = false) - private String password; - - @Column(name = "nonexpired", nullable = false) - private boolean accountNonExpired; - - @Column(name = "nonlocked", nullable = false) - private final boolean accountNonLocked; - - @Column(name = "nonexpired_credentials", nullable = false) - private final boolean credentialsNonExpired; - - @Column(name = "enabled", nullable = false) - private boolean enabled; - - @Column(name = "firsttime_login_remaining", nullable = false) - private boolean firstTimeLoginRemaining; - - @Column(name = "is_deleted", nullable = false) - private boolean deleted; - - @ManyToOne - @JoinColumn(name = "office_id", nullable = false) - private Office office; - - @ManyToOne - @JoinColumn(name = "staff_id", nullable = true) - private Staff staff; - - @ManyToMany(fetch = FetchType.EAGER) - @JoinTable(name = "m_appuser_role", joinColumns = @JoinColumn(name = "appuser_id"), inverseJoinColumns = @JoinColumn(name = "role_id")) - private Set roles; - - public static AppUser fromJson(final Office userOffice, - final Set allRoles, final JsonCommand command) { - - final String username = command.stringValueOfParameterNamed("username"); - String password = command.stringValueOfParameterNamed("password"); - final Boolean sendPasswordToEmail = command - .booleanObjectValueOfParameterNamed("sendPasswordToEmail"); - - if (sendPasswordToEmail.booleanValue()) { - password = new RandomPasswordGenerator(13).generate(); - } - - final boolean userEnabled = true; - final boolean userAccountNonExpired = true; - final boolean userCredentialsNonExpired = true; - final boolean userAccountNonLocked = true; - - final Collection authorities = new ArrayList(); - authorities.add(new SimpleGrantedAuthority( - "DUMMY_ROLE_NOT_USED_OR_PERSISTED_TO_AVOID_EXCEPTION")); - - final User user = new User(username, password, userEnabled, - userAccountNonExpired, userCredentialsNonExpired, - userAccountNonLocked, authorities); - - 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.accountNonLocked = false; - this.credentialsNonExpired = false; - this.roles = new HashSet(); - } - - public AppUser(final Office office, final User user, final Set roles, - final String email, final String firstname, final String lastname) { - this.office = office; - this.email = email.trim(); - this.username = user.getUsername().trim(); - this.firstname = firstname.trim(); - this.lastname = lastname.trim(); - this.password = user.getPassword().trim(); - this.accountNonExpired = user.isAccountNonExpired(); - this.accountNonLocked = user.isAccountNonLocked(); - this.credentialsNonExpired = user.isCredentialsNonExpired(); - this.enabled = user.isEnabled(); - this.roles = roles; - this.firstTimeLoginRemaining = true; - } - - public EnumOptionData organisationalRoleData() { - EnumOptionData organisationalRole = null; - if (this.staff != null) { - organisationalRole = this.staff.organisationalRoleData(); - } - return organisationalRole; - } - - public void updatePassword(final String encodePassword) { - this.password = encodePassword; - this.firstTimeLoginRemaining = false; - } - - public void changeOffice(final Office differentOffice) { - this.office = differentOffice; - } - - public void updateRoles(final Set allRoles) { - if (!allRoles.isEmpty()) { - this.roles.clear(); - this.roles = allRoles; - } - } - - 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, getId())) { - final String passwordEncodedValue = command - .passwordValueOfParameterNamed(passwordParamName, - platformPasswordEncoder, getId()); - actualChanges.put(passwordEncodedParamName, - passwordEncodedValue); - updatePassword(passwordEncodedValue); - } - } - - if (command.hasParameter(passwordEncodedParamName)) { - if (command.isChangeInStringParameterNamed( - passwordEncodedParamName, this.password)) { - final String newValue = command - .stringValueOfParameterNamed(passwordEncodedParamName); - actualChanges.put(passwordEncodedParamName, newValue); - updatePassword(newValue); - } - } - - final String officeIdParamName = "officeId"; - if (command.isChangeInLongParameterNamed(officeIdParamName, - this.office.getId())) { - final Long newValue = command - .longValueOfParameterNamed(officeIdParamName); - actualChanges.put(officeIdParamName, newValue); - } - - final String rolesParamName = "roles"; - if (command.isChangeInArrayParameterNamed(rolesParamName, - getRolesAsIdStringArray())) { - final String[] newValue = command - .arrayValueOfParameterNamed(rolesParamName); - actualChanges.put(rolesParamName, newValue); - } - - 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() { - final List roleIds = new ArrayList(); - - for (final Role role : this.roles) { - roleIds.add(role.getId().toString()); - } - - return roleIds.toArray(new String[roleIds.size()]); - } - - /** - * Delete is a soft delete. Updates flag so it wont appear in - * query/report results. - * - * Any fields with unique constraints and prepended with id of record. - */ - public void delete() { - this.deleted = true; - this.enabled = false; - this.accountNonExpired = false; - this.firstTimeLoginRemaining = true; - this.username = getId() + "_DELETED_" + this.username; - } - - public boolean isDeleted() { - return this.deleted; - } - - @Override - public Collection getAuthorities() { - return populateGrantedAuthorities(); - } - - private List populateGrantedAuthorities() { - final List grantedAuthorities = new ArrayList(); - for (final Role role : this.roles) { - final Collection permissions = role.getPermissions(); - for (final Permission permission : permissions) { - grantedAuthorities.add(new SimpleGrantedAuthority(permission - .getCode())); - } - } - return grantedAuthorities; - } - - @Override - public String getPassword() { - return this.password; - } - - @Override - public String getUsername() { - return this.username; - } - - @Override - public boolean isAccountNonExpired() { - return this.accountNonExpired; - } - - @Override - public boolean isAccountNonLocked() { - return this.accountNonLocked; - } - - @Override - public boolean isCredentialsNonExpired() { - return this.credentialsNonExpired; - } - - @Override - public boolean isEnabled() { - return this.enabled; - } - - public String getFirstname() { - return this.firstname; - } - - public String getLastname() { - return this.lastname; - } - - public String getEmail() { - return this.email; - } - - public Set getRoles() { - return this.roles; - } - - public Office getOffice() { - return this.office; - } - - public boolean canNotApproveLoanInPast() { - return hasNotPermissionForAnyOf("ALL_FUNCTIONS", "APPROVEINPAST_LOAN"); - } - - public boolean canNotRejectLoanInPast() { - return hasNotPermissionForAnyOf("ALL_FUNCTIONS", "REJECTINPAST_LOAN"); - } - - public boolean canNotWithdrawByClientLoanInPast() { - return hasNotPermissionForAnyOf("ALL_FUNCTIONS", "WITHDRAWINPAST_LOAN"); - } - - public boolean canNotDisburseLoanInPast() { - return hasNotPermissionForAnyOf("ALL_FUNCTIONS", "DISBURSEINPAST_LOAN"); - } - - public boolean canNotMakeRepaymentOnLoanInPast() { - return hasNotPermissionForAnyOf("ALL_FUNCTIONS", "REPAYMENTINPAST_LOAN"); - } - - public boolean hasNotPermissionForReport(final String reportName) { - - if (hasNotPermissionForAnyOf("ALL_FUNCTIONS", "ALL_FUNCTIONS_READ", - "REPORTING_SUPER_USER", "READ_" + reportName)) { - return true; - } - - return false; - } - - public boolean hasNotPermissionForDatatable(final String datatable, - final String accessType) { - - final String matchPermission = accessType + "_" + datatable; - - if (accessType.equalsIgnoreCase("READ")) { - - if (hasNotPermissionForAnyOf("ALL_FUNCTIONS", "ALL_FUNCTIONS_READ", - matchPermission)) { - return true; - } - - return false; - } - - if (hasNotPermissionForAnyOf("ALL_FUNCTIONS", matchPermission)) { - return true; - } - - return false; - } - - public boolean hasNotPermissionForAnyOf(final String... permissionCodes) { - boolean hasNotPermission = true; - for (final String permissionCode : permissionCodes) { - final boolean checkPermission = hasPermissionTo(permissionCode); - if (checkPermission) { - hasNotPermission = false; - break; - } - } - return hasNotPermission; - } - - public void validateHasReadPermission(final String resourceType) { - - final String authorizationMessage = "User has no authority to view " - + resourceType.toLowerCase() + "s"; - final String matchPermission = "READ_" + resourceType.toUpperCase(); - - if (!hasNotPermissionForAnyOf("ALL_FUNCTIONS", "ALL_FUNCTIONS_READ", - matchPermission)) { - return; - } - - throw new NoAuthorizationException(authorizationMessage); - } - - private boolean hasNotPermissionTo(final String permissionCode) { - return !hasPermissionTo(permissionCode); - } - - private boolean hasPermissionTo(final String permissionCode) { - boolean hasPermission = hasAllFunctionsPermission(); - if (!hasPermission) { - for (final Role role : this.roles) { - if (role.hasPermissionTo(permissionCode)) { - hasPermission = true; - break; - } - } - } - return hasPermission; - } - - private boolean hasAllFunctionsPermission() { - boolean match = false; - for (final Role role : this.roles) { - if (role.hasPermissionTo("ALL_FUNCTIONS")) { - match = true; - break; - } - } - return match; - } - - public boolean hasIdOf(final Long userId) { - return getId().equals(userId); - } - - private boolean hasNotAnyPermission(final List permissions) { - return !hasAnyPermission(permissions); - } - - private boolean hasAnyPermission(final List permissions) { - boolean hasAtLeastOneOf = false; - - for (final String permissionCode : permissions) { - if (hasPermissionTo(permissionCode)) { - hasAtLeastOneOf = true; - break; - } - } - - return hasAtLeastOneOf; - } - - public void validateHasPermissionTo(final String function, - final List allowedPermissions) { - if (hasNotAnyPermission(allowedPermissions)) { - final String authorizationMessage = "User has no authority to: " - + function; - throw new NoAuthorizationException(authorizationMessage); - } - } - - public void validateHasPermissionTo(final String function) { - if (hasNotPermissionTo(function)) { - final String authorizationMessage = "User has no authority to: " - + function; - logger.info("Unauthorized access: userId: " + getId() + " action: " - + function + " allowed: " + getAuthorities()); - throw new NoAuthorizationException(authorizationMessage); - } - } - - public void validateHasCheckerPermissionTo(final String function) { - - final String checkerPermissionName = function.toUpperCase() - + "_CHECKER"; - if (hasNotPermissionTo("CHECKER_SUPER_USER") - && hasNotPermissionTo(checkerPermissionName)) { - final String authorizationMessage = "User has no authority to be a checker for: " - + function; - throw new NoAuthorizationException(authorizationMessage); - } - } - - public void validateHasDatatableReadPermission(final String datatable) { - if (hasNotPermissionForDatatable(datatable, "READ")) { - throw new NoAuthorizationException( - "Not authorised to read datatable: " + datatable); - } - } - - public Long getStaffId() { - Long staffId = null; - if (this.staff != null) { - staffId = this.staff.getId(); - } - return staffId; - } - - public String getStaffDisplayName() { - String staffDisplayName = null; - if (this.staff != null) { - staffDisplayName = this.staff.displayName(); - } - return staffDisplayName; - } + private final static Logger logger = LoggerFactory.getLogger(AppUser.class); + + @Column(name = "email", nullable = false, length = 100) + private String email; + + @Column(name = "username", nullable = false, length = 100) + private String username; + + @Column(name = "firstname", nullable = false, length = 100) + private String firstname; + + @Column(name = "lastname", nullable = false, length = 100) + private String lastname; + + @Column(name = "password", nullable = false) + private String password; + + @Column(name = "nonexpired", nullable = false) + private boolean accountNonExpired; + + @Column(name = "nonlocked", nullable = false) + private final boolean accountNonLocked; + + @Column(name = "nonexpired_credentials", nullable = false) + private final boolean credentialsNonExpired; + + @Column(name = "enabled", nullable = false) + private boolean enabled; + + @Column(name = "firsttime_login_remaining", nullable = false) + private boolean firstTimeLoginRemaining; + + @Column(name = "is_deleted", nullable = false) + private boolean deleted; + + @ManyToOne + @JoinColumn(name = "office_id", nullable = false) + private Office office; + + @ManyToOne + @JoinColumn(name = "staff_id", nullable = true) + private Staff staff; + + @ManyToMany(fetch = FetchType.EAGER) + @JoinTable(name = "m_appuser_role", joinColumns = @JoinColumn(name = "appuser_id"), inverseJoinColumns = @JoinColumn(name = "role_id")) + private Set roles; + + public static AppUser fromJson(final Office userOffice, final Set allRoles, final JsonCommand command) { + + final String username = command.stringValueOfParameterNamed("username"); + String password = command.stringValueOfParameterNamed("password"); + final Boolean sendPasswordToEmail = command.booleanObjectValueOfParameterNamed("sendPasswordToEmail"); + + if (sendPasswordToEmail.booleanValue()) { + password = new RandomPasswordGenerator(13).generate(); + } + + final boolean userEnabled = true; + final boolean userAccountNonExpired = true; + final boolean userCredentialsNonExpired = true; + final boolean userAccountNonLocked = true; + + final Collection authorities = new ArrayList(); + authorities.add(new SimpleGrantedAuthority("DUMMY_ROLE_NOT_USED_OR_PERSISTED_TO_AVOID_EXCEPTION")); + + final User user = new User(username, password, userEnabled, userAccountNonExpired, userCredentialsNonExpired, userAccountNonLocked, + authorities); + + 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.accountNonLocked = false; + this.credentialsNonExpired = false; + this.roles = new HashSet(); + } + + public AppUser(final Office office, final User user, final Set roles, final String email, final String firstname, + final String lastname) { + this.office = office; + this.email = email.trim(); + this.username = user.getUsername().trim(); + this.firstname = firstname.trim(); + this.lastname = lastname.trim(); + this.password = user.getPassword().trim(); + this.accountNonExpired = user.isAccountNonExpired(); + this.accountNonLocked = user.isAccountNonLocked(); + this.credentialsNonExpired = user.isCredentialsNonExpired(); + this.enabled = user.isEnabled(); + this.roles = roles; + this.firstTimeLoginRemaining = true; + } + + public EnumOptionData organisationalRoleData() { + EnumOptionData organisationalRole = null; + if (this.staff != null) { + organisationalRole = this.staff.organisationalRoleData(); + } + return organisationalRole; + } + + public void updatePassword(final String encodePassword) { + this.password = encodePassword; + this.firstTimeLoginRemaining = false; + } + + public void changeOffice(final Office differentOffice) { + this.office = differentOffice; + } + + public void updateRoles(final Set allRoles) { + if (!allRoles.isEmpty()) { + this.roles.clear(); + this.roles = allRoles; + } + } + + 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, getId())) { + final String passwordEncodedValue = command.passwordValueOfParameterNamed(passwordParamName, platformPasswordEncoder, + getId()); + actualChanges.put(passwordEncodedParamName, passwordEncodedValue); + updatePassword(passwordEncodedValue); + } + } + + if (command.hasParameter(passwordEncodedParamName)) { + if (command.isChangeInStringParameterNamed(passwordEncodedParamName, this.password)) { + final String newValue = command.stringValueOfParameterNamed(passwordEncodedParamName); + actualChanges.put(passwordEncodedParamName, newValue); + updatePassword(newValue); + } + } + + final String officeIdParamName = "officeId"; + if (command.isChangeInLongParameterNamed(officeIdParamName, this.office.getId())) { + final Long newValue = command.longValueOfParameterNamed(officeIdParamName); + actualChanges.put(officeIdParamName, newValue); + } + + final String rolesParamName = "roles"; + if (command.isChangeInArrayParameterNamed(rolesParamName, getRolesAsIdStringArray())) { + final String[] newValue = command.arrayValueOfParameterNamed(rolesParamName); + actualChanges.put(rolesParamName, newValue); + } + + 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() { + final List roleIds = new ArrayList(); + + for (final Role role : this.roles) { + roleIds.add(role.getId().toString()); + } + + return roleIds.toArray(new String[roleIds.size()]); + } + + /** + * Delete is a soft delete. Updates flag so it wont appear in + * query/report results. + * + * Any fields with unique constraints and prepended with id of record. + */ + public void delete() { + this.deleted = true; + this.enabled = false; + this.accountNonExpired = false; + this.firstTimeLoginRemaining = true; + this.username = getId() + "_DELETED_" + this.username; + } + + public boolean isDeleted() { + return this.deleted; + } + + @Override + public Collection getAuthorities() { + return populateGrantedAuthorities(); + } + + private List populateGrantedAuthorities() { + final List grantedAuthorities = new ArrayList(); + for (final Role role : this.roles) { + final Collection permissions = role.getPermissions(); + for (final Permission permission : permissions) { + grantedAuthorities.add(new SimpleGrantedAuthority(permission.getCode())); + } + } + return grantedAuthorities; + } + + @Override + public String getPassword() { + return this.password; + } + + @Override + public String getUsername() { + return this.username; + } + + @Override + public boolean isAccountNonExpired() { + return this.accountNonExpired; + } + + @Override + public boolean isAccountNonLocked() { + return this.accountNonLocked; + } + + @Override + public boolean isCredentialsNonExpired() { + return this.credentialsNonExpired; + } + + @Override + public boolean isEnabled() { + return this.enabled; + } + + public String getFirstname() { + return this.firstname; + } + + public String getLastname() { + return this.lastname; + } + + public String getEmail() { + return this.email; + } + + public Set getRoles() { + return this.roles; + } + + public Office getOffice() { + return this.office; + } + + public boolean canNotApproveLoanInPast() { + return hasNotPermissionForAnyOf("ALL_FUNCTIONS", "APPROVEINPAST_LOAN"); + } + + public boolean canNotRejectLoanInPast() { + return hasNotPermissionForAnyOf("ALL_FUNCTIONS", "REJECTINPAST_LOAN"); + } + + public boolean canNotWithdrawByClientLoanInPast() { + return hasNotPermissionForAnyOf("ALL_FUNCTIONS", "WITHDRAWINPAST_LOAN"); + } + + public boolean canNotDisburseLoanInPast() { + return hasNotPermissionForAnyOf("ALL_FUNCTIONS", "DISBURSEINPAST_LOAN"); + } + + public boolean canNotMakeRepaymentOnLoanInPast() { + return hasNotPermissionForAnyOf("ALL_FUNCTIONS", "REPAYMENTINPAST_LOAN"); + } + + public boolean hasNotPermissionForReport(final String reportName) { + + if (hasNotPermissionForAnyOf("ALL_FUNCTIONS", "ALL_FUNCTIONS_READ", "REPORTING_SUPER_USER", "READ_" + reportName)) { return true; } + + return false; + } + + public boolean hasNotPermissionForDatatable(final String datatable, final String accessType) { + + final String matchPermission = accessType + "_" + datatable; + + if (accessType.equalsIgnoreCase("READ")) { + + if (hasNotPermissionForAnyOf("ALL_FUNCTIONS", "ALL_FUNCTIONS_READ", matchPermission)) { return true; } + + return false; + } + + if (hasNotPermissionForAnyOf("ALL_FUNCTIONS", matchPermission)) { return true; } + + return false; + } + + public boolean hasNotPermissionForAnyOf(final String... permissionCodes) { + boolean hasNotPermission = true; + for (final String permissionCode : permissionCodes) { + final boolean checkPermission = hasPermissionTo(permissionCode); + if (checkPermission) { + hasNotPermission = false; + break; + } + } + return hasNotPermission; + } + + public void validateHasReadPermission(final String resourceType) { + + final String authorizationMessage = "User has no authority to view " + resourceType.toLowerCase() + "s"; + final String matchPermission = "READ_" + resourceType.toUpperCase(); + + if (!hasNotPermissionForAnyOf("ALL_FUNCTIONS", "ALL_FUNCTIONS_READ", matchPermission)) { return; } + + throw new NoAuthorizationException(authorizationMessage); + } + + private boolean hasNotPermissionTo(final String permissionCode) { + return !hasPermissionTo(permissionCode); + } + + private boolean hasPermissionTo(final String permissionCode) { + boolean hasPermission = hasAllFunctionsPermission(); + if (!hasPermission) { + for (final Role role : this.roles) { + if (role.hasPermissionTo(permissionCode)) { + hasPermission = true; + break; + } + } + } + return hasPermission; + } + + private boolean hasAllFunctionsPermission() { + boolean match = false; + for (final Role role : this.roles) { + if (role.hasPermissionTo("ALL_FUNCTIONS")) { + match = true; + break; + } + } + return match; + } + + public boolean hasIdOf(final Long userId) { + return getId().equals(userId); + } + + private boolean hasNotAnyPermission(final List permissions) { + return !hasAnyPermission(permissions); + } + + private boolean hasAnyPermission(final List permissions) { + boolean hasAtLeastOneOf = false; + + for (final String permissionCode : permissions) { + if (hasPermissionTo(permissionCode)) { + hasAtLeastOneOf = true; + break; + } + } + + return hasAtLeastOneOf; + } + + public void validateHasPermissionTo(final String function, final List allowedPermissions) { + if (hasNotAnyPermission(allowedPermissions)) { + final String authorizationMessage = "User has no authority to: " + function; + throw new NoAuthorizationException(authorizationMessage); + } + } + + public void validateHasPermissionTo(final String function) { + if (hasNotPermissionTo(function)) { + final String authorizationMessage = "User has no authority to: " + function; + logger.info("Unauthorized access: userId: " + getId() + " action: " + function + " allowed: " + getAuthorities()); + throw new NoAuthorizationException(authorizationMessage); + } + } + + public void validateHasReadPermission(final String function, final Long userId) { + if ("USER".equalsIgnoreCase(function) && userId.equals(getId())) { + // abstain from validation as user allowed fetch their own data no matter what permissions they have. + } else { + validateHasPermissionTo(function); + } + } + + public void validateHasCheckerPermissionTo(final String function) { + + final String checkerPermissionName = function.toUpperCase() + "_CHECKER"; + if (hasNotPermissionTo("CHECKER_SUPER_USER") && hasNotPermissionTo(checkerPermissionName)) { + final String authorizationMessage = "User has no authority to be a checker for: " + function; + throw new NoAuthorizationException(authorizationMessage); + } + } + + public void validateHasDatatableReadPermission(final String datatable) { + if (hasNotPermissionForDatatable(datatable, "READ")) { throw new NoAuthorizationException("Not authorised to read datatable: " + + datatable); } + } + + public Long getStaffId() { + Long staffId = null; + if (this.staff != null) { + staffId = this.staff.getId(); + } + return staffId; + } + + public String getStaffDisplayName() { + String staffDisplayName = null; + if (this.staff != null) { + staffDisplayName = this.staff.displayName(); + } + return staffDisplayName; + } } \ No newline at end of file