Paragraph access check using incorrect revision of its parent, leading to issues editing and viewing paragraphs when content moderation is involved.

Created on 25 October 2019, over 4 years ago
Updated 9 April 2024, 2 months ago

Summary

When access is checked for a paragraph, part of the logic checks if the user has access to the parent entity. It does this by loading the default revision of the parent entity which is not correct. It should load the revision of the parent that the paragraph is attached to.

Because of this, paragraphs will not be viewable or editable unless the user has access to view/edit the default revision of the parent entity. Both scenarios can happen if a site has content moderation enabled, where users may be editing future revisions, or viewing past/future revisions of a parent entity.

Original report

My company is using paragraphs, custom content blocks, layout builder and content moderation with revisions. Overall it works really well for us, but we ran into a blocker with this combination when it came to content moderation. Normally, everything works wonderfully, until we want to make changes to a node that is already published, and have this new "draft" revision go through a moderation process before replacing the "current" published revision. When we have a "current revision" published and a "latest revision" going through the moderation process, we noticed that if we edited custom blocks with paragraphs in them, these paragraphs would disappear from the published "current revision". They would also fail to render in the "preview" mode of the layout builder after the draft revision was made. This is not the expected behavior: Not only would we expect the paragraph to render in both places, it was jarring to see that the creation of a draft revision effecting the display of the published revision! Normally the published revision should look untouched, but we were suddenly having entire paragraphs go missing. I believe I might have an edge case but wanted to share my workaround in case others are experiencing this issue.

Steps to reproduce:

  1. You will need the custom block module (core) and entity reference revision module in addition to paragraphs.
  2. Create a content type that utilizes layout builder and allows overrides on a per node basis.
  3. Enable a moderation workflow on this content type.
  4. Create a paragraph entity with some test fields.
  5. Create a custom paragraph block type utilizing this paragraph with the "custom blocks" module
  6. Create a new node, save it as a draft.
  7. Edit this node and click on the layout builder tab.
  8. Make sure the "Show content preview" checkbox is checked in the layout builder.
  9. Add a paragraph block into the layout, add sample text to the fields. After placing the block inside the layout builder, confim that the fields appear in the content preview within the layout builder.
  10. Save the layout and "publish" the node.
  11. "View" the published revision and confirm that the fields inside of the paragraph are rendered and present.
  12. Edit the node, click on the layout builder tab again and edit the paragraph fields, maybe adding some more text. Save the layout as a draft.
  13. Compare the current revision (published) with the latest revision (draft), you may find that the content inside the paragraph no longer renders on the published current revision, but appears fine in the draft revision.
  14. Return to the "layout" builder tab, note that the paragraph fields no longer render within the layout builder preview when "Show content preview" is checked

Proposed resolution

I do not know what is planned for additional revision support with the paragraphs module, but I have created a work around for block_content and paragraph parent entities, where the checkAccess method performs some due diligence to look up the correct revision ID of it's parent, instead of returning the most recent or active one which will always return the incorrect revision ID. I would love some help to modify this workaround to potentially work for all types of parent entities. The layout builder loads the parent entities for the page being viewed and generates a list of which revision IDs are present. This is checked against the parent entity passed by paragraphs, and in cases where we have a published current revision and a draft latest revision being juggled at the same time we need make sure the correct parent revision ID is passed along. What I have here is more of a workaround until better revision support is worked out for the paragraphs module.

Remaining tasks

  1. Need others experiencing this issue to test the patch & provide additions and feedback
  2. Need to identify scenarios where the revision ID query added to checkAccess might return more than one result, I cannot think of any, however if there is some sort of case where this would happen we'd need to add some code to determine of the results is the one we're looking for.
  3. figure out how to handle differing types of parent entities, my use case deals with block_content and also paragraph parent entities, there are probably others out there but I'm not sure what the best way is to make this parent type agnostic.
  4. I don't have a lot of testing experience, could use some input on how to create a test for this added parent revision ID check.

User interface changes

none

API changes

Modify ParagraphAccessControlHandler::checkAccess() to perform a query using information on the parent entity and the loaded paragraph to find the correct revision ID of the parent when a node has a different published and active revision. The current loaded paragraph revision and target ID is queried against all revisions of it's parent, this extracts the parent revision ID where the current loaded child is referenced. The parent is then loaded by it's revision ID and passed along to complete the access check process.

Data model changes

none

Release notes snippet

When using layout builder, custom blocks and content moderation, Paragraph access checks do not always return the the paragraph's correct parent revision ID. This is a bit of an edge case: when there is a published current revision along with a draft latest revision the parent's revision ID can not be assumed to be the default latest revision, otherwise access checks will automatically fail. This adds a query for parent entities of the block_content and paragraph type to have their correct revision IDs looked up before proceeding with the rest of the access check. It would not effect other parent types.

πŸ› Bug report
Status

Needs review

Version

1.9

Component

Code

Created by

πŸ‡ΊπŸ‡ΈUnited States Poindexterous

Live updates comments and jobs are added and updated live.
  • Needs tests

    The change is currently missing an automated test that fails when run with the original code, and succeeds when the bug has been fixed.

Sign in to follow issues

Comments & Activities

Not all content is available!

It's likely this issue predates Contrib.social: some issue and comment data are missing.

Production build 0.69.0 2024