Node Access by Menu Position -- Does this exist, or should we build it (and can it be built)?
A client of ours -- a university -- has quite an extensive hierarchical menu structure. They want the ability to take a top-level menu item, such as "Current Students" and control which roles can manage (create/edit/delete, based on their role's permissions under admin/user/permissions) and view the content under that section. Permissions should cascade down to sub-items in the tree unless explicitly overridden. They also need to then restrict access to adding new pages underneath menu items they do not have access to.
Here's a mock-up that describes what we're after, since it's easier than me explaining. :) Also, I should point out that this is for Drupal 6.

I know of Menu Sub-tree Permissions which should be able to handle the limiting of placing things in the menu on node addition, and Menu Per Role which restricts access of viewing. Anyone know of one that does it for create/edit/delete? Is this worth rolling into one of the above modules (once they're ported to D6), or as a separate project, or am I missing a big, blinking cluestick of a module that does this already?
Thanks for any assistance!
| Attachment | Size |
|---|---|
| menu-access.png | 189.71 KB |


Monster Menus at Amherst
Monster Menus at Amherst looks for a similar goal in a university environment.
http://groups.drupal.org/node/10231
organic groups access control
Yeah, you definately want to read about monster menus. But ultimately that approach is very costly since it does not play nice with node access and thus you can't get your Views to respect its access control. Perhaps Views can be plugged so that it understands monster menus notion of access control. I suspect not, since it is't a pure SQL system.
You are still missing a major piece of the puzzle. Namely, the nodes themselves are not protected. If I understand it right, Menu Per Role just protects menu callbacks. Your search, notifications, etc. will not know who has access to what.
I don't know of a perfect, available solution here. To me, the closest fit is OG and its access control. You could use hook_user() to sync users into the right groups based on their roles. Even better, you could help me enhance OG so that group membership can be swappable for any given content type. These "role based membership groups" would dynamically determine their member list based on the users_roles table. In addition to roles, this swappability would be interesting for user profile fields (e.g. users in the Marketing department automatically are members of the marketing group.)
I don't know that you need it here, but the OG Subgroups module is actually quite elegant in D6. That might confuse more than help so just ignore that if needed.
Hm...
Well I was thinking this would be a node access module based on the menu system. So gid would be equivalent to.. hm. mlid? Or maybe the node's path?
The disadvantage obviously is that this would only work for nodes, and other things such as views or module-exposed menu items wouldn't work in the same system. Unless maybe we did some funkyiness with hook_menu_alter() too. Hm...
We can use OG, and we're prepared to do that, but it's pretty heavy. We shouldn't need an entire group to just hold a map of the campus so that 3 people can edit it, ya know? :)
I've downloaded a copy of menu monster and will take a more thorough look through it tomorrow. But there seems to be lots of unrelated code there (which, to the author's credit, he warned about) as well as scary bitwise operator stuff that I don't quite understand. ;)
Anyway, thanks for your thoughts!
Oh, wait. I see.
So one OG per "Role" or "Department" (like Admissions, IT, etc.) and put the individual pages (Prospective Students, Undergrad Programs, etc.) into the group(s) that has the access that we want. The users' group assignments get synched when the user is edited and their roles change, via hook_user(). Yeah, that could work. Then maybe just add a UI on top of it so that it matches the user expectations.
Do you have a link to an issue about the group membership abstraction? That might come in handy indeed.
Beware, the group membership
Beware, the group membership issue has some ancient baggage in it. I am very willing to use an OO based solution now that we are on all on PHP5 and the DB system has gone that way. I was thinking that this might be an interesting use case for handlers (code). That is, each content type or perhaps each group has its membership managed by a 'handler'
please work on an existing project
My hope is that you will work towards updating an existing project. A good candidate is the Remove Nonviewable Menu Items module. From the project description:
Another module that's Drupal 6-challenged is Menu per Role, which can be applied to all types of menu items (custom, node, views, etc.).
taxonomy?
Maybe I'm not understanding exactly, but if the menu is hierarchical... a taxonomy can replicate the same structure (and maybe the menu can be generated from the taxonomy). And access by taxonomy is well fleshed out, no?
-Cathy (a newbie)
Cathy Theys
http://YesTrainingAndEducation.com
Yeah, I considered that...
Taxonomy has a nice advantage where you can setup your site's navigation ahead of time and not do it slowly and painfully on a page by page basis. In Drupal 5 and below, you used to be able to sketch out your menu structure, but in D6 it won't let you do that until a page exists at that URL. Ugh. So taxonomy would be great because it would let you add pages individually when you needed them and then choose which section they belong to.
The disadvantage of taxonomy is that it's intended to generate a list of pages with the same term. In the case of site structure, you only ever want a 1:1 term:node mapping. So you're already in a place where you need to begin by working around taxonomy's default behaviour. Also, the Taxonomy Menu module seems to stick the vocabulary name in as the top-level menu item with all of its terms below it. For example, instead of me getting Current Students, Prospective Students, etc. I get "Site section" in primary links. There's not a way that I can see to say "Make this entire vocabulary the primary links." That would probably be pretty easy to add though. But true enough that Taxonomy Access / Tac Lite would let you perform this sort of access control.
Hm.. books?
Book / Book Access actually gets /very/ close.
The hierarchy is built in. You get a nice built-in sidebar block with:
In Drupal 6, you can specify that different node types (e.g. "Page") are the ones that get added to the outline, and remove the confusing "Book page" type. The outline is also menu-based (although that doesn't seem to be reflected in the UI anywhere).
Book Access module provides a very similar interface to what we're looking for:
Disadvantages:
- Still tedious to build out site structure on a page-by-page basis.
- Book Access doesn't support overriding sub-pages.
- No indication on the main admin/content/book page of what the access permissions are.
Seems like these last two could be worked around as patches to Book Access.
Still a concern?
1) yes managing hierarchical content is tedious, but only a mind reading robot could automate that
2) no, book_access does not let you enable access to a single page in a book and not others. for that type of functionality, i'd probably point users to content_access.module, but now you'd have to manage all the pages individually. Or you could use book_access to set role level permissions, then use content_access to fine tune individual nodes (which i think is the best use of content_access anyway). however, i'd need to enable a configurable grant priority so that book_access could be given lower priority than content_access. but that should work. i would implement that if there were a need.
3) since it's not meant for highly granular (ie user based) permissions, i didn't think there was a real need for an additional tab. but now that you mention it, it might be a good idea to display the roles that have access to a book in the book itself (to those with 'administer node' perms or whatever of course).
--
Drupal tips, tricks and services
http://devbee.com/ - Effective Drupal
Alternative
We may be faced with a similar client issue, and I tend to think that Node Access is not the right way to go here, since these are exceptional rules for only a few users, you don't want to introduce the overhead of the Node Access system.
One option works cleanly IFF, other users still have the ability to create and edit content, and that is to use hook_form_alter() (or possibly hook_menu_alter()) to enforce your business logic.
With hook_menu_alter(), you could introduce a different access callback for node editing pages. With hook_form_alter(), you could restrict certain settings or actions based on the business logic.
--
http://ken.therickards.com/
any solution?
Just wondering if you found a solution for this?
One clarification
I'm coming late to this discussion, having only just recently found out about it. As the primary author of Monster Menus, I feel I have to comment on one thing Moshe said:
The only aspect of node access that does not work as expected regards the use of node_access to determine whether or not a particular link (usually edit or delete) should be displayed to the user. Without a patch to core, which was discussed in another thread, the user gets links to functions they aren't actually allowed to perform. Authorization itself is handled during hook_nodeapi(), and is quite effective and robust.
We use MM with Views, without any changes to Views' code. I recently wrote a Views plugin for MM to correctly display edit/delete/revisions links only for the nodes upon which the user has permission to perform these actions.
It is fair to say, however, that it is not easy to write a view that omits rows for which users do not have read (or write) access in MM. Because permissions are hierarchical, there is no single table join that can be added to a SQL statement in order to calculate this.
This situation can often be worked around by limiting your views to segments of the site where you know in advance that the user most likely has a particular set of permissions for all of the nodes. For example, at our college, we put the course catalog editing process into Views and CCK. We created a particular part of the menu tree where only people who can edit the catalog have read permission, and used views to show them tables of the courses in a given year and subject area. Because all of the users who can get there in the first place have the ability to read every course, it doesn't matter that these tables contain all of the courses.
Update
This module is now possible, using the Menu Node API. http://drupal.org/project/menu_node
A slight variant on the approach is available as Menu Node Edit, which only deals with editing access and is not a node access module.
http://drupal.org/project/menu_node_edit
--
http://ken.therickards.com/
Thanks
Just a quick note of thanks to Ken (agentrickard). Your work on the menu_node module gave me an idea for a way to get rid of the one place where we had to modify core for Monster Menus. Assuming testing goes as anticipated, we'll be 100% core-mod free.
Monster Menu Update?
Gribnif: Are you going to post/make available a new version of monster menu once you have finished testing? I think your module would be very useful in our university site I'm building. Thanks, Scott
http://drupal.org/project/men
http://drupal.org/project/menu_node_edit is indeed a great tip, seems to do the trick nicely, thanks!
Dekbedovertrek kinderen