10

I want to implement a custom access check in Drupal 8, where users assigned to the node field node-owner have view/edit and revisions view/edit permissions for this specific node.

I have implemented it for node view/edit using the node access system with hook_node_access_records() and hook_node_grants(). But I cannot find how to implement it for the node revisions, since the access check performed in NodeRevisionAccessCheck takes into account only the 'view revisions' and 'revert revisions' role permissions and I cannot see a relevant hook.

Should I do custom access checking on routes as described here? https://www.drupal.org/docs/8/api/routing-system/access-checking-on-routes

And if yes, how do I implement the route check and fetch the current node?

2
  • what's exactly url you want check access?
    – Jonh
    Commented Jan 22, 2019 at 10:41
  • @Jonh /node/%/revisions/%/view
    – user20765
    Commented Jan 22, 2019 at 10:51

1 Answer 1

3

As you said, node revision does not have hook implement for check access. So you need other way to resolved your problem. My way is alter existing services. Just following document, there is file my_module/src/MyModuleServiceProvider.php

<?php

namespace Drupal\my_module;

use Drupal\Core\DependencyInjection\ContainerBuilder;
use Drupal\Core\DependencyInjection\ServiceProviderBase;
use Symfony\Component\DependencyInjection\Reference;

/**
 * Class MyModuleServiceProvider.
 *
 * @package Drupal\mymodule
 */
class MyModuleServiceProvider extends ServiceProviderBase {

  /**
   * {@inheritdoc}
   */
  public function alter(ContainerBuilder $container) {
    $definition = $container->getDefinition('access_check.node.revision');
    $definition->setClass('Drupal\my_module\Access\MyModuleNodeRevisionAccessCheck');
    $definition->setArguments(
      [
        new Reference('entity.manager'),
      ]
    );
  }

}

After alter access_check.node.revision service. I'll define new class check access view node revision with extend class NodeRevisionAccessCheck and override method access like this. File src/Access/MyModuleNodeRevisionAccessCheck

<?php

namespace Drupal\my_module\Access;

use Drupal\Core\Access\AccessResult;
use Drupal\node\Access\NodeRevisionAccessCheck;
use Drupal\Core\Session\AccountInterface;
use Drupal\node\NodeInterface;
use Symfony\Component\Routing\Route;

/**
 * Provides an access checker for node revisions.
 *
 * @ingroup node_access
 */
class MyModuleNodeRevisionAccessCheck extends NodeRevisionAccessCheck {

  public function access(Route $route, AccountInterface $account, $node_revision = NULL, NodeInterface $node = NULL) {
    if ($node_revision) {
      $node = $this->nodeStorage->loadRevision($node_revision);
    }
    $operation = $route->getRequirement('_access_node_revision');
    // You can override logic check access here or provide a new hook.
  }

}
2
  • Worked as a charm. Actually I overrid the checkAccess method of the NodeRevisionAccessCheck class.
    – user20765
    Commented Jan 23, 2019 at 13:00
  • Yes, If you understand about logic of the method checkAcesss, you can override it. If no, better override method acess, just procces logic of you and return before line return AccessResult::allowedIf($node && $this->checkAccess($node, $account, $operation))->cachePerPermissions()->addCacheableDependency($node);
    – Jonh
    Commented Jan 24, 2019 at 0:57

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.