0

UPDATE: Narrowing this a bit. I need to, for either (a) all nodes of a given type or (b) all nodes on a specified list of node id's or (c) all users on a list of iser id's, clear the cached permissions because, due to changes not necessarily made on a given node, a user's access permission may have changed.

I have built and published a module (Access by Reference) that grants update access to nodes based on edit permissions on nodes referenced in the target node.

I am concerned that the module will not work as intended if permissions cache interferes with recognizing changes made elsewhere (eg, rights to the referenced node are changed)

What I would like to do is clear permissions caches relating to particular nodes and/or particular users or roles. I've been studying the Cache Contexts for several days but the light bulb has not yet lit. I'd appreciate some guidance.

closed as too broad by leymannx, Alfred Armstrong, mradcliffe, Felix Eve, Shawn Conn Sep 8 '18 at 20:23

Please edit the question to limit it to a specific problem with enough detail to identify an adequate answer. Avoid asking multiple distinct questions at once. See the How to Ask page for help clarifying this question. If this question can be reworded to fit the rules in the help center, please edit the question.

  • Too broad, TBH. But maybe you can get some co-maintainers onboard and discuss it with them. Or maybe you can present this problem in a series of talks/discussions at a local Drupal meetup/user group. – leymannx Aug 29 '18 at 17:21
  • 1
    Implementing Custom Cache Tags should help with what you are trying to do. – LittleCoding Aug 29 '18 at 17:27
  • 1
    Agree with this being a bit broad. If you can find a specific set of steps that result in a problem then it might be possible to provide a specific answer on how to solve that, but this is too unspecific. This isn't a discussion forum, it's a question/answer site. – Berdir Aug 29 '18 at 19:15
1

Access results can store cache metadata like cache tags and cache contexts. As a shortcut AccessResult has two specific methods to apply the correct cache metadata. Different membership in roles or a modified role results in a different set of permissions, use cachePerPermissions() to add a cache context for the hashed permissions. The second method is for the cache context of the current user cachePerUser().

If you get field data from a node or user, add addCacheableDependency($node) or addCacheableDependency($user).

See this example from the node module:

core/modules/node/node.module, line 938

function node_node_access(NodeInterface $node, $op, $account) {
  $type = $node
    ->bundle();
  switch ($op) {
    case 'create':
      return AccessResult::allowedIfHasPermission($account, 'create ' . $type . ' content');
    case 'update':
      if ($account
        ->hasPermission('edit any ' . $type . ' content', $account)) {
        return AccessResult::allowed()
          ->cachePerPermissions();
      }
      else {
        return AccessResult::allowedIf($account
          ->hasPermission('edit own ' . $type . ' content', $account) && $account
          ->id() == $node
          ->getOwnerId())
          ->cachePerPermissions()
          ->cachePerUser()
          ->addCacheableDependency($node);
      }
  • Okay, this is helping me move forward, and it seems to be workable for a given single node. Here's the clarification I just added to the OP Narrowing this a bit. I need to, for either (a) all nodes of a given type or (b) all nodes on a specified list of node id's or (c) all users on a list of iser id's, clear the cached permissions because, due to changes not necessarily made on a given node, a user's access permission may have changed. – Michael D. Moradzadeh Aug 30 '18 at 13:49
  • a+b) You get a context for the node automatically, because the access is tight to a specific route with its parameters. c) cachePerPermissions() is very powerful, because it hashes all permissions. Use cachePerUser() only if the access depends on the specific user id, because this is far more expensive to cache. I think you should get with the methods I've described quite far. Important is that you add all entities (nodes, user, paragraphs, taxonomy terms ...) and config objects you use data from to calculate the access. Then test it and if you find a specific problem ask another question. – 4k4 Aug 30 '18 at 18:14
  • Well, I have still not figured it out. I am stuck on what to put in as a cid. I hacked some code and found that this is working for me now.... -------------------- PhpStorageFactory::get('twig') ->deleteAll(); – Michael D. Moradzadeh Aug 31 '18 at 2:21
  • You don't need to think about the cache cid, this is on a lower level in the caching system. As described you deal with cache contexts and tags. Now your module returns no cache metadata at all, so you should start with the obvious I've described and test if there are any caching issues left. – 4k4 Aug 31 '18 at 10:33
  • Thanks for sticking with me. Here is my concern with that code. It appears to set the cache dependency on the $node. Any change to the node will invalidate the cache wrt that object. Well, that already happens, but my module changes access based on changes to OTHER nodes. I fear it won't do the trick. I'll check. – Michael D. Moradzadeh Sep 1 '18 at 14:20

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