1

Related to this question, I have a functional test asserting that hook_node_access is doing what it should for different users.

While I can access edit and delete routes, I add an additional check for $node->access() and see what its result is:

$low_user->set('field_suppliers', $supplier->id());
$low_user->save();

// With the supplier set, now we should have access.
$this->drupalGet('/node/' . $offer->id() . '/edit');
$this->assertSession()->statusCodeEquals(200);

$this->drupalGet('/node/' . $offer->id() . '/delete');
$this->assertSession()->statusCodeEquals(200);

// Why is this required?
$offer->save();
$this->assertSame(TRUE, $offer->access('update', $low_user));
$this->assertSame(TRUE, $offer->access('delete', $low_user));

Everything passes except the last two statements unless I save the node. I assume this is due to the line:

AccessResult::allowedIf(!empty($user_has_suppliers_with_node))->cachePerUser()->addCacheableDependency($node);

I also tried using resetCache and invalidateTags against the node, neither worked. Only saving the node will the test pass - but this is not required in implementation.

Edit:

Swapping $offer->save() with \Drupal::service('plugin.cache_clearer')->clearCachedDefinitions(); also works.

I suppose I should be simulating an admin logging in and updating that user account and hitting "Save" on the user form, but I also had trouble getting the edit array to do anything for an autocomplete field. That is the difference between what is implemented and how its being tested (user action vs code).

3
  • Did you try to invalidate the cache contexts?
    – avpaderno
    Commented Jul 16, 2022 at 16:15
  • This says cache contexts cannot be invalidated: drupal.stackexchange.com/a/252891/57
    – Kevin
    Commented Jul 16, 2022 at 16:35
  • The access result is cached, for example with AccessResult::allowed()->cachePerPermissions(). cachePerPermissions() adds the user.permissions cache context.
    – avpaderno
    Commented Jul 17, 2022 at 7:30

1 Answer 1

3

This looks like the access result is stored in the static cache. Try to clear it before testing node access:

\Drupal::entityTypeManager()->getAccessControlHandler('node')->resetCache();
3
  • Yeah, this also does it. Is this required for testing, or is the implementation not quite right?
    – Kevin
    Commented Jul 16, 2022 at 17:40
  • 1
    This is only required for testing. In a normal request your implementation should work without problems because the static cache doesn't persist between requests.
    – 4uk4
    Commented Jul 16, 2022 at 17:54
  • Yes, EntityAccessControlHandler::access() tries to retrieve the access value from its static cache. The same issue could happen to any code that creates an entity and calls its access() method without first saving the entity.
    – avpaderno
    Commented Jul 17, 2022 at 7:39

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.