Hi, I'm trying to understand how Drupal access system works. I read through the documentation of node_access_example.module but I don't understand few things here. Mainly how this access realms work. For example how is it they just type in 'example_author' as realm and it knows what they mean? Especially since its sometimes this and sometimes 'example_owner' or anything similar. Obviously I'm missing on something, which is probably coded in core drupal.
Another is this whole 'access private content' permission. Are "access" and "content" some predefined words?

Is there some tutorial describing this? Explaining how to work with it?

Comments

newbie888’s picture

it's role based. Users are assigned roles, roles are assigned permissions.

jaypan’s picture

The realm is arbitrary. It can be pretty much anything you want. Basically it's a reference for a type of permissions.

If you look at the node_access_example.module, they have defined two realms: 'example', which has permission to view only, and 'example_author', which has permission to view, edit and delete.

It's kind of tricky to wrap your head around this concept, but basically what this is saying is that there are two types of users who will have permission to access the node in question. First, the word 'example' is kind of confusing, because in this case it doesn't example, it's just the title that they are using. So let's rename them for the sake of understanding. 'example' could be called 'user', and 'example_author' could be called 'author'. So these are two types of users who will access the content type - an author and a user.

Each time a node is saved, hook_node_access_records() is called, and the grants you are defining are attached to that node. I find it helpful to look at the db table - 'node_access'. You can see that the node id is saved along with the grants name, and a grant ID. Permissions are also saved, lets leave them for now. Basically, hook_node_access_records() tells Drupal that 'these types of users will have permission to do something on the node'.

Next, each time a node is accessed, hook_node_grants() is called. In this hook, some of the users data is compiled. It is then put in an array, and sent to the grants system. This array tells Drupal that 'this user is this type of user'. Drupal then compares the type of user that this is (hook_node_grants) with the type of user that is allowed to do something to the node (hook_node_access_records) and if there is a match, it allows them to use the permissions outlined in that row of the table.

So for example, with hook node_access_records, you can use this:

function mymodule_node_access_records($node)
{
  $grants = array();
  $grants[] = array
  (
    'realm' => 'node_author', // this name is arbitrary. It is basically a description of the type of user that will be allowed to access the node, in this case, the type of user is the author of the node that is being saved
    'gid' => $node->uid, // This is the uid of the author of the node being saved.
    'grant_view' => TRUE,  // The author of the node will have permission to view it
    'grant_update' => TRUE,  // the author of the node will have permission to edit it
    'grant_delete' => TRUE,  // The author of the node will have permission to delete it
    'priority' => 0,  // Until and unless you know what you are doing, leave this at zero
  );
  return $grants;
}

So now we have defined one type of user who will have access to the node. Remember, hook_node_access_records() is called for each node. That means that each and every single node will grant permissions to a user who matches the profile defined here. So lets look at how we check that:

function mymodule_node_grants($account, $op)
{
  // we have the user's details in the $account variable. So we can use them to create the user's profile
  $grants = array();
  $grants['author'][] = $account->uid; 
  return $grants;
}

Here we have built a profile of this user. We are giving the user's UID and telling the grants system to compare it to the 'author' realm. Again, this realm is arbitrary when setting it in hook_node_access_records(), but here we must use the realm that we defined there, or else we are comparing it to nothing. So lets look at this example:

1) User with a UID of 6 creates the node
2) hook node_access_records() saves the grant, saying that the author has a UID of 6
3) User with a UID of 10 tries to access the node
4) hook_node_grants() sends back the profile, which says that for the author realm, the UID is 10. Since the UID of the author was 6, the comparison fails, and the user isn't granted access.

1) User with a UID of 8 creates the node
2) hook_node_access_records() saves the grant, saying that the author has a UID of 8
3) User with a UID of 8 tries to access the node
4) hook_node_grants() sends back the profile, which says that for the author realm, the UID is 8. Since the UID of the author was 8, this comparison matches, and the user is granted the access permissions defined for that realm. In this case, that is viewing, editing and deleting permissions.

I hope this helps! The grants system is tricky to wrap your head around.

Contact me to contract me for D7 -> D10/11 migrations.

svihel’s picture

Hello. It actually really did helped! :)
That was exactly what I needed to know! Especially that node_grants() function wasn't very clear to me, but I think I get it now. I'm going to try to create few modules of my own to test it.

Anyway thank you for your support it really helped a lot! BTW as I think this is really useful guide I posted a link directly to node_access_example.module in API section.

samtherobot’s picture

I've created a basic module very similar to the example node access module. However my module checks current IP against a list of IPs. However I'm getting fairly random results. Sometimes it works, sometimes not and I'm not really sure why either way. One thing I'm not clear on is how do I come up with a GID? It seems completely arbitrary just like the realm.

jaypan’s picture

The GID is completely arbitrary. If you are working with IPs, you may even want to just make the GID the IP address. Then you can pass back the IP from hook_node_grants() and if it is the right IP, access will be granted, if it isn't, it won't. Although I don't know how your module works, so I may be way off base here. The point is though that the GID is arbitrary.

Contact me to contract me for D7 -> D10/11 migrations.

creazion_dev’s picture

It has to be node_author instead of author to work correctly:

function mymodule_node_grants($account, $op)
{
  // we have the user's details in the $account variable. So we can use them to create the user's profile
  $grants = array();
  $grants['node_author'][] = $account->uid; 
  return $grants;
}
jaypan’s picture

Ahh, typo. I'll go back and edit my original post on the matter.

Edit: or actually I won't. I guess Drupal has a time limit on post edits.

Contact me to contract me for D7 -> D10/11 migrations.

binford2k’s picture

Is this supposed to affect the node listing?

I've got the realms defined just as described here. eg, for node 8, I've got this realm only:

 nid | gid | realm | grant_view | grant_update | grant_delete 
-----+-----+-------+------------+--------------+--------------
   8 |   4 | waddl |          1 |            0 |            0

And hook_node_grants returns this:

Array
(
    [waddl] => Array
        (
            [0] => 1
        )

)

Note that the two GIDs are not equal--yet the node still appears in the listing page. What am I missing?