Problem/Motivation

We have a nice media library in core. We also have a nice content moderation/workflow system in core.

We also have no real, solid idea how these two systems interact with each other. This is a pretty large blind spot in the media system and its test coverage.

Proposed resolution

  • Implement a media specific version of the 'Published status or admin user' views filter, to allow unpublished items to be filtered for users that do not have access to these items.
  • Write a test to prove the content moderation integration works as expected in the media library
    1. Install media + media library + content_moderation.
    2. Install the 'Editoral workflow'
    3. Configure the Editorial workflow to apply to a new image media type.
    4. Configure a media field in an article node type.
    5. Create 3 image media items. Put one in the archived content moderation state, one in draft, one in published.
    6. User 1 should be able to see all three when viewing the media library.
    7. User 2 (with admin permissions assigned) should be able to see all three when viewing the media library.
    8. User 3 (with only View media) should be able to see only the published one when viewing the media library.
    9. User 4 (with only View media + View own unpublished media) should be able to see only the published one when viewing the media library.
    10. Repeat previous test case, but make all three media items owned by user 4, now they should be able to see all three.

Remaining tasks

  • Write patch
  • Review
  • Commit

User interface changes

Added a 'Published status or admin user' filter for media based views.

API changes

None.

Data model changes

None.

Release notes snippet

The Media Library view is now integrated with Content Moderation,. The view will only list unpublished media items to users that have explicit permission to access them. This is accomplished via the addition of a Media-specific "Published status or admin user" filter, which is also available to any views displaying media entities. Note that this may result in unpublished media entities no longer being visible to users that do not have permission to access them. Their permissions should be adjusted if they continue to need access.

CommentFileSizeAuthor
#72 2969678-72.patch755 bytesoknate
#71 sqlite.png143.81 KBoknate
#71 mysql.png137.18 KBoknate
#67 2969678-66.patch38.21 KBseanB
#67 interdiff-63-66.txt1.38 KBseanB
#65 2969678-65.patch38.21 KBseanB
#65 interdiff-63-65.txt1.38 KBseanB
#63 2969678-63.patch38.21 KBseanB
#63 interdiff-59-63.txt6.3 KBseanB
#59 2969678-59.patch34.89 KBseanB
#59 interdiff-48-59.txt8.64 KBseanB
#48 2969678-48.patch26.25 KBseanB
#48 interdiff-45-48.txt2.07 KBseanB
#45 2969678--interdiff-40-45.txt1.88 KBoknate
#45 2969678-45.patch26.25 KBoknate
#43 2969678-43.patch26.15 KBoknate
#43 2969678--interdiff-40-43.txt1.88 KBoknate
#40 2969678-40.patch26.15 KBseanB
#40 interdiff-30-40.txt29.22 KBseanB
#31 interdiff-28-30.txt1.67 KBseanB
#30 2969678-30.patch37.5 KBseanB
#30 interdiff-28-30.txt425 bytesseanB
#28 2969678-28.patch37.52 KBseanB
#28 interdiff-26-28.txt7.59 KBseanB
#26 2969678-26.patch30.66 KBseanB
#26 interdiff-14-26.txt20.47 KBseanB
#18 2969678-14-3063216-18.patch18.34 KBseanB
#15 2969678-14-3063216-7.patch17.24 KBseanB
#15 2969678-14.patch10.85 KBseanB
Support from Acquia helps fund testing for Drupal Acquia logo

Comments

phenaproxima created an issue. See original summary.

marcoscano’s picture

Thinking on a 80/20 mindset, I wonder how many sites really have media items "moderatable", instead of having their host entities' revisions pointing to different media items in their workflows.

I personally think most sites will have the host entity being moderated. If that's the case, and considering that this is just a view, maybe these sites can just remove the published field from the view manually?

Trying to solve this automatically could become tricky, once content moderation is set per bundle (media type), but in the view we are showing several types. So the published field could make sense for some media types but not for others, in some scenarios...

phenaproxima’s picture

Title: [PP-1] Improve Media Library integration with Content Moderation » Improve Media Library integration with Content Moderation
Status: Postponed » Active

The blocker is in.

Version: 8.6.x-dev » 8.7.x-dev

Drupal 8.6.0-alpha1 will be released the week of July 16, 2018, which means new developments and disruptive changes should now be targeted against the 8.7.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.7.x-dev » 8.8.x-dev

Drupal 8.7.0-alpha1 will be released the week of March 11, 2019, which means new developments and disruptive changes should now be targeted against the 8.8.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

phenaproxima’s picture

After discussing this issue with @seanb, @xjm, and Wim Leers, I think we need to retitle and rescope this.

Integrating Media with Content Moderation is, right now, a big question mark. It's not clear what the 80% use cases/user stories would be, and there are many "unknown unknowns". We simply have not extensively tested media entities with moderation, so we don't know what works and what doesn't. Without knowing that, we have no way of knowing what, if anything, is important to address in this space.

So this issue should, for now, be a meta-issue in which we test Media with Content Moderation and discover problems. Then, we can organize, prioritize, and fix those problems.

phenaproxima’s picture

Title: Improve Media Library integration with Content Moderation » [META] Integrate Media Library with Content Moderation
Issue tags: -Needs title update
phenaproxima’s picture

Updated the IS and tagging for product manager review to determine the next steps here.

Wim Leers’s picture

To clarify: per #2834729-169: [META] Roadmap to stabilize Media Library, release manager @xjm has indicated this is a must-have.

pavlosdan’s picture

How is the 80/20 determined?

We are using Content Moderation for our Media Types as our Marketing and Comms department requires strict control of what images get published (danger of getting sued if someone just lifts a stock image off of google for example). This is done separately to the content as usually M&C doesn't have context on what a media item will be used on. They only need to vet and check the image.

Similarly Documents usually need to be moderated before they are approved to be added on some content or shown in the "Approved Media Library" for regulatory and compliance reasons.

One of the pain points right now is that Media are not handling revisions the same way as nodes do. (e.g missing the revisions tab).

marcoscano’s picture

#2987911: Make media compatible with content moderation points out some parts of the media system that don't seem to be ready for content-moderation-prime-time yet

phenaproxima’s picture

Thanks, @marcoscano! I have added that to #2825215: Media initiative: Roadmap since the bugs mentioned in that issue are not Media Library-specific. :)

xjm’s picture

Thanks @pavlosdan! Those do sound like issues we should identify here.

To add to #9: The must-have scope of this issue is to identify and file issues for whatever bugs, incompatibilities, etc. we have. Once we do that testing, then we'll go back through the issue list and sort whatever specific issues are identified into must/should/could blockers for the stable release. I imagine the issues in #10 are probably major bugs.

Wim Leers’s picture

On a Media-related meeting just now @seanB and @phenaproxima said they aren't sure that something even needs to change as far as media_library.module is concerned (this issue is specifically about media_library.module, not about media.module).

@seanB indicated that the view used by the Media Library simply respects the published flag, and that that is what Content Moderation is using to ensure only authorized users are able to see the appropriate Media entities. Hence that should also work in the Media Library.

If this is true — and I sure hope it is! — then it should be easy to write test coverage proving this is the case:

  1. Install standard + content_moderation. This also results in core/profiles/standard/config/optional/workflows.workflow.editorial.yml getting installed.
  2. Configure the Editorial workflow to apply to image media.
  3. Create 3 image media items. Put one in the archived content moderation state, one in draft, one in published.
  4. User 1 should be able to see all three when viewing the media library.
  5. User 2 (with admin permissions assigned) should be able to see all three when viewing the media library.
  6. User 3 (with only View media) should be able to see only the published one when viewing the media library.
  7. User 4 (with only View media + View own unpublished media) should be able to see only the published one when viewing the media library.
  8. Repeat previous test case, but make all three media items owned by user 4, now they should be able to see all three.

Note: IDK exactly what the difference in effect is between draft and archived. I think that draft means a forward (non-default) revision is created, but Views lists only default revisions of entities. So that'd mean that the draft entity would be visible to anybody with the View media permission. Content Moderation expert should chime in.


If a Content Moderation expert (ideally maintainer) confirms the above testing scenarios are sufficient, then the tests will either show we have no work to do (like @seanB thinks 🌞) or will show exactly which scenarios are failing and hence where the bugs are hiding 🤓

seanB’s picture

Just wrote the tests for the scenario's of #14. Some remarks.

Attached is a combined patch with #3063216: Inaccessible Media entities still have rows generated for them in the Media Library view, containing form wrapper markup *and* the media label to prove it works, and a patch with just the content moderation test.

seanB’s picture

Status: Needs review » Needs work

The last submitted patch, 15: 2969678-14-3063216-7.patch, failed testing. View results
- codesniffer_fixes.patch Interdiff of automated coding standards fixes only.

seanB’s picture

Status: Needs review » Needs work

The last submitted patch, 18: 2969678-14-3063216-18.patch, failed testing. View results
- codesniffer_fixes.patch Interdiff of automated coding standards fixes only.

Sam152’s picture

#2987911: Make media compatible with content moderation contains a few issues with media generally that should probably be addressed, but as far as I can see these don't really relate to the media library.

In general content moderation manages revisions on two axis: the publishing status and the default/non-default status of a revision. If the user facing views/lists/rendering of media items generally load and use the default revision, then in theory as long as you are respecting your own published/unpublished semantics, you shouldn't need any kind of special integration or consideration for content moderation. In all workflow states, you are either getting a published or unpublished revision, so for the purposes of display unless you are loading non-default revisions you don't need to be concerned by defaultness.

As far as updating revisions, I would assume updates are made via an entity form? Content moderation switches some of the routing upcasting to load the latest revision of an entity for entity forms, but it might be worth asserting that if you create a pending revision via a draft, that reloading or visiting an interface to update media items, the draft content is still loaded as the starting point. I can't really see any scenarios like that, but I'm not sure if that's actually within the scope of the media library?

(Note, 'draft' state content is only placed into a pending revision if there was a previously published revision, so it's not enough to simply create draft content when testing the above)

In terms of actually providing an experience for users of the CMS to view revisions and possibly see a list of in-flight moderated entities, nodes have the following:

  • A revision UI, I don't know which other entity types (if any!) have a revisions UI, but there is work to make that generic here: #2350939: Implement a generic revision UI.
  • Content moderation ships with a view specially for nodes being moderated, which shows the latest translation affected revision of content and a moderation state filter. Modules like blocks or media could also ship with a view to display moderated entities, but I believe this is effort individual sub-systems should evaluate and undertake with all the relevant steps for introducing new user interfaces.

So in short, #10 is correct, but this isn't necessarily a content moderation integration problem. Even without content moderation, media entities are missing a way to view past revisions.

oknate’s picture

I have reviewed the test and it looks great. I don't see any issues. If it were checking only visible rows, it would pass and prove that media library respects the accessibility of media based on user permissions. As it's checking using raw assertions, it's blocked on #3063216: Inaccessible Media entities still have rows generated for them in the Media Library view, containing form wrapper markup *and* the media label. I don't have anything new to add other than to saw I reviewed the test and it looks great.

effulgentsia’s picture

#3063216: Inaccessible Media entities still have rows generated for them in the Media Library view, containing form wrapper markup *and* the media label is about handling media access in general, but for purposes of this issue (integration with Content Moderation), we only need to handle the special case of Published, right?

In which case, can't we solve it in exactly the same way that the /admin/content View does: by adding a filter for "Published status or admin user"? Grep HEAD for status_extra to see the different code pieces needed for that, including the Drupal\node\Plugin\views\filter\Status class. I think for the purposes of this issue, maybe we can just duplicate all that stuff to Media? As a follow-up, maybe we can genericize the code for other entity types to benefit from too?

seanB’s picture

In which case, can't we solve it in exactly the same way that the /admin/content View does: by adding a filter for "Published status or admin user"? Grep HEAD for status_extra to see the different code pieces needed for that, including the Drupal\node\Plugin\views\filter\Status class. I think for the purposes of this issue, maybe we can just duplicate all that stuff to Media? As a follow-up, maybe we can genericize the code for other entity types to benefit from too?

That would solve it for admin users, but saving an unpublished media item would then only be available for admin users. I guess that could be very confusing, since users could have permissions to view their own unpublished media?
Specially since media also doesn't have a canonical route by default, which means a view is the only way to find and edit existing media.

effulgentsia’s picture

[non-admin] users could have permissions to view their own unpublished media

The label of the filter is misleading. Although it says "or admin user", what it really means is "or the user has permission to the unpublished media". The query in Drupal\node\Plugin\views\filter\Status includes checks for "view own unpublished content" and "view any unpublished content".

seanB’s picture

My apologies, that does seems to solve it. I guess this would remove the dependency on the other issues. Thanks!

seanB’s picture

Status: Needs work » Needs review
FileSize
20.47 KB
30.66 KB

This implements the 'Published status or admin user' filter for media. It makes the tests from #14 pass and is a much nicer solution compared to #3063216: Inaccessible Media entities still have rows generated for them in the Media Library view, containing form wrapper markup *and* the media label.

For now I skipped an upgrade path for existing media / media_library views. I feel adding this to existing sites should be a site builder decision and could potentially cause rows to be removed unexpectedly. Views are tricky and existing sites could be depending on the existing behaviour.

Status: Needs review » Needs work

The last submitted patch, 26: 2969678-26.patch, failed testing. View results

seanB’s picture

Status: Needs work » Needs review
FileSize
7.59 KB
37.52 KB

Ok, this should hopefully fix the tests.

Status: Needs review » Needs work

The last submitted patch, 28: 2969678-28.patch, failed testing. View results

seanB’s picture

Status: Needs work » Needs review
FileSize
425 bytes
37.5 KB

Some minor doc improvements and also updated the content moderation test name and namespace.

seanB’s picture

FileSize
1.67 KB

Sorry, the last interdiff was not correct, here is the correct interdiff for #30.

phenaproxima’s picture

I think this looks really good overall. The test coverage unambiguously proves that the views respect the publishing status (with administrative superpowers), which is controlled by Content Moderation.

  1. +++ b/core/modules/media/config/optional/views.view.media.yml
    @@ -826,6 +865,10 @@ display:
    +      filter_groups:
    +        operator: AND
    +        groups:
    +          1: AND
    

    This is interesting, I wonder why it changed?

  2. +++ b/core/modules/media/tests/src/Functional/MediaOverviewPageTest.php
    @@ -88,46 +89,35 @@ public function testMediaOverviewPage() {
    -    $row3 = $assert_session->elementExists('css', 'table tbody tr:nth-child(3)');
     
         // Media thumbnails.
         $assert_session->elementExists('css', 'td.views-field-thumbnail__target-id img', $row1);
         $assert_session->elementExists('css', 'td.views-field-thumbnail__target-id img', $row2);
    -    $assert_session->elementExists('css', 'td.views-field-thumbnail__target-id img', $row3);
     
         // Media names.
         $name1 = $assert_session->elementExists('css', 'td.views-field-name a', $row1);
         $this->assertSame($media1->label(), $name1->getText());
         $name2 = $assert_session->elementExists('css', 'td.views-field-name a', $row2);
    -    $this->assertSame($media2->label(), $name2->getText());
    -    $name3 = $assert_session->elementExists('css', 'td.views-field-name a', $row3);
    -    $this->assertSame($media3->label(), $name3->getText());
    +    $this->assertSame($media3->label(), $name2->getText());
         $assert_session->linkByHrefExists('/media/' . $media1->id());
    -    $assert_session->linkByHrefExists('/media/' . $media2->id());
    

    Why were these (and other) assertions removed?

  3. +++ b/core/modules/media/tests/src/Functional/MediaOverviewPageTest.php
    @@ -142,6 +132,36 @@ public function testMediaOverviewPage() {
    +    $this->drupalGet('/admin/content/media');
    +    $assert_session->pageTextNotContains($media2->label());
    +    $role->grantPermission('view own unpublished media')->save();
    +    $this->drupalGet('/admin/content/media');
    

    Pro tip: We can call $this->getSession()->reload() to avoid repeating the URL. (Not a big deal, obviously.)

  4. +++ b/core/modules/media/tests/src/Functional/MediaOverviewPageTest.php
    --- a/core/modules/media_library/config/install/views.view.media_library.yml
    +++ b/core/modules/media_library/config/install/views.view.media_library.yml
    

    So I see our changes to this view are causing the filters' configuration to be overridden from the defaults. Why is that?

    Also, much of the diff of changes to this view looks very chaotic. I suspect (assume, really) that's actually a red herring; chances are, the filters have been re-ordered, causing the diff to appear crazier than it normally would. No need to change it, just calling it out.

  5. +++ b/core/modules/media_library/tests/src/FunctionalJavascript/ContentModerationTest.php
    @@ -0,0 +1,312 @@
    +/**
    + * Tests media library integration with content moderation.
    + *
    + * @group media
    + */
    

    The @group should be media_library.

  6. +++ b/core/modules/media_library/tests/src/FunctionalJavascript/ContentModerationTest.php
    @@ -0,0 +1,312 @@
    +  /**
    +   * {@inheritdoc}
    +   */
    +  protected $profile = 'standard';
    

    Why does this need to be tested with the Standard profile? If it's to bring in the content type and workflow, we can just use $this->drupalCreateContentType() and ContentModerationTestTrait::createEditorialWorkflow(), respectively.

  7. +++ b/core/modules/media_library/tests/src/FunctionalJavascript/ContentModerationTest.php
    @@ -0,0 +1,312 @@
    +  /**
    +   * {@inheritdoc}
    +   */
    +
    +  protected static $modules = [
    +    'content_moderation',
    +    'media',
    +    'media_library',
    +  ];
    

    Nit: There's an errant blank line here.

  8. +++ b/core/modules/media_library/tests/src/FunctionalJavascript/ContentModerationTest.php
    @@ -0,0 +1,312 @@
    +  /**
    +   * User with uid 1.
    +   *
    +   * @var \Drupal\Core\Session\AccountInterface
    +   */
    +  protected $userOne;
    

    Couldn't we use the $this->rootUser property inherited from BrowserTestBase?

  9. +++ b/core/modules/media_library/tests/src/FunctionalJavascript/ContentModerationTest.php
    @@ -0,0 +1,312 @@
    +    // Create a draft, published and archived media item.
    +    $image = File::create([
    +      'uri' => $this->getTestFiles('image')[0]->uri,
    +    ]);
    +    $image->setPermanent();
    +    $image->save();
    +
    

    This comment is misleadingly placed; it should probably come after this chunk of code.

  10. +++ b/core/modules/media_library/tests/src/FunctionalJavascript/ContentModerationTest.php
    @@ -0,0 +1,312 @@
    +      'name' => 'Hoglet',
    

    😍

phenaproxima’s picture

I briefly talked to @seanB in Slack about what sort of update path we want to provide here, if any. I don't think such an update (which would really just be adding the status_extra filter to our media views) would be too hard to write, but Sean rightfully pointed out that it could break existing sites which may be depending on the current, "broken", behavior. My feeling is that we should open a separate issue to talk about the update path; basically, if the product managers think it should be done, we should do it in there.

Wim Leers’s picture

Assigned: Unassigned » webchick

My feeling is that we should open a separate issue to talk about the update path; basically, if the product managers think it should be done, we should do it in there.

+1

Assigning to @webchick, this feels like a thing she'd be most opinionated about. Plus, she's already reviewed this issue before.

webchick’s picture

So, just so I’m understanding… the question being posed is…

“We are making a change to the default view to make it so that you don’t see media you shouldn’t have access to (e.g. unpublished where you do not have perms to see unpublished), and we are wondering whether to retroactively apply this to all existing sites?”

I mean. I think the answer can only be yes? Isn’t it an information disclosure vulnerability otherwise?

And if people are truly depending on broken behaviour, as @seanB frets, they can just remove the filter, no? But we’d still leave all other sites “secure by default”?

So yes, I think I would recommend the spin-off issue, unless I'm missing something here.

webchick’s picture

Assigned: webchick » Unassigned
effulgentsia’s picture

Status: Needs review » Needs work
+++ b/core/modules/media/src/Plugin/views/filter/Status.php
@@ -0,0 +1,52 @@
+    $snippet = "$table.status = 1 OR ($table.uid = ***CURRENT_USER*** AND ***CURRENT_USER*** <> 0 AND ***VIEW_OWN_UNPUBLISHED_MEDIA*** = 1) OR ***ADMINISTER_MEDIA*** = 1";

If Content Moderation module is enabled, we also need to add a condition for "view any unpublished content", just like the filter in the node namespace does. The reason is because content_moderation_entity_access() checks that permission for all EntityPublishedInterface types, not just nodes.

effulgentsia’s picture

I also don't think this needs Product Manager review anymore, especially after #36. It's a stale tag from #8.

effulgentsia’s picture

Title: [META] Integrate Media Library with Content Moderation » Integrate Media Library with Content Moderation

This isn't a meta issue anymore. #30 is almost a complete fix. Just needs to incorporate the reviews since then.

seanB’s picture

Status: Needs work » Needs review
FileSize
29.22 KB
26.15 KB

#32

1. Fixed. Not sure why it was there, works without it as well.
2. The non-admin user doesn't have permissions to view unpublished media. The default view was not using rendered entities, so the view was not preventing the user from seeing media they shouldn't.
3. Fixed.
4. Fixed. I indeed changed the order of the filters for more consistency with the content view, but that is not really necessary. Reverted the unrelated changes.
5. Fixed.
6. Fixed. Initially implemented the test as suggested in #14, but it is true we can also test without the standard profile.
7. Fixed.
8. Fixed.
9. Fixed.
10. :)

#37

Fixed and updated the content moderation test for this.

Status: Needs review » Needs work

The last submitted patch, 40: 2969678-40.patch, failed testing. View results
- codesniffer_fixes.patch Interdiff of automated coding standards fixes only.

oknate’s picture

There are some coding standard warnings:

/var/lib/drupalci/workspace/jenkins-drupal_patches-8661/source/core/modules/media_library/tests/src/FunctionalJavascript/ContentModerationTest.php ✗ 4 more
line 13	Unused use statement
14	Unused use statement
76	Short array syntax must be used to define arrays
282	Functions must not contain multiple empty lines in a row; found 2 empty lines
oknate’s picture

Status: Needs work » Needs review
FileSize
1.88 KB
26.15 KB

Fixing the coding standard warnings and fixing the config test.

Status: Needs review » Needs work

The last submitted patch, 43: 2969678-43.patch, failed testing. View results
- codesniffer_fixes.patch Interdiff of automated coding standards fixes only.

oknate’s picture

Status: Needs work » Needs review
FileSize
26.25 KB
1.88 KB

Same as the last comment. Trying this again, the last comment, the interdiff had the changes, but the patch lacked them. I must have been on the wrong branch when doing the diff against 8.8.x branch.

seanB’s picture

Don't think I can RTBC, but thanks @oknate! I think this is ready now.

Wim Leers’s picture

Status: Needs review » Reviewed & tested by the community
  1. +++ b/core/modules/media_library/tests/src/FunctionalJavascript/ContentModerationTest.php
    @@ -0,0 +1,328 @@
    +class ContentModerationTest extends WebDriverTestBase {
    

    👍 This test looks excellent, and it does what I recommended in #14. It does more, actually, because I had not mentioned view any unpublished content in #14.

    @effulgentsia pointed out the need for this in #37. I think this is extremely misleading in the Content Moderation module and frankly downright dangerous. But that's how HEAD works, so … 🤷‍♂️

  2. +++ b/core/modules/media_library/tests/src/FunctionalJavascript/ContentModerationTest.php
    @@ -0,0 +1,328 @@
    +    // unpublished media', and a user the has 'view media' and 'view any
    

    🤓 Nit: s/the/that/. Can be fixed on commit.

  3. +++ b/core/modules/media_library/tests/src/FunctionalJavascript/ContentModerationTest.php
    @@ -0,0 +1,328 @@
    +    // The media viewer user that can also view it's own unpublished media
    

    🤓 Übernit: s/it's/its/. Can be fixed on commit.

seanB’s picture

Fixed the nits to make it easier for committers :)

seanB’s picture

Issue summary: View changes

Updated the IS.

seanB’s picture

Issue summary: View changes
effulgentsia’s picture

Crediting @phenaproxima and @Wim Leers for patch review.

I was torn on whether to also credit @marcoscano, @pavlosdan, and @Sam152. You all wrote very helpful comments earlier in this issue, but because they're more in the scope of #2987911: Make media compatible with content moderation, I added issue credit to you there instead of here.

  • effulgentsia committed bb5dc7a on 8.8.x
    Issue #2969678 by seanB, oknate, phenaproxima, Wim Leers: Integrate...
effulgentsia’s picture

Status: Reviewed & tested by the community » Needs work
Issue tags: +Needs followup

Pushed to 8.8.x, but per #35, this needs a followup for a post_update function.

xjm’s picture

Issue tags: -Needs followup

I'v reverted this for now. We need upgrade paths to be included in the same issue, not in followups. Thanks!

  • xjm committed cf72c87 on 8.8.x
    Revert "Issue #2969678 by seanB, oknate, phenaproxima, Wim Leers:...
seanB’s picture

The first question is, do we really want an upgrade path at all and add this new filter to all media views on all existing sites?
This could mean users will all of a sudden not be able to see content they previously could, and I'm not sure if we want this. User could be relying on the existing behaviour.

phenaproxima’s picture

The first question is, do we really want an upgrade path at all and add this new filter to all media views on all existing sites?
This could mean users will all of a sudden not be able to see content they previously could, and I'm not sure if we want this. User could be relying on the existing behaviour.

#35 has already answered this, I think. Personally, I agree with it. We should add the post-update hook. We can have it return a translated string (which is something post-update hooks can do, according to the documentation of hook_post_update_NAME) explaining what was changed, and how to restore the previous behavior.

effulgentsia’s picture

do we really want an upgrade path at all and add this new filter to all media views on all existing sites?

No. Not all views. Just the 2 Views shipped with core and being changed by this patch. Views shipped by contrib/custom modules are the responsibility of those other modules. Views created by the end user via the UI already get a Status=1 default filter applied on them, and if the user removed it, it's their responsibility.

explaining what was changed, and how to restore the previous behavior

I'm fine with us returning text that explains what was changed. I don't think we need to explain how to restore the previous behavior. There's no legitimate reason to restore the previous behavior for these 2 Views. If someone really wants to do it for an illegitimate reason, they can, but we shouldn't communicate any text that encourages it.

seanB’s picture

Status: Needs work » Needs review
FileSize
8.64 KB
34.89 KB

Ok, added the update hooks and tests.

phenaproxima’s picture

Thank you so much for taking this on, @seanB. Your heroism knows no bounds!

  1. +++ b/core/modules/media/media.post_update.php
    @@ -28,3 +30,67 @@ function media_post_update_enable_standalone_url() {
    +  if (!isset($filters['status_extra'] )) {
    

    Supernit: There is a space before the )) here.

  2. +++ b/core/modules/media/media.post_update.php
    @@ -28,3 +30,67 @@ function media_post_update_enable_standalone_url() {
    +        'remember_roles' => ['authenticated' => 'authenticated'],
    

    Should we use RoleInterface::AUTHENTICATED_ID here?

  3. +++ b/core/modules/media/media.post_update.php
    @@ -28,3 +30,67 @@ function media_post_update_enable_standalone_url() {
    +    return t("The 'Published status or admin user' filter was added to the media view.");
    

    I wonder if we might want to use the label of the view here, instead of just hard-coding 'media'. It's possible the site builder changed the label.

  4. +++ b/core/modules/media/tests/src/Functional/Update/MediaUpdateTest.php
    @@ -114,4 +114,24 @@ public function testEnableStandaloneUrl() {
    +    $this->assertNotNull($config->get('display.default.display_options.filters.status_extra'));
    +    $this->assertSame('status_extra', $config->get('display.default.display_options.filters.status_extra.field'));
    +    $this->assertSame('media', $config->get('display.default.display_options.filters.status_extra.entity_type'));
    +    $this->assertSame('media_status', $config->get('display.default.display_options.filters.status_extra.plugin_id'));
    +    $this->assertSame('status_extra', $config->get('display.default.display_options.filters.status_extra.id'));
    +    $this->assertFalse($config->get('display.default.display_options.filters.status_extra.exposed'));
    

    It would be more readable, IMHO, to do something like this, rather than repeat the very long key:

    $filter = $config->get('display.default.display_options.filters.status_extra');
    $this->assertInternalType('array', $filter);
    $this->assertSame('status_extra', $filter['field']);
    // ...etc.
    
  5. +++ b/core/modules/media_library/media_library.post_update.php
    @@ -240,3 +240,67 @@ function media_library_post_update_add_media_library_image_style() {
    +  if (!$view) {
    +    return t('The media_library view could not be updated because it has been deleted. The Media Library module needs this view in order to work properly. Uninstall and reinstall the module so the view will be re-created.');
    +  }
    

    Not sure if this is in scope, but this advice is actually incorrect. If they uninstall and reinstall the module, I believe they will run into PreExistingConfigException. I guess what I'm asking is...have we actually tested this advice?

    Also: do we consider this to be an error condition? If so, we should be throwing UpdateException, per the documentation at https://api.drupal.org/api/drupal/core%21lib%21Drupal%21Core%21Extension...

phenaproxima’s picture

Also, another question -- for (site builder) simplicity and/or performance reasons, should we replace the existing status filter with status_extra, rather than have both?

If we do replace it, and the status filter has been customized in some way(s) by the site builder, should we copy that configuration into status_extra? In other words, should we maybe just take the existing status filter, do the minimum number of changes we need to do in order to convert it to status_extra, and then blow away the original filter?

I realize this would complicate the update path, but it might be more "seamless" from a site builder perspective. So, I defer to a framework manager for this one.

seanB’s picture

As a first response to #61:
The existing status filter is exposed and allows user to change it. The status extra filter is a hidden thing and does something similar, but different. So I think they should both be there.

I will take a look at #60 tonight.

seanB’s picture

New patch to address #60:

1. Fixed.
2. Fixed.
3. Fixed. I tried referring to the machine name of the view. But I guess the label would be better.
4. Fixed.
5. Just checked, removing the media library view, then uninstall/install the module will bring back the media library view as expected. So yeah, this seems to be correct. Not sure how hard the update should fail, the site is not at risk of being more/less broken by continuing the updates. I copied this from media_library_post_update_table_display() btw.

phenaproxima’s picture

+++ b/core/modules/media/media.post_update.php
@@ -91,6 +92,8 @@ function media_post_update_add_status_extra_filter() {
+    return t("The 'Published status or admin user' filter was added to the '@label' view.", [
+      '@label' => $view->storage->label(),
+    ]);

Small nit: The label should be placeholdered in as %label, not '@label', since it's a human-readable name.

Otherwise, as far as I can tell this is good to go.

seanB’s picture

phenaproxima’s picture

Status: Needs review » Reviewed & tested by the community
+++ b/core/modules/media/media.post_update.php
@@ -92,8 +92,8 @@ function media_post_update_add_status_extra_filter() {
+    return t("The 'Published status or admin user' filter was added to the '%label' view.", [

We don't need the single quotes around %label, I think. But this is fixable on commit.

This is, as far as I can tell, done.

seanB’s picture

No worries, it's already end of the day here. Missed the quotes. Sorry!

  • effulgentsia committed 6749e8d on 8.8.x
    Issue #2969678 by seanB, oknate, phenaproxima, Wim Leers: Integrate...
effulgentsia’s picture

Status: Reviewed & tested by the community » Fixed

The post_update functions and tests look great to me. Thanks! Pushed to 8.8.x.

oknate’s picture

Thanks!

oknate’s picture

Status: Fixed » Needs work
FileSize
137.18 KB
143.81 KB

Tests are failing in SQLite and Postgre: https://www.drupal.org/node/3060/qa

https://www.drupal.org/pift-ci-job/1417227
https://www.drupal.org/pift-ci-job/1417228

The order of the items differs. Since they are all programmatically created at the same time, the sort by 'changed' is brittle.

Mysql:
mysql

SQLite:
sqlite

oknate’s picture

Here's a patch that addressed #71. It fixes the sorting by changed date, so the expected item is in the second position.

phenaproxima’s picture

Status: Needs review » Reviewed & tested by the community

Thanks, @oknate. That should help; it's not the first time we've been burned by implicit sorting differences across databases. RTBC once green on all backends.

Wim Leers’s picture

We recently had to do a similar thing in JSON:API: when no explicit sort is specified, the underlying DB's default sort is used. Which is obviously different between MySQL/MariaDB, PostgreSQL and SQLite.

catch’s picture

Status: Reviewed & tested by the community » Fixed

Committed 2dfe9e9 and pushed to 8.8.x. Thanks!

  • catch committed 2dfe9e9 on 8.8.x
    Issue #2969678 by seanB, oknate, phenaproxima, effulgentsia, Wim Leers,...
catch’s picture

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.

xjm’s picture

Issue tags: +8.8.0 highlights

We can mention this in the highlights as part of what a stabilized Media Library offers, e.g. "CKEditor support, Content Moderation integration..."

xjm’s picture

Status: Closed (fixed) » Needs work
Issue tags: +Needs change record, +8.8.0 release notes, +Needs release note

Actually this needs a change record for the API addition (also, isn't the codebase missing API documentation for it?).

I think this also may need a release note since it changes the result of the view to (by design) not include media the user can access. (It does that, correct?) In the past when we've had security issues that similarly revoke access to things, we've also mentioned it in the release notes for sites that might have been relying on this behavior rather than on correct access control handling. So, let's add a release note too (if I'm correct about that).

xjm’s picture

We should also describe the disruption from the un-access-bypassing: Before stuff you shouldn't have access to was listed; now it's not. If your permissions were configured incorrectly, you'll want to fix that.

bnjmnm’s picture

Issue summary: View changes

Added change record draft and release notes snippet.

It may require some refining as I'm not sure what API documentation needs to be added, which was mentioned in #80. If there's something equivalent elsewhere in core I could be made aware of, that's all the reference I'll need to take care of it.

bnjmnm’s picture

Status: Needs work » Needs review
Issue tags: -Needs change record, -Needs release note

CR https://www.drupal.org/node/3088444 and release note added. Setting to Needs Review.

bnjmnm’s picture

Status: Needs review » Fixed

Created followup to update the API documentation in the codebase #3088632: Add the Content Moderation changes from 2969678 to Media API docs, and received confirmation that CR/RN are all set. Setting back to Fixed.

xjm’s picture

Perfect, thanks @bnjmnm!

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.