1

I'm writing a module that allows users to configure special access restrictions on nodes to reflect academic publishing agreements (called 'embargoes'), which are stored in a custom config entity that points to a node and describes what types of access restrictions should be applied, and who is exempt (users, roles, IP ranges, etc). One of the requirements for the module is that users should be able to restrict access to the entire node (a "node embargo"), OR just the files on the node (a 'file embargo') so that the node itself is accessible and shows up in searches, but the files associated with it are not accessible.

I have implemented the 'node embargo' portion of the module using hook_node_access and checking a custom service to determine if the user should see the node or not, and returning \Drupal\Core\Access\AccessResult::forbidden() if they shouldn't. This works exactly as desired, and not only blocks access to viewing the node, but also access to the files associated with the node.

function embargoes_node_access(\Drupal\node\NodeInterface $node, $op, \Drupal\Core\Session\AccountInterface $account) {
  $nid = $node->id();
  $ip = \Drupal::request()->getClientIp();
  $embargoes = \Drupal::service('embargoes.embargoes')->getActiveNodeEmbargoesByNode($nid, $ip, $account);
  if (!empty($embargoes)) {
    $access = \Drupal\Core\Access\AccessResult::forbidden();
  }
  else {
    $access = \Drupal\Core\Access\AccessResult::neutral();
  }
  return $access;
}

What I cannot figure out how to do is implement the "file embargoes" in which the node is still viewable but the files are not. Since the private files are no longer accessible when hook_node_access returns \Drupal\Core\Access\AccessResult::forbidden() on the node they belong to, there must be some system in Drupal that is checking to see what node the files belong too. If I could figure out how to access that I might be able to use hook_file_download and check the node the file belongs to and see if the file should be accessible or not; in fact I already have a function in my custom service that does exactly this, but it needs a node ID in order to see what embargoes exist for the node.

Does anyone know how to do this? What is Drupal doing when a private file is accessed to see if the associated node is accessible or not?

2
1

The answer ended up being the function file_get_file_references(), referenced in /core/modules/file/src/FileAccessControlHandler.php

https://api.drupal.org/api/drupal/core%21modules%21file%21file.module/function/file_get_file_references/8.2.x

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.