I'm trying to bypass some of the permissions set by Workbench Moderation, only under specific circumstances. For a specific content type, I need the users of a specific Role to be able to: - View all Published nodes of that content type (this works fine as it is quite general) - View Unpublished nodes only if the nodes 1. are related to them (through Entity Reference field) or 2. they have created themselves. - Edit nodes only if they are related to them (through Entity Reference field) or nodes they have created themselves. This should be allowed only in a specific State.

I've tried implementing hook_node_access_records() & hook_node_grants() hooks in my module but this doesn't seem to work. In the following example, the conditionals are different than what's mentioned above but the logic is the same:

function mymodule_node_access_records($node){
    $grants = array();
    if ($node->nid == 1234 && $node->uid == 99) { //(example conditions)
        $grants[] = array(
            'realm' => 'mymodule',
            'gid' => 123,
            'grant_view' => 1,
            'grant_update' => 0,
            'grant_delete' => 0,
            'priority' => 0,
    return $grants;

function mymodule_node_grants($account, $op){
    $grants = array();
    if (($op == 'view' || $op == 'update') && $account->uid == 99) { //(example conditions)
        $grants['mymodule'] = array(
    return $grants;

This does add a line in node_access table where only grant_view has a value of 1. It should just allow related users to view the specific (unpublished) node but not edit it.

UPDATE: I installed Devel node access and here are my findings for the test case above (node 1234 is Unpublished, user 99 is author):

  • Test User can View the node - OK
  • Test User can Edit the unpublished node (non-Published draft) - NOT OK
  • Test User cannot Delete the node - OK
  • Test User can Moderate the Unpublished node (allowed transitions set by WM config.) - OK

Here is what Devel actually displays on that node's view page:

  • Create: YES: by node (permissions) - OK
  • View: YES: view own unpublished content - OK
  • Update: YES: by node (permissions) - This should be overridden by my access module
  • Delete: NO: no reason - OK

How can I override this edit permission with my module? I'd eventually like to expand the functionality of this module to cover other cases as well.

  • Both look OK. Can you follow the help at drupal.stackexchange.com/a/109025 and tell us what is denying the page? It could be several things.
    – mpdonadio
    Apr 10, 2014 at 12:20
  • I'll check it out and come back with the information, thanks.
    – webmaniac
    Apr 10, 2014 at 14:53
  • I just added my findings from Devel Node Access. I also simplified the wording.
    – webmaniac
    Apr 11, 2014 at 9:30

2 Answers 2


Access to the 'node/%node/edit' path is done by node_access(). It first checks some global permissions, and then invokes hook_node_access() to check for explicit allows and denys. node_node_access() checks the permissions at admin/people/permissions, and will return NODE_ACCESS_ALLOW if set.

Based on your debug information, it looks like a permission is allowing the update operation, so the grants aren't being checked.

I think you need to do one of two things.

You could implement your own hook_node_access() that returns an explicit NODE_ACCESS_DENY when you need to. This will override any explicit NODE_ACCESS_ALLOW.

The other option is to remove the explicit edit permissions for your content type(s), and then use grants. You would have to update the logic in your hooks to cover all of the cases where someone can edit the content, and not just your special cases.

Make sure you also read up on node access rights (see also this article), as they can be confusing until you really grasp how they work. Just remember

  • If using hook_node_access(), a NODE_ACCESS_DENY will override a NODE_ACCESS_ALLOW, but not the other way around.
  • If using grants, the default is to deny to all, and then allow to some. It's early, and I can't quite remember if you can explicitly have a grant that denies one that has already been granted.
  • Thank you for that, I already have that extremely useful article in my bookmarks and my decision to use grants was heavily based on it as I really need my grants to be respected by Views, menus etc. I had the "Edit Any Content" permission checked for the Content Type & User Role I'm working on as I thought it would be better to first allow all and then restrict some access. It wasn't clear to me that grants are not checked if op is allowed. I'll have a go and see what happens.
    – webmaniac
    Apr 11, 2014 at 14:08
  • I tested and it's now working. I believe I can now cover all the access cases I need for my content type. There is still a little issue though, permissions are not rebuilt whenever Workbench Moderation imposes a State change to my nodes as this is not a "clean" node save. How does the idea of rebuilding permissions every time WM state changes sound?
    – webmaniac
    Apr 14, 2014 at 10:38
  • @webmaniacgr Try implementing hook_workbench_moderation_transition() and calling node_access_acquire_grants($node).
    – mpdonadio
    Apr 14, 2014 at 13:40
  • I'm rebuilding permissions but I'm testing my module and Drupal asks me to rebuild permissions whenever I visit a node while logged in as a different user. When I rebuild permissions as admin and then visit the same exact node as test_user, permissions are wrong and I have to rebuild permissions as test_user. Then the problem is fixed for test_user but the same problem happens when I login as admin etc etc. (!!!)
    – webmaniac
    Apr 15, 2014 at 14:00
  • The problem described in my last comment is not exactly correct as it was caused by an additional unnecessary grants I was mistakenly adding for Viewing specific nodes, when the user had already access to View them. I'll mark your answer as correct as it truly helped answering my question, thank you.
    – webmaniac
    Apr 16, 2014 at 11:15

A helper module that I use for managing node access is ACL .

The ACL module, short for Access Control Lists, is an API for other modules to create lists of users and give them access to nodes. It has no UI of its own and will not do anything by itself

What I suggest is that instead of handling the grants yourself, you outsource it to ACL. The module has a simple (YMMV) to use high-level API that let you grant individual users access (and revoke it).

The documentation is a little sparse, but on the ACL project page existing client projects are listed. I learnt how to use it by reading the source code of those.

Alternatively, you can read the source code of ACL to see how to do low-level manipulation of permissions.

If you end up writing your own module, the introduction to this page gives a good introduction to how Drupal's node access system works. In particular, you should be aware of:

Node access modules always GRANT access and never restrict it. (It is a whitelisting rather than a blacklisting system.)

I understand you already use DNA (Devel Node Access), but if somebody else stumble across this: DNA (part of the Devel project) is absolutely essential if you are going to debug node access.

  • It looks like a nice module for access control but I need to avoid installing additional modules like node access or ACL as WM already adds complexity to access issues and I just need to fine tune access under very specific circumstances.
    – webmaniac
    Apr 11, 2014 at 10:36

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.