Last updated February 20, 2014. Created by jfall on March 15, 2011.
Edited by HeBD. Log in to edit this page.

Views provides basic access control by role or permission for each View display. This is usually sufficient. But what if you need finer control? For example, only allow access to the view if the current user has a specific relation to the view argument.

Use-case

  • Authenticated Users on my site manage their own node pages - they have update access on the nodes they author, but only view access on pages authored by others.
  • Moderators and Administrators have update access on all pages.
  • A node page typically contain "attached" views - such as a list of photos or products associated with the page via a Node Reference. (see the wonderful Views Attach module)
  • I want to add a tab to the page that displays all the items "attached" to the page, with edit & delete links, AJAX field editing, etc. (a mini CMS for the user's attached content items.)
  • BUT, this tab should be visible ONLY to users with update access on the page's node.

Another example would involve adding a tab to the user's profile page that was only visible to the user themselves. (For complete case study, see: http://www.urbaninsight.com/2010/09/20/custom-access-control-drupal-views)

General Solution

Other solutions have been proposed, but Ki Kim's solution is very flexible and can all be coded within the view itself.
The basic idea is simple:

  1. add an argument to the view
  2. use PHP validation code to validate the argument
  3. as part of the validation code, check the access control rule
  4. select "Hide View" if validation fails

Voila. You can add whatever access control logic you like to the argument validation, and if the request fails to meet those criteria, the view will not be displayed.

Specific Solution for Use-Case

The view defines:

  • its path as: node/%/product-list
  • a tab menu (this tab will appear on the node/% page)
  • a relationship to a Node (required), based on the Node Reference in the targets
  • an argument: Node:nid on that relation, so that only nodes with a reference to page node are listed
  • a filter to select the related node type

On the Node:nid argument, a "PHP Code" validator is defined, with "Hide View" as the action to take if the validation fails. This is the code used to validate the Node:nid argument:

    // Code taken from views_plugin_argument_validate_node.inc : validate_argument()
    // It validates that the argument is a nid for a node of specific type (the page node type)
    //  What's different is that it validates that the current user has UPDATE rights for this node.
    if (!is_numeric($argument)) {
        return FALSE;
    }
    $node = node_load($argument);
    if (!$node || $node->type != 'page_node_type') {  // NOTE: page_node_type is the node type id.
        return FALSE;
    }
    // does current user have update access to this node?
    return node_access('update', $node);

I think this is a very general approach and could be applied to a range of view access control issues.
Again, my thanks to Ki Kim for the original idea!

Looking for support? Visit the Drupal.org forums, or join #drupal-support in IRC.

Comments

you also need to understand that view arguments restrict the view to the argument provided (node view, uid argument -> display only nodes owned by uid), so if you dont actually want an argument, use one that will not filter anything, so for eg if i already filter my node based view with a filter content type "profile", i would add an argument for content type, specify default when not provided to be again "profile", and enter the php validation like above..
thing is that although this works, its not a true access check, as in if you have a menu link to that view, the menu link will still be shown but the page will return 404, whereas with a true access check, the menu link will be hidden
but you can hide the menu through other means

Views 2 makes your live easier. If you use Views 2 you can use

hook_views_pre_execute (&$view)

There many Views 2 hooks, see http://views.doc.logrus.com/ for complete information and samples.