From d4c6b3217fe09a2e4580d1db831e2573101bdce8 Mon Sep 17 00:00:00 2001 From: Lauri Eskola <lauri.eskola@acquia.com> Date: Wed, 8 Nov 2023 11:55:37 +0200 Subject: [PATCH] Issue #2911977 by yash.rode, acbramley, bnjmnm, smustgrave, phenaproxima, Wim Leers, chr.fritsch, larowlan: Add Media revision UI --- .../block_content/src/Entity/BlockContent.php | 2 +- .../tests/src/Functional/MediaTest.php | 2 +- core/modules/media/media.routing.yml | 15 -- core/modules/media/src/Entity/Media.php | 15 +- .../media/src/MediaAccessControlHandler.php | 15 +- core/modules/media/src/MediaPermissions.php | 9 + .../src/Functional/MediaRevisionTest.php | 185 +++++++++++++--- .../Kernel/MediaAccessControlHandlerTest.php | 199 +++++++++++++++++- 8 files changed, 386 insertions(+), 56 deletions(-) diff --git a/core/modules/block_content/src/Entity/BlockContent.php b/core/modules/block_content/src/Entity/BlockContent.php index 2a2c78475eee..7e652eea8ade 100644 --- a/core/modules/block_content/src/Entity/BlockContent.php +++ b/core/modules/block_content/src/Entity/BlockContent.php @@ -177,7 +177,7 @@ public function getInstances() { public function preSaveRevision(EntityStorageInterface $storage, \stdClass $record) { parent::preSaveRevision($storage, $record); - if (!$this->isNewRevision() && isset($this->original) && (!isset($record->revision_log) || $record->revision_log === '')) { + if (!$this->isNewRevision() && isset($this->original) && empty($record->revision_log_message)) { // If we are updating an existing block_content without adding a new // revision and the user did not supply a revision log, keep the existing // one. diff --git a/core/modules/jsonapi/tests/src/Functional/MediaTest.php b/core/modules/jsonapi/tests/src/Functional/MediaTest.php index 58e027af822b..84ad99b7da93 100644 --- a/core/modules/jsonapi/tests/src/Functional/MediaTest.php +++ b/core/modules/jsonapi/tests/src/Functional/MediaTest.php @@ -65,7 +65,7 @@ class MediaTest extends ResourceTestBase { protected function setUpAuthorization($method) { switch ($method) { case 'GET': - $this->grantPermissionsToTestedRole(['view media']); + $this->grantPermissionsToTestedRole(['view media', 'view any camelids media revisions']); break; case 'POST': diff --git a/core/modules/media/media.routing.yml b/core/modules/media/media.routing.yml index 03a5c5afe861..eaf908fb340e 100644 --- a/core/modules/media/media.routing.yml +++ b/core/modules/media/media.routing.yml @@ -1,18 +1,3 @@ -entity.media.revision: - path: '/media/{media}/revisions/{media_revision}/view' - defaults: - _controller: '\Drupal\Core\Entity\Controller\EntityRevisionViewController' - _title_callback: '\Drupal\Core\Entity\Controller\EntityController::title' - options: - parameters: - media: - type: entity:media - media_revision: - type: entity_revision:media - requirements: - _entity_access: 'media_revision.view all revisions' - media: \d+ - media.oembed_iframe: path: '/media/oembed' defaults: diff --git a/core/modules/media/src/Entity/Media.php b/core/modules/media/src/Entity/Media.php index 967e933063ec..7fcf32b94cda 100644 --- a/core/modules/media/src/Entity/Media.php +++ b/core/modules/media/src/Entity/Media.php @@ -39,10 +39,13 @@ * "edit" = "Drupal\media\MediaForm", * "delete" = "Drupal\Core\Entity\ContentEntityDeleteForm", * "delete-multiple-confirm" = "Drupal\Core\Entity\Form\DeleteMultipleForm", + * "revision-delete" = \Drupal\Core\Entity\Form\RevisionDeleteForm::class, + * "revision-revert" = \Drupal\Core\Entity\Form\RevisionRevertForm::class, * }, * "views_data" = "Drupal\media\MediaViewsData", * "route_provider" = { * "html" = "Drupal\media\Routing\MediaRouteProvider", + * "revision" = \Drupal\Core\Entity\Routing\RevisionHtmlRouteProvider::class, * } * }, * base_table = "media", @@ -80,6 +83,9 @@ * "delete-multiple-form" = "/media/delete", * "edit-form" = "/media/{media}/edit", * "revision" = "/media/{media}/revisions/{media_revision}/view", + * "revision-delete-form" = "/media/{media}/revision/{media_revision}/delete", + * "revision-revert-form" = "/media/{media}/revision/{media_revision}/revert", + * "version-history" = "/media/{media}/revisions", * } * ) */ @@ -381,18 +387,13 @@ public function postSave(EntityStorageInterface $storage, $update = TRUE) { public function preSaveRevision(EntityStorageInterface $storage, \stdClass $record) { parent::preSaveRevision($storage, $record); - $is_new_revision = $this->isNewRevision(); - if (!$is_new_revision && isset($this->original) && empty($record->revision_log_message)) { + if (!$this->isNewRevision() && isset($this->original) && empty($record->revision_log_message)) { // If we are updating an existing media item without adding a // new revision, we need to make sure $entity->revision_log_message is // reset whenever it is empty. // Therefore, this code allows us to avoid clobbering an existing log // entry with an empty one. - $record->revision_log_message = $this->original->revision_log_message->value; - } - - if ($is_new_revision) { - $record->revision_created = self::getRequestTime(); + $this->setRevisionLogMessage($this->original->getRevisionLogMessage()); } } diff --git a/core/modules/media/src/MediaAccessControlHandler.php b/core/modules/media/src/MediaAccessControlHandler.php index f34c638f4602..159cab18d271 100644 --- a/core/modules/media/src/MediaAccessControlHandler.php +++ b/core/modules/media/src/MediaAccessControlHandler.php @@ -50,7 +50,6 @@ public static function createInstance(ContainerInterface $container, EntityTypeI * {@inheritdoc} */ protected function checkAccess(EntityInterface $entity, $operation, AccountInterface $account) { - /** @var \Drupal\media\MediaInterface $entity */ // Allow admin permission to override all operations. if ($account->hasPermission($this->entityType->getAdminPermission())) { return AccessResult::allowed()->cachePerPermissions(); @@ -120,9 +119,9 @@ protected function checkAccess(EntityInterface $entity, $operation, AccountInter return AccessResult::neutral("The following permissions are required: 'delete any media' OR 'delete own media' OR '$type: delete any media' OR '$type: delete own media'.")->cachePerPermissions(); case 'view all revisions': - // Perform basic permission checks first. - if (!$account->hasPermission('view all media revisions')) { - return AccessResult::neutral("The 'view all media revisions' permission is required.")->cachePerPermissions(); + case 'view revision': + if ($account->hasPermission('view any ' . $type . ' media revisions') || $account->hasPermission("view all media revisions")) { + return AccessResult::allowed()->cachePerPermissions(); } // First check the access to the default revision and finally, if the @@ -135,6 +134,14 @@ protected function checkAccess(EntityInterface $entity, $operation, AccountInter } return $access->cachePerPermissions()->addCacheableDependency($entity); + case 'revert': + return AccessResult::allowedIfHasPermission($account, 'revert any ' . $type . ' media revisions') + ->cachePerPermissions()->addCacheableDependency($entity); + + case 'delete revision': + return AccessResult::allowedIfHasPermission($account, 'delete any ' . $type . ' media revisions') + ->cachePerPermissions()->addCacheableDependency($entity); + default: return AccessResult::neutral()->cachePerPermissions(); } diff --git a/core/modules/media/src/MediaPermissions.php b/core/modules/media/src/MediaPermissions.php index 6489db7f1674..a8d99a7157b3 100644 --- a/core/modules/media/src/MediaPermissions.php +++ b/core/modules/media/src/MediaPermissions.php @@ -82,6 +82,15 @@ protected function buildPermissions(MediaTypeInterface $type) { "delete any $type_id media" => [ 'title' => $this->t('%type_name: Delete any media', $type_params), ], + "view any $type_id media revisions" => [ + 'title' => $this->t('%type_name: View any media revision pages', $type_params), + ], + "revert any $type_id media revisions" => [ + 'title' => $this->t('Revert %type_name: Revert media revisions', $type_params), + ], + "delete any $type_id media revisions" => [ + 'title' => $this->t('Delete %type_name: Delete media revisions', $type_params), + ], ]; } diff --git a/core/modules/media/tests/src/Functional/MediaRevisionTest.php b/core/modules/media/tests/src/Functional/MediaRevisionTest.php index 44e02905d6c6..8f57b2206976 100644 --- a/core/modules/media/tests/src/Functional/MediaRevisionTest.php +++ b/core/modules/media/tests/src/Functional/MediaRevisionTest.php @@ -4,6 +4,7 @@ use Drupal\Core\Entity\EntityInterface; use Drupal\field\Entity\FieldConfig; +use Drupal\media\Entity\Media; use Drupal\media\MediaInterface; use Drupal\user\Entity\Role; use Drupal\user\RoleInterface; @@ -20,40 +21,59 @@ class MediaRevisionTest extends MediaFunctionalTestBase { */ protected $defaultTheme = 'stark'; + /** + * {@inheritdoc} + */ + protected function setUp(): void { + parent::setUp(); + $this->createMediaType('test', ['id' => 'test', 'label' => 'test']); + } + + /** + * Creates a media item. + * + * @param string $title + * Title of media item. + * + * @return \Drupal\media\Entity\Media + * A media item. + */ + protected function createMedia(string $title): Media { + $media = Media::create([ + 'bundle' => 'test', + 'name' => $title, + ]); + $media->save(); + + return $media; + } + /** * Checks media revision operations. */ public function testRevisions() { $assert = $this->assertSession(); - /** @var \Drupal\Core\Entity\Sql\SqlContentEntityStorage $media_storage */ - $media_storage = $this->container->get('entity_type.manager')->getStorage('media'); - - // Create a media type and media item. - $media_type = $this->createMediaType('test'); - $media = $media_storage->create([ - 'bundle' => $media_type->id(), - 'name' => 'Unnamed', - ]); - $media->save(); + $media = $this->createMedia('Sample media'); + $originalRevisionId = $media->getRevisionId(); // You can access the revision page when there is only 1 revision. - $this->drupalGet('media/' . $media->id() . '/revisions/' . $media->getRevisionId() . '/view'); + $this->drupalGet($media->toUrl('revision')); $assert->statusCodeEquals(200); // Create some revisions. - $media_revisions = []; - $media_revisions[] = clone $media; $revision_count = 3; for ($i = 0; $i < $revision_count; $i++) { $media->revision_log = $this->randomMachineName(32); $media = $this->createMediaRevision($media); - $media_revisions[] = clone $media; } - // Get the last revision for simple checks. - /** @var \Drupal\media\MediaInterface $media */ - $media = end($media_revisions); + // Confirm that the last revision is the default revision. + $this->assertTrue($media->isDefaultRevision(), 'Last revision is the default.'); + + // Get the original revision for simple checks. + $media = \Drupal::entityTypeManager()->getStorage('media') + ->loadRevision($originalRevisionId); // Test permissions. $this->drupalLogin($this->nonAdminUser); @@ -62,18 +82,22 @@ public function testRevisions() { // Test 'view all media revisions' permission ('view media' permission is // needed as well). - user_role_revoke_permissions($role->id(), ['view media', 'view all media revisions']); - $this->drupalGet('media/' . $media->id() . '/revisions/' . $media->getRevisionId() . '/view'); + user_role_revoke_permissions($role->id(), [ + 'view media', + 'view all media revisions', + ]); + $this->drupalGet($media->toUrl('revision')); $assert->statusCodeEquals(403); - $this->grantPermissions($role, ['view media', 'view all media revisions']); - $this->drupalGet('media/' . $media->id() . '/revisions/' . $media->getRevisionId() . '/view'); + $this->grantPermissions($role, ['view any test media revisions']); + $this->drupalGet($media->toUrl('revision')); + $assert->statusCodeEquals(200); + user_role_revoke_permissions($role->id(), ['view any test media revisions']); + $this->grantPermissions($role, ['view all media revisions']); + $this->drupalGet($media->toUrl('revision')); $assert->statusCodeEquals(200); // Confirm the revision page shows the correct title. $assert->pageTextContains($media->getName()); - - // Confirm that the last revision is the default revision. - $this->assertTrue($media->isDefaultRevision(), 'Last revision is the default.'); } /** @@ -209,4 +233,117 @@ protected function assertRevisionCount(EntityInterface $entity, int $expected_re $this->assertSame($expected_revisions, (int) $count); } + /** + * Creates a media with a revision. + * + * @param \Drupal\media\Entity\Media $media + * The media object. + */ + private function createMediaWithRevision(Media $media): void { + $media->setNewRevision(); + $media->setName('1st changed title'); + $media->setRevisionLogMessage('first revision'); + // Set revision creation time to check the confirmation message while + // deleting or reverting a revision. + $media->setRevisionCreationTime((new \DateTimeImmutable('11 January 2009 4pm'))->getTimestamp()); + $media->save(); + } + + /** + * Tests deleting a revision. + */ + public function testRevisionDelete(): void { + $user = $this->drupalCreateUser([ + 'edit any test media', + 'view any test media revisions', + 'delete any test media revisions', + ]); + $this->drupalLogin($user); + + $media = $this->createMedia('Sample media'); + $this->createMediaWithRevision($media); + $originalRevisionId = $media->getRevisionId(); + + // Cannot delete latest revision. + $this->drupalGet($media->toUrl('revision-delete-form')); + $this->assertSession()->statusCodeEquals(403); + + // Create a new revision. + $media->setNewRevision(); + $media->setRevisionLogMessage('second revision') + ->setRevisionCreationTime((new \DateTimeImmutable('12 March 2012 5pm'))->getTimestamp()) + ->setName('Sample media updated') + ->save(); + + $this->drupalGet($media->toUrl('version-history')); + $this->assertSession()->pageTextContains("First revision"); + $this->assertSession()->pageTextContains("Second revision"); + $this->assertSession()->elementsCount('css', 'table tbody tr', 3); + + // Reload the previous revision, and ensure we can delete it in the UI. + $revision = \Drupal::entityTypeManager()->getStorage('media') + ->loadRevision($originalRevisionId); + $this->drupalGet($revision->toUrl('revision-delete-form')); + $this->assertSession()->pageTextContains('Are you sure you want to delete the revision from Sun, 01/11/2009 - 16:00?'); + $this->submitForm([], 'Delete'); + $this->assertSession()->pageTextNotContains("First revision"); + $this->assertSession()->pageTextContains("Second revision"); + $this->assertSession()->statusCodeEquals(200); + $this->assertSession()->addressEquals(sprintf('media/%s/revisions', $media->id())); + $this->assertSession()->pageTextContains('Revision from Sun, 01/11/2009 - 16:00 of test 1st changed title has been deleted.'); + // Check that only two revisions exists, i.e. the original and the latest + // revision. + $this->assertSession()->elementsCount('css', 'table tbody tr', 2); + } + + /** + * Tests reverting a revision. + */ + public function testRevisionRevert(): void { + /** @var \Drupal\user\UserInterface $user */ + $user = $this->drupalCreateUser([ + 'edit any test media', + 'view any test media revisions', + 'revert any test media revisions', + ]); + $this->drupalLogin($user); + + $media = $this->createMedia('Initial title'); + $this->createMediaWithRevision($media); + $originalRevisionId = $media->getRevisionId(); + $originalRevisionLabel = $media->getName(); + + // Cannot revert latest revision. + $this->drupalGet($media->toUrl('revision-revert-form')); + $this->assertSession()->statusCodeEquals(403); + + // Create a new revision. + $media->setNewRevision(); + $media->setRevisionLogMessage('Second revision') + ->setRevisionCreationTime((new \DateTimeImmutable('12 March 2012 5pm'))->getTimestamp()) + ->setName('Sample media updated') + ->save(); + + $this->drupalGet($media->toUrl('version-history')); + $this->assertSession()->pageTextContains("First revision"); + $this->assertSession()->pageTextContains("Second revision"); + $this->assertSession()->elementsCount('css', 'table tbody tr', 3); + + // Reload the previous revision, and ensure we can revert to it in the UI. + $revision = \Drupal::entityTypeManager()->getStorage('media') + ->loadRevision($originalRevisionId); + $this->drupalGet($revision->toUrl('revision-revert-form')); + $this->assertSession()->pageTextContains('Are you sure you want to revert to the revision from Sun, 01/11/2009 - 16:00?'); + + $this->submitForm([], 'Revert'); + $this->assertSession()->statusCodeEquals(200); + $this->assertSession()->pageTextContains('Copy of the revision from Sun, 01/11/2009 - 16:00'); + $this->assertSession()->addressEquals(sprintf('media/%s/revisions', $media->id())); + $this->assertSession()->pageTextContains(sprintf('test %s has been reverted to the revision from Sun, 01/11/2009 - 16:00.', $originalRevisionLabel)); + $this->assertSession()->elementsCount('css', 'table tbody tr', 4); + $this->drupalGet($media->toUrl('edit-form')); + // Check if the title is changed to the reverted revision. + $this->assertSession()->pageTextContains('1st changed title'); + } + } diff --git a/core/modules/media/tests/src/Kernel/MediaAccessControlHandlerTest.php b/core/modules/media/tests/src/Kernel/MediaAccessControlHandlerTest.php index a2984c22c8f9..b017783d9609 100644 --- a/core/modules/media/tests/src/Kernel/MediaAccessControlHandlerTest.php +++ b/core/modules/media/tests/src/Kernel/MediaAccessControlHandlerTest.php @@ -33,15 +33,18 @@ class MediaAccessControlHandlerTest extends MediaKernelTestBase { * Expected cache contexts. * @param string[] $expected_cache_tags * Expected cache tags. + * @param bool $is_latest_revision + * If FALSE, the media is historic revision. * * @covers ::checkAccess * @dataProvider providerAccess */ - public function testAccess(array $permissions, array $entity_values, $operation, AccessResultInterface $expected_result, array $expected_cache_contexts, array $expected_cache_tags) { + public function testAccess(array $permissions, array $entity_values, string $operation, AccessResultInterface $expected_result, array $expected_cache_contexts, array $expected_cache_tags, bool $is_latest_revision) { + /** @var \Drupal\Core\Entity\RevisionableStorageInterface $entityStorage $entity_storage */ + $entity_storage = $this->container->get('entity_type.manager')->getStorage('media'); + // Set a fixed ID so the type specific permissions match. - $media_type = $this->createMediaType('test', [ - 'id' => 'test', - ]); + $media_type = $this->createMediaType('test', ['id' => 'test']); $user = $this->createUser($permissions); @@ -53,6 +56,20 @@ public function testAccess(array $permissions, array $entity_values, $operation, $entity = Media::create($entity_values); $entity->save(); + + $load_revision_id = NULL; + if (!$is_latest_revision) { + $load_revision_id = $entity->getRevisionId(); + // Set up for a new revision to be saved. + $entity = $entity_storage->createRevision($entity); + } + $entity->save(); + + // Reload a previous revision. + if ($load_revision_id !== NULL) { + $entity = $entity_storage->loadRevision($load_revision_id); + } + /** @var \Drupal\Core\Entity\EntityAccessControlHandlerInterface $access_handler */ $access_handler = $this->container->get('entity_type.manager')->getAccessControlHandler('media'); $this->assertAccess($expected_result, $expected_cache_contexts, $expected_cache_tags, $access_handler->access($entity, $operation, $user, TRUE)); @@ -127,6 +144,7 @@ public function providerAccess() { AccessResult::neutral(), ['user.permissions'], ['media:1'], + TRUE, ]; $test_data['owner, no permissions / published / update'] = [ [], @@ -135,6 +153,7 @@ public function providerAccess() { AccessResult::neutral(), ['user.permissions'], [], + TRUE, ]; $test_data['owner, no permissions / published / delete'] = [ [], @@ -143,6 +162,7 @@ public function providerAccess() { AccessResult::neutral(), ['user.permissions'], [], + TRUE, ]; $test_data['owner, no permissions / unpublished / view'] = [ [], @@ -151,6 +171,7 @@ public function providerAccess() { AccessResult::neutral(), ['user.permissions'], ['media:1'], + TRUE, ]; $test_data['owner, no permissions / unpublished / update'] = [ [], @@ -159,6 +180,7 @@ public function providerAccess() { AccessResult::neutral(), ['user.permissions'], [], + TRUE, ]; $test_data['owner, no permissions / unpublished / delete'] = [ [], @@ -167,6 +189,7 @@ public function providerAccess() { AccessResult::neutral(), ['user.permissions'], [], + TRUE, ]; // Check published / unpublished media access for a user not owning the @@ -178,6 +201,7 @@ public function providerAccess() { AccessResult::neutral(), ['user.permissions'], ['media:1'], + TRUE, ]; $test_data['not owner, no permissions / published / update'] = [ [], @@ -186,6 +210,7 @@ public function providerAccess() { AccessResult::neutral(), ['user.permissions'], [], + TRUE, ]; $test_data['not owner, no permissions / published / delete'] = [ [], @@ -194,6 +219,7 @@ public function providerAccess() { AccessResult::neutral(), ['user.permissions'], [], + TRUE, ]; $test_data['not owner, no permissions / unpublished / view'] = [ [], @@ -202,6 +228,7 @@ public function providerAccess() { AccessResult::neutral(), ['user.permissions'], ['media:1'], + TRUE, ]; $test_data['not owner, no permissions / unpublished / update'] = [ [], @@ -210,6 +237,7 @@ public function providerAccess() { AccessResult::neutral(), ['user.permissions'], [], + TRUE, ]; $test_data['not owner, no permissions / unpublished / delete'] = [ [], @@ -218,6 +246,7 @@ public function providerAccess() { AccessResult::neutral(), ['user.permissions'], [], + TRUE, ]; // Check published / unpublished media access for a user owning the media @@ -229,6 +258,7 @@ public function providerAccess() { AccessResult::allowed(), ['user.permissions'], ['media:1'], + TRUE, ]; $test_data['owner, can view media / published / update'] = [ ['view media'], @@ -237,6 +267,7 @@ public function providerAccess() { AccessResult::neutral(), ['user.permissions'], [], + TRUE, ]; $test_data['owner, can view media / published / delete'] = [ ['view media'], @@ -245,6 +276,7 @@ public function providerAccess() { AccessResult::neutral(), ['user.permissions'], [], + TRUE, ]; $test_data['owner, can view media / unpublished / view'] = [ ['view media'], @@ -253,6 +285,7 @@ public function providerAccess() { AccessResult::neutral(), ['user.permissions'], ['media:1'], + TRUE, ]; $test_data['owner, can view media / unpublished / update'] = [ ['view media'], @@ -261,6 +294,7 @@ public function providerAccess() { AccessResult::neutral(), ['user.permissions'], [], + TRUE, ]; $test_data['owner, can view media / unpublished / delete'] = [ ['view media'], @@ -269,6 +303,7 @@ public function providerAccess() { AccessResult::neutral(), ['user.permissions'], [], + TRUE, ]; // Check published / unpublished media access for a user not owning the @@ -280,6 +315,7 @@ public function providerAccess() { AccessResult::allowed(), ['user.permissions'], ['media:1'], + TRUE, ]; $test_data['not owner, can view media / published / update'] = [ ['view media'], @@ -288,6 +324,7 @@ public function providerAccess() { AccessResult::neutral(), ['user.permissions'], [], + TRUE, ]; $test_data['not owner, can view media / published / delete'] = [ ['view media'], @@ -296,6 +333,7 @@ public function providerAccess() { AccessResult::neutral(), ['user.permissions'], [], + TRUE, ]; $test_data['not owner, can view media / unpublished / view'] = [ ['view media'], @@ -304,6 +342,7 @@ public function providerAccess() { AccessResult::neutral(), ['user.permissions'], ['media:1'], + TRUE, ]; $test_data['not owner, can view media / unpublished / update'] = [ ['view media'], @@ -312,6 +351,7 @@ public function providerAccess() { AccessResult::neutral(), ['user.permissions'], [], + TRUE, ]; $test_data['not owner, can view media / unpublished / delete'] = [ ['view media'], @@ -320,6 +360,7 @@ public function providerAccess() { AccessResult::neutral(), ['user.permissions'], [], + TRUE, ]; // Check published / unpublished media access for a user owning the media @@ -331,6 +372,7 @@ public function providerAccess() { AccessResult::allowed(), ['user.permissions'], ['media:1'], + TRUE, ]; $test_data['owner, can view own unpublished media / published / update'] = [ ['view media', 'view own unpublished media'], @@ -339,6 +381,7 @@ public function providerAccess() { AccessResult::neutral(), ['user.permissions'], [], + TRUE, ]; $test_data['owner, can view own unpublished media / published / delete'] = [ ['view media', 'view own unpublished media'], @@ -347,6 +390,7 @@ public function providerAccess() { AccessResult::neutral(), ['user.permissions'], [], + TRUE, ]; $test_data['owner, can view own unpublished media / unpublished / view'] = [ ['view media', 'view own unpublished media'], @@ -355,6 +399,7 @@ public function providerAccess() { AccessResult::allowed(), ['user.permissions', 'user'], ['media:1'], + TRUE, ]; $test_data['owner, can view own unpublished media / unpublished / update'] = [ ['view media', 'view own unpublished media'], @@ -363,6 +408,7 @@ public function providerAccess() { AccessResult::neutral(), ['user.permissions'], [], + TRUE, ]; $test_data['owner, can view own unpublished media / unpublished / delete'] = [ ['view media', 'view own unpublished media'], @@ -371,6 +417,7 @@ public function providerAccess() { AccessResult::neutral(), ['user.permissions'], [], + TRUE, ]; // Check published / unpublished media access for a user not owning the @@ -382,6 +429,7 @@ public function providerAccess() { AccessResult::allowed(), ['user.permissions'], ['media:1'], + TRUE, ]; $test_data['not owner, can view own unpublished media / published / update'] = [ ['view media', 'view own unpublished media'], @@ -390,6 +438,7 @@ public function providerAccess() { AccessResult::neutral(), ['user.permissions'], [], + TRUE, ]; $test_data['not owner, can view own unpublished media / published / delete'] = [ ['view media', 'view own unpublished media'], @@ -398,6 +447,7 @@ public function providerAccess() { AccessResult::neutral(), ['user.permissions'], [], + TRUE, ]; $test_data['not owner, can view own unpublished media / unpublished / view'] = [ ['view media', 'view own unpublished media'], @@ -406,6 +456,7 @@ public function providerAccess() { AccessResult::neutral(), ['user.permissions', 'user'], ['media:1'], + TRUE, ]; $test_data['not owner, can view own unpublished media / unpublished / update'] = [ ['view media', 'view own unpublished media'], @@ -414,6 +465,7 @@ public function providerAccess() { AccessResult::neutral(), ['user.permissions'], [], + TRUE, ]; $test_data['not owner, can view own unpublished media / unpublished / delete'] = [ ['view media', 'view own unpublished media'], @@ -422,6 +474,145 @@ public function providerAccess() { AccessResult::neutral(), ['user.permissions'], [], + TRUE, + ]; + // View all revisions: + $test_data['view all revisions:none'] = [ + [], + [], + 'view all revisions', + AccessResult::neutral(), + ['user.permissions'], + ['media:1'], + TRUE, + ]; + $test_data['admins can view all revisions'] = [ + ['administer media'], + [], + 'view all revisions', + AccessResult::allowed(), + ['user.permissions'], + [], + TRUE, + ]; + $test_data['view all revisions with view bundle permission'] = [ + ['view any test media revisions'], + [], + 'view all revisions', + AccessResult::allowed(), + ['user.permissions'], + [], + TRUE, + ]; + // Revert revisions: + $test_data['revert a latest revision with no permissions'] = [ + [], + [], + 'revert', + AccessResult::forbidden(), + [], + [], + TRUE, + ]; + $test_data['revert a historical revision with no permissions'] = [ + [], + [], + 'revert', + AccessResult::neutral(), + ['user.permissions'], + ['media:1'], + FALSE, + ]; + $test_data['revert latest revision with administer media permission'] = [ + ['administer media'], + [], + 'revert', + AccessResult::forbidden(), + [], + [], + TRUE, + ]; + $test_data['revert a historical revision with administer media permission'] = [ + ['administer media'], + [], + 'revert', + AccessResult::allowed(), + ['user.permissions'], + [], + FALSE, + ]; + $test_data['revert a latest revision with revert bundle permission'] = [ + ['revert any test media revisions'], + [], + 'revert', + AccessResult::forbidden(), + [], + [], + TRUE, + ]; + $test_data['revert a historical revision with revert bundle permission'] = [ + ['revert any test media revisions'], + [], + 'revert', + AccessResult::allowed(), + ['user.permissions'], + ['media:1'], + FALSE, + ]; + // Delete revisions: + $test_data['delete a latest revision with no permission'] = [ + [], + [], + 'delete revision', + AccessResult::forbidden(), + [], + [], + TRUE, + ]; + $test_data['delete a historical revision with no permission'] = [ + [], + [], + 'delete revision', + AccessResult::neutral(), + ['user.permissions'], + ['media:1'], + FALSE, + ]; + $test_data['delete a latest revision with administer media permission'] = [ + ['administer media'], + [], + 'delete revision', + AccessResult::forbidden(), + [], + [], + TRUE, + ]; + $test_data['delete a historical revision with administer media permission'] = [ + ['administer media'], + [], + 'delete revision', + AccessResult::allowed(), + ['user.permissions'], + [], + FALSE, + ]; + $test_data['delete a latest revision with delete bundle permission'] = [ + ['delete any test media revisions'], + [], + 'delete revision', + AccessResult::forbidden(), + [], + [], + TRUE, + ]; + $test_data['delete a historical revision with delete bundle permission'] = [ + ['delete any test media revisions'], + [], + 'delete revision', + AccessResult::allowed(), + ['user.permissions'], + ['media:1'], + FALSE, ]; return $test_data; -- GitLab