You've been doing Drupal permissions wrong for years (probably). And the fix is pretty simple.

The Problem

Drupal permissions are an administrator's nightmare. The settings page is a daunting wall of nondescript checkboxes with overlapping meaning and lots of duplication. This makes bugs hard to find and permissions hard to manage. Worst of all, this user experience poses a security risk. It's just too tempting to scroll and check box after box without thinking too deeply about the consequences.

Permissions tend to be an afterthought and so the permissions story often goes like this: There are the developers and we get the 'Administrator' role. Maybe one or two technical people on the client side get this one as well. A project manager might get the admin role too. Then, there's everyone else and they get the 'Content Editor' role. Then, when final QA starts or, worse, a few weeks after launch, it becomes clear that a department head in the client's office needs a little more access. We don't want to overwhelm them with the 'Administrator' role so we create a 'Content Administrator' role. This person can delete and edit others' posts, they might even be able to change some configurations. All seems fine. But time passes and one day the client hires an intern. They certainly can't have the same permissions as the the editors the client says. We know what to do, we'll just create a new role for the intern. Now, the intern can do just about everything that a 'content editor' can, minus 5 or 6 checkboxes and so you just scroll and click, duplicating all the permissions into a new role. More time passes and this process repeats itself.

A year later, a small bug is found and your hunch is that it's a permissions mismatch. Terrified of the long, slow scroll down the permissions page, reading every line, you try a few keywords in vain before giving in and starting to read each line one by one. The culprit is always at the bottom.

The Fix

First, internalize this: Drupal roles are not job titles, and you shouldn't treat them as such. Put another way, a 'Content Editor' isn't a person, it's a responsibility.

Stop treating roles as people. Treat them as responsibilities. Lots of people can be 'Content Editors', some can be 'Content Publishers', others 'Views Editors'. This idea is simple but powerful. Rather that trying to define a person's job in a role, create many small, single-purpose roles and then compose them together by giving many roles to your users to achieve your goals.

For example, imagine you have a small blog that needs some basic workflow controls but doesn't quite merit investing in the Workflow module. There are a few types of users that this blog has: Readers, Guest Writers, Editors, and Administrators. Before we were enlightened by this blog, we all know what we would have done. We would have thought, "these titles are my roles!" and we would have quickly created them, not so happily scrolling down the permissions page clicking and clicking. Now, we know better.

Instead, we should ask ourselves "what are each of these users' responsibilities?"

The first is pretty trivial, a 'Reader' reads content and perhaps can also comment on that content. Right off the bat, we can extract two Drupal roles from this: a Viewer and Commentor role. These roles should have no other permissions except those that allow them to do what their names imply. That is to say, a Viewer role should have the permission: 'View published content' and the Commentor role should have the permissions: 'View comments', 'Edit own Comments', and finally, 'Post Comments'. Nothing more, nothing less.

While looking at the permissions for the Commentor role, you may have noticed the 'Skip comment approval' and 'Administer comments and comment settings'. We didn't give them to the Commentor, however, they should be in a role. Let's call this one a Comment Moderator.

It's easy to think of this exercise as tedious, especially if we know that all of our Editors will always be Comment Moderators. Wouldn't it be easier to just assign these permissions to an Editor role? The answer is probably 'yes' in that moment, but a year from now, when things are different (as they always are with software), you'll be wishing you had taken the time to do things well. It's much easier to assign the Comment Moderator role to an intern than it is to duplicate the permissions needed for that role over and over for all the roles that need those same permissions.

Continuing the exercise, if we look a the Guest Writer user type, we might be able to derive a few more roles like, Blog Writer and Article Writer (whether to make content type specific roles is up to you).

Finally, we can look at the Editor role, note that we do not need to give this user the ability to create content or 'edit own content'. That's because any Editor that we assign this role will probably also receive the Blog Writer role too. We should avoid duplicating those permissions. The role we really need is a Content Editor role (this one should sound familiar, it comes out of the box with Drupal). This role could be allowed to edit and delete any content. Again, nothing more, nothing less.

So, what's the point of all this? Really, it's just like writing good documentation or, clean, well-documented code. It makes life easier on you and anyone else down the road. As people come and go at your client's office and their job titles change, building roles suitable for those newly minted job descriptions will be easy and reasonable. By simply composing the position out of the responsibilities (read roles) that you already have, you can create varied and unique sets of permissions for any user when the need arises.

Best of all, when you get a bug report a year or two later and you suspect that it has to do with permissions, it will be easier to track down. You'll be able to look at all of the bug reporter's roles to first narrow down the permissions involved. When you see a likely role that the user has (or doesn't have) you can look at just the permissions of that role. Drupal even has viewing permissions by role built right in!

If you're truly lucky, you'll get a bug report to this effect: "this user can see this, but this user can't." You should be jumping for joy because you'll be able to happily compare the two users' assigned roles, rather than scrolling line by line looking for possible permissions differences between ye olde 'Administrator' and 'Content Editor'.

What's Next?

Manually assigning many roles to every new user isn't a very enjoyable experience. There are modules that can help with this like Auto Assign Role.

Finally, there's nothing ready to show, but I'm working on a simple module which will add some level of abstraction on top of Drupal Roles. It will let you create named role groups and then assign those groups of roles to users rather than assigning all their roles individually. This extra layer would give us back the comfort of looking at users's job titles and just checking a single checkbox for it, while maintaining the responsibilities-based roles under the hood. This should mean it will work just fine with core and contrib. If this already exists, be sure to let me know! (No, OG doesn't count).