[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