Follow-up to #2429261: Replace the hardcoded cache key on the book navigation block with a 'book navigation' cache context
Currently masquerade block does not use caching but should.
The extra field for user entity with link to masquerade uses post render cache to allow more granular access checking, but probably could be cached too.
Block used to expose an auto-complete for user names to switch to.
The form/block is accessible when user have 'masquerade as any user' permission and user is not masquerading (session flag).
Plus we use toolbar button to switch back, but no idea how toolbar is cached...
On other hand we are trying to implement menu link(s) to switch(back) that should be cached the same way.
Once we implement cache context the masquerade advanced could start add new UI elements.
| Comment | File | Size | Author |
|---|---|---|---|
| #15 | interdiff.txt | 552 bytes | mr.baileys |
| #15 | implement_caching_for-2448699-15.patch | 6.2 KB | mr.baileys |
| #15 | implement_caching_for-2448699-15-test-fail.patch | 5.87 KB | mr.baileys |
| #13 | implement_caching_for-2448699-13.patch | 4.32 KB | andypost |
Comments
Comment #1
wim leersSo now that rendered menus/menu blocks are finally correctly cached, this is no longer blocked.
Right now, it is always caching per user: http://cgit.drupalcode.org/masquerade/tree/src/Access/SwitchAccessCheck.... — but that is not correct. Because it actually is happening on a per-permissions basis. And yes, even the UID==1 edge case is wrong/unnecessary, because Drupal already takes care of that for you: it grants user 1 *all* permissions. See https://api.drupal.org/api/drupal/core%21modules%21user%21src%21Entity%2....
So:
SwitchAccessCheckneeds to be updated to fix these bugs. It will be simpler in the end :)Finally, to answer the key question here: . Usually the answer is trivial. But here it is not, because what Masquerade does, affects the entire response, and even affects other cache contexts.
If you haven't yet, read https://www.drupal.org/developing/api/8/cache/contexts.
So, let's analyze it at a UI level:
is_masqueradingcache context for that purpose, which just checks for the presence of that$_SESSION['some key']array value.max-age = 0, but once there is ais_masqueradingcache context, themax-age = 0can be removed in favor of varying by that cache context.That way, everything is perfectly cacheable, and simple & clear to understand :)
Comment #2
andypostAdded cache context and it's usage, but the "Unmasquerade" menu link is still visible for UID=1
@Wim please point me why that could happen
Comment #3
andypostAnother part for #2615434: Implement proper access for masquerade block
Comment #4
andypostThe reason why menu link is always visible
Comment #5
andypostThe only question left... is it ok to give different cache contexts for the blockAccess()?
Comment #6
andypostI tested block and looks that works fine but caching of access still a question
Comment #7
andypostComment #10
wim leersIs there still a question for me here or not?
Comment #11
andypost@Wim yep, the question is #5 - is it ok to return different cache contexts from access handler?
Comment #12
wim leersHere you go :)
This should be renamed to
cache_context.session.is_masquerading, because it's stored in the session, and thus if something already varies bysession, it already varies by whether it's masquerading or not.See https://www.drupal.org/developing/api/8/cache/contexts#optimizing
Then this would become
'session.is_masquerading'.Oh, hah, I not even know this service existed!
So, if the user is masquerading, we DO NOT want to show this block.
Which means the access result depends on
session.is_masquerading.It is handled correctly for the case where the user is masquerading. But it's not handled correctly in the other case. In the other case, we only vary by whether the user has permission. But we need that to also vary by
session.is_masquerading! Because the return value of this method always depends onsession.is_masquerading.So, you want to add
addCacheContexts(['session.is_masquerading'])to that last line also.Comment #13
andypostSo that context should be used all over
Comment #14
wim leersLooks good :) Test coverage should prove that the earlier patch has fails, and the latest patch does not.
Comment #15
mr.baileysI started writing tests for this, but applying the most recent patch against Masquerade-8.x-2.x-dev did not yield the expected result. Steps to reproduce:
This is one reproducible scenario. While playing around, it frequently occurred that the block was unexpectedly shown or hidden.
I tracked this down to MasqueradeCacheContext::getContext(), which has 2 issues:
2 patches attached: one is the unaltered patch from #13, but with a specific test for this behaviour, the second patch fixes the session context return value (in a follow-up issue, Masquerade should probably switch from using $_SESSION to using the Symfony Session.
Comment #17
andypostThanx for tests, looks module's tests broken but this change makes a lot of sense, so commited
Exactly this! Filed follow-up #2688650: Switch from using $_SESSION to using the Symfony Session
Comment #18
andypostI'm reopening #2448707: Fix masquerade tests