Node access control handler only respects 'administer nodes' on revision operatons

Created on 20 September 2023, 12 months ago

Problem/Motivation

The administer nodes permission is pretty much useless and the "real" administration permission is bypass node access. This is pretty confusing.

The logic in \Drupal\node\NodeAccessControlHandler::checkAccess checks the administer nodes permission here:

    // Revision operations.
    if ($revision_permission_operation) {
....
      elseif ($account->hasPermission('administer nodes')) {
        return AccessResult::allowed()->cachePerPermissions();
      }

It also does not invoke the parent method, which has:

    if ($operation == 'delete' && $entity->isNew()) {
      return AccessResult::forbidden()->addCacheableDependency($entity);
    }
    if ($admin_permission = $this->entityType->getAdminPermission()) {
      return AccessResult::allowedIfHasPermission($account, $admin_permission);
    }

That means all logic is delegated to hook_entity_access and node_node_access performs per-bundle access checks.

Steps to reproduce

Assign administer nodes to a role and try to actually manage content.

Proposed resolution

Add admin_permission annotation to Nodes with administer nodes. Have \Drupal\node\NodeAccessControlHandler::checkAccess call its parent so that the admin permission is respected.

Remaining tasks

User interface changes

API changes

Data model changes

Release notes snippet

πŸ› Bug report
Status

Active

Version

11.0 πŸ”₯

Component
Node systemΒ  β†’

Last updated less than a minute ago

No maintainer
Created by

πŸ‡ΊπŸ‡ΈUnited States mglaman WI, USA

Live updates comments and jobs are added and updated live.
Sign in to follow issues

Comments & Activities

  • Issue created by @mglaman
  • πŸ‡ΊπŸ‡ΈUnited States mglaman WI, USA

    The same is true for \Drupal\node\NodeAccessControlHandler::checkCreateAccess

    Parent:

      protected function checkCreateAccess(AccountInterface $account, array $context, $entity_bundle = NULL) {
        if ($admin_permission = $this->entityType->getAdminPermission()) {
          return AccessResult::allowedIfHasPermission($account, $admin_permission);
        }
        else {
          // No opinion.
          return AccessResult::neutral();
        }
      }
    

    Node:

      protected function checkCreateAccess(AccountInterface $account, array $context, $entity_bundle = NULL) {
        return AccessResult::allowedIf($account->hasPermission('create ' . $entity_bundle . ' content'))->cachePerPermissions();
      }
    

    It should call the parent as well.

Production build 0.71.5 2024