Enable a handler based on roles required for the method it is calling [message #516508] |
Wed, 24 February 2010 09:38 |
Peter Rademaker Messages: 4 Registered: February 2010 |
Junior Member |
|
|
I would like to disable/enable a handler based on the role required for the service method it is calling and the role of the logged in user. (let's assume for simplicity that a user can have only one role)
I've defined the role required for a service method at its declaration using the Spring Security @Secured annotation as follows:
public interface IExampleService {
@Secured("ROLE_ADMIN")
public void exampleSecuredMethod();
}
It would therefore be nice if I would not have to repeat myself when enabling/disabling handlers which call these service methods.
After all, the role required for calling the method should be obtainable by reflection.
Ideally, I would like to be able to do something like this:
<extension
point="org.eclipse.ui.handlers">
<handler
class="com.example.ExampleHandler"
commandId="com.example.exampleCommand">
<enabledWhen>
<with
variable="com.example.roleLoggedInUser">
<test
property="com.example.RoleRequired"
args="com.example.ExampleHandler" />
</with>
</enabledWhen>
</handler>
</extension>
<extension
point="org.eclipse.core.expressions.propertyTesters">
<propertyTester
class="com.example.RolePropertyTester"
id="com.example.rolepropertytester"
namespace="com.example"
properties="RoleRequired"
type="java.lang.String">
</propertyTester>
</extension>
The (intended) result would be that changes to the security configuration/annotation of service methods are automatically reflected in the
enablement of commands in the user interface.
In an attempt to implement this, I've currently created an ISourceProvider which provides the role of the currently logged in user via the variable "com.example.roleLoggedInUser".
However, I'm struggling on how to implement a test to check whether this "com.example.roleLoggedInUser" equals the role that is required for calling the service method.
For now I came up with the idea of havin a PropertyTester which takes the classname of the handler for which the <enabledWhen> clause is defined as argument and returns whether this handler should be enabled based on the role of the logged in user.
For this to work the handler should implement something like an IRoleProvider interface which defines a method getRoles(). My handler implementation
would then use reflection to return the role that is required for calling the service method.
The test(..) method in RolePropertyTester should then look something like this:
public boolean test(Object receiver, String property, Object[] args, Object expectedValue) {
if ("RoleRequired".equals(property) && receiver instanceof String) {
String roleLoggedInUser = (String)receiver;
String enclosingHandlerName = (String) args[0];
// Do something to obtain the handler for which this property tester was called.
IHandler enclosingHandler = ...
String roleRequiredForServiceMethod = ((IRoleProvider)enclosingHandler).getRoles();
return roleLoggedInUser.equals(roleRequiredForServiceMethod);
}
return false;
}
But I do not see how to obtain a reference to the handler enclosing/defining the command core expressions in which I use the property tester.
As you can see I've tried to pass the handler class as argument, but I do not know how to proceed from there.
Is this the way to go? If so, how can I obtain a reference to the handler in my RolePropertyTester?
If not, what would be a viable way to implement something like this?
[Updated on: Wed, 24 February 2010 10:35] Report message to a moderator
|
|
|
|
Re: Enable a handler based on roles required for the method it is calling [message #518200 is a reply to message #516590] |
Wed, 03 March 2010 13:30 |
Peter Rademaker Messages: 4 Registered: February 2010 |
Junior Member |
|
|
Paul, thanks for your reply, it helped me a lot.
I have been away for a few days so I've not been able to reply any sooner.
Since it may be useful to others I'll explain shortly what I've done for now. (Which was inspired by the insights I've obtained from your post)
I'm still not completely happy with it (in some way it does not feel completely right) but it works well and fits most of our requirements.
I did have to drop the requirement/idea of having the handler itself providing the method it calls to the propertytester.
Our RCP application depends on a set of libraries (in-house and third party)
which we've added as "one big bundle". For some of these libraries in this bundle to work
we had to use Buddy-Classloading.
In this bundle I've created an IAuthorizationService with a method isAllowedToCall(Collection<GrantedAuthorities>, String className, String methodName)
Its implementation is also in that bundle, thus with help of the buddy classloading it should be able to load the necessary classes.
The IAuthorizationService is called from an AuthenticationPropertyTester, passing in a collection of granted authorities from the Authentication object and the classname and methodname which were provided as arguments.
The core expressions then looks as follows:
<enabledWhen>
<with variable="com.example.security.currentAuthentication">
<test property="com.example.security.isAllowedToCall"
args="com.example.IExampleService,exampleMethod" />
</with>
</enabledWhen>
A disadvantage of this approach is that there is still some duplication in the sense that the service method
which is called by the handler is repeated in the command core expression.
[Updated on: Wed, 03 March 2010 13:32] Report message to a moderator
|
|
|
Powered by
FUDForum. Page generated in 0.10245 seconds