From 59e21652361ba1086771d0f66660717e3b1b4a9b Mon Sep 17 00:00:00 2001 From: xjm <xjm@65776.no-reply.drupal.org> Date: Sat, 24 Dec 2022 20:10:37 -0600 Subject: [PATCH] Issue #3171047 by rpayanm, catch, jonathanshaw, Berdir, xjm, larowlan, hchonov, mxr576: Entity query in UniqueFieldValueValidator must not use access checking --- .../Constraint/UniqueFieldValueValidator.php | 6 ++-- .../unique_field_constraint_test.module | 14 ++++++++ .../Validation/UniqueFieldConstraintTest.php | 35 +++++++++++++++++++ 3 files changed, 51 insertions(+), 4 deletions(-) diff --git a/core/lib/Drupal/Core/Validation/Plugin/Validation/Constraint/UniqueFieldValueValidator.php b/core/lib/Drupal/Core/Validation/Plugin/Validation/Constraint/UniqueFieldValueValidator.php index 1aad291d9a58..e965310861a3 100644 --- a/core/lib/Drupal/Core/Validation/Plugin/Validation/Constraint/UniqueFieldValueValidator.php +++ b/core/lib/Drupal/Core/Validation/Plugin/Validation/Constraint/UniqueFieldValueValidator.php @@ -23,10 +23,8 @@ public function validate($items, Constraint $constraint) { $entity_type_id = $entity->getEntityTypeId(); $id_key = $entity->getEntityType()->getKey('id'); - $query = \Drupal::entityQuery($entity_type_id); - - // @todo Don't check access. http://www.drupal.org/node/3171047 - $query->accessCheck(TRUE); + $query = \Drupal::entityQuery($entity_type_id) + ->accessCheck(FALSE); $entity_id = $entity->id(); // Using isset() instead of !empty() as 0 and '0' are valid ID values for diff --git a/core/modules/system/tests/modules/unique_field_constraint_test/unique_field_constraint_test.module b/core/modules/system/tests/modules/unique_field_constraint_test/unique_field_constraint_test.module index 0488d3d606e6..54547421b5cc 100644 --- a/core/modules/system/tests/modules/unique_field_constraint_test/unique_field_constraint_test.module +++ b/core/modules/system/tests/modules/unique_field_constraint_test/unique_field_constraint_test.module @@ -6,6 +6,7 @@ */ use Drupal\Core\Entity\EntityTypeInterface; +use Drupal\Core\Database\Query\AlterableInterface; /** * Implements hook_entity_base_field_info_alter(). @@ -15,4 +16,17 @@ function unique_field_constraint_test_entity_base_field_info_alter(&$fields, Ent /** @var \Drupal\Core\Field\BaseFieldDefinition[] $fields */ $fields['name']->addConstraint('UniqueField'); } + if ($entity_type->id() === 'entity_test') { + /** @var \Drupal\Core\Field\BaseFieldDefinition[] $fields */ + $fields['name']->addConstraint('UniqueField'); + } +} + +/** + * Implements hook_query_entity_test_access_alter(). + */ +function unique_field_constraint_test_query_entity_test_access_alter(AlterableInterface $query) { + // Set an impossible condition to filter out all entities. + /** @var \Drupal\Core\Database\Query\Select|\Drupal\Core\Database\Query\AlterableInterface $query */ + $query->condition('entity_test.id', 0); } diff --git a/core/tests/Drupal/KernelTests/Core/Validation/UniqueFieldConstraintTest.php b/core/tests/Drupal/KernelTests/Core/Validation/UniqueFieldConstraintTest.php index 11ba975481de..1e8cb229427b 100644 --- a/core/tests/Drupal/KernelTests/Core/Validation/UniqueFieldConstraintTest.php +++ b/core/tests/Drupal/KernelTests/Core/Validation/UniqueFieldConstraintTest.php @@ -3,6 +3,7 @@ namespace Drupal\KernelTests\Core\Validation; use Drupal\Component\Render\FormattableMarkup; +use Drupal\entity_test\Entity\EntityTest; use Drupal\entity_test\Entity\EntityTestStringId; use Drupal\KernelTests\KernelTestBase; @@ -112,4 +113,38 @@ public function providerTestEntityWithStringIdWithViolation() { ]; } + /** + * Tests validating inaccessible entities. + * + * The unique_field_constraint_test_entity_test_access() function + * forbids 'view' access to entity_test entities. + * + * @covers ::validate + */ public function testViolationDespiteNoAccess() { + $this->installEntitySchema('entity_test'); + + // Create and save an entity with a given field value in the field that has + // the unique constraint. + EntityTest::create([ + 'name' => 'A totally unique entity name', + ])->save(); + + // Prepare a second entity with the same value in the unique field. + $entity = EntityTest::create([ + 'name' => 'A totally unique entity name', + ]); + /** @var \Symfony\Component\Validator\ConstraintViolationList $violations */ + $violations = $entity->get('name')->validate(); + + $message = new FormattableMarkup('A @entity_type with @field_name %value already exists.', [ + '%value' => 'A totally unique entity name',, + '@entity_type' => $entity->getEntityType()->getSingularLabel(), + '@field_name' => 'Name', + ]); + + // Check that the validation has created the appropriate violation. + $this->assertCount(1, $violations); + $this->assertEquals($message, $violations[0]->getMessage()); + } + } -- GitLab