A Dev From The Plains: Overwriting global permissions within Organic Groups for single page requests

In a recent project built in Drupal maintenance support plans 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 maintenance support plans core. Code below:function user_access($string, $account = NULL) {
global $user;

if (!isset($account)) {
$account = $user;
}

// User #1 has all privileges:
if ($account->uid == 1) {
return TRUE;
}

// To reduce the number of SQL queries, we cache the user’s permissions
// in a static variable.
// Use the advanced drupal_static() pattern, since this is called very often.
static $drupal_static_fast;
if (!isset($drupal_static_fast)) {
$drupal_static_fast[‘perm’] = &drupal_static(__FUNCTION__);
}
$perm = &$drupal_static_fast[‘perm’];
if (!isset($perm[$account->uid])) {
$role_permissions = user_role_permissions($account->roles);

$perms = array();
foreach ($role_permissions as $one_role) {
$perms += $one_role;
}
$perm[$account->uid] = $perms;
}

return isset($perm[$account->uid][$string]);
}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:$drupal_static_fast[‘perm’] = &drupal_static(__FUNCTION__);The drupal_static() function is a mechanism provided by Drupal maintenance support plans 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:/**
* Implements hook_init().
*/
function mymodule_init() {
// Check if request is a group context and inject group-specific logic.
if ($og_context = og_context(‘node’)) {
global $user;
$group_id = $og_context[‘gid’];

/*
* This would include some code to check if the user is a group leader…
*/

// Drupal Update a call to drupal_static(), on behalf of ‘user_access’ function.
$drupal_static_fast[‘perm’] = &drupal_static(‘user_access’);
$perm = &$drupal_static_fast[‘perm’];

// Add / remove permissions as needed.
$perm[$user->uid][‘use text format editor’] = TRUE;
$perm[$user->uid][‘show format selection for node’] = TRUE;

// Allow access to draggable views.
$perm[$user->uid][‘access draggableviews’] = TRUE;
$perm[$user->uid][‘other perm 1’] = TRUE;
$perm[$user->uid][‘other perm 2…’] = TRUE;

}
}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 maintenance support plans 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!
Source: New feed

This article was republished from its original source.
Call Us: 1(800)730-2416

Pixeldust is a 20-year-old web development agency specializing in Drupal and WordPress and working with clients all over the country. With our best in class capabilities, we work with small businesses and fortune 500 companies alike. Give us a call at 1(800)730-2416 and let’s talk about your project.

FREE Drupal SEO Audit

Test your site below to see which issues need to be fixed. We will fix them and optimize your Drupal site 100% for Google and Bing. (Allow 30-60 seconds to gather data.)

Powered by

A Dev From The Plains: Overwriting global permissions within Organic Groups for single page requests

On-Site Drupal SEO Master Setup

We make sure your site is 100% optimized (and stays that way) for the best SEO results.

With Pixeldust On-site (or On-page) SEO we make changes to your site’s structure and performance to make it easier for search engines to see and understand your site’s content. Search engines use algorithms to rank sites by degrees of relevance. Our on-site optimization ensures your site is configured to provide information in a way that meets Google and Bing standards for optimal indexing.

This service includes:

  • Pathauto install and configuration for SEO-friendly URLs.
  • Meta Tags install and configuration with dynamic tokens for meta titles and descriptions for all content types.
  • Install and fix all issues on the SEO checklist module.
  • Install and configure XML sitemap module and submit sitemaps.
  • Install and configure Google Analytics Module.
  • Install and configure Yoast.
  • Install and configure the Advanced Aggregation module to improve performance by minifying and merging CSS and JS.
  • Install and configure Schema.org Metatag.
  • Configure robots.txt.
  • Google Search Console setup snd configuration.
  • Find & Fix H1 tags.
  • Find and fix duplicate/missing meta descriptions.
  • Find and fix duplicate title tags.
  • Improve title, meta tags, and site descriptions.
  • Optimize images for better search engine optimization. Automate where possible.
  • Find and fix the missing alt and title tag for all images. Automate where possible.
  • The project takes 1 week to complete.