background image
HomeRecent PostsDrupalSearchTagsRSSContactAboutAccount
Eric.London's picture

I've been working on an intranet site that needed to have typical intranet permissions: unauthenticated users can see a handful of pages and the rest of the nodes are only visible to authenticated users. Instead of having the user specify permissions for every page, I figured it would be more usable to have them specify a list of pages available to unauth users.

I created an admin settings page callback to generate the form with a single textarea input. Users will enter a list of URLs in the textarea, one per line:

<?php
function MYMODULE_menu() {
 
$items = array();

 
$items['admin/settings/MYMODULE'] = array(
   
'title' => 'MYMODULE Settings',
   
'page callback' => 'drupal_get_form',
   
'page arguments' => array('_MYMODULE_callback_admin_settings'),
   
'type' => MENU_NORMAL_ITEM,
   
'access arguments' => array('administer site configuration'),
  );

  return
$items;
}

function
_MYMODULE_callback_admin_settings() {
 
$form = array();

 
$form['MYMODULE_unauth_pages'] = array(
   
'#type' => 'textarea',
   
'#title' => 'Unauth Pages',
   
'#default_value' => variable_get('MYMODULE_unauth_pages',''),
  );
   
  return
system_settings_form($form);
}
?>

For this example, I entered the following URLs in the textarea:

<front>
about-us
contact-us

I then added a menu_alter hook function to override the access control for viewing nodes:

<?php
function MYMODULE_menu_alter(&$items) {
 
// per unauth pages, replace the callback function
 
if (function_exists('_MYMODULE_node_access')) {
   
// note: access callback function was previously: node_access
   
$items['node/%node']['access callback'] = '_MYMODULE_node_access';
  }
}
?>

And, then added a new access control function:

<?php
function _MYMODULE_node_access($op, $node) {

 
// check if user is unauth
 
if (in_array('anonymous user', array_values($GLOBALS['user']->roles))) {

   
// get a list of unauth pages
   
$unauth = variable_get('MYMODULE_unauth_pages','');
   
$unauth = explode("\r\n", trim($unauth));
       
   
// replace <front> with empty string
   
if (in_array('<front>', $unauth)) {
     
$unauth[array_search('<front>',$unauth)] = '';
    }
       
   
// check for unauth entries
   
if (is_array($unauth) && count($unauth)) {
     
// check if current url is allowed
     
if (!in_array($_REQUEST['q'], $unauth)) {
        return
false;
      }           
    }
  }
   
 
// default to node_access function result
 
return node_access($op, $node);
   
}
?>

Now, unauth users have access ONLY to the pages you define and the rest of the node viewing permissions default to the node_access function.

In a recent Drupal implementation, we used the Organic Groups module to allow users in a certain role to add content to group nodes. On the content type edit screens, for "Organic groups usage", we chose "Standard group post (typically only author may edit)". Unfortunately, this text is a little deceiving. The OG module grants group administrators the ability to edit any node in the group, which was undesired for our situation.

In the og.module module file, the function og_menu_alter() overrides the normal access control of a user's ability to edit nodes:

<?php
function og_menu_alter(&$menu) {
 
// If og_access is disabled, we at least add back the edit tab for group admins to edit their posts.
 
$menu['node/%node/edit']['access callback'] = 'og_menu_access_node_edit';
 
$menu['node/%node/edit']['access arguments'] = array(1);
}
?>

Prior to og_menu_alter() being executed, the menu structure was:

[access callback] => node_access
[access arguments] => Array
    (
        [0] => update
        [1] => 1
    )

The above array structure relies on the node_access() function to determine if a user has permission to edit a node. One solution to this problem is to define code in a module to reset this menu structure:

<?php
function MYMODULE_menu_alter(&$menu) {
 
$menu['node/%node/edit']['access callback'] = 'node_access';
 
$menu['node/%node/edit']['access arguments'] = array('update',1);
}
?>

Now, group administrators no longer have permission to edit every content item in a group.

Syndicate content