~ 2 min read

Implementing user-specific, role-based access control per node type, per group. (Part 1)

share this story on
Understanding Drupal's node access system and how to hook into it to implement

We’re going to review a fringe case of setting an access control system, such that, the view access to a node is dependant upon the role the user have. To further complicate it, users get different roles in different groups they are in.

Basic node access system overview

To understand first how Drupal’s node access system behaves by default, let’s follow this process flow that presents what happens when a node is being accessed via node_load():


Process (1) and (2) are pretty obvious. If the user is an administer the node access checks are bypassed and the process gets short-circuit there.

Process (3) is rather interesting, this is Drupal’s attempt to be modular and it looks out which module created (or is in-charge of) this node content type and fires it with the operation and extra parameters. It’s a nice attempt and at best, only that. It’s not really helpful because most chances are that our module did not define the content type. So yay, still no luck to hook in here and get our job done.

Process (4) is the final step of attempting to resolve the node access requirement and hits the heart of Drupal’s node access system. We’ll focus on this part next.

Node access is handled in 2 places

  1. When the node is loaded via node_load() (and goes through the process visualized previously)
  2. When a database query is crafted to return node related information:
    1. This happens either in a developer’s custom code when executing db_query() and then wrapping it with db_rewrite_sql(), which re-structure your SQL to join the node_access table for node records (if you’re not wrapping your queries when fetching node information for users you’re doing it “wrong”, bypassing any underlying ACLs).
    2. The Views module is an administrative GUI which yields a database query that fetches relevant data and then themes it. The Views module does not perform a node_load() for each node in the generated result-set (for obvious performance reasons) which is why it’s also using internally db_rewrite_sql() for the actual generated result.

As you may have realized by now, it doesn’t really matter if you’re doing a node_load() or a custom database query, in either case the underlying node access system is involved in the process of determining access.