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.infrastructure.ApiJsonSerializerService;
import org.mifosng.platform.api.infrastructure.ApiParameterHelper;
import org.mifosng.platform.exceptions.NoAuthorizationException;
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.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
@@ -42,38 +45,55 @@ import org.springframework.stereotype.Component;
@Scope("singleton")
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
private ReadExtraDataAndReportingService readExtraDataAndReportingService;
@Autowired
private ApiJsonSerializerService apiJsonSerializerService;
@GET
@Consumes({MediaType.APPLICATION_JSON})
@Produces({MediaType.APPLICATION_JSON})
public String datasets(@QueryParam("type") final String type, @Context final UriInfo uriInfo) {
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
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());
return this.apiJsonSerializerService.serializeAdditionalFieldsSetDataToJson(prettyPrint, result);
boolean prettyPrint = ApiParameterHelper.prettyPrint(uriInfo
.getQueryParameters());
return this.apiJsonSerializerService
.serializeAdditionalFieldsSetDataToJson(prettyPrint, result);
}
@GET
@Path("{type}/{set}/{id}")
@Consumes({MediaType.APPLICATION_JSON})
@Produces({MediaType.APPLICATION_JSON})
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
public String extraData(@PathParam("type") final String type,
@PathParam("set") final String set, @PathParam("id") final Long id,
@Context final UriInfo uriInfo) {
try {
GenericResultsetData result = this.readExtraDataAndReportingService.retrieveExtraData(type, set, id);
checkUserPermissionForSet(type, set, "READ");
boolean prettyPrint = ApiParameterHelper.prettyPrint(uriInfo.getQueryParameters());
return this.apiJsonSerializerService.serializeGenericResultsetDataToJson(prettyPrint, result);
try {
GenericResultsetData result = this.readExtraDataAndReportingService
.retrieveExtraData(type, set, id);
boolean prettyPrint = ApiParameterHelper.prettyPrint(uriInfo
.getQueryParameters());
return this.apiJsonSerializerService
.serializeGenericResultsetDataToJson(prettyPrint, result);
} catch (InvalidSqlException e) {
List<ApiParameterError> dataValidationErrors = new ArrayList<ApiParameterError>();
ApiParameterError error = ApiParameterError.parameterError(
@@ -88,12 +108,14 @@ public class AdditionalFieldsApiResource {
@POST
@Path("{type}/{set}/{id}")
@Consumes({MediaType.APPLICATION_JSON})
@Produces({MediaType.APPLICATION_JSON})
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
public Response saveExtraData(@PathParam("type") final String type,
@PathParam("set") final String set, @PathParam("id") final Long id,
final String jsonRequestBody) {
checkUserPermissionForSet(type, set, "UPDATE");
try {
Map<String, String> queryParams = new HashMap<String, String>();
@@ -139,4 +161,14 @@ public class AdditionalFieldsApiResource {
"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);
}
}
}
@@ -25,102 +25,109 @@ import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.User;
@Entity
@Table(name = "m_appuser", uniqueConstraints=@UniqueConstraint(columnNames = {"username"}, name="username_org"))
public class AppUser extends AbstractAuditableCustom<AppUser, Long> implements PlatformUser {
@Table(name = "m_appuser", uniqueConstraints = @UniqueConstraint(columnNames = { "username" }, name = "username_org"))
public class AppUser extends AbstractAuditableCustom<AppUser, Long> implements
PlatformUser {
@Column(name = "email", nullable=false, length=100)
private String email;
@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 = "username", nullable = false, length = 100)
private String username;
@Column(name = "password", nullable=false)
private String password;
@Column(name = "firstname", nullable = false, length = 100)
private String firstname;
@Column(name = "nonexpired", nullable=false)
private boolean accountNonExpired;
@Column(name = "lastname", nullable = false, length = 100)
private String lastname;
@Column(name = "nonlocked", nullable=false)
private final boolean accountNonLocked;
@Column(name = "password", nullable = false)
private String password;
@Column(name = "nonexpired_credentials", nullable=false)
private final boolean credentialsNonExpired;
@Column(name = "nonexpired", nullable = false)
private boolean accountNonExpired;
@Column(name = "enabled", nullable=false)
private boolean enabled;
@Column(name = "nonlocked", nullable = false)
private final boolean accountNonLocked;
@SuppressWarnings("unused")
@Column(name = "firsttime_login_remaining", nullable=false)
private boolean firstTimeLoginRemaining;
@Column(name = "is_deleted", nullable=false)
private boolean deleted;
@Column(name = "nonexpired_credentials", nullable = false)
private final boolean credentialsNonExpired;
@ManyToOne
@JoinColumn(name = "office_id")
private Office office;
@Column(name = "enabled", nullable = false)
private boolean enabled;
@ManyToMany(fetch = FetchType.EAGER)
@JoinTable(name = "m_appuser_role", joinColumns = @JoinColumn(name = "appuser_id"), inverseJoinColumns = @JoinColumn(name = "role_id"))
private Set<Role> roles;
@SuppressWarnings("unused")
@Column(name = "firsttime_login_remaining", nullable = false)
private boolean firstTimeLoginRemaining;
@Column(name = "is_deleted", nullable = false)
private boolean deleted;
@ManyToOne
@JoinColumn(name = "office_id")
private Office office;
@ManyToMany(fetch = FetchType.EAGER)
@JoinTable(name = "m_appuser_role", joinColumns = @JoinColumn(name = "appuser_id"), inverseJoinColumns = @JoinColumn(name = "role_id"))
private Set<Role> roles;
public static AppUser createNew(final Office office,
final Set<Role> allRoles, final String username, final String email,
final String firstname, final String lastname, final String password) {
final Set<Role> allRoles, final String username,
final String email, final String firstname, final String lastname,
final String password) {
boolean userEnabled = true;
boolean userAccountNonExpired = true;
boolean userCredentialsNonExpired = true;
boolean userAccountNonLocked = true;
Collection<SimpleGrantedAuthority> authorities = new ArrayList<SimpleGrantedAuthority>();
authorities.add(new SimpleGrantedAuthority("DUMMY_ROLE_NOT_USED_OR_PERSISTED_TO_AVOID_EXCEPTION"));
User user = new User(username, password, userEnabled, userAccountNonExpired, userCredentialsNonExpired, userAccountNonLocked, authorities);
authorities.add(new SimpleGrantedAuthority(
"DUMMY_ROLE_NOT_USED_OR_PERSISTED_TO_AVOID_EXCEPTION"));
User user = new User(username, password, userEnabled,
userAccountNonExpired, userCredentialsNonExpired,
userAccountNonLocked, authorities);
return new AppUser(office, 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<Role>();
this.firstTimeLoginRemaining = true;
}
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.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;
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<Role>();
this.firstTimeLoginRemaining = true;
}
}
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.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 void updatePassword(final String encodePassword) {
this.password = encodePassword;
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()) {
this.roles.clear();
this.roles = allRoles;
@@ -141,9 +148,10 @@ public class AppUser extends AbstractAuditableCustom<AppUser, Long> implements P
this.email = userCommand.getEmail();
}
}
/**
* 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.
*/
@@ -159,53 +167,54 @@ public class AppUser extends AbstractAuditableCustom<AppUser, Long> implements P
return deleted;
}
@Override
public Collection<GrantedAuthority> getAuthorities() {
return this.populateGrantedAuthorities();
}
@Override
public Collection<GrantedAuthority> getAuthorities() {
return this.populateGrantedAuthorities();
}
private List<GrantedAuthority> populateGrantedAuthorities() {
List<GrantedAuthority> grantedAuthorities = new ArrayList<GrantedAuthority>();
for (Role role :this.roles) {
Collection<Permission> permissions = role.getPermissions();
for (Permission permission : permissions) {
grantedAuthorities.add(new SimpleGrantedAuthority(permission.code()));
}
}
return grantedAuthorities;
}
private List<GrantedAuthority> populateGrantedAuthorities() {
List<GrantedAuthority> grantedAuthorities = new ArrayList<GrantedAuthority>();
for (Role role : this.roles) {
Collection<Permission> permissions = role.getPermissions();
for (Permission permission : permissions) {
grantedAuthorities.add(new SimpleGrantedAuthority(permission
.code()));
}
}
return grantedAuthorities;
}
@Override
public String getPassword() {
return this.password;
}
@Override
public String getPassword() {
return this.password;
}
@Override
public String getUsername() {
return this.username;
}
@Override
public String getUsername() {
return this.username;
}
@Override
public boolean isAccountNonExpired() {
return this.accountNonExpired;
}
@Override
public boolean isAccountNonExpired() {
return this.accountNonExpired;
}
@Override
public boolean isAccountNonLocked() {
return this.accountNonLocked;
}
@Override
public boolean isAccountNonLocked() {
return this.accountNonLocked;
}
@Override
public boolean isCredentialsNonExpired() {
return this.credentialsNonExpired;
}
@Override
public boolean isCredentialsNonExpired() {
return this.credentialsNonExpired;
}
@Override
public boolean isEnabled() {
return this.enabled;
}
public String getFirstname() {
@Override
public boolean isEnabled() {
return this.enabled;
}
public String getFirstname() {
return firstname;
}
@@ -213,50 +222,82 @@ public class AppUser extends AbstractAuditableCustom<AppUser, Long> implements P
return lastname;
}
public String getEmail() {
return this.email;
}
public String getEmail() {
return this.email;
}
public Set<Role> getRoles() {
return this.roles;
}
public Set<Role> getRoles() {
return this.roles;
}
public Office getOffice() {
return this.office;
}
public Office getOffice() {
return this.office;
}
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() {
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() {
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() {
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() {
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) {
for (Role role : this.roles) {
if ((role.getName().equalsIgnoreCase("Super User")) || (role.getName().equalsIgnoreCase("Read Only"))) {
if (role.getName().equalsIgnoreCase("Super User"))
return false;
if (role.getName().equalsIgnoreCase("Read Only"))
return false;
}
}
if (hasPermissionTo("CAN_RUN_" + reportName)) 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;
}
}
String matchPermission = "CAN_" + accessType + "_" + type + "_x" + set;
if (hasPermissionTo(matchPermission))
return false;
return true;
}
public boolean hasNotPermissionForAnyOf(final String... permissionCodes) {
boolean hasNotPermission = true;
for (String permissionCode : permissionCodes) {
@@ -280,7 +321,6 @@ public class AppUser extends AbstractAuditableCustom<AppUser, Long> implements P
return match;
}
public boolean hasIdOf(final Long userId) {
return getId().equals(userId);