If you create a menu item for a node (using the menu module), that menu item will always be visible in navigation blocks. If you restrict access to that node, using node access modules such as OG or TAC, then that restriction has no effect on the display of menu items. Users who do not have access to the node are still able to see the menu links, and when they click these links, they receive an 'access denied' error.

The reason for this undesirable situation is the way that the node access system (or should I say, Drupal's access control system) is currently set up. The 'node' menu item is a static, cached item, and all users with the 'access content' permission are able to access it. The 'node/x' menu items, however, are dynamic and non-cached, and Drupal doesn't determine their actual access until a node page is requested, and the whole node access mechanism kicks in.

So in determining the access for display of menu links, Drupal simply looks at the 'access content' permission for the 'node' menu item (which is the 'parent' of all 'node/x' pages), and never gets round to looking at what node_access has to say about it.

This patch presents a complete hack solution which fixes the problem. It looks through the 'menu' table in the DB, to see if there are any user-defined menu items for node pages. For each one that it finds, it defines a cached menu item whose access is determined by the full power of node_access. The menu items must be defined in the cached part of hook_menu(), because if they're in the non-cached part, the custom items have already been loaded from the DB, and it's too late to define their permissions.

I fully admit that this patch is a hack, and that it is not a proper solution, and that it does NOT belong in core. This patch could even be implemented as a separate module, without needing to hack the core node.module. But I posted it here in order to draw people's attention to this issue, and to see if anyone can think of a better and more long-term solution. I understand that REALLY solving this problem could be quite hard, and may involve seriously re-thinking certain aspects of the menu system. But at least this is a start. And for people that need access control to be observed in displaying links to node pages, this is a solution that will work today.

CommentFileSizeAuthor
node_access_menu_items.patch1.03 KBJaza

Comments

Jaza’s picture

I just found http://drupal.org/node/45988, which is a related but slightly different issue. The patch committed in that issue made the situation better than it was before, but it definitely left THIS issue outstanding.

killes@www.drop.org’s picture

this looks like ressource intensive. I recommend putting it into a custom module.

chx’s picture

Status: Needs review » Needs work

Let me quote from the linked issue!

#44 submitted by Jose A Reyero on March 20, 2006 - 20:42

An now you forgot the '$' in '$_menu' :-)

The thing is the patch works, but I still see the menu item -though it returns access denied-. Should I see it?
#45 submitted by chx on March 20, 2006 - 20:51
Attachment: node_51.patch (1.33 KB)

yes you should. it's still not possible to cure, unless you do the aforementioned set $_GET[q'] to path and gather !$may_cache for each. Would be slow as hell.

This code is inadequate. If you start walking the road, walk it fully and gather all noncachable items for the visible menu items.

decafdennis’s picture

The functionality would be great, but it'll be difficult to implement without affecting performance/speed. Currently I'm using a home brewn theme_menu_item solution, and try to minimize the number of nodes in my menu. (No good solution either.)

Jaza’s picture

To follow up from the quote that chx posted from the related issue:

This patch takes the first step in "walking the road fully", by gathering all non-cacheable menu items for node pages, and defining cacheable items for them. The most resource-intensive thing about the patch is the DB query: the actual process of defining extra menu items is not as intensive as it looks, because those items would have been defined anyway, when the menu system found them in the DB.

As I said, I did not post this patch with the aim of getting it in core. I posted it in order to show people just how crappy the current option is for defining node menu items properly, and to highlight the need for an improvement to the menu system that may allow for a cleaner and more efficient solution. I haven't thought of such a solution myself, and I'd love to hear if anyone else has some ideas.

killes@www.drop.org’s picture

killes@www.drop.org’s picture

Status: Needs work » Closed (duplicate)

see referenced issue