0

I want to hook into hook_node_access and if the action is update or delete on a particular node type, I want to check the current user and the current node and see if they share field values. If they do, that user should have access to edit or delete the node even if they are not the node owner.

With Content Moderation enabled, the $op passed to hook_node_access is always 'view all revisions' even on the Edit or Delete page. Why? How can I implement this?

1 Answer 1

0

Here is what I came up with so far... I am not sure if this is bulletproof. The $op seems to change depending where you are (or maybe who you are) - for example the Content overview the $op is 'view all revisions' for an administrator. In a View listing nodes with operation links, the op is 'update', 'view', 'delete'. I'm unsure when the $op is one thing versus another, but I have:

/**
 * Implements hook_node_access().
 */
function mymodule_node_access(NodeInterface $node, $op, $account) {
  $type = $node->bundle();
  $route = \Drupal::routeMatch()->getRouteName();

  if ($type != 'offer_detail_page') {
    return AccessResult::neutral();
  }

  $op_check = [
    'update',
    'delete',
  ];

  $route_check = [
    'entity.node.edit_form',
    'entity.node.delete_form',
  ];

  if (!in_array($route, $route_check) && !in_array($op, $op_check)) {
    return AccessResult::neutral();
  }

  // Jump out if user is admin
  $admin_roles = [
    'administrator',
    'content_publisher',
    'supplier_author'
  ];

  $user_roles = $account->getRoles();

  foreach ($user_roles as $rid) {
    if (in_array($rid, $admin_roles)) {
      return AccessResult::neutral();
    }
  }

  // Get full account
  $account = User::load($account->id());
  $user_suppliers = array_column($account->get('field_suppliers')->getValue(), 'target_id');
  $node_suppliers = array_column($node->get('field_supplier')->getValue(), 'target_id');
  $user_has_suppliers_with_node = array_intersect($user_suppliers, $node_suppliers);
  return AccessResult::allowedIf(!empty($user_has_suppliers_with_node))->cachePerUser()->addCacheableDependency($node);
}

This appears to grant edit/delete access to related users at a glance. Is this enough? Am I missing something?

Edit: you also need to enable permission per Content Moderation transition state they should have access to. If they have no transition state access, they will never get the edit button, even if you grant it in code.

Your Answer

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

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