On Apr 24, 2012, at 3:17 PM, Boleslaw Dawidowicz wrote:
>
> On Apr 24, 2012, at 2:59 PM, Marek Posolda wrote:
>
>> On 24.4.2012 14:41, Shane Bryzak wrote:
>>> 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.
>> I agree that Query API would be definitely more flexible. I've introduced
>> some code snippets with possibilities how can Query API look like in my
>> previous mail. You can take a look in case that you missed it. Nothing
>> final, just some possibilities how to proceed.
>>
>
> I think something aligned with my IDM proposal would look like this:
>
> public interface PermissionQuery
> {
>
> // Operations
>
> PermissionQuery reset();
>
> PermissionQuery getImmutable();
>
> List<Permission> executeQuery();
>
> // Conditions
>
> PermissionQuery setIdentityType(IdentityType it);
>
> IdentityType getIdentityType();
>
> PermissionQuery setIdentityTypeKey(String key)
>
> String getIdentityTypeKey()
>
> PermissionQuery setResource(Object resource);
>
> Object getResource();
>
> PermissionQuery setResourceIdentifier(ResourceIdentifier resource);
>
> ResourceIdentifier getResourceIdentifier();
>
> PermissionQuery setOperation(String op);
>
> String getOperation();
>
>
> RoleQuery sortByIdentityType(boolean ascending);
>
> RoleQuery sortByResource(boolean ascending);
>
> void setRange(Range range);
>
> Range getRange();
>
> }
>
> (not sure if sorting makes sense here)
>
> Usage like:
>
> PermissionQuery
> x.createPermissionQuery().setIdentityType(it).setResource(res).setOperation("READ").setRange(0,10);
>
> x.execute();
> x.getRange().next().execute();
Actually wrote it wrong:
PermissionQuery query =
x.createPermissionQuery().setIdentityType(it).setResource(res).setOperation("READ").setRange(0,10);
query.execute();
query.getRange().next().execute();
>
>
>
>
>
>>
>>>
>>>>
>>>> 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%';
>>>>>
>>>>>
>>>>
>>>
>>>
>>
>