I've brought up this idea associated with various modules since 4.3, and now that 4.5 is out with several different modules that use the node_access hooks for granular permissions, I thought I'd bring it up again, because it seems as if the way node_access is implemented in node.module may prevent another module from doing what I'd want-- or, at least, require bypassing node_access to make it work.

As I understand from the comments in node.module, the default rule in the node_access table allows all users to access the view function of all nodes. As the node_access function assumes a user is denied access unless explicitly allowed, and any rule allowing access is respected for any combination of users or nodes, this seems to make this system very useful in some situations but much less so in others.

For instance: At a site catering to three separate groups of comparable size that need to see some of their own content, and some of one or more of the other groups' content, this module would appear to work well. The number of nodes any given user may have access to may range between, say, 1/3 to 2/3 of the total number of nodes, so it makes sense to assume users will not have access unless explicitly granted, and that any rule that grants such access should be respected.

However, for a site that is more of a traditional news portal, or anything not based on a small community working on different projects (such as Drupal.org itself) you might have a quite different scenario: a large number of users, most of which are either anonymous or authenticated, but have no other special role, and yet are still assumed to be allowed to have access to the vast majority of the site's content, save for a small number of items reserved for administrators or for some other small group of users.

Such is the situation on my site, and I am finding that with two of the current permission modules, privacy_by_role and taxonomy_access, the use of these modules generates a large number of costly table joins. To administrate all the site's taxonomies with taxonomy_access, for instance, requires checking the "view" permission for the site's taxonomy terms (over 100) for each group of users (five of them) that are all allowed to see such content, all for the sake of unchecking the one or two terms that these user groups are not allowed to see.

Then, when displaying node listings, each node ID is checked for the appropriate permissions, even though in the vast majority of cases the default deny rule is overridden by one of the many rules that grant access to most terms.

And in the end, because of the way taxonomy is used on this site-- to categorize news stories, for instance, according to various criteria-- this scheme does not allow any content to be restricted because any rule allowing access overrides the absence of a rule allowing access.

Just to show I'm not trying to be dense-- the site in question is a game site. It has two major vocabularies; one identifies which game is associated with the item (story, page, image) by title, and the other indicates what kind of content the item contains (interview, review, preview, etc). My goal is to create one or more terms in the latter taxonomy that are available to only certain roles-- regardless of what other terms are assigned to the item. In this case, the term is "spoiler"-- indicating that the item will reveal a portion of a game that a user who has not played it might not want to see.

Under the current scheme, this is impossible. An item tagged with only two terms-- "doom" and "spoiler" for instance, indicating the item will spoil doom if the user plays it, cannot be restricted in any meaningful way without losing the categorization information. If a user in a group has access to neither term, then NO items with the "doom" term will be visible, regardless of what kind of content it is. Not desirable.

If the user has access to items with the "doom" term, but not the "spoiler" term, then the system will grant access to that item, since the rule that allows access for the "doom" term overrides the absence of a grant on the "spoiler"-- meaning that even users without permission to see spoilers will see them anyway.

In short, it seems that the current node_access scheme is about a quarter of what you'd expect from a usual firewall-- it is set up by default to DENY ALL to ALL, and any rule that allows access overrides any other rule that denies access.

What I would want, at least for my site, would be an optional configuration where the default permission was ALLOW ALL TO ALL, with the node_access table used to store DENY rules, where any deny rule would override any grant. With a setup such as this, it would be relatively trivial to restrict access to nodes, regardless of what other terms they are associated with, based on a single term or collection of terms that are supposed to be available only to privileged users, using a very small number of entries in the node_access table.

My questions are: Is it likely or possible that a configuration setting could be made in node.module that would change the default behavior from DENY BEFORE ALLOW with all further ALLOW rules authoritative for any given node to ALLOW BEFORE DENY with all further DENY rules authoritative for any given node?

If this is possible, would it be necessary to change the way other modules that update the node_access table work? Or would it only be necessary to update the help text, indicating that, for instance, in the taxonomy_access.module, that when DENY BEFORE ALLOW is the default, that a check in a term permission screen means ALLOW, and that when ALLOW BEFORE DENY is the default, that a check would mean DENY. It strikes me that this could and should mean far fewer entries in the node_access table, if one assumes most users can see most content, as it would not be necessary to make any additional rules to grant access to content, but only to deny it.

Sorry this is so long-winded; this is something I've actually been trying to do with Drupal since before 4.0 with various ugly hacks of my own and a series of contributed modules; it seems like things are getting so tantalizingly close, and yet still... not.. quite there...

Comments

robb’s picture

I think my new module node_access may be able to help you. It works a bit different than you describe but I think the end result is the same. The module is still in development but is ready for Beta testing under MySQL, PgSQL support is still being tested. If it doesn't do what you need let me know.

http://drupal.org/node/24868

magico’s picture

Version: 4.5.0 » x.y.z

Anything new about the Drupal node access system?

lilou’s picture

Version: x.y.z » 7.x-dev
Status: Active » Closed (fixed)

See contributed module.

lilou’s picture

Version: 7.x-dev » 4.7.0

Node Access Arbitrator