From dce52d1ff1e181870d6984e9fd9c09396517e609 Mon Sep 17 00:00:00 2001 From: Lee Rowlands <lee.rowlands@previousnext.com.au> Date: Thu, 24 Feb 2022 10:56:52 +1000 Subject: [PATCH] Issue #3154962 by alexpott, vijaycs85, bbrala, Berdir, Wim Leers: TemporaryJsonapiFileFieldUploader::checkFileUploadAccess() checks for bundle --- .../TemporaryJsonapiFileFieldUploader.php | 8 +- .../TemporaryJsonapiFileFieldUploaderTest.php | 179 ++++++++++++++++++ 2 files changed, 185 insertions(+), 2 deletions(-) create mode 100644 core/modules/jsonapi/tests/src/Kernel/Controller/TemporaryJsonapiFileFieldUploaderTest.php diff --git a/core/modules/jsonapi/src/Controller/TemporaryJsonapiFileFieldUploader.php b/core/modules/jsonapi/src/Controller/TemporaryJsonapiFileFieldUploader.php index 62e96a57129b..0551812fa848 100644 --- a/core/modules/jsonapi/src/Controller/TemporaryJsonapiFileFieldUploader.php +++ b/core/modules/jsonapi/src/Controller/TemporaryJsonapiFileFieldUploader.php @@ -303,13 +303,17 @@ public function validateAndParseContentDispositionHeader(Request $request) { * @param \Drupal\Core\Entity\EntityInterface $entity * (optional) The entity to which the file is to be uploaded, if it exists. * If the entity does not exist and it is not given, create access to the - * file will be checked. + * entity the file is attached to will be checked. * * @return \Drupal\Core\Access\AccessResultInterface * The file upload access result. */ public static function checkFileUploadAccess(AccountInterface $account, FieldDefinitionInterface $field_definition, EntityInterface $entity = NULL) { - assert(is_null($entity) || $field_definition->getTargetEntityTypeId() === $entity->getEntityTypeId() && $field_definition->getTargetBundle() === $entity->bundle()); + assert(is_null($entity) || + $field_definition->getTargetEntityTypeId() === $entity->getEntityTypeId() && + // Base fields do not have target bundles. + (is_null($field_definition->getTargetBundle()) || $field_definition->getTargetBundle() === $entity->bundle()) + ); $entity_type_manager = \Drupal::entityTypeManager(); $entity_access_control_handler = $entity_type_manager->getAccessControlHandler($field_definition->getTargetEntityTypeId()); $bundle = $entity_type_manager->getDefinition($field_definition->getTargetEntityTypeId())->hasKey('bundle') ? $field_definition->getTargetBundle() : NULL; diff --git a/core/modules/jsonapi/tests/src/Kernel/Controller/TemporaryJsonapiFileFieldUploaderTest.php b/core/modules/jsonapi/tests/src/Kernel/Controller/TemporaryJsonapiFileFieldUploaderTest.php new file mode 100644 index 000000000000..38ed1552855e --- /dev/null +++ b/core/modules/jsonapi/tests/src/Kernel/Controller/TemporaryJsonapiFileFieldUploaderTest.php @@ -0,0 +1,179 @@ +<?php + +namespace Drupal\Tests\jsonapi\Kernel\Controller; + +use Drupal\Core\Field\FieldStorageDefinitionInterface; +use Drupal\jsonapi\Controller\TemporaryJsonapiFileFieldUploader; +use Drupal\node\Entity\Node; +use Drupal\node\Entity\NodeType; +use Drupal\Tests\jsonapi\Kernel\JsonapiKernelTestBase; +use Drupal\user\Entity\Role; +use Drupal\user\Entity\User; + +/** + * @coversDefaultClass \Drupal\jsonapi\Controller\TemporaryJsonapiFileFieldUploader + * @group jsonapi + */ +class TemporaryJsonapiFileFieldUploaderTest extends JsonapiKernelTestBase { + + /** + * {@inheritdoc} + */ + protected static $modules = [ + 'node', + 'field', + 'jsonapi', + 'serialization', + 'system', + 'user', + ]; + + /** + * {@inheritdoc} + */ + protected function setUp(): void { + parent::setUp(); + // Add the entity schemas. + $this->installEntitySchema('node'); + $this->installEntitySchema('user'); + // Add the additional table schemas. + $this->installSchema('system', ['sequences']); + $this->installSchema('node', ['node_access']); + $this->installSchema('user', ['users_data']); + NodeType::create([ + 'type' => 'lorem', + ])->save(); + $type = NodeType::create([ + 'type' => 'article', + ]); + $type->save(); + $type = NodeType::create([ + 'type' => 'page', + ]); + $type->save(); + $this->createEntityReferenceField('node', 'article', 'field_relationships', 'Relationship', 'node', 'default', ['target_bundles' => ['article']], FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED); + + Role::create([ + 'id' => 'article editor', + 'label' => 'article editor', + 'permissions' => [ + 'access content', + 'create article content', + 'edit any article content', + ], + ])->save(); + + Role::create([ + 'id' => 'page editor', + 'label' => 'page editor', + 'permissions' => [ + 'access content', + 'create page content', + 'edit any page content', + ], + ])->save(); + + Role::create([ + 'id' => 'editor', + 'label' => 'editor', + 'permissions' => [ + 'bypass node access', + ], + ])->save(); + } + + /** + * @covers ::checkFileUploadAccess + */ + public function testCheckFileUploadAccessWithBaseField() { + // Create a set of users for access testing. + $article_editor = User::create([ + 'name' => 'article editor', + 'mail' => 'article@localhost', + 'status' => 1, + // Do not use UID 1 as that has access to everything. + 'uid' => 2, + 'roles' => ['article editor'], + ]); + $page_editor = User::create([ + 'name' => 'page editor', + 'mail' => 'page@localhost', + 'status' => 1, + 'uid' => 3, + 'roles' => ['page editor'], + ]); + $editor = User::create([ + 'name' => 'editor', + 'mail' => 'editor@localhost', + 'status' => 1, + 'uid' => 3, + 'roles' => ['editor'], + ]); + $no_access_user = User::create([ + 'name' => 'no access', + 'mail' => 'user@localhost', + 'status' => 1, + 'uid' => 4, + ]); + + // Create an entity to test access against. + $node = Node::create([ + 'title' => 'dummy_title', + 'type' => 'article', + 'uid' => 1, + ]); + + // While the method is only used to check file fields it should work without + // error for any field whether it is a base field or a bundle field. + $base_field_definition = $this->container->get('entity_field.manager')->getBaseFieldDefinitions('node')['title']; + $bundle_field_definition = $this->container->get('entity_field.manager')->getFieldDefinitions('node', 'article')['field_relationships']; + + // Tests the expected access result for each user. + // The $article_editor account can edit any article. + $result = TemporaryJsonapiFileFieldUploader::checkFileUploadAccess($article_editor, $base_field_definition, $node); + $this->assertTrue($result->isAllowed()); + // The article editor cannot create a node of undetermined type. + $result = TemporaryJsonapiFileFieldUploader::checkFileUploadAccess($article_editor, $base_field_definition); + $this->assertFalse($result->isAllowed()); + // The article editor can edit any article. + $result = TemporaryJsonapiFileFieldUploader::checkFileUploadAccess($article_editor, $bundle_field_definition, $node); + $this->assertTrue($result->isAllowed()); + // The article editor can create an article. The type can be determined + // because the field is a bundle field. + $result = TemporaryJsonapiFileFieldUploader::checkFileUploadAccess($article_editor, $bundle_field_definition); + $this->assertTrue($result->isAllowed()); + + // The $editor account has the bypass node access permissions and can edit + // and create all node types. + $result = TemporaryJsonapiFileFieldUploader::checkFileUploadAccess($editor, $base_field_definition, $node); + $this->assertTrue($result->isAllowed()); + $result = TemporaryJsonapiFileFieldUploader::checkFileUploadAccess($editor, $base_field_definition); + $this->assertTrue($result->isAllowed()); + $result = TemporaryJsonapiFileFieldUploader::checkFileUploadAccess($editor, $bundle_field_definition, $node); + $this->assertTrue($result->isAllowed()); + $result = TemporaryJsonapiFileFieldUploader::checkFileUploadAccess($editor, $bundle_field_definition); + $this->assertTrue($result->isAllowed()); + + // The $page_editor account can only edit and create pages therefore has no + // access. + $result = TemporaryJsonapiFileFieldUploader::checkFileUploadAccess($page_editor, $base_field_definition, $node); + $this->assertFalse($result->isAllowed()); + $result = TemporaryJsonapiFileFieldUploader::checkFileUploadAccess($page_editor, $base_field_definition); + $this->assertFalse($result->isAllowed()); + $result = TemporaryJsonapiFileFieldUploader::checkFileUploadAccess($page_editor, $bundle_field_definition, $node); + $this->assertFalse($result->isAllowed()); + $result = TemporaryJsonapiFileFieldUploader::checkFileUploadAccess($page_editor, $bundle_field_definition); + $this->assertFalse($result->isAllowed()); + + // The $no_access_user account has no access at all. + $result = TemporaryJsonapiFileFieldUploader::checkFileUploadAccess($no_access_user, $base_field_definition, $node); + $this->assertFalse($result->isAllowed()); + $result = TemporaryJsonapiFileFieldUploader::checkFileUploadAccess($no_access_user, $base_field_definition); + $this->assertFalse($result->isAllowed()); + $result = TemporaryJsonapiFileFieldUploader::checkFileUploadAccess($no_access_user, $bundle_field_definition, $node); + $this->assertFalse($result->isAllowed()); + $result = TemporaryJsonapiFileFieldUploader::checkFileUploadAccess($no_access_user, $bundle_field_definition); + $this->assertFalse($result->isAllowed()); + } + +} -- GitLab