Problem/Motivation

When previewing a comment as an anonymous user, the comment body doesn't show up. Given the user does not have the skip approval permissions

Steps to reproduced:

1. Fill in the fields to create a comment as an anonymous user
2. Click the preview button
3. No body field shows up in the preview.

The problem is that CommentAccessControlHandler checks entity access for the entity on every single field. And the comment is unpublished and the fields therefore not visible.

Proposed resolution

Clean up that logic, remove all entity-level access logic.

Remaining tasks

User interface changes

API changes

Data model changes

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

Upchuk created an issue. See original summary.

Upchuk’s picture

Issue summary: View changes
jhedstrom’s picture

Issue tags: +Needs tests
Berdir’s picture

Status: Active » Needs review
FileSize
1.67 KB

The problem here is that comment field access is wrong. It checks entity access, but that's not the place to do that. Field access by definition assumes that you have access to the entity, so all that published and so on checking (which is what broke this) is unneeded and can be simplified a lot.

Status: Needs review » Needs work

The last submitted patch, 4: comment-field-access-2574597-4.patch, failed testing.

Upchuk’s picture

Status: Needs work » Needs review
FileSize
6.19 KB
7.1 KB

Made a few changes:

* Using allowedIfHasPermission in the fieldAccess to ensure caching.
* Removed the view related logic from the fieldAccess test and replaced with simple checks access the the hostname field (nobody should have access to that).
* Since there are no longer checks again unpublished comments, removing the two unpublished comments from the permutations.

Upchuk’s picture

jhedstrom’s picture

This adds tests for anonymous comment previewing which we didn't have any before.

alexpott’s picture

The last submitted patch, 4: comment-field-access-2574597-4.patch, failed testing.

The last submitted patch, 6: 2574597-5.patch, failed testing.

The last submitted patch, 7: 2574597-7.patch, failed testing.

Upchuk’s picture

Fixing also the CommentFieldNameTest which for some reason also checks field access on the comment

The last submitted patch, 8: 2574597-08-TEST-ONLY.patch, failed testing.

The last submitted patch, 8: 2574597-08.patch, failed testing.

The last submitted patch, 6: 2574597-5.patch, failed testing.

klausi’s picture

I think we should not modify the test cases like that. We should always test all fields for access, even if it is quite clear that view access to almost all of them is allowed. This is important for regression testing, when somebody tries to change comment field access logic later.

The last submitted patch, 7: 2574597-7.patch, failed testing.

Upchuk’s picture

Alright,

* Adding back the 2 comment entities in the test.
* Keeping the field access checks but asserting that the user has access to view all of them except for the hostname and mail fields which have special checks at the bottom.

klausi’s picture

Status: Needs review » Needs work
  1. +++ b/core/modules/comment/src/Tests/CommentFieldAccessTest.php
    @@ -213,12 +213,7 @@ public function testAccessToAdministrativeFields() {
    -        $this->assertEqual($may_view, $set['user']->hasPermission('administer comments') || ($set['comment']->isPublished() && $set['user']->hasPermission('access comments')), SafeMarkup::format('User @user @state view field @field on comment @comment', [
    -          '@user' => $set['user']->getUsername(),
    -          '@state' => $may_update ? 'can' : 'cannot',
    -          '@comment' => $set['comment']->getSubject(),
    -          '@field' => $field,
    -        ]));
    +        $this->assertEqual($may_view, TRUE);
    

    hm, can we keep the nice message from above? Makes it easier to see what is going on when looking at the test results.

  2. +++ b/core/modules/comment/src/Tests/CommentFieldAccessTest.php
    @@ -244,13 +239,11 @@ public function testAccessToAdministrativeFields() {
    -        $this->assertEqual($may_view, $field != 'hostname' && ($set['user']->hasPermission('administer comments') ||
    -            ($set['comment']->isPublished() && $set['user']->hasPermission('access comments'))), SafeMarkup::format('User @user @state view field @field on comment @comment', [
    -          '@user' => $set['user']->getUsername(),
    -          '@state' => $may_view ? 'can' : 'cannot',
    -          '@comment' => $set['comment']->getSubject(),
    -          '@field' => $field,
    -        ]));
    +        // Nobody has access to to view the hostname field and this case is
    ...
    +        if ($field !== 'hostname') {
    +          $this->assertEqual($may_view, TRUE);
    +        }
    

    same here. And I think we should have an else{} here that checks the hostname field right here instead of farther down.

  3. +++ b/core/modules/comment/src/Tests/CommentFieldAccessTest.php
    @@ -266,13 +259,7 @@ public function testAccessToAdministrativeFields() {
    -        $this->assertEqual($may_view, $field != 'hostname' && ($set['user']->hasPermission('administer comments') ||
    -            ($set['comment']->isPublished() && $set['user']->hasPermission('access comments'))), SafeMarkup::format('User @user @state view field @field on comment @comment', [
    -          '@user' => $set['user']->getUsername(),
    -          '@state' => $may_view ? 'can' : 'cannot',
    -          '@comment' => $set['comment']->getSubject(),
    -          '@field' => $field,
    -        ]));
    +        $this->assertEqual($may_view, TRUE);
    

    and here

The last submitted patch, 8: 2574597-08-TEST-ONLY.patch, failed testing.

The last submitted patch, 8: 2574597-08.patch, failed testing.

Upchuk’s picture

Status: Needs work » Needs review
FileSize
3.78 KB
9.35 KB

You're right.

Here we go.

jhedstrom’s picture

klausi’s picture

Status: Needs review » Needs work
  1. +++ b/core/modules/comment/src/CommentAccessControlHandler.php
    @@ -130,18 +130,14 @@ protected function checkFieldAccess($operation, FieldDefinitionInterface $field_
    +      // Nobody has access to the hostname. The mail field is hidden
    +      // from non-admins.
    

    Can we move the comment about mail down to the other if?

  2. +++ b/core/modules/comment/src/Tests/CommentAnonymousTest.php
    @@ -40,6 +40,32 @@ function testAnonymous() {
    +    // Preview comments (with skip grant permission).
    

    skip grant permission? You mean skip comment approval permission?

  3. +++ b/core/modules/comment/src/Tests/CommentAnonymousTest.php
    @@ -40,6 +40,32 @@ function testAnonymous() {
    +    $title = $this->randomMachineName(8);
    +    $body = $this->randomMachineName(16);
    

    Please, please no more randomness in tests :-( See #2571183: Deprecate random() usage in tests to avoid random test failures

    Let's replace this with hard coded example strings.

  4. +++ b/core/modules/comment/src/Tests/CommentFieldAccessTest.php
    @@ -213,9 +213,8 @@ public function testAccessToAdministrativeFields() {
    +        $this->assertEqual($may_view, TRUE, SafeMarkup::format('User @user can view field @field on comment @comment', [
    

    we should use assertTrue()

  5. +++ b/core/modules/comment/src/Tests/CommentFieldAccessTest.php
    @@ -244,13 +243,21 @@ public function testAccessToAdministrativeFields() {
    +        // Nobody has access to to view the hostname field.
    +        if ($field !== 'hostname') {
    +          $this->assertEqual($may_view, TRUE, SafeMarkup::format('User @user can view field @field on comment @comment', [
    +            '@user' => $set['user']->getUsername(),
    +            '@comment' => $set['comment']->getSubject(),
    +            '@field' => $field,
    +          ]));
    +        }
    +        else {
    +          $this->assertEqual($may_view, FALSE, SafeMarkup::format('User @user cannot view field @field on comment @comment', [
    +            '@user' => $set['user']->getUsername(),
    +            '@comment' => $set['comment']->getSubject(),
    +            '@field' => $field,
    +          ]));
    +        }
    

    Can we just have this long assert once and only set a $view_access variable to TRUE/FALSE within the if()?

  6. +++ b/core/modules/comment/src/Tests/CommentFieldAccessTest.php
    @@ -266,10 +273,8 @@ public function testAccessToAdministrativeFields() {
    +        $this->assertEqual($may_view, TRUE, SafeMarkup::format('User @user can view field @field on comment @comment', [
    

    asserTrue()

Upchuk’s picture

Status: Needs work » Needs review
FileSize
5.13 KB
9.1 KB

Hey @klausi,

I addressed all the issues from #25 (hopefully :) )

Status: Needs review » Needs work

The last submitted patch, 26: 2574597-26.patch, failed testing.

Status: Needs work » Needs review

Upchuk queued 26: 2574597-26.patch for re-testing.

Berdir’s picture

Issue summary: View changes

Updated issue summary a bit.

yched’s picture

The fix looks reasonable, I'll let @klausi approve the recent changes.

larowlan’s picture

Status: Needs review » Reviewed & tested by the community

Looks good to me - thanks all

webchick’s picture

Status: Reviewed & tested by the community » Fixed

Looks like @klausi's feedback has been addressed, and subsystem maintainer signed off.

Committed and pushed to 8.0.x. Thanks!

  • webchick committed 5a89e6a on 8.0.x
    Issue #2574597 by Upchuk, jhedstrom, Berdir, klausi: Comment body doesn'...

Status: Fixed » Closed (fixed)

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