The Drupal node access grants system has always been a powerful and flexible way to control access to your nodes. It's been there from Drupal 5 (if not earlier) and it continues to exist in Drupal 8 as we move forward. In this article, I want to quickly highlight this system from a D8 perspective and how I propose to use it in a OOP architecture.
What is it?
The node access grant system is a way by which you can control programatically and very granularly access to all four operations on your Drupal nodes (view, create, edit, delete). It allows to define certain realms of functionality (related to your access requirements) and a set of grants that are required for any of the four mentioned operations, within that realm. Users will then need to posses the grants in the respective realms in order to be granted access.
The two main components of this system are therefore:
- The implementation of
hook_node_access_records()which is called whenever a node is saved (or site-wide permissions rebuilt). It is responsible for storing the access requirements for that given node.
- The implementation of
hook_node_grants()which is called whenever a user is trying to access a node (or a query is being performed in the name of that user). It is responsible for presenting the grants for the current user, which if match the access requirements of the node, allows them access.
The great thing about this node access grants is that it's system-wide in the sense of who checks for the access. In contrast to implementing
hook_node_access() which only is called when viewing a node on its canonical URL, the access grants are checked almost everywhere such as views or even custom queries with much ease.
In Drupal 8 these 2 hooks remain the foundation of the node access grants system, albeit with type hinted parameters. This means that we need to place their implementation inside our
Node access grants are not used on every site because they serve relatively complex access rules. Complex access rules usually also require a fair bit of calculating what grants a particular node must have for a given realm, as well as whether a given user possesses them. For this very reason I am not so fond of having to put all this logic in my
So I came up with a basic developer module that defines an interface that has two methods:
grants(). Other modules which want to implement the access grants hooks can instead now create a service which implements this interface and tag it with
node_access_grants. My module will do the rest and you won't have to touch any
.module file. You can inject whatever dependencies from the container you need and perform whatever logic is needed for determining your grants and access records.
Let me what you think down in the comments. Would love your feedback.