There are basically two problems with the 8.5.8 and 8.6.2 security changes to Content Moderation:
- They introduce a new method to an existing interface. There is at least 1 contributed module that I know of that has an implementation of this interface -- Workflow Participants -- and another one that has an issue to include it -- Group. Any site that attempts to take the security update while one of these is enabled will encounter immediate, site-wide fatal errors due to the missing method implementation.
- They don't provide sufficient information for existing use cases. Both of those contributed modules require the context of the actual content entity in order to determine if a transition is valid, but the new method that was introduced doesn't offer that information. As a result, neither of these modules can even implement the new method properly.
Possible solutions
- Remove the new method from the interface. There is already a
getValidTransitions()method on the interface. The constraint validator can simply get all the valid transitions and then check if the new state is among them. - Adjust the method arguments from "Workflow/Current state/New state/User" to just "Entity/New state/User". (Both the workflow and the current state can be derived from the entity.) Adjust the implementation of Content Moderation's implementation accordingly.
- Introduce the content entity as an optional 5th argument to the method, making note that it will end up being required in a future version of Drupal.
Based on discussion, option #3 is the route that best complies with Drupal policies around API changes, so that is what has been chosen.
| Comment | File | Size | Author |
|---|---|---|---|
| #18 | 3007716-18.patch | 7.98 KB | sam152 |
| #18 | interdiff.txt | 884 bytes | sam152 |
| #16 | 2915383-48.patch | 45.79 KB | sam152 |
| #16 | interdiff.txt | 884 bytes | sam152 |
| #13 | 3007716-13.patch | 7.9 KB | sam152 |
Comments
Comment #2
kevin.dutra commentedComment #3
kevin.dutra commentedHere's an implementation of the first proposed solution.
Comment #5
larowlanWe debated the API break and opted for a BC break to ensure there wasn't a silent security issue
I'd be in favour of option 2.
we lost the permissions check
Comment #6
kevin.dutra commentedI'm not sure I follow.
getValidTransitions()finds all the transitions from the current state of the entity and filters out any that the user doesn't have access to with the permission check.There is, apparently, an issue with the way it determines the current state when translations are involved, which should be why the test failures occurred, so here's a revised patch that should take care of that problem.
Comment #7
sam152 commentedOne of the suggestions in the private issue was to remove the additional method. Here was an analysis of that which helps explain some of the motivations and problems with the approach you suggested:
I haven't looked into those contrib modules, but perhaps entity could be an additional optional argument for advanced use cases?
Edit: Reviewing your patch in more detail, not sure if it gets around these issues, looks like you've come up with an approach for this.
Comment #9
sam152 commentedThis has the problem that it's a change implementations would have to make, that would fail silently otherwise. So while the current BC break is annoying, it has forced the issue to the surface.
I think now that the existing fix is in stable releases, we unfortunately might have to do the following:
We could surmise that the method may have been called outside the context of having an entity available (despite the chances of that being pretty slim) and I don't think removing a method from an interface or changing an existing methods signature is an option anymore.
Comment #10
kevin.dutra commentedDefinitely a bummer, but I totally understand. Here's the optional argument approach. (No interdiff since it's a totally different approach.)
Comment #11
sam152 commentedThanks for sticking with this issue, really appreciate you helping to minimise disruption of this change.
I think we need to add the
(Optional)tag to the comment here and possibly describe why it's optional, that is: the default implementation in core does not rely on this, some implementations do rely on this and that the entity param should be provided whenever possible by users of the API to ensure compatibility with contributed projects.I wonder if we should actually deprecate NOT passing the entity in and do a
trigger_errorwhen it is not provided, that way we respect the existing BC, inform users$entityshould be passed and then also be able to make it a required part of the interface for D9. Thoughts? In addition to that, lets add a change record.Let me know if you have capacity to continue working on this, otherwise I'll see if I can put some time towards this.
Comment #12
kevin.dutra commentedI like the idea of deprecating the optional aspect. I think that'll help bring some visibility and help prevent potential issues. I'm a little tight for time this week, so if you end up having some bandwidth, please feel free. Thanks for your help!
Comment #13
sam152 commentedOkay great, adding the patch.
Comment #14
jhedstromShould this docblock note that the optional part of this is deprecated as well? Alternatively, since does it need to mention it's optional at all?
Comment #15
sam152 commentedGood point, I don't mind either of those options.
Comment #16
sam152 commentedFixing comment.
Comment #18
sam152 commentedWhoops, correct patch this time.
Comment #19
jhedstromPatch in #18 looks RTBC to me. Anything left to be done here? It would be great to get this in so #3007906: Core security release breaks workflow participants can get committed.
Comment #20
sam152 commentedNothing else to do here as far as I'm aware.
Comment #21
jhedstromThen let's get this in :)
Comment #22
alexpottThe issue summary is out-of-date with the chosen solution. Given the complexity and how it was arrived at I think it is important that the issue summary is correct. Especially as the chosen solution doesn't appear to be amongst the possible solutions.
Comment #23
alexpottWe also should have a change record here.
Comment #24
kevin.dutra commentedUpdating issue summary. I'll work on a CR.
Comment #25
kevin.dutra commentedAdded a draft change record: https://www.drupal.org/node/3026087
If someone can take a quick glance at the IS update and the CR, then this can probably go back to RTBC.
Comment #26
sam152 commentedI think the IS slightly mischaracterises the other options. This isn't exactly true:
Other than that, looks good to me.
Comment #27
sam152 commentedComment #28
sam152 commentedSlightly tweaking the IS and RTBCing the CR here: https://www.drupal.org/node/3026087. I think I'm fine to RTBC given no changes were requested with the actual patch.
Comment #29
alexpottCommitted 73d9d9b and pushed to 8.7.x. Thanks!
Only committing to 8.7.x just to get a second opinion on backport because there is a change record and interface addition. I think this is eligible because it is not a break and critical.
Leaving at rtbc against 8.6.x
Fixed coding standard on commit.
Comment #31
alexpott@catch +1'd the backport in slack. Committed 82a677a32e and pushed to 8.6.x. Thanks!