I'm writing a spring application which uses spring-data-rest to expose a restish API for CRUD operations on my entities.
I'm using role based permissions and most of my entity repositories have either a @PreAuthorize("hasAnyRole('ADMIN')
or @PreAuthorize("hasAnyRole('USER')
annotation to restrict access.
For updatng the Person
entity (containing username, password and roles), I would like to have a slightly more complicated logic:
- users with the ADMIN role may do everything
- a user should be able edit their own
Person
entity (except therole
property) - only
ADMIN
s can edit therole
property
I've tried to implement those conditions in a custom isUpdateAllowed
method
@PreAuthorize("@personAuthorizationChecker.isUpdateAllowed(#entity,principal)")
@Override
<S extends Person> S save(S entity);
public boolean isUpdateAllowed(Person updatedEntity, PersonSecurityDetails principal) {
if (principal.getAuthorities().contains(new SimpleGrantedAuthority("ROLE_" + Role.ADMIN))) {
return true;
}
Person existingState = personRepository.getById(updatedEntity.getId());
if (updatedEntity.getRoles() != existingState.getRoles()) {
return false;
}
if (loggedInPersonProvider.getLoggedInUser().getId() == principal.getId()) {
return true;
}
return false;
}
The problem I'm experiencing is that Person existingState = personRepository.getById(updatedEntity.getId());
returns the exact same object as the updatedEntity
argument. So I can't check the changes requested by the client.
I'm surprised by this. I was expecting that updatedEntity
contains the changes requested by the client, while existingState
contains the currently persisted state in the database. But when I look in the debugger, both are the exact same object.
Even though I'm sure that the requested changes are not already persisted to the DB.
How can I force receiving an updated entity from the DB?
Thanks in advance!