christophe blin (Migrated from SEC-1872) said:
The @PreAuthorize and @PostAuthorize are very handy to quickly write a simple rule.
The problem is that, sometimes, the expression may become quite messy (to the point where you want to see compilation errors and even unit test the expression)
Here is an example from my code :
private static final String PREAUTH_LOAN = "hasPermission(#libraryId, 'Library', 'perm_loan') " +
"and (#f.force.forceStatus == false or hasPermission(#libraryId, 'Library', 'perm_loan_advanced')) " +
"and (#f.force.forceBlockingTrap == false or hasPermission(#libraryId, 'Library', 'perm_loan_advanced')) ";
@RequestMapping(value="", method=RequestMethod.POST)
@PreAuthorize(PREAUTH_LOAN)
@PostAuthorize("returnObject == null or returnObject.res.user.library.id == #libraryId")
public EPpkResult<LoanDto> create(@PathVariable("networkId") String networkId,
@PathVariable("libraryId") String libraryId, @RequestBody LoanForm f) {
Basically, it means that to be allowed to force the action you mast have the perm_loan_advanced acl.
My proposition is to be able to do something like
@PreAuthorize(clazz=LoanControllerCreatePreAuthorize.class)
public EPpkResult<LoanDto> create(@PathVariable("networkId") String networkId,@PathVariable("libraryId") String libraryId, @RequestBody LoanForm f) {
public class LoanControllerCreatePreAuthorize implements PreAuthorizeCbk {
@Autowired
private PermissionEvaluator permEvaluator;
public isAllowed(Principal p, Xxx request) {
String libraryId = request.getPathVariable("libraryId").as(String.class);
LoanForm f = request.getBodyAs(LoanForm.class);
boolean allowed = permEvaluator.hasPermission(p, libraryId, 'Library', 'perm_loan');
allowed = allowed && isAllowedToForce(p, f.getForce().getForceStatus(), libraryId);
allowed = allowed && isAllowedToForce(p, f.getForce().getForceBlockingTrap(), libraryId);
return allowed;
}
private boolean isAllowedToForce(Principal p, boolean forceParam, String libraryId) {
return ! forceParam || permEvaluator.hasPermission(p, libraryId, 'Library', 'perm_loan_advanced');
}
}
For the PostAuthorize, we would have
public class LoanControllerCreatePostAuthorize implements PostAuthorizeCbk<EPpkResult<LoanDto>> {
public isAllowed(Principal p, Xxx request, EPpkResult<LoanDto> res) {
return res == null || res.getUser().getLibrary().getId().equals(request.getPathVariable("libraryId").as(String.class));
}
}
What do you think of that proposition ?
Comment From: rwinch
You can use @beanName.methodThatReturnsBoolean(args...) to move logic outside of the SpEL expression