Overwriting global permissions within Organic Groups for single page requests

Druplicon logo with avatar icons

In a recent project built in Drupal 7, I came across a bit of an uncommon scenario, by which some users needed to have access to certain features that were normally restricted to them, when viewing, editing or creating groups content (ie: whenever they are visiting a part of the site that is considered part of a group).

For example, while normal users didn’t have access to use certain text formats in the wysiwyg editor, those that were considered group leaders needed to make use of that particular text format. In this scenario, a group leader was an existing role within Organic Groups.

While a simple solution could be a dedicated, global user role that is assigned to users when they become group leaders, and assign any extra permissions to that role, it wasn’t the right solution for this scenario, because a user could be a group leader for some groups, but just a normal group member for other groups, whereas the permissions needed to be applied specifically for the groups in which the user is a group leader. In other words, permissions had to be resolved dynamically depending on what group a user is working on at any given moment.

So, what other options are there available to accomplish this? One would be to use drupal alters and hook mechanisms to change the way each feature restricts access to users, but that will become messy very quickly, particularly if you have to do it for several features, in which case each one might need to be tackled in a different way. Besides, what looks simple on the surface, might involve some more hacking and tweaking than expected: for example, for wysiwyg-related alters, hacks need to be made not only when rendering the wysiwyg editor, but also when validating the input data.

I was looking for a more generic solution that could be easily applied and extended to any feature on the system, and I found it while reviewing the user_access function from Drupal core. Code below:

As you can see, the permissions are fetched for a given user (if they haven’t been already gathered in the current page request), and then statically cached, so that on subsequent calls they don’t need to be fetched from the database again. The key line of the code above that allows custom code to override system permissions, is this:

The drupal_static() function is a mechanism provided by Drupal core to serve as a central static variable storage. Due to the way it works, it is possible for a custom module to call the function with a parameter to get the values stored in it by some other function. More importantly, because it always returns a variable by reference, it means the returned values can be replaced or modified as we please. In this particular case, user_access() maintains the permissions for a given user, as a reference to the values stored by drupal_static().

Knowing this, all I had to do was calling drupal_static() as if it was being called from user_access() itself, and modify the variable returned by reference, to inject permissions dynamically. The best place to do this was in a hook_init() implementation, to make sure all the permissions are in place from as early as possible in the page request. This can be done in just a few lines of code:

I removed the logic to check if a user is leader of the current group, for simplicity, but other than that this is a fully functional snippet that could be used in nearly every Drupal 7 project that uses Organic Groups. Essentially, it checks if page request is in a group context, then check if user is a group leader (or any other role your groups setup could have), and then add the permissions needed for him during that page request.

 Bonus points

  •  With this in place, it’d be very simple to build an UI to configure the extra permissions that need to be added to specific group roles, even on a per-group level. That way, full control over who can do what, can be achieved from the UI as configuration, keeping the code tweaks at a minimum.
  • I removed some extra logic here for simplicity, but our scenario was on a very busy site. We used a session variable to keep track of the groups for which the user is a group leader, to save yet another database query on each page request.

Related links

Although I didn’t find any existing solution to this scenario, I came across a module that does just the opposite: OG Role Override. It allows to specify certain global roles, that will be treated as specific group roles automatically, even if they don’t belong to a given group. Very handy, as I also had that particular scenario in this same project!

One thought on “Overwriting global permissions within Organic Groups for single page requests

  1. Dezső Biczó

    Hey,

    Nice trick! I have been looking for similar solutions for a while, but until this time, luckily it was enough to assign an “accompanying” Drupal role to a specific group role and keep them in sync.
    As you mentioned, it would be really easy to write a contrib module which can provide a UI for this and I’d like to support this idea, because this module could fulfill a real need of Organic group users. I have taken the liberty to create a placeholder for this on D.o. I hope I’ll have some time in the upcoming days to create a placeholder for this module.

    Best, Dezső.

    Reply

Leave a Reply to Dezső Biczó Cancel reply

Your email address will not be published. Required fields are marked *