If a module defines a new contextual likes in a *.links.contextual.yml file they are not available unless 1 of these things happens:
- The user's permissions change
- The user opens a new browser session
- The user logs out and in.
This is because the contextual links are cached on the client-side and the cache is not cleared unless the hash created by the user's permissions hash changes.
I found while working on #2753941: [Experimental] Create Outside In module MVP to provide block configuration in Off-Canvas tray and expand site edit mode which creates a new contextual link.
This could be fixed by a relying on a hash of current modules installed in addition to permissions.
| Comment | File | Size | Author |
|---|---|---|---|
| #80 | 2773591-80.patch | 5.82 KB | steyep |
| #74 | interdiff_73-74.txt | 2.66 KB | sourabhjain |
| #74 | 2773591-74.patch | 5.82 KB | sourabhjain |
| #73 | 2773591-73.patch | 5.55 KB | ion.macaria |
| #71 | 2773591-71.patch | 8.11 KB | _utsavsharma |
Issue fork drupal-2773591
Show commands
Start within a Git clone of the project using the version control instructions.
Or, if you do not have SSH keys set up on git.drupalcode.org:
Comments
Comment #2
dawehnerThe alternative I could like to propose is to calculate a hash of all contextual links and send this along when the contextual links are rendered. This also fixes the problem that clearing the cache when changing the YML file, doesn't cause the new links to appear.
Comment #4
xjmWith the Outside In patch, neither of these is sufficient for me to get the contextual links to work. It only works if (as @effulgentsia suggested), I enable the module, do a full site cache clear through the UI, and THEN open a new browser session and log in again.
I am also not sure this is true of all contextual links. Using these steps:
Note that I tried it both with and without Toolbar enabled at the start, just in case.
So I do not think this is a core bug. Thus far it appears to only happen with Outside In.
Comment #5
effulgentsia commentedI tried a different variation of #4 (all of the following steps except #1 done through UI, not Drush):
standard.info.yml, comment out theviews_uidependency./admin/config/development/performance.So yes, #4's conclusion seems correct that Outside In is behaving differently, because a cache clear alone isn't enough, like it is with Views UI. And instead, Outside In seems to also require some client-side invalidation (per #2753941-193: [Experimental] Create Outside In module MVP to provide block configuration in Off-Canvas tray and expand site edit mode), which Views UI does not seem to require.
Comment #6
dawehnerHere is a way of reproducing that I stumble and get smad (sad and mad) about all the time.
links.contextual.ymlfile ✓window.sessionStorage.clear()While there might be some weird problem of the outside in module.
To be honest I somehow cannot believe that views_ui actually is able to fix that problem :)
Comment #7
sweetchuckThis is what I have done so far. I am not sure about this is the right direction
Comment #8
dawehner@Sweetchuck
This is looking great. I would argue that we maybe still want to vary to links in cache, also when the permissions change.
Comment #9
effulgentsia commentedIn addition to the client-side work in #7, there's also the problem that
ContextualLinkManager::getContextualLinkPluginsByGroup()calls$this->cacheBackend->set()without passing$this->cacheTags. As a result, whenclearCachedDefinitions()is called, such as during module install, these cache entries aren't cleared. Additionally, ContextualLinkManager should probably also extend clearCachedDefinitions() to also clear its local properties, such as$this->pluginsByGroup.Comment #10
wim leersThe correct solution is already listed in the IS:
That would solve the reported problem.
However, @dawehner is right that his proposed solution in #2 would go even further: it'd also fix the problem of modules having updated their set of contextual links and those changes not being reflected for end users.
So, the patch in #7 is correct in that respect. But it sadly also removes the checking of
permissionsHash, which is absolutely incorrect. @dawehner also pointed this out in #8, but he seems to think it's more optional than it is. It's essential.This shows that we really want JS test coverage of this, which we now can, because we now have JS tests that can use
window.sessionStorage! :)Comment #11
wim leersComment #13
james.williamsHere's a patch that checks both the permissions hash, and the hash of contextual link plugins, as that was fairly easy to put together. It doesn't go as far as checking a hash of links themselves, sorry.
I've assumed it's ok to just deal with the permissions and plugins hashes separately rather than sticking them somewhere together.
Comment #15
james.williamsAw, patch needs a re-roll as it was actually made against 8.3.x, sorry!
Comment #16
james.williamsComment #17
tedbow@james.williams thanks for starting work on this again.
We have 2 todo's about this issue in the outside_in module. I wonder if we removed the code, search for "https://www.drupal.org/node/2773591", If the tests would still pass.
Though I wonder in our tests if it is fully covered because I am not sure if we are making request before the module is enabled.
It would be interesting to have 2 patches
1) Just remove code that points to this issue in outside_in. Don't include any changes from above patch. The test should fail(if not we should add test)
2). remove code that points to this issue in outside_in. combined with the patch above. The tests should pass.
Comment #18
pk188 commentedRe rolled.
Comment #19
wim leersStill needs tests.
Do we really need to salt this?
Comment #20
tedbowWorking on a test
Comment #21
tedbowThis is not working for me.
Here is test that I think proves it does not work.
I added the check for a contextual link after a module is installed to \Drupal\Tests\contextual\FunctionalJavascript\ContextualLinksTest::testContextualLinksVisibility
I changed a bunch of existing lines in the test because this line was repeated:
$contextualLinks = $this->assertSession()->waitForElement('css', '.contextual button');Since this is actually checking for the button and not the links and we are now testing for the actual links it would have confusing to leave the variable name.
So I changed it to
$contextualButtonIn the test I added enabling the new contextual_test module which simply provides a contextual link.
It does not show after the page reloaded.
This confirms what I have seen manually that the link does not show up until I add a new block. The old blocks do not get the link.
Settings to Needs Review for the test to run but probably Needs Work if the test fails and others think the test is correct.
Comment #22
tedbowComment #24
sardara commentedWe have in our project a similar issue, but it's caused by the fact that some permissions come from the organic group module.
This leads to:
A solution might be to swap out the
user_permissions_hash_generatorservice to include the og permissions/roles, but that will mess with thecache_context.user.permissionsand we don't think it's the proper approach.Comment #27
wim leersLet's get this moving forward again. This would remove two
@todos from the Settings Tray module and would help the Drupal contrib ecosystem (see #24) too.Comment #28
wim leersComment #29
pfrenssenI agree that limiting this use case only to enabling / disabling modules is not enough. A very simple use case we are having in Organic Groups is affected by this:
Joining and leaving a group are very trivial actions for a user in a site that uses OG. It basically makes the use of contextual links impossible for managing group related stuff.
Neither checking the list of enabled modules, or hashing the set of available contextual menus will solve this case. The ideal solution would be to have a cache context / cache tag like system. But being able to nuke the links from the PHP side would be a good workaround. Also having an event that fires when the hash is calculated would be a good idea, then developers can hook into it if they have any need for customizing the hash generation.
Comment #30
pfrenssenComment #32
tim.plunkettSaw someone else get bit by this again today
Comment #37
nwom commented#21 looks like it needs a re-roll for both 9.1.x/9.2.x
Comment #38
ankithashettyRe-rolled patch in #21 as suggested in #37... Thanks!
Comment #40
smustgrave commentedUpdated the es6 file.
Comment #41
smustgrave commentedTypo in patch sorry!
Comment #42
karishmaamin commentedTried to fix Custom Commands failure in #40
Comment #43
marcvangendI think this should fix the custom commands failures. At least commit-code-check.sh passes on my local system.
Comment #45
smustgrave commentedSo we may be seeing this error again. But it’s not consistent as some devs are seeing while others not. Is there a cache table we could check?
Comment #47
larowlanI don't think we need the intermediary $cl_manager variable for a single use
ubernit, but we don't need the cl_ prefix here in my opinion
We need to retain the old hash too right? For when permissions are changed.
So I think we need both flavours
These changes feel out of scope and should probably be done in their own issue
This is probably too reliant on the classy base theme, which we're hoping to remove.
Can we instead assert the link text, rather than the class?
Comment #48
sourabhjainResolved the 1st point suggested in #47
Comment #50
proweb.ua commented#48 works
drupal 9.4.5
Comment #51
smustgrave commentedCurious at #48 why just fix one issue from #47 when a few more were low hanging
Starting at #43 addressed the bullets in #47
Interdiff had a hard time generating though so may not contain all the changes.
Comment #53
super_romeo commentedPatch #51 Failed to Apply on D9.5.x.
Comment #54
smustgrave commentedRerolled for 9.5 + 10.1
Comment #55
smustgrave commentedComment #57
catchThis looks like a good solution, but it needs a comment.
Comment #58
smustgrave commentedAdded a comment.
Comment #59
larowlannit: JavaScript
I don't know if we should be using the hash salt for this, its kind of leaking privileged data, we really only want a hash, doesn't need to be secure
do we need the equivalent type check for the new hash?
Comment #60
larowlanthis doesn't fail if the link is missing, we need $this->fail() outside the loop
Comment #61
smustgrave commented#59
1 = fixed
2 = removed hash salt
3 = don't think we need it as there is a check before this code
#60
1 = actually showed the tests weren't working and false positive. Updated tests.
Comment #62
tim.plunkettUse
$this->resetAll()instead (and maybe a line break after, for readability)Comment #63
smustgrave commentedSo #61 the tests pass with the cache clear.
Is the original goal to have contextual links appear without a cache clear?
Not sure if the tests or fix need work but should of got red/green
Comment #64
tim.plunkettafaik, a cache clear currently doesn't fix the bug in any way, because it's stored in
sessionStorage:I'm not sure how best to ensure that a test is happening within the same page session. But that strikes me as the problem here
Comment #65
socialnicheguru commentedNumber #54 patch no longer applies to Drupal 9.5.9.
Comment #66
james.williamsHere's a patch that applies to Drupal 9.5.x; just to assist those of us needing that. It includes the es6.js file and the transpiled version, since both are needed in D9.5 patches as far as I can see.
Comment #68
larowlanDoes the comment in #9 help? It might remove the need for this and get you a failing test?
Comment #69
ion.macaria commentedI know Drupal 9 is close to the end. But for last months maybe it is necessary for someone:
Drupal 9.5.11 patch.
Comment #70
ion.macaria commentedUpdate for broken patch:
Core 9.5.11
Comment #71
_utsavsharma commentedFixed failures in #70.
Comment #72
johnpitcairn commentedComment #73
ion.macaria commentedReroll patch for drupal 10.1.7
Comment #74
sourabhjainFixed the #73 testing failed issue. Please review.
Comment #75
sourabhjainComment #76
needs-review-queue-bot commentedThe Needs Review Queue Bot tested this issue.
While you are making the above changes, we recommend that you convert this patch to a merge request. Merge requests are preferred over patches. Be sure to hide the old patch files as well. (Converting an issue to a merge request without other contributions to the issue will not receive credit.)
Comment #78
sourabhjainComment #79
smustgrave commentedWas tagged for issue summary which is still needed. Please don't put tickets in review without checking core gates and any open tags.
Now that we are mixing patches and MRs that will need to be cleaned up and noted in the updated issue summary.
Comment #80
steyep commentedI could not get the patch in #74 nor the diff from the MR to apply cleanly in 10.3. I've attached a re-rolled the patch for 10.3
Comment #81
xjmAmending attribution.