On 24/04/12 18:56, Marek Posolda wrote:
Hi Shane,
If I understand correctly this PermissionManager would be used by
PersistentPermissionResolver, which will be the default
PermissionResolver implementation? As it will be good if people have
flexibility to implement their own PermissionResolver and use some
completely different security framework of their own, if they need it.
Some feedback for the PermissionManager itself:
1) I think we should provide also methods for dealing with
ResourceIdentifier case? So we should have also methods like:
List<Permission> listPermissions(ResourceIdentifier resource, String
operation)
List<Permission> listPermissions(ResourceIdentifier resource)
etc.
Good point, we probably have to add these methods also.
2) How about cover user identity in the API? For example: I want to
know that user "john" has permission to READ customer "Mary Kelly".
With current API I would need to call:
listPermissions(maryKellyCustomer, "READ") and then iterate through
all the Permission objects from result list and see if they are
applicable for John. It does not seem to be good from usability and
performance perspective.
So I guess we need also methods like:
List<Permission> listPermissions(Object resource, Identity String
operation, User user)
When more thinking about it, I think the recipient of the Permission
can be single user or also group? And IMO we should also think about
roles to have things more complicated :)
So you can easily ask PermissionManager for questions like: Has
"MANAGER" of group "PowerUsers" permissions to "READ" customer "Mary
Kelly" ? This may be fine with method like:
List<Permission> listPermissions(Object resource, Identity String
operation, String identityId, String identityType, String roleType);
Maybe instead of using Strings as last 3 arguments, we can encapsulate
all recipient informations into single object.
WDYT?
3) Another potentially missing thing is pagination. I assume that we
can have thousands of users in DB and thousands of resource objects,
which in next turn means that you can have millions of permissions. In
large environments, invoking of
PermissionManager.listPermissions(Object resource, String operation)
could return like 10.000 records. So counting with this case and
provide additional methods for pagination support may be good IMO.
Something like:
List<Permission> listPermissions(Object resource, Identity String
operation, int offset, int pageSize);
In response to both 2) and 3), I've been thinking quite a lot about how
we retrieve permissions from the database, and yes when there are
thousands or millions of records it would be useful to support some kind
of pagination. The idea that appeals to me the most would be to
implement a Query API similar to what Bolek has proposed for IDM, except
for permissions. This would allow us much greater flexibility and allow
us to support pagination, etc.
Thanks,
Marek
On 23.4.2012 11:56, Shane Bryzak wrote:
Following up to the recent outline of object permissions, I'd like to
continue with a description of the permission management API.
At the centre of this API is the PermissionManager bean. This bean
provides all of the operations required to grant, deny and query
object permissions. Here's a description of the methods:
List<Permission> listPermissions(Object resource, String operation)
Returns a List of all the Permissions that have been granted for the
specified resource and operation.
List<Permission> listPermissions(Object resource)
Returns a List of all the Permissions that have been granted for the
specified resource
boolean grantPermission(Permission permission)
Grants the specified permission, returns true if successful.
boolean grantPermissions(List<Permission> permissions)
Grants all the permissions contained in the specified List, returns
true if successful.
boolean revokePermission(Permission permission)
Revokes the specified permission, returns true if successful.
boolean revokePermissions(List<Permission> permissions)
Revokes the specified permissions, returns true if successful.
List<String> listAvailableOperations(Object resource)
Returns a list containing all the known allowed operations for the
specified resource.
Each of these methods in turn will invoke a permission check to
ensure that the current user has permission to invoke that particular
permission management operation.
Behind the scenes, the PermissionManager uses a PermissionStore to do
the actual work. The PermissionStore interface is practically
identical to the PermissionManager interface, in face we can possibly
just have it extend it. DeltaSpike should provide one
PermissionStore implementation out of the box, JpaPermissionStore
which allows the user to store their permissions in a database
table. We can use annotations to configure the entity that is used
to store permissions:
@Entity
public class ObjectPermission
{
private Long permissionId;
@PermissionRecipient private String recipient;
@PermissionResourceIdentifier private String resourceId;
@PermissionOperation private String operation;
@PermissionDiscriminator private String discriminator;
}
It should also be possible to use multiple tables to store
permissions. Take for example the use case where a user might wish
to query a table based on assigned permissions:
SELECT
C.*
FROM
CUSTOMER C,
CUSTOMER_PERMISSION CP
WHERE
C.CUSTOMER_ID = CP.CUSTOMER_ID
AND CP.OPERATION CONTAINS '%READ%';