Hi all,
Is it possible to hide menu items that a user is not authorised to view? For example, a setup such that premium content is not visible to unregistered users. Currently with node_privacy_byrole, the node is still visible in the menu, but clicking on it gives the access denied message.

TIA,
Rohan

Comments

Steve Dondley’s picture

The node privacy byrole module lets you control permissions for individual nodes while the taxonomy access module lets you control permissions for entire categories. The taxonomy access module also has a patch included with it that will solve the problem you cite above, where users can still see the links to restricted content.

Azzor’s picture

I tried taxonomy access, but I still get the same behaviour (the links being visible from the menu, but access denied when clicked on). I applied the patch taxonomy.patch during installation. Is there another patch i need to apply?

Rohan

Steve Dondley’s picture

Just diable the menu item. Do you have the menu.module disabled?

Azzor’s picture

menu.module is enabled.
With the menu item disabled, the menu item isnt visible to anyone, even to the administrator. The desired setup is such that a section of the menu is only visible to users who are logged on.

Rohan

Steve Dondley’s picture

I don't know of any way to do that with the current menu.module. I think your best bet is to create a new block with some custom code.

Azzor’s picture

I've created a patch to includes/menu.inc to solve this issue. I know that this is a bit of a hack, but it was the best i could come up with with my current knowledge of the code base. The patch can be found at http://undefined.homelinux.net/~zero/menu-visibility.patch for anyone interested.

Rohan

MartinL’s picture

I am part of a group migrating an existing community website to drupal. We had more or less the same problem. We do node access control with taxonomy_access, but the basic problem we wanted to solve, hiding menu items linking to inaccessible nodes, is the same. (We have different sub-communities with different access rights, in our case by taxonomy.) Our solution is a bit different, perhaps you can comment on this:

  • Instead of _menu_build_visible_tree we modified _menu_item_is_accessible. (but in a similar way, cf. below.)
  • I think that calling node_access on the node is not necessary, since node_load already checks the current permissions.
  • I hope that this is still true if one truncates node_load to a version that just does SELECT nid with all the WHERE clauses added. This should be significantly faster for large menu hierarchies... (This last part was added later. Initially we successfully tried just calling node_load.)

We modified menu.inc as follows:

function _menu_item_is_accessible($mid) {
  $menu = menu_get_menu();

  // Follow the path up to find the first "access" attribute.
  $path = $menu['items'][$mid]['path'];

+  // Menu item access hack: show items only if you have access to node
+  if (substr ($path, 0, 5) == "node/") { 
+    $nid = substr ($path, 5);
+    if (is_numeric($nid)) {
+      $node = node_try_load (array ('nid' => $nid));
+      if (!$node->nid) return FALSE;
+    }
+  }

  while ($path && (!array_key_exists($path, $menu['path index']) ||
         !array_key_exists('access', $menu['items'][$menu['path index'][$path]]))) {
    $path = substr($path, 0, strrpos($path, '/'));
  }
  if (empty($path)) {
    return FALSE;
  }
  return $menu['items'][$menu['path index'][$path]]['access'];
}

And node_try_load is the following significantly truncated version of node_load:

// Experimental: Try to load node in order to determine access
function node_try_load($conditions) {

  // Turn the conditions into a query.
  foreach ($conditions as $key => $value) {
    $cond[] = 'n.'. db_escape_string($key) ." = '". db_escape_string($value) ."'";
  }

  // Retrieve the node.
  $node = db_fetch_object(db_query(db_rewrite_sql('SELECT nid FROM {node} n WHERE '. implode(' AND ', $cond))));

  return $node;
}

Nobody of us is really familiar with the drupal code, so I would be happy to get some feedback on this by drupal experts.

And, by the way: Access control for menu items (especially based on node permissions - what point is there in displaying a menu item that leads to a forbidden node?) seems to me to be a very general problem that is not really addressed in drupal. Would it be sensible to post a feature request for this?

With best regards,
Martin