From 49f78bc356972152747ddf7138ddb1bf76fbe933 Mon Sep 17 00:00:00 2001 From: Alex Pott Date: Mon, 13 Jul 2020 13:38:03 +0100 Subject: [PATCH] Issue #3124302 by Sam152, seanB: The media library should perform access checks against the revision of the entity being edited (cherry picked from commit d901cf487be7462a4bd54abaf5d1b6f23a992160) --- .../src/MediaLibraryFieldWidgetOpener.php | 6 +- .../Field/FieldWidget/MediaLibraryWidget.php | 4 + .../src/Kernel/MediaLibraryWidgetTest.php | 158 ++++++++++++++++++ 3 files changed, 167 insertions(+), 1 deletion(-) create mode 100644 core/modules/media_library/tests/src/Kernel/MediaLibraryWidgetTest.php diff --git a/core/modules/media_library/src/MediaLibraryFieldWidgetOpener.php b/core/modules/media_library/src/MediaLibraryFieldWidgetOpener.php index 84099ed3f6..348f22f104 100644 --- a/core/modules/media_library/src/MediaLibraryFieldWidgetOpener.php +++ b/core/modules/media_library/src/MediaLibraryFieldWidgetOpener.php @@ -69,7 +69,11 @@ public function checkAccess(MediaLibraryState $state, AccountInterface $account) $storage = $this->entityTypeManager->getStorage($entity_type_id); $access_handler = $this->entityTypeManager->getAccessControlHandler($entity_type_id); - if ($parameters['entity_id']) { + if (!empty($parameters['revision_id'])) { + $entity = $storage->loadRevision($parameters['revision_id']); + $entity_access = $access_handler->access($entity, 'update', $account, TRUE); + } + elseif ($parameters['entity_id']) { $entity = $storage->load($parameters['entity_id']); $entity_access = $access_handler->access($entity, 'update', $account, TRUE); } diff --git a/core/modules/media_library/src/Plugin/Field/FieldWidget/MediaLibraryWidget.php b/core/modules/media_library/src/Plugin/Field/FieldWidget/MediaLibraryWidget.php index 5933ea7409..d23f11538f 100644 --- a/core/modules/media_library/src/Plugin/Field/FieldWidget/MediaLibraryWidget.php +++ b/core/modules/media_library/src/Plugin/Field/FieldWidget/MediaLibraryWidget.php @@ -465,6 +465,10 @@ public function formElement(FieldItemListInterface $items, $delta, array $elemen // tamper-proof hash in a consistent way. if (!$entity->isNew()) { $opener_parameters['entity_id'] = (string) $entity->id(); + + if ($entity->getEntityType()->isRevisionable()) { + $opener_parameters['revision_id'] = (string) $entity->getRevisionId(); + } } $state = MediaLibraryState::create('media_library.opener.field_widget', $allowed_media_type_ids, $selected_type_id, $remaining, $opener_parameters); diff --git a/core/modules/media_library/tests/src/Kernel/MediaLibraryWidgetTest.php b/core/modules/media_library/tests/src/Kernel/MediaLibraryWidgetTest.php new file mode 100644 index 0000000000..450bbda0dc --- /dev/null +++ b/core/modules/media_library/tests/src/Kernel/MediaLibraryWidgetTest.php @@ -0,0 +1,158 @@ +baseField = BaseFieldDefinition::create('entity_reference') + ->setName('media') + ->setSetting('target_type', 'media') + ->setSetting('handler_settings', ['target_bundles' => ['test_type' => 'test_type']]); + $this->container->get('state')->set('entity_test.additional_base_field_definitions', [ + 'media' => $this->baseField, + ]); + $this->container->get('state')->set('entity_test_rev.additional_base_field_definitions', [ + 'media' => $this->baseField, + ]); + + $this->installEntitySchema('entity_test'); + $this->installEntitySchema('entity_test_rev'); + $this->installEntitySchema('user'); + $this->installSchema('system', ['sequences', 'key_value_expire']); + $this->installConfig([ + 'system', + 'image', + 'media', + 'media_library', + ]); + + MediaType::create([ + 'id' => 'test_type', + 'label' => 'Test type', + 'source' => 'image', + ])->save(); + + // Create user 1 so the test user doesn't bypass access control. + $this->createUser(); + + $this->adminUser = $this->createUser([ + 'administer entity_test content', + 'view media', + ]); + } + + /** + * Test the media library widget access. + */ + public function testWidgetAccess() { + $entity = EntityTest::create([ + 'name' => 'sample entity', + ]); + $entity->save(); + $element = $this->buildWidgetForm($entity); + $this->assertMediaLibraryStateAccess(TRUE, $this->adminUser, $element['open_button']['#media_library_state']); + } + + /** + * Test the media library widget access with a revisionable entity type. + */ + public function testRevisionableWidgetAccess() { + $allowed_revision = EntityTestRev::create([ + 'name' => 'allowed_access', + ]); + $allowed_revision->save(); + + $denied_revision = clone $allowed_revision; + $denied_revision->setNewRevision(); + $denied_revision->name = 'forbid_access'; + $denied_revision->save(); + + $element = $this->buildWidgetForm($allowed_revision); + $this->assertMediaLibraryStateAccess(TRUE, $this->adminUser, $element['open_button']['#media_library_state']); + + $element = $this->buildWidgetForm($denied_revision); + $this->assertMediaLibraryStateAccess(FALSE, $this->adminUser, $element['open_button']['#media_library_state']); + } + + /** + * Assert if the given user has access to the given state. + * + * @param bool $access + * The access result to assert. + * @param \Drupal\Core\Session\AccountInterface $user + * The user account. + * @param \Drupal\media_library\MediaLibraryState $state + * The media library state. + * + * @throws \Exception + */ + protected function assertMediaLibraryStateAccess($access, $user, $state) { + $ui_builder = $this->container->get('media_library.ui_builder'); + $access_result = $ui_builder->checkAccess($user, $state); + $this->assertEquals($access, $access_result->isAllowed()); + } + + /** + * Build the media library widget form. + * + * @param \Drupal\Core\Entity\EntityInterface $entity + * The entity to build the form for. + * + * @return array + * A built form array of the media library widget. + */ + protected function buildWidgetForm($entity) { + $form = [ + '#parents' => [], + ]; + return $this->container->get('plugin.manager.field.widget')->createInstance('media_library_widget', [ + 'field_definition' => $this->baseField, + 'settings' => [], + 'third_party_settings' => [], + ])->formElement($entity->media, 0, ['#description' => ''], $form, new FormState()); + } + +} -- GitLab