[kforge-dev] access control role authorisation sequence

John Bywater john.bywater at appropriatesoftwarefoundation.org
Sat Aug 26 20:09:02 UTC 2006


Just to say that I've really speeded up the access controller, and hence 
the KForge and CKAN systems, by reversing the previous 
isRoleAuthorised() method, which checks if a role has been granted a 
permission (to take an action with an object).

In summary, I replaced "for" loops and lists of object, with "if" 
statements and dictionary-type look ups. This stablises the number of 
operations and creates a much more direct style.

The following code is a fragment of the access controller, from:

http://project.knowledgeforge.net/domainmodel/trac/browser/trunk/src/dm/accesscontrol.py



66         def getPermissionObject(self):
67             if self.permissionObject == None:
68                 permission = 
self.protectionObject.permissions[self.action]
69                 self.permissionObject = permission
70             return self.permissionObject
71           
72         def isRoleAuthorised(self, role):
73             permission = self.getPermissionObject()
74             if permission in role.grants:
75                 if self.debug:
76                     msg = "Access by role authorised: '%s' to '%s' 
with '%s'." % (
77                         role.name, self.actionName, self.protectedObject
78                     )
79                     self.logger.debug(msg)
80                 return True


The code now constructs a "protected name", and uses it directly to look 
up the pertaining protection object, which returns a permission object 
from its register of permissions when that register is indexed with an 
action object key (line 68).

A permission holds a register of grants made to roles. So the next thing 
we do is to see if the role and permission are associated with a grant 
(line 74). I decided to pass the permission as a key into the role's 
grants register (rather than the other way around. This is because in 
this way we immediately support other objects that have grants, so they 
will pas for "roles" in our "role based" access controller. (In other 
words, the role interface for the access control interface is a register 
of grants keyed by permission. Currently Person has personalGrants but 
this should be renamed to grants to conform to this interface, and this 
method reused rather than the current method. Also perhaps projects or 
services can have grants?)

Anyway, this method is super fast, requiring a small and fixed number of 
database queries for a given access controller.

In detail, we find the action object (0, or 1 if not cached), find the 
protection object (1, or sometimes 2), retrieve the required permission 
(1), and then look up a grant on the role of the permission (oncee more 
for each role involved by the access controller: session person system 
role, visitor person system role, project membership role, visitor 
project membership role -- missing?, personal role; total 4).

So on average we should just need 6 look ups per authorisation request 
for a controller involving 4 roles. This compares to the previous 
routine, which I expect retrieved half the population of protection 
objects on average, asking them each in turn if they protected the 
protected object. It was taking a while :-).

I'm not sure if I've broken something as a result of changing all this 
round, but I am very pleased that this piece seems now to have fallen 
into place. KForge is performing very snappily now. :-)

Regards,

John.

PS Indeed, a few more of the tests aren't passing now. I suspect some of 
the tests need improving, but I didn't do anything about it yet. We need 
to get all the tests passing again as an urgent next step. But I won't 
be able to do anything about them for a few days now. I'm sure nothing 
major has broken, but I think some of the tests aren't any longer doing 
the right things to the objects that are testing. Let's pull this back 
in and together asap.






More information about the kforge-dev mailing list