Problem/Motivation
The in_trash query parameter is prone to "leaking" into all the links displayed on pages that have it.
Proposed resolution
1) Fix the outbound route processor to append this parameter to all generated links only on the entity's canonical page, since that was its intended purpose (see #3398774: Trash breaks any local tabs on trashed content).
2) Harden all delete forms to ensure that content can not be accidentally deleted permanently if they're accessed with the ?in_trash=1 query string
Remaining tasks
Review.
Issue fork trash-3560348
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 #3
amateescu commentedComment #4
codebymikey commentedThere's a couple issues that needs to be addressed here with the new permission checks, I'll try and push my fixes up in due course:
1. Optimization: Only check the permissions if the
$event->getRequest()->query->has('in_trash')isTRUE.2. There's a very specific edge case involving multilingual sites and the
domain_config_uimodule where as per the comments the trashignorecontext will not work (even for users with the necessary permissions) because theParamNotConvertedExceptionis thrown during the permission check and because the language negotiation happened to be called before ours. It also only gets triggered if the user has a preferred "Administration pages language" specified in their user profile.Steps to reproduce edge case
1. Have a user with the
access administration pagesorview the administration themepermission.2. Give them a preferred language code.
3. Have something trigger the language negotiations before the
\Drupal\trash\EventSubscriber\TrashIgnoreSubscriber::onRequestPreRouting()listener is called.4. Attempt to access the deleted
/node/{node}?in_trash=1route as that user.One "easy" fix (but seems more like a hack) is to increase the prerequest event listener priority so it's as close to 300 as possible by passing a float string (we can't mix floats and integers in an array index, so it has to be a float string) for the priority (that way, it always runs before any other event subscribers with a priority of 299):
But I think the "cleaner" fix is something along the lines of this (or do we keep both, to ensure the
onRequestPreRoutingbehaviour is always consistent):That way, we're also able to react to situations where a user account is switched multiple times within the same page request, so we may disable/enable the trash context as necessary.
I'll try and push those fixes up and add a potential kernel test to replicate the edge case issue if I have the time to.
edit: on further thoughts, having the'299.999'priority might not be a hack, and just the way to do it. I think it's cleaner than trying to alter the event listener order to ensure the trash module is the first of the subscribers with a priority of 299 to be ran, and if that breaks in the future for whatever reason, then it can be addressed.Comment #5
amateescu commentedGood point! Did that and another small optimization so we don't instantiate the entity type manager on most requests.
For the second part, I'm fine with both options. If the string float "hack" works, it's not the worst code needed for Trash to do its job.
Comment #6
codebymikey commentedPushed an update addressing the edge case, including a test case showcasing the 404 behaviour when the language negotiation is triggered earlier than the trash module expects.
The test-only changes pipeline is failing as expected.
The hack only worked for older versions of Drupal using
Drupal\Component\EventDispatcher\ContainerAwareEventDispatcher, from 10.3.0, it's handled by the symfony event dispatcher, which enforces the priority as an int.I've addressed the event subscriber priority issue through the service provider and adding a subscriber to enforce the appropriate trash context as soon as the account is switched to (useful for things like masquerade) - the account set listener alone might be sufficient to fix the bug (haven't tested), but I think it's still good to keep the logic as a means of addressing other trash ignore priority precedence issues in the future (in the event even the account switch priority might need a specific value).
Comment #7
codebymikey commentedComment #8
amateescu commentedPosted a suggestion to simplify a bit the code that reorder services.
Comment #9
codebymikey commentedAddressed the feedback and test case for if the state was originally 'inactive' before the user was logged in.
Comment #11
amateescu commentedNice! Thanks for sticking with this. Merged into 3.x :)