Problem/Motivation
#2785155: _node_access_rebuild_batch_operation uses queries that check access shows how easy it is to forget to use accessCheck(FALSE) when writing entity queries that need to ignore access. In this case when rebuilding the very table that does the access checks (when access checking is likely to be foremost in your mind).
I've run into this on site builds too - i.e. if you forget to do this in an update, then you can end up not updating anything on sites where anonymous users can't access anything and updates are run via drush - unless you run the update as user/1 from update.php in which case it'll run OK.
The result of a bad query can often be data-integrity issues - i.e. an incomplete node grants table. Also not only is it easy to forget accessCheck(FALSE) when writing queries, but in many cases that code will run fine (because it's written on an install not using node grants), then fail when node access is introduced.
Defaulting access checks to TRUE was done to avoid information disclosure bugs, but this has been at the cost of making it very easy to introduce data integrity bugs instead.
Proposed resolution
Require an ::accessCheck() call when building a query, deprecate not calling it.
To do this, we had to fix all existing entity query uses in core in #3200985: [meta] Fix undesirable access checking on entity query usages.
Alternative resolutions that we considered
1. Move the decision about access checking earlier, by having an entity query that by default has accessCheck(FALSE). This is potentially just an extra factory and service (entity.query.all_access? entity.query.no_access_check?) that would add accessCheck(FALSE) to the query object before returning it from the factory.
Most classes will either being doing audit-type queries so can inject the different service or only rendering so can use the current one. Ones that are using both can use both services separately. Either way this ought to be easier to keep track of than checking every query for whether or not it needs an accessCheck(FALSE) or not.
2. Add an $access_check parameter to ::getQuery(), and deprecate not calling that.
Remaining tasks
- Decide on a solution
- Ensure that all core entity queries specify accessCheck
- Code fix & test
- Write change record
- Review
- Commit
User interface changes
None
API changes
The accessCheck() method must be called on an entity query.
Data model changes
None