Beefy Boxes and Bandwidth Generously Provided by pair Networks
Welcome to the Monastery

Re: Optimising a flexibile privilege system

by Theory (Beadle)
on May 05, 2006 at 17:24 UTC ( #547708=note: print w/replies, xml ) Need Help??

in reply to Optimising a flexibile privilege system


Since you asked me via email to comment on this query, with specific reference to Bricolage, let me tell you how it works in Bricolage.

First, there are no permissions granted to individual users or to individual objects. It just made the schema too complex. So we only have groups of users and groups of objects that function as subjects and objects in Bricolage.

When you load an object from the database, the IDs of the groups of which it is a member are also loaded, in the same query. This list of group IDs is available via a call to get_grp_ids().

To check a permission, an object is passed to the user object's can_do() method, along with the permission in question. So if I want to know if a user has Edit permission to an object, I simply do something like this: if ($user->can_do($obj, EDIT)) {...}. The can_do() method then compares the object's group IDs against an ACL loaded for the user.

The user object is cached in the session, so it only gets loaded once for each user. Whenever permissions change, a flag is set in the system-wide cache and all user sessions automatically reload the user whenever it is set, so that permission changes are always immediate. This is not ideal, but generally expiring all users is more efficient that expiring all objects.

The ACL contains a hash mapping object group IDs to their permissions. So all can_do() has to do is iterate over this hash, find all of the relevant group IDs that the object is in, and compare the permissions.

Now, I wrote this a _long_ time ago, and it's far from ideal. It used to be that each object had to have its group IDs loaded in a separate query, and as you can imagine this made permission checking (and therefore Bricolage) extremely slow. It was _much_ better after all objects started loading their group IDs at the same time that they were loaded.

Now, as to your questions, I have the following feedback:

  • Make your objects always load their own ACLs at the same time that they're loaded, so that you don't have to send a separate query for every object for which you want to check the permissions.
  • If you do store calculated permissions in the database, use triggers to keep them updated, rather than a cron job. Then you won't have to think about them and they'll always be up-to-date. Besides, the data isn't really redundant because it's a calculated sum that must be dynamically maintained for every object. It makes sense to cache it like this.
  • Do use memcached or a MySQL table for centralized caching. The performance difference is not worth the bother compared to the convenience of centralized caching for multiple servers. It works great for LiveJournal, it can work for you. Perrin nails this one.



Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: note [id://547708]
and all is quiet...

How do I use this? | Other CB clients
Other Users?
Others drinking their drinks and smoking their pipes about the Monastery: (4)
As of 2018-01-21 01:58 GMT
Find Nodes?
    Voting Booth?
    How did you see in the new year?

    Results (227 votes). Check out past polls.