Take the 2-minute tour ×
Drupal Answers is a question and answer site for Drupal developers and administrators. It's 100% free, no registration required.

I'm working on a project that involves group ownership and editing of nodes. The rules that determine the visibility and editability of nodes are complicated, such that I'm having to roll my own node access code (that is, I couldn't find a module that would provide the kinds of control I need).

The following scenario is causing me some grief:

  • Alice and Bob are part of a group, and are working on node 123. Node access entries exist that allow Alice and Bob to both edit the node under "normal" circumstances.
  • Alice edits node 123, and so becomes the "owner" of the node, in the sense that the uid field of the database entry for node 123 points to her.
  • Bob now edits node 123; he becomes the owner.
  • Alice, who has some degree of admin privileges in the group, takes the node private: She should be able to edit it, but Bob shouldn't. "Taking the node private" means setting up some node access entries that are meant to deny access to the node to everyone but her.
  • However, since Bob is the most recent person to have edited the node, he's still the "owner of record", and node/123/edit is available to him, as a result of the standard node access rules regarding node ownership. (This is how I'm thinking about it, anyway.)

Any ideas for how I can get around this, and keep Bob blocked from editing the node? I've thought about:

  • adding some node_insert and node_update hooks that would force the uid of the node to always point to Alice; the node access entries would allow Bob to edit the node when he's supposed to be able to. Might work, but this seems questionable/risky/horrifically hackish at best.

  • Maybe there's a hook that would reach down into the access system and let me test whether a request for node/123/edit should be permitted based on the current user and system state?

Any other possibilities out there? Thanks!

share|improve this question

3 Answers 3

See my recent answer here: http://drupal.stackexchange.com/a/55144/7153

But basically, you can use

nodeaccess_userreference

or

nodeaccess_nodereference

to acheive that access control functionality there.

Basically you could deny author access and control edit access with one multi-value reference field instead.

More info, including screenshots at first link.

share|improve this answer
    
Worth a look; thanks! –  Jim Miller Jan 8 '13 at 17:46

If you decide to create your own node access module, you may save a lot of work by making use of the ACL (Access Control List) module API. Basically, it is a well-maintained and simple to use framework to create and maintain ACLs for nodes.

The business logic you seem to have in my mind is complex (too complex for my taste), so it may be hard to solve this with only front end tools. An alternative is to rethink the business logic, and adapt it to what can be done with front end tools, such as the Node Access module (as suggested by David Thomas). However, the Node Access module has been abandoned and is listed as unsupported. This is also something you need to take into consideration when deciding on the route to follow.

share|improve this answer
    
Thanks for the notes. I think you're right that this is not a front-end matter; the logic is indeed complex, but makes a bit more sense in the full context of the site and its domain. In any case, I've bumped into the ACL stuff before, and will look at it again. –  Jim Miller Jan 8 '13 at 17:46

For this, you have to implement hook_node_grants and hook_node_access_records. Something like that-

/**
 * Implement @hook_node_grants 
 */
function MODULENAME_node_grants($account, $op) {

  $grants =array();
  $grants['Node_OWNER'][]=array($account->uid);
  $grants['Node_GROUP'][]=array($account->uid);
 return $grants;
}

/**
 * Implement @hook_node_access_records
 */
function MODULENAME_node_access_records($node) {

  $grants = array();

  if ($node->type == 'node_type') { 
    $user_id_group = /* list of user id which you want to block */;
    $user_id_owner = /* list of user id which you want to perform operation */;
     // Revoke Permissions from these Users
    if (!empty($user_id_group) {
      foreach ($user_id_group as $uid) {
        if (isset($uid)) {

          $grants[] = array(
            'realm' => 'Node_Edit_Permission',
            'gid' => $uid,
            'grant_view' => 1,
            'grant_update' => 0,
            'grant_delete' => 0,
            'priority' => 0,
          );
        }
      }
    }

     // Grant Permissions from these Users
    if (!empty($user_id_owner) {
      foreach ($user_id_owner as $uid) {
        if (isset($uid)) {

          $grants[] = array(
            'realm' => 'Node_Edit_Permission',
            'gid' => $uid,
            'grant_view' => 1,
            'grant_update' => 1,
            'grant_delete' => 1,
            'priority' => 0,
          );
        }
      }
    }
  }

  return $grants;
}
share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.