Managing Drupal content permissions with the Permissions by Term module

Submitted by Peter Majmesku on Sun, 11/04/2018 - 20:20

I have spent a lot of time (years) in development of the Permissions by Term Drupal module. Now it's time to create a blogpost about it.

Per default, Drupal allows you only to restrict access to Drupal nodes by coupling node content types to user roles. The Permissions by Term module extends Drupal by functionality for restricting view and edit access to single nodes via taxonomy terms. If you have installed the Permissions by Entity sub-module, any other content entity type, such as media entities, can be controlled in access restriction, too.

Taxonomy term permissions can be coupled to specific user accounts and/or user roles. Taxonomy terms are part of the Drupal core functionality. Since Permissions by Term is using Node Access Records, every other core system will be restricted:

  • search results
    • Works well with Search API  modules search result lists, since PbT version 8.x-2.0
    • Drupal core search
  • menu items
  • views list items
  • content from all content entity types (nodes, media)

After you install Permissions by Term, you can easily access its configuration:

Then you are able to configure the module to suite your purpose.

Config option: Require all terms granted

By default users are granted access content, as long they have access to a single related taxonomy term. If the require all terms granted option is checked, they must have access to all related taxonomy terms to access an node.

Config option: Permission mode

This mode makes nodes accessible (view and edit) only, if editors have been explicitly granted the permission to them. Users won't have access to nodes matching any of the following conditions: 

  • nodes without any terms 
  • nodes without any terms which grant them permission

Config option: Disable node access records

By disabling node access records, PbT won't hide nodes in: 

  • listings made by the Views module (e.g. search result pages) 
  • menus

This setting can be useful, if you just want to restrict nodes on node view and node edit. Like hiding unpublished nodes from editors during a content moderation workflow. Disabling node access records will save you some time on node save and taxonomy save, since the node access records must not be rebuild.

Then it's time to edit your taxonomy terms. You will see the Permissions by Term fieldset for adding your users and/or roles permissions. See the extended form:

Afterwards let's edit an node. You will see that the advanced widget for term related permissions will be filled with info (via AJAX) as soon you edit any taxonomy term related information.

Restricting access to taxonomy terms

Editors won't be able to use taxonomy terms for content relations, if specific taxonomy terms have access restrictions, which deny them access. See the following screenshots:

Securing documents in your filesystem

You can enable the Permissions by Entity module, which is integrated as a sub-module in the Permissions by Term base module. Then access to all content entity types can be handled via taxonomy terms. Not only the node content entity type. A prominent content entity type could be a document bundle from the media type.

I will show you, how you can restrict the access to documents from your file system via a document media type bundle.

  1. Firstly enable drupals private file system
  2. Make sure your fields file is located in the private file system (field settings)
  3. install the Permissions by Entity module
  4. and implement hook_file_download() by adapting the following code into your custom modules *.module file:
 * Implements hook_file_download().
function fancy_module_media_document_file_download(string $uri) {
$files = \Drupal::entityTypeManager()
loadByProperties(['uri' => $uri]);

  foreach (
$files as $file) {
$multipleMedia = \Drupal::entityTypeManager()
loadByProperties(['field_document' => $file->id()]);

$oneMedia array_shift($multipleMedia);

    if (
$oneMedia instanceof Media) {
       * @var AccessChecker $accessChecker
$accessChecker = \Drupal::service('permissions_by_entity.access_checker');


Now requests to https.//my-website/private-file-folder/secure-document.pdf will be handled over your permissions. Users without permissions will be redirected to a "Access denied" page (HTTP status code 403)

Permissions by Term Redirect

This module builds upon the functionality provided by Permissions by Term in the following ways:

  • registers a subscriber for the event fired by PbT in case of Access Denied
  • sends a redirect to the login form if:
    • the user is anonymous
    • they are trying to directly access the restricted node
  • after a successful login sends a redirect back to the originally requested node

Code quality via automated tests in a continuous integration environment offers the ability to execute automated tests. However, this tests are not executed immediatelly after any code changes occur. Developers must wait until their modules code gets queued. For this I am using Bitbucket as a CI environment. I have learned a lot via developing the Permissions by Term module. I am using not only Drupal tests like PHP unit test or functional tests like tests which are inheriting from the KernelTestBase class. I am also using Behat tests, which are testing the module against a real web browser. Permissions by Term is containing JavaScript code. So I am testing the JavaScript code via QUnit and Webpack plus Babel for packaging my JavaScript code.


I would like to thank all people which have been contributing to Permissions by Term via sharing bug reports, patches, feature improvements, documentation, spelling and other. Also I would like to thank my employer publicplan for providing me paid time to work on Permissions by Term during my regular work hours. If you are searching support for your governmental website, then you should really consider publicplan. Furthermore publicplan is constantly looking for Drupal talents. So do not miss your opportunity.


If you have any feedback in forms of suggestions or questions, I would be happy, if you could leave here a comment. Also the Permissions by Term issue queue is a good place for sharing information.