Change record status: 
Project: 
Introduced in branch: 
9.2.x
Introduced in version: 
9.2.0
Description: 

The \Drupal\Core\Entity\Query\QueryInterface::accessCheck() allows developers to specify whether only content entities that the current user has view access for should be returned when the query is executed. Although all entity queries support this method, core only actually implements access checking on the results for content entities that use sql-storage.

If ::accessCheck() is not called, then the query defaults to checking access, i.e. behaves as if ::accessCheck(TRUE) had been called. This behavior has been the source of many bugs, as it is easy for developers to forget that this happens.

In Drupal 9.2, not calling ::accessCheck() has been deprecated, and all entity queries on content entities should always include an explicit call to ::accessCheck() prior to the query being executed. For Drupal 10 this will be enforced by throwing an exception if ::accessCheck() is not called.

Example:

BEFORE

// This gets all articles the current user can view.
$ids = \Drupal::entityQuery('node')
  ->condition('type', 'article')
  ->execute();

// This also gets all articles the current user can view.
$ids = \Drupal::entityQuery('node')
  ->accessCheck(TRUE)
  ->condition('type', 'article')
  ->execute();

// This gets all articles that exist regardless of access.
$ids = \Drupal::entityQuery('node')
  ->accessCheck(FALSE)
  ->condition('type', 'article')
  ->execute();

AFTER

// This will trigger a deprecation error.
$ids = \Drupal::entityQuery('node')
  ->condition('type', 'article')
  ->execute();

// Unchanged: This gets all articles the current user can view.
$ids = \Drupal::entityQuery('node')
  ->accessCheck(TRUE)
  ->condition('type', 'article')
  ->execute();

// Unchanged: This gets all articles that exist regardless of access.
$ids = \Drupal::entityQuery('node')
  ->accessCheck(FALSE)
  ->condition('type', 'article')
  ->execute();

This change doesn't apply to config entities.

Impacts: 
Module developers
Distribution developers
Updates Done (doc team, etc.)
Online documentation: 
Not done
Theming guide: 
Not done
Module developer documentation: 
Not done
Examples project: 
Not done
Coder Review: 
Not done
Coder Upgrade: 
Not done
Other: 
Other updates done

Comments

claudiu.cristea’s picture

Shouldn't be explained that this doesn't apply to config entity types? EDIT: In fact it was explained but I didn't notice. I've made it more visible.

Claudiu Cristea | Webikon.com

ressa’s picture

Most "Remaining self deprecation notices" in #3252256: Fix the tests, including missing @group annotation were sorted out, but how can this warning can be fixed?

2x: 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
    1x in StringTest::testFieldString from Drupal\Tests\field_defaults\Functional
    1x in BooleanTest::testFieldBoolean from Drupal\Tests\field_defaults\Functional
Gonzalo2683’s picture

@ressa Using ->accessCheck(FALSE) or ->accessCheck(FALSE) according to the need of your queries, so the warnings no longer appear.

ressa’s picture

Thanks for the tip @Gonzalo2683, the solution you suggest was added by @beatrizrodrigues a while ago:
https://git.drupalcode.org/project/field_defaults/-/merge_requests/3/dif...

mglaman’s picture

Due to the complexity of this change, it cannot be automated with drupal-rector. It has been proven challenging to correctly report missing access check calls with phpstan-drupal.

podarok’s picture

Friendly comment

Whoever did this change - does not actually love people much...

This patch https://github.com/podarok/drupal/commit/5656ba39204d105ca7c26535ed963d0... helped me to find places where accessCheck was missed in the code.

---------------
Andrii Podanenko
CEO, ITCare

jonathanshaw’s picture

That would be me :) I hate the ugliness of adding accessCheck(FALSE) to almost every entity query and making Drupal developers spend time adding it to existing code. But I hated having developers wasting hours of time chasing weird bugs because they forgot that queries were assuming accessCheck(TRUE) by default when that wasn't the behavior that 95% of time is wanted.

podarok’s picture

Ah, UK )))

Thank you for the support

---------------
Andrii Podanenko
CEO, ITCare

Parashram’s picture

Thanks! It really helps.

Oleks Iv’s picture

I guess drupal community needs to learn more from Golang, which always guarantees backward compatibility in every new version.
This is hell to update from D9 to D10, because of "Entity queries must explicitly set whether the query should be access checked or not." that is super complicated to debug!

robbdavis’s picture

With that enabled, you can scan all your custom modules. It will show you exactly where you need to add the new access checks.

https://www.drupal.org/project/upgrade_status