Problem/Motivation

I'm encountering a strange problem with a custom access callback on a Controller being cached indefinitely, once access is denied, despite the proper cache metadata being added.

How to reproduce

1. Create (or use an existing) content entity type.
2. Create a Controller that accepts an entity of that type and has a custom access callback with the following code (adapted to match a field that exists):

return AccessResult::allowedIf(!$entity->some_field->isEmpty())
  ->andIf($entity->access('view', NULL, TRUE))
  ->cachePerUser()
  ->addCacheableDependency($entity);

In this example, access is granted if the entity has a field populated, and if the user can view the entity.

3. Create a local action link that places a link to this route when viewing the canonical page of the given entity type.
4. Create an entity that has the given field populated, using a user that has access to view it.
5. View the entity and see that the local action link appears.
6. Edit the entity, removing the value from the field.
7. View the entity again and see that the link disappeared.
8. Edit the entity again, adding a value to the field.
9. View the entity again and see that the link is still missing. Repeat as many times as you want. It will not appear until the cache is cleared.

What is failing?

I dug in to the cache_render table and I believe the problem is in there. When access is granted, the [user]={uid} context is added to the cid and the {entity_type}:{entity_id} tag is added. Once access it forbidden, a new cache entry is added with both entirely removed. Since that continues to be served, altering the entity never clears it.

After the initial viewing of the link while access is granted, the cache entry is something like:

cid:
entity_view:block:seven_local_actions:[languages:language_interface]=en:[route]=entity.channel.canonical2cdbfd30db6c0a00042de607c691780171e151826e7af21973539625a592cef4:[theme]=seven:[user]=1
tags:
block_view channel:2 config:block.block.seven_local_actions config:user.role.authenticated rendered user:1

After access is denied, a new entry is created like:

cid:
entity_view:block:seven_local_actions:[languages:language_interface]=en:[route]=entity.channel.canonical2cdbfd30db6c0a00042de607c691780171e151826e7af21973539625a592cef4:[theme]=seven:[user.permissions]=959dfab36c6GpFyh8nJi-O9PTd_Pfkjuip-Mn_ad24OMSM_HPErIU
tags:
block_view config:block.block.seven_local_actions rendered

Comments

mstef created an issue. See original summary.

berdir’s picture

I guess it won't fix the problem, although pretty sure that it should be passed up, but instead of calling access() and adding the cacheable metadata yourself, you should do something like this:

return AccessResult::allowedIf(!$entity->some_field->isEmpty())->andIf($entity->access('view', NULL, TRUE)->addCacheableDependency($entity).

(the call on $entity still makes sense because you are doing that check).

by combining the AccessResult response from the access call, you are collecting all the cacheablity metadata that that check involves while your current code hardcodes that assumption (that it is based on the current user).

mstef’s picture

That's good advice and makes complete sense. I actually didn't even know andIf() existed. That's useful.

Unfortunately, as you guessed, it does not impact the issue though.

mstef’s picture

Issue summary: View changes
berdir’s picture

A failing test case would be helpful to investigate this and confirm that it is not related to something else that's specific to your site.

mstef’s picture

Issue summary: View changes
dave reid’s picture

I can confirm this as well. I also have a custom access callback on my local action controller which is dependent on a module config entity value not being empty. When it results in allowed, the entry in cache_render includes the cache tag of the config entity as expected, but when it is not allowed, the cache entry does not include the cache tag.

Version: 8.5.x-dev » 8.6.x-dev

Drupal 8.5.6 was released on August 1, 2018 and is the final bugfix release for the Drupal 8.5.x series. Drupal 8.5.x will not receive any further development aside from security fixes. Sites should prepare to update to 8.6.0 on September 5, 2018. (Drupal 8.6.0-rc1 is available for testing.)

Bug reports should be targeted against the 8.6.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.7.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.6.x-dev » 8.8.x-dev

Drupal 8.6.x will not receive any further development aside from security fixes. Bug reports should be targeted against the 8.8.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.9.x-dev branch. For more information see the Drupal 8 and 9 minor version schedule and the Allowed changes during the Drupal 8 and 9 release cycles.

Version: 8.8.x-dev » 8.9.x-dev

Drupal 8.8.7 was released on June 3, 2020 and is the final full bugfix release for the Drupal 8.8.x series. Drupal 8.8.x will not receive any further development aside from security fixes. Sites should prepare to update to Drupal 8.9.0 or Drupal 9.0.0 for ongoing support.

Bug reports should be targeted against the 8.9.x-dev branch from now on, and new development or disruptive changes should be targeted against the 9.1.x-dev branch. For more information see the Drupal 8 and 9 minor version schedule and the Allowed changes during the Drupal 8 and 9 release cycles.

Version: 8.9.x-dev » 9.2.x-dev

Drupal 8 is end-of-life as of November 17, 2021. There will not be further changes made to Drupal 8. Bugfixes are now made to the 9.3.x and higher branches only. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

Version: 9.2.x-dev » 9.3.x-dev

Version: 9.3.x-dev » 9.4.x-dev

Drupal 9.3.15 was released on June 1st, 2022 and is the final full bugfix release for the Drupal 9.3.x series. Drupal 9.3.x will not receive any further development aside from security fixes. Drupal 9 bug reports should be targeted for the 9.4.x-dev branch from now on, and new development or disruptive changes should be targeted for the 9.5.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

Version: 9.4.x-dev » 9.5.x-dev

Drupal 9.4.9 was released on December 7, 2022 and is the final full bugfix release for the Drupal 9.4.x series. Drupal 9.4.x will not receive any further development aside from security fixes. Drupal 9 bug reports should be targeted for the 9.5.x-dev branch from now on, and new development or disruptive changes should be targeted for the 10.1.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

Version: 9.5.x-dev » 11.x-dev

Drupal core is moving towards using a “main” branch. As an interim step, a new 11.x branch has been opened, as Drupal.org infrastructure cannot currently fully support a branch named main. New developments and disruptive changes should now be targeted for the 11.x branch. For more information, see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

acbramley’s picture

Status: Active » Postponed (maintainer needs more info)
Issue tags: +Bug Smash Initiative

This is almost 6 years old with no additional comments, is this still a valid bug on 11.x?

acbramley’s picture

Status: Postponed (maintainer needs more info) » Closed (outdated)

Since it's been 6+ months without a follow up for steps going to close out. If still an issue please reopen