[DISCUSS] DELTASPIKE-79 Authorization API - Permission Management and ACLs

classic Classic list List threaded Threaded
16 messages Options
Reply | Threaded
Open this post in threaded view
|

[DISCUSS] DELTASPIKE-79 Authorization API - Permission Management and ACLs

Shane Bryzak-2
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%';

Reply | Threaded
Open this post in threaded view
|

Re: [DISCUSS] DELTASPIKE-79 Authorization API - Permission Management and ACLs

Marek Posolda
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.

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);

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%';
>
>

Reply | Threaded
Open this post in threaded view
|

Re: [DISCUSS] DELTASPIKE-79 Authorization API - Permission Management and ACLs

Marek Posolda
On 24.4.2012 10: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.
>
> 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?
Based on your last mail with subject "[DISCUSS] DELTASPIKE-79
Authorization API - Identity Model" I assume that best case would be to
cover IdentityType in the API, which will allow possibility to cover
users/groups/roles. So having method like:

List<Permission> listPermissions(Object resource, Identity String
operation, IdentityType identityType)

>
>
>
> 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);
>
> 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%';
>>
>>
>
>

Reply | Threaded
Open this post in threaded view
|

Re: [DISCUSS] DELTASPIKE-79 Authorization API - Permission Management and ACLs

Boleslaw Dawidowicz
In reply to this post by Marek Posolda

On Apr 24, 2012, at 10:56 AM, Marek Posolda wrote:
>
> 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);
>

For pagination I propose using something like Range object

https://github.com/bdaw/DeltaSpikeMirror/blob/fc7752409f289b6dfbd577292b70a786a4fb62f4/deltaspike/modules/security/api/src/main/java/org/apache/deltaspike/security/api/idm/Range.java

List<Permission> listPermissions(Object resource, Identity String operation, Range range);

with usage like:

listPermissions(customerRecord, READ, Range.of(10,20));

or

Range page = new Range(0, 10);
x.listPermissions(customerRecord, READ, page.next());

Bolek



Reply | Threaded
Open this post in threaded view
|

Re: [DISCUSS] DELTASPIKE-79 Authorization API - Permission Management and ACLs

Marek Posolda
On 24.4.2012 11:17, Boleslaw Dawidowicz wrote:

> On Apr 24, 2012, at 10:56 AM, Marek Posolda wrote:
>> 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);
>>
> For pagination I propose using something like Range object
>
> https://github.com/bdaw/DeltaSpikeMirror/blob/fc7752409f289b6dfbd577292b70a786a4fb62f4/deltaspike/modules/security/api/src/main/java/org/apache/deltaspike/security/api/idm/Range.java
>
> List<Permission>  listPermissions(Object resource, Identity String operation, Range range);
>
> with usage like:
>
> listPermissions(customerRecord, READ, Range.of(10,20));
>
> or
>
> Range page = new Range(0, 10);
> x.listPermissions(customerRecord, READ, page.next());
yes, slightly better and more flexible than using only "int offset, int
pageSize".

Maybe instead of providing more overloaded "listPermissions" methods
with different signatures, we can think about using query API and create
concept of PermissionQuery?
So on PermissionManager having single method:

List<Permission> listPermissions(PermissionQuery query);



and having

public interface PermissionQuery
{
    private final IdentityType;
    private final String operation;
    private final Object resource;
    private final ResourceIdentifier resourceIdentifier;

    private Range range;
    private int countOfObjects = -1;

    public PermissionQuery(IdentityType idType, String operation, Object
resource, ResourceIdentifier resourceIdentifier, Range range)
    {
        // snipet
    }

    public void setRange()
    {
        this.range = range;
    }

    public void nextPage()
    {
        range.next();
    }

    public boolean hasAvailableResultsOnCurrentPage()
    {
       if (countOfObjects == -1)
       {
           // compute total count of poermission objects from DB
       }

        return range.getLimit() < countOfObjects;
    }

    // getters

}



Now I want to obtain all available actions of user John for resource  
object "maryCustomer":

PermissionQuery permissionQuery = new PermissionQuery(new User("john"),
null, maryCustomer,null, Range.of(0,10));

while (permissionQuery.hasAvailableResultsOnCurrentPage())
{
      List<Permission> currentPage =
permissionManager.listPermissions(permissionQuery);

      // Do something with results
      permissionQuery.nextPage();
}




I am not sure if methods related to pagination should be covered
directly in PermissionQuery as it won't be immutable then and method
hasAvailableResultsOnCurrentPage() will need to access DB to compute
total number of available results. Maybe we can have two separate
methods on PermissionManager. One for case without pagination and second
with pagination. And for pagination case, we will probably need to count
total number of results:

List<Permission> listPermissions(PermissionQuery query);
List<Permission> listPermissions(PermissionQuery query, Range page);
int getPermissionsCount(PermissionQuery);

WDYT?

Marek

> Bolek
>
>
>
>

Reply | Threaded
Open this post in threaded view
|

Re: [DISCUSS] DELTASPIKE-79 Authorization API - Permission Management and ACLs

Shane Bryzak-2
In reply to this post by Marek Posolda
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%';
>>
>>
>

Reply | Threaded
Open this post in threaded view
|

Re: [DISCUSS] DELTASPIKE-79 Authorization API - Permission Management and ACLs

Shane Bryzak-2
In reply to this post by Marek Posolda
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%';
>>
>>
>

Reply | Threaded
Open this post in threaded view
|

Re: [DISCUSS] DELTASPIKE-79 Authorization API - Permission Management and ACLs

Boleslaw Dawidowicz

On Apr 24, 2012, at 2:41 PM, Shane Bryzak wrote:

>>
>> 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 was actually about to reply in similar way. Would be good to keep consistent pattern around pagination. Not forcing my design here but whatever we choose it is best to have similar Query API for both IDM and Permission.

>>
>> 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%';
>>>
>>>
>>
>

Reply | Threaded
Open this post in threaded view
|

Re: [DISCUSS] DELTASPIKE-79 Authorization API - Permission Management and ACLs

Shane Bryzak-2
In reply to this post by Marek Posolda
On 24/04/12 19:03, Marek Posolda wrote:

> On 24.4.2012 10: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.
>>
>> 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?
> Based on your last mail with subject "[DISCUSS] DELTASPIKE-79
> Authorization API - Identity Model" I assume that best case would be
> to cover IdentityType in the API, which will allow possibility to
> cover users/groups/roles. So having method like:
>
> List<Permission> listPermissions(Object resource, Identity String
> operation, IdentityType identityType)

Actually, this is quite a challenge because we have Role and Group
memberships for users (not to mention that groups can be members of
other groups).  So a particular IdentityObject might indirectly inherit
permissions via its memberships, making it tricky for the
PermissionStore to know exactly which permissions should be granted for
any single IdentityObject.  My gut feeling is that this complex logic
belongs at a higher level of abstraction, simply because of the limited
scope of PermissionStore/PermissionManager which don't have access to
the User/Group hierarchy needed to make a determination whether the
IdentityType is actually granted a particular Permission.  I need some
more time to think on this problem, and if you can describe some use
cases that require this functionality it would be greatly helpful in
finding a suitable solution.

>
>>
>>
>>
>> 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);
>>
>> 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%';
>>>
>>>
>>
>>
>

Reply | Threaded
Open this post in threaded view
|

Re: [DISCUSS] DELTASPIKE-79 Authorization API - Permission Management and ACLs

Marek Posolda
In reply to this post by Shane Bryzak-2
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.


>
>>
>> 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%';
>>>
>>>
>>
>
>

Reply | Threaded
Open this post in threaded view
|

Re: [DISCUSS] DELTASPIKE-79 Authorization API - Permission Management and ACLs

Shane Bryzak-2
In reply to this post by Marek Posolda
On 24/04/12 20:19, Marek Posolda wrote:

> On 24.4.2012 11:17, Boleslaw Dawidowicz wrote:
>> On Apr 24, 2012, at 10:56 AM, Marek Posolda wrote:
>>> 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);
>>>
>> For pagination I propose using something like Range object
>>
>> https://github.com/bdaw/DeltaSpikeMirror/blob/fc7752409f289b6dfbd577292b70a786a4fb62f4/deltaspike/modules/security/api/src/main/java/org/apache/deltaspike/security/api/idm/Range.java 
>>
>>
>> List<Permission>  listPermissions(Object resource, Identity String
>> operation, Range range);
>>
>> with usage like:
>>
>> listPermissions(customerRecord, READ, Range.of(10,20));
>>
>> or
>>
>> Range page = new Range(0, 10);
>> x.listPermissions(customerRecord, READ, page.next());
> yes, slightly better and more flexible than using only "int offset,
> int pageSize".
>
> Maybe instead of providing more overloaded "listPermissions" methods
> with different signatures, we can think about using query API and
> create concept of PermissionQuery?
> So on PermissionManager having single method:
>
> List<Permission> listPermissions(PermissionQuery query);
>
>
>
> and having
>
> public interface PermissionQuery
> {
>    private final IdentityType;
>    private final String operation;
>    private final Object resource;
>    private final ResourceIdentifier resourceIdentifier;
>
>    private Range range;
>    private int countOfObjects = -1;
>
>    public PermissionQuery(IdentityType idType, String operation,
> Object resource, ResourceIdentifier resourceIdentifier, Range range)
>    {
>        // snipet
>    }
>
>    public void setRange()
>    {
>        this.range = range;
>    }
>
>    public void nextPage()
>    {
>        range.next();
>    }
>
>    public boolean hasAvailableResultsOnCurrentPage()
>    {
>       if (countOfObjects == -1)
>       {
>           // compute total count of poermission objects from DB
>       }
>
>        return range.getLimit() < countOfObjects;
>    }
>
>    // getters
>
> }
>
>
>
> Now I want to obtain all available actions of user John for resource  
> object "maryCustomer":
>
> PermissionQuery permissionQuery = new PermissionQuery(new
> User("john"), null, maryCustomer,null, Range.of(0,10));
>
> while (permissionQuery.hasAvailableResultsOnCurrentPage())
> {
>      List<Permission> currentPage =
> permissionManager.listPermissions(permissionQuery);
>
>      // Do something with results
>      permissionQuery.nextPage();
> }
>
>
>
>
> I am not sure if methods related to pagination should be covered
> directly in PermissionQuery as it won't be immutable then and method
> hasAvailableResultsOnCurrentPage() will need to access DB to compute
> total number of available results. Maybe we can have two separate
> methods on PermissionManager. One for case without pagination and
> second with pagination. And for pagination case, we will probably need
> to count total number of results:
>
> List<Permission> listPermissions(PermissionQuery query);
> List<Permission> listPermissions(PermissionQuery query, Range page);
> int getPermissionsCount(PermissionQuery);
>
> WDYT?

Ah, I sent my previous response before I read this - yes, I think we're
on the same wavelength here and a Query API for Permissions is a great
idea.  +1.

>
> Marek
>
>> Bolek
>>
>>
>>
>>
>

Reply | Threaded
Open this post in threaded view
|

Re: [DISCUSS] DELTASPIKE-79 Authorization API - Permission Management and ACLs

Boleslaw Dawidowicz
In reply to this post by Marek Posolda

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();





>
>>
>>>
>>> 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%';
>>>>
>>>>
>>>
>>
>>
>

Reply | Threaded
Open this post in threaded view
|

Re: [DISCUSS] DELTASPIKE-79 Authorization API - Permission Management and ACLs

Boleslaw Dawidowicz

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%';
>>>>>
>>>>>
>>>>
>>>
>>>
>>
>

Reply | Threaded
Open this post in threaded view
|

Re: [DISCUSS] DELTASPIKE-79 Authorization API - Permission Management and ACLs

Marek Posolda
In reply to this post by Shane Bryzak-2

>> Based on your last mail with subject "[DISCUSS] DELTASPIKE-79
>> Authorization API - Identity Model" I assume that best case would be
>> to cover IdentityType in the API, which will allow possibility to
>> cover users/groups/roles. So having method like:
>>
>> List<Permission> listPermissions(Object resource, Identity String
>> operation, IdentityType identityType)
>
> Actually, this is quite a challenge because we have Role and Group
> memberships for users (not to mention that groups can be members of
> other groups).  So a particular IdentityObject might indirectly
> inherit permissions via its memberships, making it tricky for the
> PermissionStore to know exactly which permissions should be granted
> for any single IdentityObject.  My gut feeling is that this complex
> logic belongs at a higher level of abstraction, simply because of the
> limited scope of PermissionStore/PermissionManager which don't have
> access to the User/Group hierarchy needed to make a determination
> whether the IdentityType is actually granted a particular Permission.  
> I need some more time to think on this problem, and if you can
> describe some use cases that require this functionality it would be
> greatly helpful in finding a suitable solution.
One of the good reasons is performance. If we have only this on
PermissionManager:

listPermissions(Object resource, String action)

without possibility to specify IdentityType as argument (actually I am
omitting query API for simplicity), then we would need to obtain whole
list of Permission objects for this resource and then manually iterating
in Java code through the whole list and check if some permission is
appropriate for current Identity. It seems to be ineffective from the
performance perspective.

I am assuming that IdentityType means only that single object with it's
type (user/group/role).

Example: I have user "john" and he has role "MEMBER" in group "/foo" and
role "MANAGER" in group "/bar".
I configured in my permission DB, that customer "maryCustomer" can be
READ by members of group "/foo".

In this case:
listPermission(maryCustomer, "READ", new User("john") - will return false
listPermission(maryCustomer, "READ", new Role(new Group("/foo"),
"MEMBER") - will return true

Overally user "john" can read object "maryCustomer". But these
permission is granted indirectly to him because he is member of group
"/foo". Permissions are not granted directly to user "john" but to his
role "MEMBER" of group "/foo".





Now integration with query API. If we want to obtain all permissions
with single DB query, we may want to add list of IdentityType instead of
single IdentityType. So maybe PermisisonQuery can look like this:


public class PermissionQuery
{
   private final Object resource;
   private final String action;
   private final List<IdentityType> identityTypes;

   // snipet


}

and possible PersistentPermissionResolver implementation like:

public class PersistentPermissionResolver
{
   @Inject Identity identity;
   @Inject IdentityManager identityManager;

   public boolean hasPermission(Object resource, String action)
   {
     User user = identity.getUser();
     List<Role> roles = identityManager.getRoles(user); // assuming that
roles of user john will be obtained this way

     List<IdentityType> identityTypes = new ArrayList<IdentityType>();

     identityTypes.add(user);
     identityTypes.add(roles);

     // In our example case, we have 3 objects in the list.
     // 1) IdentityType representing user "john"
     // 2) Role "MEMBER" of group "/foo"
     // 3) Role "MANAGER" of group "/bar"
     PermissionQuery query =
x.createPermissionQuery().setIdentityTypes(identityTypes).setResource(resource).setAction(action).setRange(0,
10);

     // execute query and return true if some objects are returned

   }

}


Reply | Threaded
Open this post in threaded view
|

Re: [DISCUSS] DELTASPIKE-79 Authorization API - Permission Management and ACLs

Boleslaw Dawidowicz
On Apr 25, 2012, at 12:52 AM, Marek Posolda wrote:

>
>>> Based on your last mail with subject "[DISCUSS] DELTASPIKE-79 Authorization API - Identity Model" I assume that best case would be to cover IdentityType in the API, which will allow possibility to cover users/groups/roles. So having method like:
>>>
>>> List<Permission> listPermissions(Object resource, Identity String operation, IdentityType identityType)
>>
>> Actually, this is quite a challenge because we have Role and Group memberships for users (not to mention that groups can be members of other groups).  So a particular IdentityObject might indirectly inherit permissions via its memberships, making it tricky for the PermissionStore to know exactly which permissions should be granted for any single IdentityObject.  My gut feeling is that this complex logic belongs at a higher level of abstraction, simply because of the limited scope of PermissionStore/PermissionManager which don't have access to the User/Group hierarchy needed to make a determination whether the IdentityType is actually granted a particular Permission.  I need some more time to think on this problem, and if you can describe some use cases that require this functionality it would be greatly helpful in finding a suitable solution.
> One of the good reasons is performance. If we have only this on PermissionManager:
>
> listPermissions(Object resource, String action)
>
> without possibility to specify IdentityType as argument (actually I am omitting query API for simplicity), then we would need to obtain whole list of Permission objects for this resource and then manually iterating in Java code through the whole list and check if some permission is appropriate for current Identity. It seems to be ineffective from the performance perspective.
>
> I am assuming that IdentityType means only that single object with it's type (user/group/role).
>
> Example: I have user "john" and he has role "MEMBER" in group "/foo" and role "MANAGER" in group "/bar".
> I configured in my permission DB, that customer "maryCustomer" can be READ by members of group "/foo".
>
> In this case:
> listPermission(maryCustomer, "READ", new User("john") - will return false
> listPermission(maryCustomer, "READ", new Role(new Group("/foo"), "MEMBER") - will return true
>
> Overally user "john" can read object "maryCustomer". But these permission is granted indirectly to him because he is member of group "/foo". Permissions are not granted directly to user "john" but to his role "MEMBER" of group "/foo".
>
>
>
>
>
> Now integration with query API. If we want to obtain all permissions with single DB query, we may want to add list of IdentityType instead of single IdentityType. So maybe PermisisonQuery can look like this:
>
>
> public class PermissionQuery
> {
>  private final Object resource;
>  private final String action;
>  private final List<IdentityType> identityTypes;
>
>  // snipet
>
>
> }
>
> and possible PersistentPermissionResolver implementation like:
>
> public class PersistentPermissionResolver
> {
>  @Inject Identity identity;
>  @Inject IdentityManager identityManager;
>
>  public boolean hasPermission(Object resource, String action)
>  {
>    User user = identity.getUser();
>    List<Role> roles = identityManager.getRoles(user); // assuming that roles of user john will be obtained this way
>
>    List<IdentityType> identityTypes = new ArrayList<IdentityType>();
>
>    identityTypes.add(user);
>    identityTypes.add(roles);
>
>    // In our example case, we have 3 objects in the list.
>    // 1) IdentityType representing user "john"
>    // 2) Role "MEMBER" of group "/foo"
>    // 3) Role "MANAGER" of group "/bar"
>    PermissionQuery query = x.createPermissionQuery().setIdentityTypes(identityTypes).setResource(resource).setAction(action).setRange(0, 10);
>
>    // execute query and return true if some objects are returned
>
>  }
>
> }


I think it is reaching the point where it would be easier to follow and discuss some real code prototype on github.


On additional note there is different notion of Role between what I proposed for IDM API and to what Shane and Marek refers too.

1) In my case it was (simplified version)

public interface Role extends IdentityType
{
String getName();
boolean exists(User user, Group group);
void add(User user, Group group);
Collection<User> getUsers(Group group);
Collection<Group> getGroups(User user);
}

So Role is a matching between Role name (think RoleType) User and Group

In Shane's proposal it is just a Name/Group relation.

public interface Role extends IdentityType
{
   Group getGroup();
   String getRoleName();
}

And this one makes more sense in context of Permissions like in code snippets presented by Marek:

listPermission(maryCustomer, "READ", new Role(new Group("/foo"), "MEMBER")

where permission will be indirectly granted to all users with such role.

Other way is to keep what Shane proposed and then use altered Membership interface that I initially proposed as just a helper to do queries.

public interface Membership
{
 User getUser();
 Role getRole();
}

Or to avoid confusion use different interface in authorization API like:

listPermission(maryCustomer, "READ", new RoleMatch(new Group("/foo"), "MEMBER")

Still I think we are hitting a point where we start to discuss 2 more complex APIs that overlap and it would be better to try put more consistent prototype on github to discuss.

Bolek



Reply | Threaded
Open this post in threaded view
|

Re: [DISCUSS] DELTASPIKE-79 Authorization API - Permission Management and ACLs

Gerhard Petracek
Administrator
hi @ all,

fyi:
we will discuss a thin query layer which supports pagination,... soon.
-> imo the security-jpa module should use it.

regards,
gerhard



2012/4/25 Boleslaw Dawidowicz <[hidden email]>

> On Apr 25, 2012, at 12:52 AM, Marek Posolda wrote:
>
> >
> >>> Based on your last mail with subject "[DISCUSS] DELTASPIKE-79
> Authorization API - Identity Model" I assume that best case would be to
> cover IdentityType in the API, which will allow possibility to cover
> users/groups/roles. So having method like:
> >>>
> >>> List<Permission> listPermissions(Object resource, Identity String
> operation, IdentityType identityType)
> >>
> >> Actually, this is quite a challenge because we have Role and Group
> memberships for users (not to mention that groups can be members of other
> groups).  So a particular IdentityObject might indirectly inherit
> permissions via its memberships, making it tricky for the PermissionStore
> to know exactly which permissions should be granted for any single
> IdentityObject.  My gut feeling is that this complex logic belongs at a
> higher level of abstraction, simply because of the limited scope of
> PermissionStore/PermissionManager which don't have access to the User/Group
> hierarchy needed to make a determination whether the IdentityType is
> actually granted a particular Permission.  I need some more time to think
> on this problem, and if you can describe some use cases that require this
> functionality it would be greatly helpful in finding a suitable solution.
> > One of the good reasons is performance. If we have only this on
> PermissionManager:
> >
> > listPermissions(Object resource, String action)
> >
> > without possibility to specify IdentityType as argument (actually I am
> omitting query API for simplicity), then we would need to obtain whole list
> of Permission objects for this resource and then manually iterating in Java
> code through the whole list and check if some permission is appropriate for
> current Identity. It seems to be ineffective from the performance
> perspective.
> >
> > I am assuming that IdentityType means only that single object with it's
> type (user/group/role).
> >
> > Example: I have user "john" and he has role "MEMBER" in group "/foo" and
> role "MANAGER" in group "/bar".
> > I configured in my permission DB, that customer "maryCustomer" can be
> READ by members of group "/foo".
> >
> > In this case:
> > listPermission(maryCustomer, "READ", new User("john") - will return false
> > listPermission(maryCustomer, "READ", new Role(new Group("/foo"),
> "MEMBER") - will return true
> >
> > Overally user "john" can read object "maryCustomer". But these
> permission is granted indirectly to him because he is member of group
> "/foo". Permissions are not granted directly to user "john" but to his role
> "MEMBER" of group "/foo".
> >
> >
> >
> >
> >
> > Now integration with query API. If we want to obtain all permissions
> with single DB query, we may want to add list of IdentityType instead of
> single IdentityType. So maybe PermisisonQuery can look like this:
> >
> >
> > public class PermissionQuery
> > {
> >  private final Object resource;
> >  private final String action;
> >  private final List<IdentityType> identityTypes;
> >
> >  // snipet
> >
> >
> > }
> >
> > and possible PersistentPermissionResolver implementation like:
> >
> > public class PersistentPermissionResolver
> > {
> >  @Inject Identity identity;
> >  @Inject IdentityManager identityManager;
> >
> >  public boolean hasPermission(Object resource, String action)
> >  {
> >    User user = identity.getUser();
> >    List<Role> roles = identityManager.getRoles(user); // assuming that
> roles of user john will be obtained this way
> >
> >    List<IdentityType> identityTypes = new ArrayList<IdentityType>();
> >
> >    identityTypes.add(user);
> >    identityTypes.add(roles);
> >
> >    // In our example case, we have 3 objects in the list.
> >    // 1) IdentityType representing user "john"
> >    // 2) Role "MEMBER" of group "/foo"
> >    // 3) Role "MANAGER" of group "/bar"
> >    PermissionQuery query =
> x.createPermissionQuery().setIdentityTypes(identityTypes).setResource(resource).setAction(action).setRange(0,
> 10);
> >
> >    // execute query and return true if some objects are returned
> >
> >  }
> >
> > }
>
>
> I think it is reaching the point where it would be easier to follow and
> discuss some real code prototype on github.
>
>
> On additional note there is different notion of Role between what I
> proposed for IDM API and to what Shane and Marek refers too.
>
> 1) In my case it was (simplified version)
>
> public interface Role extends IdentityType
> {
> String getName();
> boolean exists(User user, Group group);
> void add(User user, Group group);
> Collection<User> getUsers(Group group);
> Collection<Group> getGroups(User user);
> }
>
> So Role is a matching between Role name (think RoleType) User and Group
>
> In Shane's proposal it is just a Name/Group relation.
>
> public interface Role extends IdentityType
> {
>   Group getGroup();
>   String getRoleName();
> }
>
> And this one makes more sense in context of Permissions like in code
> snippets presented by Marek:
>
> listPermission(maryCustomer, "READ", new Role(new Group("/foo"), "MEMBER")
>
> where permission will be indirectly granted to all users with such role.
>
> Other way is to keep what Shane proposed and then use altered Membership
> interface that I initially proposed as just a helper to do queries.
>
> public interface Membership
> {
>  User getUser();
>  Role getRole();
> }
>
> Or to avoid confusion use different interface in authorization API like:
>
> listPermission(maryCustomer, "READ", new RoleMatch(new Group("/foo"),
> "MEMBER")
>
> Still I think we are hitting a point where we start to discuss 2 more
> complex APIs that overlap and it would be better to try put more consistent
> prototype on github to discuss.
>
> Bolek
>
>
>
>