2

I am exploring the node_grants and node_access_records with the following objective:

I want to be able to hide nodes where the current logged-in user is not 'friends' with the node author. The node author selects if they want to limit it to friends or not with a boolean field. Here, the subtlety is that there are a few views which list nodes on my site, so I want it to work for views too.

I am using drupal 7, user relationships for the 'friends' relationship and here is my node_grants code. How do I get the node id, especially in the context of views?

function mymod_access_node_grants($account, $op) {
// Grants all rights if the author
$grants['mymod_access_author'] = array($account->uid);

    $value_friends = field_get_items('node', $node, 'field_friends_only');
    $value_friends = $value_friends[0]["value"];
    $value_friends = 1;

    if ( $value_friends == NULL) {
        $value_friends = 0;
    }
    if ($value_friends == 0) {
        $grants['mymod_access_public'] = array(1);
        $grants['mymod_access_friends'] = array(1);
        $grants['mymod_access_notfriends'] = array(1);

    } else if ($value_friends == 1)  {
        //if node is for friends only, then check if relationship exists...
        $current_user_uid = $account->uid;
        $node_author_uid = $node->uid;

        // Set up the parameters
        $params = array('between' => array($current_user_uid, $node_author_uid));

        // Get the relationships
        $relationships = user_relationships_load($params);

        if ($relationships) {
            $grants['mymod_access_public'] = array(2);
            $grants['mymod_access_friends'] = array(2);
            $grants['mymod_access_notfriends'] = array(2);
        } else {
            $grants['mymod_access_public'] = array(3);
            $grants['mymod_access_friends'] = array(3);
            $grants['mymod_access_notfriends'] = array(3);
        }
    } else {
    } 
}

return $grants;
}
  • PS: although I have $node in my code, it is empty at the moment!
1

You actually need to implement two hooks:

It's the second hook that gets a node object, not the first. Keep in mind that you need to implement both the hooks.

As for hook_node_access(), this hook is called when a node is fully loaded, and it not called for node listings, as reported in the documentation.

Also note that this function isn't called for node listings (e.g., RSS feeds, the default home page at path 'node', a recent content block, etc.) See Node access rights for a full explanation.

As for views, a view doesn't full load a node, but executes a SQL query to get node data. merlinofchaos clearly states it in Views does not respect hook_node_access.

hook_node_access() is something that is run after a node is fully loaded. Since Views is loading nodes via query, you can't get the query to respect it unless you also use hook_db_rewrite_sql() which is what Views hooks into.

This is not true of just Views, but any query that loads nodes. For example, the default Drupal front page will not respect hook_node_access() that isn't paired with hook_db_rewrite_sql() any better.

hook_node_grants() and hook_node_access_records() will be used, however, if you set "Disable SQL rewriting" then you are specifically skipping that stuff.

Notice that hook_db_rewrite_sql() is not used from Drupal 7 and higher, though. The equivalent for Drupal 7 and higher is hook_query_alter().

4
  • Thanks Kiamlaluno. I do have both functions, it's just that node_grants tells which nodes the current user can see or not in the end. Can I create for a same realm many grant-ids? For example, for a 'friends_realm', have grant ids be the $uid of each of these friends? Nov 23 '15 at 22:40
  • No, hook_node_grants() returns the grant IDs associated with the passed account. They aren't node IDs, but integers; if they are IDs, they could be user IDs, such as in $grants['example_author'] = array($account->uid);. Yes, you can return more grant IDs for the same realm, as in $grants['node_access_test'] = array(8888, 8889);.
    – apaderno
    Nov 24 '15 at 5:44
  • Hi Kiamlaluno, my question was in the opposite way: when you create the grants for nodes in node_Access_records, can you provide multiple values of the grant ids for the same realm? For example, if following the example on the Drupal function page: code$grants[] = array('realm' =>'example_author','gid' => $node->uid,'grant_view' => 1,'grant_update' => 1,'grant_delete' => 1,'priority' => 0,);code Nov 24 '15 at 17:14
  • With the Book access module, I used multiple grant IDs for the same realm; so, yes, it is possible.
    – apaderno
    Nov 24 '15 at 20:58
0

I think that the hook you must use in your case is hook_node_access https://api.drupal.org/api/drupal/modules%21node%21node.api.php/function/hook_node_access/7 which is fired every time a node is requested and thus the $node variable is not provided by the system and is not empty

4
  • hook_node_access() doesn't work with a view because it is never invoked with a list of nodes, such as in the case of a view. See the code invoking that hook.
    – apaderno
    Nov 22 '15 at 18:03
  • seems like a bug that has been fixed. See here drupal.org/node/1266388 and here drupal.stackexchange.com/questions/23225/… Nov 22 '15 at 18:10
  • No, it has not been fixed. merlinofchaos clearly states that the Views module doesn't respect hook_node_access() since that hook is invoked when a full node is loaded, which is not what the Views module does.
    – apaderno
    Nov 22 '15 at 19:09
  • Thanks both for your contribution. I have looked a lot on the web, and it does seem like the only way to get Views to respect access to nodes is through the node_Grants and node_access_records... Nov 23 '15 at 22:45

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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