ACL permissions in Seam-Security
baraber Apr 23, 2012 3:36 PMIn a previous discussion on the forum, Shane explained that there had "several refactoring" to be done to enable persistent permission in seam-security (JpaPermissionStore).
Since here we really need this feature, I made an attempt to make those several refactorings.
This work form me.
One can pull it from my github fork : https://github.com/richardbarabe/security
By "working" I mean I was successful at granting, revoking and listing permissions for a user on a resource (object instance).
What I did :
Basically, I had to extract EntityToSpiConverter from JpaIdenityStore to put it in its own file and then reuse it in JpaPermissionStore.
For this I had to extract some configuration code from JpaIdentityStore to JpaIdentityStoreConfiguration (the part that configures the data model objects).
How it works :
Exactly has planned in the "initial implementation".
First you have to create a JPA mapping for IdentityPermission as explained here. The IdmConsole example have an example too. Then you have to create an IdentifierStrategy for the class you want to persist permissions for. Ie, for the class foo.bar.Dog, the following would work :
{code}
package foo.bar;
import javax.enterprise.context.Dependent;
import org.jboss.seam.security.permission.IdentifierStrategy;
@Dependent
public class DogIdentifierStrategy implements IdentifierStrategy {
@Override
public boolean canIdentify(Class<?> targetClass) {
return Dog.class.equals(targetClass);
}
@Override
public String getIdentifier(Object target) {
if (!(target instanceof Dog)) {
throw new IllegalArgumentException("Target [" + target + "] must be instance of "+Dog.class.getName());
}
Dog dog = (Dog) target;
String identifier = "Dog"+":"+dog.getName()+":"+dog.getRace();
return identifier;
}
}
{code}
This will be used by seam-security to identify Dog instances one from another. Note that this example assume some naming conventions if you don't want permissions on different types of objects to collide.
To use the "IdentifierStrategy", you have to annotate the Dog class like this :
{code}
package foo.bar;
import org.jboss.seam.security.annotations.permission.Identifier;
/**
*
* @author baraber
*/
@Identifier(value=DogIdentifierStrategy.class)
public class Dog {
private String name;
private String race;
public DogString name, String race) {
this.name = name;
this.race = race;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getRace() {
return race;
}
public void setRace(String race) {
this.race = race;
}
}
{code}
And to manage permissions(grant, revoke, list), you normally would @Inject PermissionManager and work with it, tough I personnaly had to directly @Inject PermissionStore to bypass security check on permissions "seam.read-permissions", "seam.grant-permission" and "seam.revoke-permission"...
As I said, this works for me. But ...
I think the PermissionManager/PermissionResolver API should change. I wanted to discuss with someone more implicated in seam3 development before changing something like this.
The problem is this one :
To use the "PermissionManager", for instance to grant a new permission, one must provide an object of type org.jboss.seam.security.permission.Permission. To create an instance of this class, one must pass an instance of org.picketlink.idm.spi.model.IdentityObject as the recipient of the permission. But, using the picketlink api, I didn't find anyway to get an org.picketlink.idm.spi.model.IdentityObject from the picketlink API (PersistenceManager). I had to provide my own implementation of org.picketlink.idm.spi.model.IdentityObject.
This is the same reason why I had to extract EntityToSpiConverter from JpaIdentityStore : When the JpaPermissionStore have to create instances of Permission to return (ie in listPermissions methods), it have to build an org.picketlink.idm.spi.model.IdentityObject from an instance of my Jpa mapping foo.bar.IdentityObject.
I think that the API have to change.
At least I'm pretty sure that is not the way I would like to use such an API. Maybe we could just use org.picketlink.idm.api.User, org.picketlink.idm.api.Group and strings as in the other picketlink apis (PersistenceManager, RelationshipManager and RoleManager).
Can anyone take a look at this and maybe work with me to integrate it for an eventual seam release ? (I don't want to maintain a fork of the project )
Should I create a JIRA feature request and associate it a pull request ? I prefered to ask ...