permissions on additional fields (WIP)

This commit is contained in:
John Woodlock
2012-08-27 17:14:00 +10:00
parent b33b70cb38
commit fbbede83f3
2 changed files with 222 additions and 150 deletions
@@ -30,7 +30,10 @@ import org.mifosng.platform.api.data.EntityIdentifier;
import org.mifosng.platform.api.data.GenericResultsetData; import org.mifosng.platform.api.data.GenericResultsetData;
import org.mifosng.platform.api.infrastructure.ApiJsonSerializerService; import org.mifosng.platform.api.infrastructure.ApiJsonSerializerService;
import org.mifosng.platform.api.infrastructure.ApiParameterHelper; import org.mifosng.platform.api.infrastructure.ApiParameterHelper;
import org.mifosng.platform.exceptions.NoAuthorizationException;
import org.mifosng.platform.exceptions.PlatformApiDataValidationException; import org.mifosng.platform.exceptions.PlatformApiDataValidationException;
import org.mifosng.platform.security.PlatformSecurityContext;
import org.mifosng.platform.user.domain.AppUser;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
@@ -42,7 +45,15 @@ import org.springframework.stereotype.Component;
@Scope("singleton") @Scope("singleton")
public class AdditionalFieldsApiResource { public class AdditionalFieldsApiResource {
private final static Logger logger = LoggerFactory.getLogger(AdditionalFieldsApiResource.class); private final static Logger logger = LoggerFactory
.getLogger(AdditionalFieldsApiResource.class);
private final PlatformSecurityContext context;
@Autowired
public AdditionalFieldsApiResource(final PlatformSecurityContext context) {
this.context = context;
}
@Autowired @Autowired
private ReadExtraDataAndReportingService readExtraDataAndReportingService; private ReadExtraDataAndReportingService readExtraDataAndReportingService;
@@ -53,12 +64,16 @@ public class AdditionalFieldsApiResource {
@GET @GET
@Consumes({ MediaType.APPLICATION_JSON }) @Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON }) @Produces({ MediaType.APPLICATION_JSON })
public String datasets(@QueryParam("type") final String type, @Context final UriInfo uriInfo) { public String datasets(@QueryParam("type") final String type,
@Context final UriInfo uriInfo) {
List<AdditionalFieldsSetData> result = this.readExtraDataAndReportingService.retrieveExtraDatasetNames(type); List<AdditionalFieldsSetData> result = this.readExtraDataAndReportingService
.retrieveExtraDatasetNames(type);
boolean prettyPrint = ApiParameterHelper.prettyPrint(uriInfo.getQueryParameters()); boolean prettyPrint = ApiParameterHelper.prettyPrint(uriInfo
return this.apiJsonSerializerService.serializeAdditionalFieldsSetDataToJson(prettyPrint, result); .getQueryParameters());
return this.apiJsonSerializerService
.serializeAdditionalFieldsSetDataToJson(prettyPrint, result);
} }
@GET @GET
@@ -69,11 +84,16 @@ public class AdditionalFieldsApiResource {
@PathParam("set") final String set, @PathParam("id") final Long id, @PathParam("set") final String set, @PathParam("id") final Long id,
@Context final UriInfo uriInfo) { @Context final UriInfo uriInfo) {
try { checkUserPermissionForSet(type, set, "READ");
GenericResultsetData result = this.readExtraDataAndReportingService.retrieveExtraData(type, set, id);
boolean prettyPrint = ApiParameterHelper.prettyPrint(uriInfo.getQueryParameters()); try {
return this.apiJsonSerializerService.serializeGenericResultsetDataToJson(prettyPrint, result); GenericResultsetData result = this.readExtraDataAndReportingService
.retrieveExtraData(type, set, id);
boolean prettyPrint = ApiParameterHelper.prettyPrint(uriInfo
.getQueryParameters());
return this.apiJsonSerializerService
.serializeGenericResultsetDataToJson(prettyPrint, result);
} catch (InvalidSqlException e) { } catch (InvalidSqlException e) {
List<ApiParameterError> dataValidationErrors = new ArrayList<ApiParameterError>(); List<ApiParameterError> dataValidationErrors = new ArrayList<ApiParameterError>();
ApiParameterError error = ApiParameterError.parameterError( ApiParameterError error = ApiParameterError.parameterError(
@@ -94,6 +114,8 @@ public class AdditionalFieldsApiResource {
@PathParam("set") final String set, @PathParam("id") final Long id, @PathParam("set") final String set, @PathParam("id") final Long id,
final String jsonRequestBody) { final String jsonRequestBody) {
checkUserPermissionForSet(type, set, "UPDATE");
try { try {
Map<String, String> queryParams = new HashMap<String, String>(); Map<String, String> queryParams = new HashMap<String, String>();
@@ -139,4 +161,14 @@ public class AdditionalFieldsApiResource {
"Validation errors exist.", dataValidationErrors); "Validation errors exist.", dataValidationErrors);
} }
} }
private void checkUserPermissionForSet(String type, String set,
String accessType) {
AppUser currentUser = context.authenticatedUser();
if (currentUser.hasNotPermissionForSet(type, set, accessType)) {
throw new NoAuthorizationException("Not Authorised to Use Set: "
+ set + " of Type: " + type);
}
}
} }
@@ -26,7 +26,8 @@ import org.springframework.security.core.userdetails.User;
@Entity @Entity
@Table(name = "m_appuser", uniqueConstraints = @UniqueConstraint(columnNames = { "username" }, name = "username_org")) @Table(name = "m_appuser", uniqueConstraints = @UniqueConstraint(columnNames = { "username" }, name = "username_org"))
public class AppUser extends AbstractAuditableCustom<AppUser, Long> implements PlatformUser { public class AppUser extends AbstractAuditableCustom<AppUser, Long> implements
PlatformUser {
@Column(name = "email", nullable = false, length = 100) @Column(name = "email", nullable = false, length = 100)
private String email; private String email;
@@ -71,8 +72,9 @@ public class AppUser extends AbstractAuditableCustom<AppUser, Long> implements P
private Set<Role> roles; private Set<Role> roles;
public static AppUser createNew(final Office office, public static AppUser createNew(final Office office,
final Set<Role> allRoles, final String username, final String email, final Set<Role> allRoles, final String username,
final String firstname, final String lastname, final String password) { final String email, final String firstname, final String lastname,
final String password) {
boolean userEnabled = true; boolean userEnabled = true;
boolean userAccountNonExpired = true; boolean userAccountNonExpired = true;
@@ -80,9 +82,12 @@ public class AppUser extends AbstractAuditableCustom<AppUser, Long> implements P
boolean userAccountNonLocked = true; boolean userAccountNonLocked = true;
Collection<SimpleGrantedAuthority> authorities = new ArrayList<SimpleGrantedAuthority>(); Collection<SimpleGrantedAuthority> authorities = new ArrayList<SimpleGrantedAuthority>();
authorities.add(new SimpleGrantedAuthority("DUMMY_ROLE_NOT_USED_OR_PERSISTED_TO_AVOID_EXCEPTION")); authorities.add(new SimpleGrantedAuthority(
"DUMMY_ROLE_NOT_USED_OR_PERSISTED_TO_AVOID_EXCEPTION"));
User user = new User(username, password, userEnabled, userAccountNonExpired, userCredentialsNonExpired, userAccountNonLocked, authorities); User user = new User(username, password, userEnabled,
userAccountNonExpired, userCredentialsNonExpired,
userAccountNonLocked, authorities);
return new AppUser(office, user, allRoles, email, firstname, lastname); return new AppUser(office, user, allRoles, email, firstname, lastname);
} }
@@ -99,7 +104,8 @@ public class AppUser extends AbstractAuditableCustom<AppUser, Long> implements P
this.firstTimeLoginRemaining = true; this.firstTimeLoginRemaining = true;
} }
public AppUser(final Office office, final User user, final Set<Role> roles, final String email, final String firstname, final String lastname) { public AppUser(final Office office, final User user, final Set<Role> roles,
final String email, final String firstname, final String lastname) {
this.office = office; this.office = office;
this.email = email.trim(); this.email = email.trim();
this.username = user.getUsername().trim(); this.username = user.getUsername().trim();
@@ -119,7 +125,8 @@ public class AppUser extends AbstractAuditableCustom<AppUser, Long> implements P
this.firstTimeLoginRemaining = false; this.firstTimeLoginRemaining = false;
} }
public void update(final Set<Role> allRoles, final Office office, final UserCommand userCommand) { public void update(final Set<Role> allRoles, final Office office,
final UserCommand userCommand) {
if (userCommand.isRolesChanged() && !allRoles.isEmpty()) { if (userCommand.isRolesChanged() && !allRoles.isEmpty()) {
this.roles.clear(); this.roles.clear();
@@ -143,7 +150,8 @@ public class AppUser extends AbstractAuditableCustom<AppUser, Long> implements P
} }
/** /**
* Delete is a <i>soft delete</i>. Updates flag so it wont appear in query/report results. * Delete is a <i>soft delete</i>. Updates flag so it wont appear in
* query/report results.
* *
* Any fields with unique constraints and prepended with id of record. * Any fields with unique constraints and prepended with id of record.
*/ */
@@ -169,7 +177,8 @@ public class AppUser extends AbstractAuditableCustom<AppUser, Long> implements P
for (Role role : this.roles) { for (Role role : this.roles) {
Collection<Permission> permissions = role.getPermissions(); Collection<Permission> permissions = role.getPermissions();
for (Permission permission : permissions) { for (Permission permission : permissions) {
grantedAuthorities.add(new SimpleGrantedAuthority(permission.code())); grantedAuthorities.add(new SimpleGrantedAuthority(permission
.code()));
} }
} }
return grantedAuthorities; return grantedAuthorities;
@@ -226,33 +235,65 @@ public class AppUser extends AbstractAuditableCustom<AppUser, Long> implements P
} }
public boolean canNotApproveLoanInPast() { public boolean canNotApproveLoanInPast() {
return hasNotPermissionForAnyOf("CAN_APPROVE_LOAN_IN_THE_PAST_ROLE", "PORTFOLIO_MANAGEMENT_SUPER_USER_ROLE"); return hasNotPermissionForAnyOf("CAN_APPROVE_LOAN_IN_THE_PAST_ROLE",
"PORTFOLIO_MANAGEMENT_SUPER_USER_ROLE");
} }
public boolean canNotRejectLoanInPast() { public boolean canNotRejectLoanInPast() {
return hasNotPermissionForAnyOf("CAN_REJECT_LOAN_IN_THE_PAST_ROLE", "PORTFOLIO_MANAGEMENT_SUPER_USER_ROLE"); return hasNotPermissionForAnyOf("CAN_REJECT_LOAN_IN_THE_PAST_ROLE",
"PORTFOLIO_MANAGEMENT_SUPER_USER_ROLE");
} }
public boolean canNotWithdrawByClientLoanInPast() { public boolean canNotWithdrawByClientLoanInPast() {
return hasNotPermissionForAnyOf("CAN_WITHDRAW_LOAN_IN_THE_PAST_ROLE", "PORTFOLIO_MANAGEMENT_SUPER_USER_ROLE"); return hasNotPermissionForAnyOf("CAN_WITHDRAW_LOAN_IN_THE_PAST_ROLE",
"PORTFOLIO_MANAGEMENT_SUPER_USER_ROLE");
} }
public boolean canNotDisburseLoanInPast() { public boolean canNotDisburseLoanInPast() {
return hasNotPermissionForAnyOf("CAN_DISBURSE_LOAN_IN_THE_PAST_ROLE", "PORTFOLIO_MANAGEMENT_SUPER_USER_ROLE"); return hasNotPermissionForAnyOf("CAN_DISBURSE_LOAN_IN_THE_PAST_ROLE",
"PORTFOLIO_MANAGEMENT_SUPER_USER_ROLE");
} }
public boolean canNotMakeRepaymentOnLoanInPast() { public boolean canNotMakeRepaymentOnLoanInPast() {
return hasNotPermissionForAnyOf("CAN_MAKE_LOAN_REPAYMENT_IN_THE_PAST_ROLE", "PORTFOLIO_MANAGEMENT_SUPER_USER_ROLE"); return hasNotPermissionForAnyOf(
"CAN_MAKE_LOAN_REPAYMENT_IN_THE_PAST_ROLE",
"PORTFOLIO_MANAGEMENT_SUPER_USER_ROLE");
} }
public boolean hasNotPermissionForReport(String reportName) { public boolean hasNotPermissionForReport(String reportName) {
for (Role role : this.roles) { for (Role role : this.roles) {
if ((role.getName().equalsIgnoreCase("Super User")) || (role.getName().equalsIgnoreCase("Read Only"))) { if (role.getName().equalsIgnoreCase("Super User"))
return false; return false;
if (role.getName().equalsIgnoreCase("Read Only"))
return false;
}
if (hasPermissionTo("CAN_RUN_" + reportName))
return false;
return true;
}
public boolean hasNotPermissionForSet(String type, String set,
String accessType) {
for (Role role : this.roles) {
if (role.getName().equalsIgnoreCase("Super User"))
return false;
if (accessType.equalsIgnoreCase("READ")) {
if (role.getName().equalsIgnoreCase("Read Only"))
return false;
} }
} }
if (hasPermissionTo("CAN_RUN_" + reportName)) return false; String matchPermission = "CAN_" + accessType + "_" + type + "_x" + set;
if (hasPermissionTo(matchPermission))
return false;
return true; return true;
} }
@@ -281,7 +322,6 @@ public class AppUser extends AbstractAuditableCustom<AppUser, Long> implements P
return match; return match;
} }
public boolean hasIdOf(final Long userId) { public boolean hasIdOf(final Long userId) {
return getId().equals(userId); return getId().equals(userId);
} }