Problem/Motivation

Using content moderation module on a site where there is some modules which implements hook_node_grants() generate a fatal error when viewing node moderated which have not been yet published.

This issue is a follow up of #2821599: Coexistence of PBF and content_moderation, where i provided a temporary workaround.

I can reproduce this bug with any modules which implements hook_node_grants(). Tested with Permissions by fields, Content Access and a tiny custom My module which implements only an empty hook_node_granst() function.

Steps to reproduce :
- configure a new clean install of drupal 8.2.1
- enable the module content_moderation and configure it to be used on the content type "Article"
- create a new role named "Editor" and some users. Enable all the content_moderation permissions related to "Article" content type for Editor.
- Create two node Article 1 and Article2. Publish the Article 1. Let the Article 2 in draft state.
- Now the users belonging to the "Editor" role can see and edit the two articles written by each other.

- Enable pbf module (or any module which implements hook_node_grants()), or generate a custom module with Drupal Console and implements hook_node_grants() in this module.

- Editor users can see and edit Article 1
- When Editor users try to see Article 2, a fatal error occurs

Fatal error: Call to a member function isRevisionTranslationAffected() on null in core/modules/content_moderation/src/ParamConverter/EntityRevisionConverter.php on line 101

The acquireGrants method in NodeAccessControlHandler provide a default grants[] only if a node is published.

if (empty($grants) && $node->isPublished()) {
  $grants[] = array('realm' => 'all', 'gid' => 0, 'grant_view' => 1, 'grant_update' => 0, 'grant_delete' => 0);
}

Then for nodes which have never been published, the getLatestRevisionId() method in the Class ModerationInformation returns always an empty value, and then the fatal error occurs.

Proposed resolution

Check if the latest_revision is an instance of EntityInterface, in the convert method of EntityRevisionConverter Class. See patch attached.

Remaining tasks

Review the patch and/or
Is there an another root cause of this issue ?

User interface changes

No changes

API changes

I believe not

Data model changes

I don't think

CommentFileSizeAuthor
#46 interdiff.txt3.79 KBamateescu
#46 2821716-46.patch4.6 KBamateescu
#41 interdiff-38-41.txt1.44 KBflocondetoile
#41 2821716-41.patch5.89 KBflocondetoile
#38 content_moderation_fatal_error_node_grants-2821716-38.patch5.98 KBanish.a
#35 content_moderation_fatal_error_node_grants-2821716-35.patch5.98 KBThew
#32 content_moderation_fatal_error_node_grants-2821716-32.patch5.53 KBanish.a
#28 content_moderation_fatal_error_node_grants-2821716-28.patch5.92 KBflocondetoile
#26 content_moderation_fatal_error_node_grants-2821716-26-test-only.patch4.12 KBflocondetoile
#24 content_moderation_fatal_error_node_grants-2821716-24-test-only.patch2.23 KBflocondetoile
#21 interdiff-2821716-14-21.txt4.13 KBflocondetoile
#21 content_moderation_fatal_error_node_grants-2821716-21.patch7.67 KBflocondetoile
#17 content_moderation_fatal_error_node_grants-2821716-14.patch7.72 KBflocondetoile
#14 interdiff-10-14.txt1.81 KBflocondetoile
#14 content_moderation_fatal_error_node_grants-2821716-14.patch7.72 KBflocondetoile
#12 interdiff-10-12.txt841 bytesflocondetoile
#12 content_moderation_fatal_error_node_grants-2821716-12.patch6.73 KBflocondetoile
#10 content_moderation_fatal_error_node_grants-2821716-10.patch5.91 KBflocondetoile
#5 content_moderation_fatal_error_node_grants-2821716-5.patch826 bytesflocondetoile
#2 content_moderation_fatal_error_node_grants-2821716.patch698 bytesflocondetoile
Support from Acquia helps fund testing for Drupal Acquia logo

Comments

flocondetoile created an issue. See original summary.

flocondetoile’s picture

flocondetoile’s picture

Status: Active » Needs review

Status: Needs review » Needs work

The last submitted patch, 2: content_moderation_fatal_error_node_grants-2821716.patch, failed testing.

flocondetoile’s picture

Oups. Wrong root directory

gabesullice’s picture

Status: Needs review » Reviewed & tested by the community

I have replicated this issue and can confirm that the #5 resolves the issue for me.

alexpott’s picture

Status: Reviewed & tested by the community » Needs work

Nice bug finding and the fix looks correct. We need an automated test for this that pretty much does what the excellent steps to reproduce in the issue summary outlines.

alexpott’s picture

Issue tags: +Needs tests
flocondetoile’s picture

Assigned: Unassigned » flocondetoile

Working on this

flocondetoile’s picture

Attached a test which reprodruce this issue. It should failed, because the fix is not included.

Status: Needs review » Needs work

The last submitted patch, 10: content_moderation_fatal_error_node_grants-2821716-10.patch, failed testing.

flocondetoile’s picture

The patch with the fix. Should pass

Status: Needs review » Needs work

The last submitted patch, 12: content_moderation_fatal_error_node_grants-2821716-12.patch, failed testing.

flocondetoile’s picture

Fixing the two exceptions caused by the getLastestRevision method which return NULL if node has never been published

Status: Needs review » Needs work

The last submitted patch, 14: content_moderation_fatal_error_node_grants-2821716-14.patch, failed testing.

flocondetoile’s picture

Status: Needs work » Needs review

Is it a fail from the testbot ? The test pass well locally. Let's retry.

flocondetoile’s picture

flocondetoile’s picture

Assigned: flocondetoile » Unassigned
flocondetoile’s picture

Issue tags: -Needs tests
Sam152’s picture

Status: Needs review » Needs work

Nits ahoy! Ye have been warned.

  1. +++ b/core/modules/content_moderation/src/Tests/NodeAccessWithGrantTest.php
    @@ -0,0 +1,162 @@
    +class NodeAccessWithGrantTest extends ModerationStateTestBase {
    

    Can you upload a test-only patch to demo the fail?

  2. +++ b/core/modules/content_moderation/src/Tests/NodeAccessWithGrantTest.php
    @@ -0,0 +1,162 @@
    +  /**
    +   * Editor user.
    +   *
    +   * @var \Drupal\Core\Session\AccountInterface
    +   */
    +  protected $editorUser;
    

    Style thing, but can't both account properties be next to each other?

  3. +++ b/core/modules/content_moderation/src/Tests/NodeAccessWithGrantTest.php
    @@ -0,0 +1,162 @@
    +    'content_moderation_test_grants'
    

    nit, trailing comma

  4. +++ b/core/modules/content_moderation/src/Tests/NodeAccessWithGrantTest.php
    @@ -0,0 +1,162 @@
    +    $nodes = \Drupal::entityTypeManager()
    +      ->getStorage('node')
    +      ->loadByProperties([
    +        'title' => 'moderated content',
    +      ]);
    

    You can use \Drupal\simpletest\NodeCreationTrait::getNodeByTitle

  5. +++ b/core/modules/content_moderation/src/Tests/NodeAccessWithGrantTest.php
    @@ -0,0 +1,162 @@
    +    if (!$nodes) {
    +      $this->fail('Test node was not saved correctly.');
    +      return;
    +    }
    

    Can we just assert the success message you get from the UI when you create content?

  6. +++ b/core/modules/content_moderation/src/Tests/NodeAccessWithGrantTest.php
    @@ -0,0 +1,162 @@
    +    $view_path = 'node/' . $node->id();
    +    $edit_path = 'node/' . $node->id() . '/edit';
    +    $latest_path = 'node/' . $node->id() . '/latest';
    

    A method would also mean we wouldn't need extra variables for the paths.

  7. +++ b/core/modules/content_moderation/src/Tests/NodeAccessWithGrantTest.php
    @@ -0,0 +1,162 @@
    +
    +
    

    extra newlines

  8. +++ b/core/modules/content_moderation/src/Tests/NodeAccessWithGrantTest.php
    @@ -0,0 +1,162 @@
    +    $this->drupalGet($edit_path);
    +    $this->assertResponse(200);
    +    $this->drupalGet($view_path);
    +    $this->assertResponse(200);
    +    // There is not yet latest revision.
    +    $this->drupalGet($latest_path);
    +    $this->assertResponse(403);
    

    This block is used 3 times, maybe we should create a method called assertPathResponses with three arguments, one for each status code?

  9. +++ b/core/modules/content_moderation/src/Tests/NodeAccessWithGrantTest.php
    @@ -0,0 +1,162 @@
    +
    

    trailing newline

flocondetoile’s picture

Attached the patch updated with your feedback.

Can you upload a test-only patch to demo the fail?

The patch in #10 do it.

flocondetoile’s picture

Status: Needs work » Needs review
Sam152’s picture

I didn't realise this test was actually pretty much what \Drupal\content_moderation\Tests\NodeAccessTest. Maybe some others can chime in here, but why not keep "content_moderation_test_grants" and just enable that during that test. Saves us from duplicating a fair bit test code.

flocondetoile’s picture

Sorry for the delay. Here a simplier patch (NodeAccessTest modified only with the test module) which demonstrate the fatal error

Status: Needs review » Needs work
flocondetoile’s picture

An another test only patch. Because I need the admin user has the "bypass node access" in order to be able to retrieve the node created. And because I need to test access from normal user before the admin user publish the test node.

Status: Needs review » Needs work
flocondetoile’s picture

The last patch with the fix now

timmillwood’s picture

Issue tags: +Workflow Initiative
timmillwood’s picture

Status: Needs review » Reviewed & tested by the community

Looks good to me.

I hate that we need to add new modules for tests like this, but I guess that's the price we pay for awesome test coverage.

Also going to add a test against 8.3.x, a lot has changed in Content Moderation, so need to make sure it works.

timmillwood’s picture

Version: 8.2.1 » 8.2.x-dev
Status: Reviewed & tested by the community » Needs work
Issue tags: +Needs reroll

Looks like this needs re-rolling for 8.3.x

anish.a’s picture

Status: Needs review » Needs work

The last submitted patch, 32: content_moderation_fatal_error_node_grants-2821716-32.patch, failed testing.

Thew’s picture

Issue tags: +Needs reroll
Thew’s picture

Status: Needs work » Needs review
Issue tags: -Needs reroll
FileSize
5.98 KB

Testing reroll.

Status: Needs review » Needs work

The last submitted patch, 35: content_moderation_fatal_error_node_grants-2821716-35.patch, failed testing.

Thew’s picture

anish.a’s picture

Messed up previous reroll

timmillwood’s picture

It'd be nice to get an interdiff to see what's changed between the patches. I still don't think #38 will pass against 8.3.x because of the workflows module.

Status: Needs review » Needs work

The last submitted patch, 38: content_moderation_fatal_error_node_grants-2821716-38.patch, failed testing.

flocondetoile’s picture

Status: Needs work » Needs review
FileSize
5.89 KB
1.44 KB

Permissions on the patch fixed. Should pass.

Status: Needs review » Needs work

The last submitted patch, 41: 2821716-41.patch, failed testing.

flocondetoile’s picture

Fails seems unrelated to the patch. Test relaunched.

Sam152’s picture

The fail looks genuine.

Version: 8.3.x-dev » 8.4.x-dev

Drupal 8.3.0-alpha1 will be released the week of January 30, 2017, which means new developments and disruptive changes should now be targeted against the 8.4.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

amateescu’s picture

Status: Needs work » Needs review
FileSize
4.6 KB
3.79 KB

I hit this problem a lot while working on the tests for #2858431: Book storage and UI is not revision aware, changes to drafts leak into live site, so here's a cleaned up patch which should be good to go for 8.4.x.

+++ b/core/modules/content_moderation/src/Plugin/Validation/Constraint/ModerationStateConstraintValidator.php
@@ -117,7 +117,9 @@ public function validate($value, Constraint $constraint) {
-    $original_id = $original_entity->moderation_state;
+    if ($original_entity) {
+      $original_id = $original_entity->moderation_state->target_id;
+    }

This is the reason for the recent test fails. Accessing the field item list object is not the same thing as accessing one of its properties :)

Also, we don't need a new module that implements hook_node_grants(), we have node_access_test_empty.module for that.

timmillwood’s picture

Status: Needs review » Reviewed & tested by the community

#46 looks good.

alexpott’s picture

Status: Reviewed & tested by the community » Fixed

Committed and pushed 2dad9ec to 8.4.x and 670c1a8 to 8.3.x. Thanks!

@timmillwood, @Sam152, @gabesullice - thanks for reviewing the patch. There were no comments that resulted in patch changes or provided test evidence that would result in commit credit. And of course thanks @flocondetoile, @anish.a, @Thew and @amateescu for working on the patch.

  • alexpott committed 2dad9ec on 8.4.x
    Issue #2821716 by flocondetoile, anish.a, amateescu, Thew: Fatal error...

  • alexpott committed 670c1a8 on 8.3.x
    Issue #2821716 by flocondetoile, anish.a, amateescu, Thew: Fatal error...
timmillwood’s picture

Status: Fixed » Closed (fixed)

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

eyilmaz’s picture

Shouldn't $original_entity->moderation_state be $original_entity->moderation_state->value here ??

timmillwood’s picture

@eyilmaz - this was committed nearly 2 months ago, if you are seeing issues, please open a new issue.

amateescu’s picture

@eyilmaz, that does look a bit weird indeed. Do you mind opening a new issue to investigate the change you proposed and link it back here so everyone who worked on this can follow along?

Thanks!

eyilmaz’s picture

Updated the patch here:
https://www.drupal.org/node/2848775
since it was more or less related.