Commit aea84a7c authored by catch's avatar catch
Browse files

Issue #2785449 by jonathanshaw, longwave, andypost, catch, timmillwood,...

Issue #2785449 by jonathanshaw, longwave, andypost, catch, timmillwood, larowlan: It's too easy to write entity queries with access checks that must not have them
parent c72c953a
Loading
Loading
Loading
Loading
+3 −3
Original line number Diff line number Diff line
@@ -95,11 +95,11 @@ abstract class QueryBase implements QueryInterface {
  protected $alterTags;

  /**
   * Whether access check is requested or not. Defaults to TRUE.
   * Whether access check is requested or not.
   *
   * @var bool
   * @var bool|null
   */
  protected $accessCheck = TRUE;
  protected $accessCheck;

  /**
   * Flag indicating whether to query the current revision or all revisions.
+3 −2
Original line number Diff line number Diff line
@@ -29,6 +29,7 @@ public function getEntityTypeId();
   * and the Polish 'siema' within a 'greetings' text field:
   * @code
   *   $entity_ids = \Drupal::entityQuery($entity_type)
   *     ->accessCheck(FALSE)
   *     ->condition('greetings', 'merhaba', '=', 'tr')
   *     ->condition('greetings.value', 'siema', '=', 'pl')
   *     ->execute();
@@ -236,7 +237,7 @@ public function execute();
   * field containing 'shape' and 'color' columns. To find all drawings
   * containing both a red triangle and a blue circle:
   * @code
   *   $query = \Drupal::entityQuery('drawing');
   *   $query = \Drupal::entityQuery('drawing')->accessCheck(FALSE);
   *   $group = $query->andConditionGroup()
   *     ->condition('figures.color', 'red')
   *     ->condition('figures.shape', 'triangle');
@@ -260,7 +261,7 @@ public function andConditionGroup();
   * containing 'building_type' and 'color' columns. To find all green and
   * red bikesheds:
   * @code
   *   $query = \Drupal::entityQuery('map');
   *   $query = \Drupal::entityQuery('map')->accessCheck(FALSE);
   *   $group = $query->orConditionGroup()
   *     ->condition('attributes.color', 'red')
   *     ->condition('attributes.color', 'green');
+4 −0
Original line number Diff line number Diff line
@@ -136,6 +136,10 @@ protected function prepare() {
      $this->sqlQuery->isNull("base_table_2.$id_field");
    }

    if (is_null($this->accessCheck)) {
      $this->accessCheck = TRUE;
      @trigger_error('Relying on entity queries to check access by default is deprecated in drupal:9.2.0 and an error will be thrown from drupal:10.0.0. Call \Drupal\Core\Entity\Query\QueryInterface::accessCheck() with TRUE or FALSE to specify whether access should be checked. See https://www.drupal.org/node/3201242', E_USER_DEPRECATED);
    }
    if ($this->accessCheck) {
      $this->sqlQuery->addTag($this->entityTypeId . '_access');
    }
+1 −0
Original line number Diff line number Diff line
@@ -166,6 +166,7 @@ public function testAggregation() {

    // Don't call aggregate to test the implicit aggregate call.
    $this->queryResult = $this->entityStorage->getAggregateQuery()
      ->accessCheck(FALSE)
      ->groupBy('id')
      ->conditionAggregate('id', 'COUNT', 8)
      ->execute();
+31 −1
Original line number Diff line number Diff line
@@ -938,6 +938,7 @@ public function testCaseSensitivity() {

    $result = $this->storage
      ->getQuery()
      ->accessCheck(FALSE)
      ->condition('field_ci', $fixtures[0]['uppercase'], 'STARTS_WITH')
      ->execute();
    $this->assertCount(1, $result, 'Case sensitive, exact match.');
@@ -952,6 +953,7 @@ public function testCaseSensitivity() {

    $result = $this->storage
      ->getQuery()
      ->accessCheck(FALSE)
      ->condition('field_cs', $fixtures[0]['uppercase'], 'STARTS_WITH')
      ->execute();
    $this->assertCount(1, $result, 'Case sensitive, exact match.');
@@ -1052,6 +1054,7 @@ public function testBaseFieldMultipleColumns() {
    $ids = $this->container->get('entity_type.manager')
      ->getStorage('taxonomy_term')
      ->getQuery()
      ->accessCheck(FALSE)
      ->condition('description.value', 'description1')
      ->execute();
    $this->assertCount(1, $ids);
@@ -1060,6 +1063,7 @@ public function testBaseFieldMultipleColumns() {
    $ids = $this->container->get('entity_type.manager')
      ->getStorage('taxonomy_term')
      ->getQuery()
      ->accessCheck(FALSE)
      ->condition('description.format', 'format1')
      ->execute();
    $this->assertCount(1, $ids);
@@ -1069,6 +1073,7 @@ public function testBaseFieldMultipleColumns() {
    $ids = $this->container->get('entity_type.manager')
      ->getStorage('taxonomy_term')
      ->getQuery()
      ->accessCheck(FALSE)
      ->condition('description', 'description1')
      ->execute();
    $this->assertCount(1, $ids);
@@ -1082,6 +1087,7 @@ public function testPendingRevisions() {
    // Ensure entity 14 is returned.
    $result = $this->storage
      ->getQuery()
      ->accessCheck(FALSE)
      ->condition('id', [14], 'IN')
      ->execute();
    $this->assertCount(1, $result);
@@ -1101,6 +1107,7 @@ public function testPendingRevisions() {
    // Entity query should still return entity 14.
    $result = $this->storage
      ->getQuery()
      ->accessCheck(FALSE)
      ->condition('id', [14], 'IN')
      ->execute();
    $this->assertCount(1, $result);
@@ -1109,12 +1116,14 @@ public function testPendingRevisions() {
    // work as expected.
    $result = $this->storage
      ->getQuery()
      ->accessCheck(FALSE)
      ->condition('id', [14], 'IN')
      ->condition("$this->figures.color", $current_values[0]['color'])
      ->execute();
    $this->assertEqual([14 => '14'], $result);
    $result = $this->storage
      ->getQuery()
      ->accessCheck(FALSE)
      ->condition('id', [14], 'IN')
      ->condition("$this->figures.color", 'red')
      ->allRevisions()
@@ -1133,6 +1142,7 @@ public function testPendingRevisions() {
    // A non-revisioned entity query should still return entity 14.
    $result = $this->storage
      ->getQuery()
      ->accessCheck(FALSE)
      ->condition('id', [14], 'IN')
      ->execute();
    $this->assertCount(1, $result);
@@ -1141,6 +1151,7 @@ public function testPendingRevisions() {
    // Now check an entity query on the latest revision.
    $result = $this->storage
      ->getQuery()
      ->accessCheck(FALSE)
      ->condition('id', [14], 'IN')
      ->latestRevision()
      ->execute();
@@ -1151,6 +1162,7 @@ public function testPendingRevisions() {
    // work as expected.
    $result = $this->storage
      ->getQuery()
      ->accessCheck(FALSE)
      ->condition('id', [14], 'IN')
      ->condition("$this->figures.color", $current_values[0]['color'])
      ->execute();
@@ -1159,6 +1171,7 @@ public function testPendingRevisions() {
    // Now there are two revisions with same value for the figure color.
    $result = $this->storage
      ->getQuery()
      ->accessCheck(FALSE)
      ->condition('id', [14], 'IN')
      ->condition("$this->figures.color", 'red')
      ->allRevisions()
@@ -1168,6 +1181,7 @@ public function testPendingRevisions() {
    // Check that querying for the latest revision returns the correct one.
    $result = $this->storage
      ->getQuery()
      ->accessCheck(FALSE)
      ->condition('id', [14], 'IN')
      ->condition("$this->figures.color", 'red')
      ->latestRevision()
@@ -1183,6 +1197,7 @@ public function testInjectionInCondition() {
    $this->expectException(\Exception::class);
    $this->queryResults = $this->storage
      ->getQuery()
      ->accessCheck(FALSE)
      ->condition('1 ; -- ', [0, 1], 'IN')
      ->sort('id')
      ->execute();
@@ -1215,6 +1230,7 @@ public function testWithTwoEntityReferenceFieldsToSameEntityType() {

    // Check that works when referring with "{$field_name}".
    $result = $storage->getQuery()
      ->accessCheck(FALSE)
      ->condition('type', 'entity_test')
      ->condition('ref1', $ref1->id())
      ->condition('ref2', $ref2->id())
@@ -1224,6 +1240,7 @@ public function testWithTwoEntityReferenceFieldsToSameEntityType() {

    // Check that works when referring with "{$field_name}.target_id".
    $result = $storage->getQuery()
      ->accessCheck(FALSE)
      ->condition('type', 'entity_test')
      ->condition('ref1.target_id', $ref1->id())
      ->condition('ref2.target_id', $ref2->id())
@@ -1233,6 +1250,7 @@ public function testWithTwoEntityReferenceFieldsToSameEntityType() {

    // Check that works when referring with "{$field_name}.entity.id".
    $result = $storage->getQuery()
      ->accessCheck(FALSE)
      ->condition('type', 'entity_test')
      ->condition('ref1.entity.id', $ref1->id())
      ->condition('ref2.entity.id', $ref2->id())
@@ -1265,6 +1283,7 @@ public function testConditionOnRevisionMetadataKeys() {

    // Query only the default revision.
    $result = $storage->getQuery()
      ->accessCheck(FALSE)
      ->condition($revision_created_field_name, $revision_created_timestamp)
      ->execute();
    $this->assertCount(1, $result);
@@ -1272,6 +1291,7 @@ public function testConditionOnRevisionMetadataKeys() {

    // Query all revisions.
    $result = $storage->getQuery()
      ->accessCheck(FALSE)
      ->condition($revision_created_field_name, $revision_created_timestamp)
      ->allRevisions()
      ->execute();
@@ -1283,7 +1303,7 @@ public function testConditionOnRevisionMetadataKeys() {
   * Tests __toString().
   */
  public function testToString() {
    $query = $this->storage->getQuery();
    $query = $this->storage->getQuery()->accessCheck(FALSE);
    $group_blue = $query->andConditionGroup()->condition("{$this->figures}.color", ['blue'], 'IN');
    $group_red = $query->andConditionGroup()->condition("{$this->figures}.color", ['red'], 'IN');
    $null_group = $query->andConditionGroup()->notExists("{$this->figures}.color");
@@ -1326,4 +1346,14 @@ public function testToString() {
    $this->assertSame($expected_string, (string) $query);
  }

  /**
   * Test the accessCheck method is called.
   *
   * @group legacy
   */
  public function testAccessCheckSpecified() {
    $this->expectDeprecation('Relying on entity queries to check access by default is deprecated in drupal:9.2.0 and an error will be thrown from drupal:10.0.0. Call \Drupal\Core\Entity\Query\QueryInterface::accessCheck() with TRUE or FALSE to specify whether access should be checked. See https://www.drupal.org/node/3201242');
    $this->storage->getQuery()->execute();
  }

}