0

I am still unable to understand what hook_node_access() does.
I am trying to give view access to the Basic content type nodes to anonymous users, but the code I wrote doesn't work, as anonymous users still get an access denied error.

function modules_session_node_access($node,$op,$account) {
  $type = is_string($node) ? $node : $node->type;
  $is_anonymous = !user_is_logged_in();
  if ($op == 'view' && $is_anonymous && $type='basic') {
    return NODE_ACCESS_ALLOW;  
  }
  return NODE_ACCESS_IGNORE;
}

Why doesn't that code allow anonymous users to view the Basic nodes?

1 Answer 1

0

There is a typo in the code. The code would grant the access to anonymous users when the operation is view, but for any content type.

  if ($op == 'view' && $is_anonymous && $type='basic') {
    return NODE_ACCESS_ALLOW;  
  }

The last part of the if() statement (&& $type='basic') always evaluate to TRUE because it's assigning 'basic' to $type and that value is then "converted" into a Boolean value. (A string that isn't empty, nor '0', is equivalent to TRUE).

The correct code would be the following one, assuming that modules_session is the machine name for the module implementing that hook.ì and basic is the content type machine name.

function modules_session_node_access($node,$op,$account) {
  $type = is_string($node) ? $node : $node->type;
  if ($op == 'view' && !user_is_logged_in() && $type == 'basic') {
    return NODE_ACCESS_ALLOW;
  }
  return NODE_ACCESS_IGNORE;
}

That apart, hook_node_access() implementations aren't invoked for pages showing more than a node and when:

  • The user accessing the node has the bypass node access permission
  • The user accessing the node doesn't have the access content permission

In the first case, the user has the permission to access the node even if one of the hook_node_access() implementations wouldn't give the user the permission to access it. In the latter case, the user doesn't have the permission to access the node even if all the hook_node_access() implementations would give the user the permission to access it.

Even if the anonymous users would have the access content permission, a single hook_node_access() implementation giving them the permission to see a node isn't sufficient for anonymous users to see it. It's enough another hook_node_access() implementation returns NODE_ACCESS_DENY for anonymous users, and the anonymous users won't access the node.

The function invoking hook_node_access() is node_access(), which contains the following code. (Comments are mine.)

// Users with the "bypass node access" permission always have access to the node.
if (user_access('bypass node access', $account)) {
  $rights[$account->uid][$cid][$op] = TRUE;
  return TRUE;
}

// Users without the "access content" permission will never have access to the node.
if (!user_access('access content', $account)) {
  $rights[$account->uid][$cid][$op] = FALSE;
  return FALSE;
}

a comment after the invocation of hook_node_access() make clear in which case the access is granted.

We grant access to the node if both of the following conditions are met:

  • No modules say to deny access.
  • At least one module says to grant access.

Then, if a node is unpublished, anonymous users cannot access it. Only the user who created it can view it, if the user has the view own unpublished content permission, which isn't checked when the author is the anonymous user.

// Check if authors can view their own unpublished nodes.
if ($op == 'view' && !$node->status && user_access('view own unpublished content', $account) && $account->uid == $node->uid && $account->uid != 0) {
  $rights[$account->uid][$cid][$op] = TRUE;
  return TRUE;
}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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