Problem/Motivation
The implementation of decoration of access_check.latest_revision
service has a small mistake that causes the Access Unpublished check src/Access/LatestRevisionCheck::access()
to be called twice in row.
- Once with all other services decorating the
access_check.latest_revision
. It might be called together with:
- Second separately as
access_unpublished.access_check.latest_revision
service alone.
As a result, you might experience the following Access Denied Warning:
Path: /node/1/latest. Drupal\Core\Http\Exception\CacheableAccessDeniedHttpException: The following permissions are required: 'view latest version' AND 'view any unpublished content'. in Drupal\Core\Routing\AccessAwareRouter->checkAccess() (line 115 of /app/web/core/lib/Drupal/Core/Routing/AccessAwareRouter.php).
The definition of the Service access_unpublished.access_check.latest_revision
adds the following Tag to the definition:
->addTag('access_check', ['applies_to' => ‘_content_moderation_latest_version']);
which is WRONG as it already decorated the Service access_check.latest_revision
and thus it does NOT need to be called as a separate “Content moderation latest version Access Check” AGAIN.
The Tag is added in src/AccessUnpublishedServiceProvider.php
:
$container->register('access_unpublished.access_check.latest_revision', LatestRevisionCheck::class)
->setDecoratedService('access_check.latest_revision')
->addArgument(new Reference('access_unpublished.access_check.latest_revision.inner'))
->addTag('access_check', ['applies_to' => '_content_moderation_latest_version']);
The Service access_check.latest_revision
defined in the core/modules/content_moderation/content_moderation.services.yml
contains tag definition with values: { name: access_check, applies_to: _content_moderation_latest_version }
so when decorating there's no reason to define the same values for the service that decorates it.
access_check.latest_revision:
class: Drupal\content_moderation\Access\LatestRevisionCheck
arguments: ['@content_moderation.moderation_information']
tags:
- { name: access_check, applies_to: _content_moderation_latest_version }
Steps to reproduce
The check is being called twice all the time.
- If you debug
core/lib/Drupal/Core/Access/AccessManager::checkRequest()
which calls core/lib/Drupal/Core/Access/AccessManager::check()
- And you review the result of the line
$checks = $route->getOption('_access_checks') ?: [];
- You should see both checks in:
access_check.latest_revision
and
access_unpublished.access_check.latest_revision
Or more complicated situation: Use the following contribs together
Proposed resolution
Remove the service Tag mentioned above.
Remaining tasks
User interface changes
API changes
Data model changes