hook_node_access

7 node.api.php hook_node_access($node, $op, $account)
8 node.api.php hook_node_access($node, $op, $account)

Control access to a node.

Modules may implement this hook if they want to have a say in whether or not a given user has access to perform a given operation on a node.

The administrative account (user ID #1) always passes any access check, so this hook is not called in that case. Users with the "bypass node access" permission may always view and edit content through the administrative interface.

Note that not all modules will want to influence access on all node types. If your module does not want to actively grant or block access, return NODE_ACCESS_IGNORE or simply return nothing. Blindly returning FALSE will break other node access modules.

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.

Parameters

$node: Either a node object or the machine name of the content type on which to perform the access check.

$op: The operation to be performed. Possible values:

  • "create"
  • "delete"
  • "update"
  • "view"

$account: The user object to perform the access check operation on.

Return value

Related topics

1 function implements hook_node_access()

1 invocation of hook_node_access()

File

modules/node/node.api.php, line 596
Hooks provided by the Node module.

Code

function hook_node_access($node, $op, $account) {
  $type = is_string($node) ? $node : $node->type;

  if (in_array($type, node_permissions_get_configured_types())) {
    if ($op == 'create' && user_access('create ' . $type . ' content', $account)) {
      return NODE_ACCESS_ALLOW;
    }

    if ($op == 'update') {
      if (user_access('edit any ' . $type . ' content', $account) || (user_access('edit own ' . $type . ' content', $account) && ($account->uid == $node->uid))) {
        return NODE_ACCESS_ALLOW;
      }
    }

    if ($op == 'delete') {
      if (user_access('delete any ' . $type . ' content', $account) || (user_access('delete own ' . $type . ' content', $account) && ($account->uid == $node->uid))) {
        return NODE_ACCESS_ALLOW;
      }
    }
  }

  // Returning nothing from this function would have the same effect.
  return NODE_ACCESS_IGNORE;
}

Comments

---

Before Drupal 7, Drupal defined the hook hook_access(); differently from hook_node_access(), hook_access() is thought to be implemented from modules to limit access to the node types they define.

Strange warning

It seems that hook_node_access() might be called in contexts where $node parameter is not actually a node. It is not even an object.

So you got the
Trying to access property of a non-object warning.
Adding


if (! is_object($node)) {
    return NODE_ACCESS_IGNORE;
}

at the beginning of the hook solved the issue.
Nevertheless, I think the issue should be invetigated more deeply.

$node is a node, or a type of node: see documentation!

Parameters

$node The node on which the operation is to be performed, or, if it does not yet exist, the type of node to be created.

(replied below but was

(replied below but was supposed to be here) - Although the 'create' op seems to be being fired for every content type on every page, whether or not the page is displaying a node (and certainly irrespective of whether I'm on a node creation page) - is this correct?

Difference to hook_node_grants()

Important note when considering using this hook:

hook_node_access() only kicks in when trying to view the full node. It doesn't prevent the rendering of menu items, nor does it prevent teasers and any other views than the full node view.

What you need to do is implement hook_node_access_records() and hook_node_grants(). This will prevent both the menu items from being rendered, as well as prevent teasers and any other views being rendered, including views created by the Views module and any other modules.

(Citing Jay Matwichuk)

Although the 'create' op

Although the 'create' op seems to be being fired for every content type on every page, whether or not the page is displaying a node (and certainly irrespective of whether I'm on a node creation page) - is this correct?

Don't test this as admin or user with bypass node access rights

It should be obvious, but sometimes you look for hours and miss these things.

I did everything right but never saw the function even being called, after a while I discovered I was logged in as admin, so the part where hook_node_access implementations are checked was being ignored. (node_access function)

<?php
if (user_access('bypass node access', $account)) {
   
$rights[$account->uid][$cid][$op] = TRUE;
    return
TRUE;
  }
?>

Login or register to post comments