Hi,

I need a node_access hook in a module, that is called for node types that are not defined by the module (standard node types like 'page' and types created with the CCK). The node module will only invoke HOOK_access on the module that define the node type.

To get around this problem, I added the following lines to node_access, effectively introducin a new nodeapi operation, 'access':

Line 2024 in node.module 6.10:

    $module = node_get_types('module', $node);
    if ($module == 'node') {
      $module = 'node_content'; // Avoid function name collisions.
    }
    $access = module_invoke($module, 'access', $op, $node, $account);

+   // Allow modules to grant or deny access.
+   $access_result = node_invoke_nodeapi($node, 'access', $op, $access);
+   foreach ($access_result as $access) {
+     if (!is_null($access) {
+       return $access;
+     }
+   }
  
    if (!is_null($access)) {
      return $access;
    }

This works fine but requires a patch to the node module.

So, now I have q couple of questions:

- Is there an equally simple way to achieve this without patching the node module?

- If not, is using nodeapi with a new operation a good idea or is it better to introduce a new hook altogether?

- Is there any chance that this could be introduced into Drupal?

TIA,
Gunnar

Comments

danielb’s picture

http://api.drupal.org/api/group/node_access
It states there why this is not done.
Also concern yourself with the function hook_node_grants and hook_node_access_records, you can do access restrictions to any node (regardless of node type) like this.

gugrim’s picture

Neither hook_node_grants nor hook_node_access_records suits my purpose. The former doesn't take a node parameter and the latter requires the access rule to be written to the database. This is not what I want. We have thousands of nodes and a module that determines update/delete access simply based on the menu trail of the node, and we don't want redundant access records in the database.

danielb’s picture

I know node access isn't easy to understand, but it is the way to go. It prevents exactly what you're concerned about, and that is duplication. Each module gives it's access rules once, when the node is updated/created. Imagine 20 modules being asked whether someone is allowed to look at a page each time a page is loaded...? What if these modules disagree?

Christopher Camps’s picture

What if the node access criteria is based on some external setting that isn't related to saving a node?

For example if I want a checkbox in the user profile:
[] hide all my stories from other users

Can I do this easily with hook_node_grants/hook_node_access_records?
When the user checks that box and saves their profile, no nodes get saved obviously.

Supposing the profile field is called $user->profile_private_stories, how would I do this in my module without hacking core?
I've been staring at the code in node_access_example, og_access and the hook apis for hours trying to figure this out.

gugrim’s picture

Just found two suggested patches that are very similar to my own:

http://drupal.org/node/91709

http://drupal.org/node/143075

I've tested them and they both solve the problem. The former is a bit more powerful since it allows the hook to take into account the access suggested by the node type owner module.

Sure hope this functionality is added soon. For now it seems we just have to patch the node module.