16

I am using hook_node_access() to deny users access to some nodes based on a custom criteria. However, I do not want this content to show up in a view that lists it if the user does not pass the criteria. Is there any way to have views respect hook_node_access() implementations?

5
  • I don't think that hook is fired until the node is actually loaded in its entirety with node_load so that's probably why it still shows up. I have however started working on a filter plugin that will use the same method for filtering that the implementation of hook_node_access() uses to lock people out. I will just have to remember to add that filter in all my views and it should work. I will get back here with info on it once i am done so that others can benifit. Commented Feb 21, 2012 at 21:17
  • Ok, so my use case was this: Customer wants 10 levels of access applyable for any node and users should be able to see all nodes bellow their access level. This was easily solved via hook_node_access for standard node view. However, as views didnt respect this i created a contextual filter with custom php code for the argument. The php code basicly returned the lower than or equal values for the users access level(in proper syntax separated by ,). The drawback of this solution is that every view will need this configuration. Commented Feb 22, 2012 at 10:53
  • I found an issue for views that deals with this problem, it also refers to a proper way of solving the issue: drupal.org/node/1266388 . Commented Feb 22, 2012 at 14:29
  • 3
    If you can write an answer about how to solve the issue, that is perfectly acceptable; as merlinofchaos says, the Views module is loading the nodes using a database query, and that is the reason why hook_node_access() implementations are not respected. As it is "by design," reporting a work-around is fine. Commented Feb 22, 2012 at 14:52
  • When I have instances like this where specific parameters must be met before a listing of nodes (or entities or whatever) must be shown, I create the callbacks by hand in a custom module. It's much easier than you think. Take a look at the EntityFieldQuery class: api.drupal.org/api/drupal/includes!entity.inc/class/…. You can get a list of nodes that meet your parameters and then display them using theme_table or something like that. Having granular control is a wonderful thing :) Commented Apr 3, 2012 at 20:59

3 Answers 3

8

I had the same question a while ago here.

hook_node_access is not recognized by views or menus. It should only be used as the last line of defense.

A better way to control node access is through hook_node_access_records and hook_node_grants as described here and here .

5

hook_node_access() only is invoked when trying to view the full node. What you need to do is implement hook_node_access_records() and hook_node_grants().

0
1

Views uses SQL determine the nodes to display. Sadly, for performance reasons it simply would not be feasible for Drupal to perform a node_load on all potential candidates and then call hook_node_access on each one of those of all of them. Imagine a view which shows thousands of nodes (especially when using a pager). If the logic isn't done in SQL then the pagers would have very unusual functionalty thus Drupal forces you do it as rik mentioned using access records in your database.

Making access_records is a fair amount more work but will make it work with SQL. Thus I recommend using an existing node_access module to solve your functionality wherever possible because it will probably be implemented using access records and thus will work with views.

By the way the access records are stored in the table node_access table as seen below: enter image description here Through the comments for each column you can get an understanding of their purpose. Think of the realm as the system used for node access and the gid as the group within a realm. That group can have view, update, and delete permissions. In general each node_access module defines one or more realms (sometimes multiple node_access modules can also work in parallel). A user has one or more gids in each of the realms.

In Drupal all queries that have the "node_access" tag will automatically have some special logic added. See the documentation to learn more about tagging. This special logic joins the "node_access" table for each realm and adds the condition that where the "gid" is equal to one of the gids applied to a user, the user has the appropriate permission.

This whole system allows all queries to properly handle node_access, even count queries, etc. It is very powerful but has a higher learning curve that just the simple hook_node_access. Whenever possible, using an existing node_access module can save you this whole headache.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.