More flexible rights management?

Submitted by Larry on 2 January 2009 - 8:54pm

Via Planet PHP comes this interesting tidbit from Markus Wolff, the original author of PEAR LiveUser. After briefly lamenting over-engineered ACL (access control list) systems in PHP, he talks about a much simpler concept that holds some interesting nuggets of joy. Might Drupal benefit from some of them?

His basic concept is actually very similar to Drupal's user_access() based permission system now. The key difference is that Drupal's system is flat natural-language terms (well, sort of) while the one Markus proposes uses nested, technical language terms. However, being nested gives it one very useful feature that Drupal's system lacks: wildcards.

One rather major failing of Drupal's access system right now is the "administer X" permissions. They are, almost universally, so broad as to be considered a security risk. "administer users" is by far the worst, as it means that "edit other users", "approve new user applications", "configure user roles", "delete users", "change password for any user", and "view blocked users" are all the same permission. That is, you cannot give someone access to process applications without giving them the ability to take over or delete the administrator account. That we still have that configuration is, honestly, embarrassing.

OK, but now consider if we had a permission structure like:

  • User.Accounts.EditAccounts
  • User.Accounts.ChangeAnyPassword
  • User.Accounts.ProcessApplications
  • User.Accounts.ViewBlockedAccounts
  • User.Permissions.ConfigurePermissions
  • User.Permissions.ConfigureRoles

(Or maybe instead of . we should use \, which from PHP 5.3 onward is the symbol for namespace? Hmmm...)

Then we could assign or check permissions with a very fine grain. If we wanted to grant someone "administer users", we would instead grant "User.Accounts.*", which gives them all account management access but not to change what roles could do what, or global User.* access, or whatever we wanted. Conversely, instead of having to check each permission separately we could check if someone had User.Accounts.*, that is, if they have at least one permission under User.Accounts. Then we'd know to, say, show the "User management" admin menu item.

But wait, aren't those permissions less readable than our current natural language ones? Well, sort of. The current permissions are not always intuitive, which is actually why as of Drupal 7 they now have full-text descriptions and translatable titles. The underlying permission string itself is no longer user-exposed, so we can change the string itself to whatever we want.

Of course, there's still the question of efficient implementation. We'd need the proper SQL format to make permission checks as fast and efficient as they are now, or at least close to it. However, I'm sure that is a solvable problem if someone put their mind to it.

Of course, this addresses only action-based permissions, not object-based permissions (which are currently addressed by the scare-fest that is the node_access system). Still, it could be a straightforward but major improvement to our underlying access control system in Drupal 7 if someone wanted to pick it up.

Think about it; a natural hierarchical structure would also allow modules to inject permissions into any category, rather than just grouped by module, and would inform vastly improved UI concepts on the "field of checkboxes" permissions page. What if it was a nested tree by category? Or each top-level category had its own tab, which would then have a smaller set of checkboxes on it grouped by sub-category? There are plenty of possibilities here.

So who wants to make Drupal 7's permission system far more flexible? I so totally don't have time to work on it myself, sadly, but there's a lot of potential here for short- and long-term improvement. Who wants it? :-)

Dagnabbit. That's what I get for blogging so much recently. :-) Fixed the link and the Drupal/PHP issue mentioned below. Thanks.

Wonder95 (not verified)

2 January 2009 - 11:28pm

Considering all the rounds I've gone (and one I'm in the middle of right now) with the node_access system, I would definitely love to rewrite this and make it much more flexible. Maybe I'll take it on once I'm done with what I'm working on now.

What comes to my mind using this hierarchy is something similar for node permissions:

Node.Blog.Create
Node.Blog.Update
Node.Blog.Delete
Node.Blog.View
Node.Page.Create
Node.Page.Update
Node.Page.Delete
Node.Page.View
etc.

Then, whenever a new content type is added, a new set of permissions could be automatically added for each content type (similar to the way it works now).

For modules, you could do something like

Module.Forums.CreateNewForums
Module.Forums.DeleteForums
Module.Forums.ForumName.CreateThread
Module.Forums.ForumName.ModerateThread
etc.

Pretty rough and off the top of my head, but I definitely see the possibilities.

Could field-level permissions work with this model?

For example, a user might have something like

Node.Blog.Create.Title
Node.Blog.Create.Body
Node.Blog.Update.Body
Node.Blog.View

The user would be able to create a blog post with a title and body, but when editing, the title is set and the user can only edit the body. The user can, of course, view the whole thing.

Field-level permissions for delete would be pretty meaningless, but for view, update, and create, it could work.

That could be quite cool! In the typical case you'd assign Node.Blog.Create.* and Node.Blog.Edit.*, to let someone edit any fields on blog nodes. However, as the linked article suggests you could then also add -Node.Blog.Edit.Title, so they could not edit the title after it was created. (Or whatever.) That would be far more flexible than the cck_field_perms module we have now.

Again, the trick is figuring out how to make the logic behind that efficient. We would also want to figure out if it's possible to make such rules contextual; Right now I have to do all sorts of weird and hacky things in order to make edit-access to certain fields on certain node types available only to admins of a given OG. It may not be any more possible with this method than what we have now, but it's worth exploring.

The one place this would not solve is View and List, which is where the node_access table is still a requirement for now. When doing list operations you *must* be able to do the filtering directly in SQL, because otherwise you would have to check, say, 10 nodes, then filter out those you don't have access to, then load 3 more to fill in the gaps, then check those, etc. And then your paging would still be totally off. Object access (which is what the node_access system is) is a whole other ball of complication that this would not really solve.

Still, someone needs to see what we can do with this, and preferably soon. :-) It would be awesome to get this into Drupal 7 yet.

Think about it; a natural hierarchical structure would also allow modules to inject permissions into any category, rather than just grouped by module, and would inform vastly improved UI concepts on the "field of checkboxes" permissions page. What if it was a nested tree by category? Or each top-level category had its own tab, which would then have a smaller set of checkboxes on it grouped by sub-category? There are plenty of possibilities here.

#1: yep, hierarchies feel most natural and are easier to navigate than enormous lists
#2: yep, Hierarchical Select to the rescue!

Alex UA (not verified)

14 January 2009 - 8:34am

I couldn't find one, and we're (well, really Jody Lynn and justinrandell) probably interested in "raising our hands" for this task. The "Administer X" thing has rubbed me the wrong way for the longest time (and I agree that the "Administer Users" could/should be considered a security hole), so it would be great to get that taken care of. Let me pester Jody a bit more and make sure I can convince her to take this on with Justin.

In the meantime, should I open an issue for it?

I don't know of an issue for it yet, so yes please do start one! I can help with architectural review and discussion if you catch me in IRC, but as I said I don't expect to have any time to help with code.