Update (Feb 1, 2011): The default permission algorithm from version 6.0+ is now 6. It uses a fast bitmask persistence implementation of RBAC and is functionally equivalent to 5. However, there is only a single table for permissions, and a single table row per resource, per role, and so the data size is significantly smaller (probably at least 1/5 of previous). There is an built-in, automated migration tool to go from 1-5 to 6. There aren't any valid reason to not migrate from 5 to 6.
Well, it's been almost 2 months since we introduced a new permission checking algorithm into the portal. The key features of the new algorithm are:
- increased speed of evaluation
- simpler usage
- increased performance
- increased speed of evaluation
- and lastly increased speed of evaluation and increased performance
So, how did we acheive this and what did we have to sacrific to get it?
With the old default algorithm (a.k.a. 2) we had all kinds of objects to which we could assign permissions; users, groups, roles, orgs, user groups. While this sounds great, it really isn't for several reasons.
1) Having this many objects to which we can assign permissions means that evaluating whether a user has a particular permission on some entity incurs a check on all those objects. Not to mention the fact that some of those objects support inheritence. This lead to some very complex and expensive JOIN queries.
2) The simple fact that EVERY User could have permissions on a given entity meant that we had to define defaults on these entities. This would lead to situations where a user would visit a portal page which contained entities they had never before encountered and suddenly there would be a tone of DB interactions to create these default permissions for these new objects. Imagine a Message Board page with 20 posts happening over night, morning comes and traffic increases to say 100 users (user who had not encountered the 20 posts before) per minute. That is 100 * 20 / minute new objects being created. This lead to hundreds of DB interactions per second on some highly dynamic sites.
3) Managing permissions on so many different objects was difficult at best, and utterly confusing a worst.
The solution
What we did was implement a system based on the Roles Based Access Control (RBAC) paradigm. We had the foundation for such a system in place, we simply had to reduce the number of objects to which we could assign permissions to only one; Role. This allowed us to perform shorter, faster queries at evaluation time with many fewer JOINS. Also, since we eliminated the assignment of Permissions to User objects we no longer had to create defaults for Users encountering new entities. This increased the concurrent load the portal could handle by a huge factor.
For a short while after the initial system was in place we realized that we had overlooked one key issue, "ownership".
Because User is not assigned permissions, how can we define the permissions granted to the original creator? Well, it took a while to discover a flexible enough solution that would not lead us back down a patch which would cause us to lose our recent performance increase. We definitely did not want to go back to one to one association of permissions to Users.
The solution came in the form of an "implied Role". The "implied" meaning that this Role, though it is a Role like any other, can't be assigned to anything, can't be assigned too, rather it is the result of "state", when a new object is created the default permissions normally associated with the User object are associated with the implied "Owner" Role. Then, on objects which are "owned" (meaning they have a userId field, like a Message Board Message, Blog Entry, Bookmarks Entry, Journal Article, etc.) we first check if the current User is the owner of the object. If so, that user inherites the "Owner" Role. Now, since the "Owner" role is actually a real role, an administrator can manage permissions associated with the Owner Role for any object, by the normal means.
Other cases where we want to customize permissions specifically for a give user or set of users, or even with User Groups or Orgs, we can do this through Roles and then assign those. We lose non of the capability we had before, we increased the performance of the portal significantly, and also made permissions management far easer.
Also, since we only have one type of object on which we can assign permissions, it's easier to map onto external autorization systems, because most of those are already RBAC based, like LDAP.

