Unverified Commit 1190672b authored by Lee Rowlands's avatar Lee Rowlands
Browse files

Issue #3043321 by jibran, acbramley, ravi.shankar, Manuel Garcia, johnwebdev,...

Issue #3043321 by jibran, acbramley, ravi.shankar, Manuel Garcia, johnwebdev, dpi, kim.pepper, mstrelan, NWOM, AaronMcHale, larowlan, Berdir, Wim Leers, kristiaanvandeneynde, bbrala, catch: Use generic access API for node and media revision UI
parent 64074071
Loading
Loading
Loading
Loading
+0 −2
Original line number Diff line number Diff line
@@ -156,8 +156,6 @@ services:
    public: false
    arguments: ['@jsonapi.resource_type.repository', '@router.no_access_checks', '@current_user', '@entity.repository']
    calls:
      - [setNodeRevisionAccessCheck, ['@?access_check.node.revision']] # This is only injected when the service is available.
      - [setMediaRevisionAccessCheck, ['@?access_check.media.revision']] # This is only injected when the service is available.
      # This is a temporary measure. JSON:API should not need to be aware of the Content Moderation module.
      - [setLatestRevisionCheck, ['@?access_check.latest_revision']] # This is only injected when the service is available.
  access_check.jsonapi.relationship_route_access:
+1 −56
Original line number Diff line number Diff line
@@ -15,10 +15,6 @@
use Drupal\jsonapi\JsonApiResource\ResourceObject;
use Drupal\jsonapi\JsonApiSpec;
use Drupal\jsonapi\ResourceType\ResourceTypeRepositoryInterface;
use Drupal\media\Access\MediaRevisionAccessCheck;
use Drupal\media\MediaInterface;
use Drupal\node\Access\NodeRevisionAccessCheck;
use Drupal\node\NodeInterface;
use Symfony\Component\Routing\RouterInterface;

/**
@@ -64,24 +60,6 @@ class EntityAccessChecker {
   */
  protected $entityRepository;

  /**
   * The node revision access check service.
   *
   * This will be NULL unless the node module is installed.
   *
   * @var \Drupal\node\Access\NodeRevisionAccessCheck|null
   */
  protected $nodeRevisionAccessCheck = NULL;

  /**
   * The media revision access check service.
   *
   * This will be NULL unless the media module is installed.
   *
   * @var \Drupal\media\Access\MediaRevisionAccessCheck|null
   */
  protected $mediaRevisionAccessCheck = NULL;

  /**
   * The latest revision check service.
   *
@@ -112,30 +90,6 @@ public function __construct(ResourceTypeRepositoryInterface $resource_type_repos
    $this->entityRepository = $entity_repository;
  }

  /**
   * Sets the node revision access check service.
   *
   * This is only called when node module is installed.
   *
   * @param \Drupal\node\Access\NodeRevisionAccessCheck $node_revision_access_check
   *   The node revision access check service.
   */
  public function setNodeRevisionAccessCheck(NodeRevisionAccessCheck $node_revision_access_check) {
    $this->nodeRevisionAccessCheck = $node_revision_access_check;
  }

  /**
   * Sets the media revision access check service.
   *
   * This is only called when media module is installed.
   *
   * @param \Drupal\media\Access\MediaRevisionAccessCheck $media_revision_access_check
   *   The media revision access check service.
   */
  public function setMediaRevisionAccessCheck(MediaRevisionAccessCheck $media_revision_access_check) {
    $this->mediaRevisionAccessCheck = $media_revision_access_check;
  }

  /**
   * Sets the media revision access check service.
   *
@@ -235,10 +189,6 @@ public function checkEntityAccess(EntityInterface $entity, $operation, AccountIn
   *
   * @return \Drupal\Core\Access\AccessResultInterface|\Drupal\Core\Access\AccessResultReasonInterface
   *   The access check result.
   *
   * @todo: remove when a generic revision access API exists in Drupal core, and
   * also remove the injected "node" and "media" services.
   * @see https://www.drupal.org/project/drupal/issues/2992833#comment-12818386
   */
  protected function checkRevisionViewAccess(EntityInterface $entity, AccountInterface $account) {
    assert($entity instanceof RevisionableInterface);
@@ -246,13 +196,8 @@ protected function checkRevisionViewAccess(EntityInterface $entity, AccountInter
    $entity_type = $entity->getEntityType();
    switch ($entity_type->id()) {
      case 'node':
        assert($entity instanceof NodeInterface);
        $access = AccessResult::allowedIf($this->nodeRevisionAccessCheck->checkAccess($entity, $account, 'view'))->cachePerPermissions()->addCacheableDependency($entity);
        break;

      case 'media':
        assert($entity instanceof MediaInterface);
        $access = AccessResult::allowedIf($this->mediaRevisionAccessCheck->checkAccess($entity, $account, 'view'))->cachePerPermissions()->addCacheableDependency($entity);
        $access = $entity->access('view all revisions', $account, TRUE);
        break;

      default:
+32 −16
Original line number Diff line number Diff line
@@ -503,6 +503,16 @@ protected function getExpectedCacheTags(array $sparse_fieldset = NULL) {
    return Cache::mergeTags($expected_cache_tags, $this->entity->getCacheTags());
  }

  /**
   * The expected cache tags when checking revision responses.
   *
   * @return string[]
   *   A set of cache tags.
   */
  protected function getExtraRevisionCacheTags() {
    return [];
  }

  /**
   * The expected cache contexts for the GET/HEAD response of the test entity.
   *
@@ -2945,7 +2955,7 @@ public function testRevisions() {
    // object.
    $expected_document['data']['links']['latest-version']['href'] = $rel_latest_version_url->setAbsolute()->toString();
    $expected_document['data']['links']['working-copy']['href'] = $rel_working_copy_url->setAbsolute()->toString();
    $this->assertResourceResponse(200, $expected_document, $actual_response, $expected_cache_tags, $expected_cache_contexts, FALSE, 'MISS');
    $this->assertResourceResponse(200, $expected_document, $actual_response, Cache::mergeTags($expected_cache_tags, $this->getExtraRevisionCacheTags()), $expected_cache_contexts, FALSE, 'MISS');

    // Install content_moderation module.
    $this->assertTrue($this->container->get('module_installer')->install(['content_moderation'], TRUE), 'Installed modules.');
@@ -3109,46 +3119,47 @@ public function testRevisions() {
    $expected_document['data']['links']['latest-version']['href'] = $rel_latest_version_url->setAbsolute()->toString();
    $expected_cache_tags = $this->getExpectedCacheTags();
    $expected_cache_contexts = $this->getExpectedCacheContexts();
    $this->assertResourceResponse(200, $expected_document, $actual_response, $expected_cache_tags, $expected_cache_contexts, FALSE, 'MISS');
    $this->assertResourceResponse(200, $expected_document, $actual_response, Cache::mergeTags($expected_cache_tags, $this->getExtraRevisionCacheTags()), $expected_cache_contexts, FALSE, 'MISS');
    // And the collection response should also have the latest revision.
    $actual_response = $this->request('GET', $rel_working_copy_collection_url, $request_options);
    $expected_response = static::getExpectedCollectionResponse([$entity], $rel_working_copy_collection_url->toString(), $request_options);
    $expected_collection_document = $expected_response->getResponseData();
    $expected_collection_document['data'] = [$expected_document['data']];
    $expected_cacheability = $expected_response->getCacheableMetadata();
    $this->assertResourceResponse(200, $expected_collection_document, $actual_response, $expected_cacheability->getCacheTags(), $expected_cacheability->getCacheContexts(), FALSE, 'MISS');
    $this->assertResourceResponse(200, $expected_collection_document, $actual_response, Cache::mergeTags($expected_cacheability->getCacheTags(), $this->getExtraRevisionCacheTags()), $expected_cacheability->getCacheContexts(), FALSE, 'MISS');

    // Test relationship responses.
    // Fetch the prior revision's relationship URL.
    $test_relationship_urls = [
      [
      'canonical' => [
        NULL,
        $relationship_url,
        $related_url,
      ],
      [
      'original' => [
        $original_revision_id,
        $original_revision_id_relationship_url,
        $original_revision_id_related_url,
      ],
      [
      'latest' => [
        $latest_revision_id,
        $latest_revision_id_relationship_url,
        $latest_revision_id_related_url,
      ],
      [
      'default' => [
        $default_revision_id,
        $rel_latest_version_relationship_url,
        $rel_latest_version_related_url,
      ],
      [
      'forward' => [
        $forward_revision_id,
        $rel_working_copy_relationship_url,
        $rel_working_copy_related_url,
      ],
    ];
    foreach ($test_relationship_urls as $revision_case) {
      list($revision_id, $relationship_url, $related_url) = $revision_case;
    $default_revision_types = ['canonical', 'default'];
    foreach ($test_relationship_urls as $relationship_type => $revision_case) {
      [$revision_id, $relationship_url, $related_url] = $revision_case;
      // Load the revision that will be requested.
      $this->entityStorage->resetCache([$entity->id()]);
      $revision = is_null($revision_id)
@@ -3161,7 +3172,9 @@ public function testRevisions() {
      $expected_document = $expected_response->getResponseData();
      $expected_cacheability = $expected_response->getCacheableMetadata();
      $expected_document['errors'][0]['links']['via']['href'] = $relationship_url->toString();
      $this->assertResourceResponse(403, $expected_document, $actual_response, $expected_cacheability->getCacheTags(), $expected_cacheability->getCacheContexts());
      // Only add node type check tags for non-default revisions.
      $expected_cache_tags = !in_array($relationship_type, $default_revision_types, TRUE) ? Cache::mergeTags($expected_cacheability->getCacheTags(), $this->getExtraRevisionCacheTags()) : $expected_cacheability->getCacheTags();
      $this->assertResourceResponse(403, $expected_document, $actual_response, $expected_cache_tags, $expected_cacheability->getCacheContexts());
      // Request the related route.
      $actual_response = $this->request('GET', $related_url, $request_options);
      // @todo: refactor self::getExpectedRelatedResponses() into a function which returns a single response.
@@ -3169,11 +3182,11 @@ public function testRevisions() {
      $expected_document = $expected_response->getResponseData();
      $expected_cacheability = $expected_response->getCacheableMetadata();
      $expected_document['errors'][0]['links']['via']['href'] = $related_url->toString();
      $this->assertResourceResponse(403, $expected_document, $actual_response, $expected_cacheability->getCacheTags(), $expected_cacheability->getCacheContexts());
      $this->assertResourceResponse(403, $expected_document, $actual_response, $expected_cache_tags, $expected_cacheability->getCacheContexts());
    }
    $this->grantPermissionsToTestedRole(['field_jsonapi_test_entity_ref view access']);
    foreach ($test_relationship_urls as $revision_case) {
      list($revision_id, $relationship_url, $related_url) = $revision_case;
    foreach ($test_relationship_urls as $relationship_type => $revision_case) {
      [$revision_id, $relationship_url, $related_url] = $revision_case;
      // Load the revision that will be requested.
      $this->entityStorage->resetCache([$entity->id()]);
      $revision = is_null($revision_id)
@@ -3186,7 +3199,9 @@ public function testRevisions() {
      $expected_document = $expected_response->getResponseData();
      $expected_document['links']['self']['href'] = $relationship_url->setAbsolute()->toString();
      $expected_cacheability = $expected_response->getCacheableMetadata();
      $this->assertResourceResponse(200, $expected_document, $actual_response, $expected_cacheability->getCacheTags(), $expected_cacheability->getCacheContexts(), FALSE, 'MISS');
      // Only add node type check tags for non-default revisions.
      $expected_cache_tags = !in_array($relationship_type, $default_revision_types, TRUE) ? Cache::mergeTags($expected_cacheability->getCacheTags(), $this->getExtraRevisionCacheTags()) : $expected_cacheability->getCacheTags();
      $this->assertResourceResponse(200, $expected_document, $actual_response, $expected_cache_tags, $expected_cacheability->getCacheContexts(), FALSE, 'MISS');
      // Request the related route.
      $actual_response = $this->request('GET', $related_url, $request_options);
      $expected_response = $this->getExpectedRelatedResponse('field_jsonapi_test_entity_ref', $request_options, $revision);
@@ -3195,7 +3210,8 @@ public function testRevisions() {
      $expected_document['links']['self']['href'] = $related_url->toString();
      // MISS or UNCACHEABLE depends on data. It must not be HIT.
      $dynamic_cache = !empty(array_intersect(['user', 'session'], $expected_cacheability->getCacheContexts())) ? 'UNCACHEABLE' : 'MISS';
      $this->assertResourceResponse(200, $expected_document, $actual_response, $expected_cacheability->getCacheTags(), $expected_cacheability->getCacheContexts(), FALSE, $dynamic_cache);
      $expected_cache_tags = !in_array($relationship_type, $default_revision_types, TRUE) ? Cache::mergeTags($expected_cacheability->getCacheTags(), $this->getExtraRevisionCacheTags()) : $expected_cacheability->getCacheTags();
      $this->assertResourceResponse(200, $expected_document, $actual_response, $expected_cache_tags, $expected_cacheability->getCacheContexts(), FALSE, $dynamic_cache);
    }

    $this->config('jsonapi.settings')->set('read_only', FALSE)->save(TRUE);
+1 −1
Original line number Diff line number Diff line
@@ -10,7 +10,7 @@ entity.media.revision:
      media_revision:
        type: entity_revision:media
  requirements:
    _access_media_revision: 'view'
    _entity_access: 'media_revision.view all revisions'
    media: \d+

media.oembed_iframe:
+1 −0
Original line number Diff line number Diff line
@@ -7,6 +7,7 @@ services:
    arguments: ['@entity_type.manager']
    tags:
      - { name: access_check, applies_to: _access_media_revision }
    deprecated: The "%service_id%" service is deprecated. You should use the 'access_check.entity' service instead. See https://www.drupal.org/node/3161210
  media.oembed.url_resolver:
    class: Drupal\media\OEmbed\UrlResolver
    arguments: ['@media.oembed.provider_repository', '@media.oembed.resource_fetcher', '@http_client', '@module_handler', '@cache.default']
Loading