diff --git a/core/modules/comment/src/CommentAccessControlHandler.php b/core/modules/comment/src/CommentAccessControlHandler.php index 47241f2..2f2311a 100644 --- a/core/modules/comment/src/CommentAccessControlHandler.php +++ b/core/modules/comment/src/CommentAccessControlHandler.php @@ -57,7 +57,7 @@ protected function checkCreateAccess(AccountInterface $account, array $context, * {@inheritdoc} */ protected function checkFieldAccess($operation, FieldDefinitionInterface $field_definition, AccountInterface $account, FieldItemListInterface $items = NULL) { - // Only users with the administer comments permission can edit + // Only users with the "administer comments" permission can edit // administrative fields. $administrative_fields = array( 'uid', @@ -71,7 +71,7 @@ protected function checkFieldAccess($operation, FieldDefinitionInterface $field_ return $account->hasPermission('administer comments'); } - // No user can change read only fields. + // No user can change read-only fields. $read_only_fields = array( 'changed', 'hostname', @@ -92,6 +92,9 @@ protected function checkFieldAccess($operation, FieldDefinitionInterface $field_ if ($operation == 'view' && !$account->hasPermission('administer comments') && (!$account->hasPermission('access comments') || !$entity->isPublished())) { return FALSE; } + if ($operation == 'edit' && !$account->hasPermission('administer comments') && (!$account->hasPermission('edit own comments') || $entity->getOwnerId() != $account->id())) { + return FALSE; + } return parent::checkFieldAccess($operation, $field_definition, $account, $items); } diff --git a/core/modules/comment/src/Tests/CommentFieldAccessTest.php b/core/modules/comment/src/Tests/CommentFieldAccessTest.php index 8febe32..7943819 100644 --- a/core/modules/comment/src/Tests/CommentFieldAccessTest.php +++ b/core/modules/comment/src/Tests/CommentFieldAccessTest.php @@ -6,17 +6,18 @@ namespace Drupal\comment\Tests; -use Drupal\Component\Utility\String; use Drupal\comment\Entity\Comment; use Drupal\comment\Entity\CommentType; +use Drupal\Component\Utility\String; use Drupal\entity_test\Entity\EntityTest; -use Drupal\simpletest\DrupalUnitTestBase; +use Drupal\simpletest\TestBase; use Drupal\system\Tests\Entity\EntityUnitTestBase; /** * Tests comment field level access. * * @group comment + * @group Access */ class CommentFieldAccessTest extends EntityUnitTestBase { @@ -59,6 +60,9 @@ class CommentFieldAccessTest extends EntityUnitTestBase { 'field_name', ); + /** + * {@inheritdoc} + */ protected function setUp() { parent::setUp(); $this->installEntitySchema('comment'); @@ -68,7 +72,6 @@ protected function setUp() { * Test permissions on comment fields. */ public function testAccessToAdministrativeFields() { - // Create a comment type. $comment_type = CommentType::create([ 'id' => 'comment', @@ -78,32 +81,32 @@ public function testAccessToAdministrativeFields() { ]); $comment_type->save(); - // Create a comment against a test entity.. + // Create a comment against a test entity. $host = EntityTest::create(); $host->save(); // An administrator user. No user exists yet, ensure that the first user // does not have UID 1. - $comment_admin_user = $this->createUser(array('uid' => 2, 'name' => 'admin'), array( + $comment_admin_user = $this->createUser(['uid' => 2, 'name' => 'admin'], [ 'administer comments', 'access comments', - )); + ]); // Two comment enabled users, one with edit access. - $comment_enabled_user = $this->createUser(['name' => 'enabled'], array( + $comment_enabled_user = $this->createUser(['name' => 'enabled'], [ 'post comments', 'skip comment approval', 'edit own comments', 'access comments', - )); - $comment_no_edit_user = $this->createUser(['name' => 'no edit'], array( + ]); + $comment_no_edit_user = $this->createUser(['name' => 'no edit'], [ 'post comments', 'skip comment approval', 'access comments', - )); + ]); // An unprivileged user. - $comment_disabled_user = $this->createUser(['name' => 'disabled'], array('access content')); + $comment_disabled_user = $this->createUser(['name' => 'disabled'], ['access content']); // List of all users. $test_users = array( @@ -118,8 +121,8 @@ public function testAccessToAdministrativeFields() { 'entity_type' => 'entity_test', 'name' => 'Tony', 'hostname' => 'magical.ponies.com', - 'mail' => 'tony.da.magical@ponies.com', - 'subject' => 'Bruce da Mesopotamian moose', + 'mail' => 'tony.the.magical@ponies.com', + 'subject' => 'Bruce the Mesopotamian moose', 'entity_id' => $host->id(), 'comment_type' => 'comment', 'field_name' => 'comment', @@ -131,7 +134,7 @@ public function testAccessToAdministrativeFields() { $comment2 = Comment::create([ 'entity_type' => 'entity_test', 'hostname' => 'magical.ponies.com', - 'subject' => 'Brian da messed up lion', + 'subject' => 'Brian the messed up lion', 'entity_id' => $host->id(), 'comment_type' => 'comment', 'field_name' => 'comment', @@ -143,6 +146,7 @@ public function testAccessToAdministrativeFields() { $comment3 = Comment::create([ 'entity_type' => 'entity_test', 'hostname' => 'magical.ponies.com', + // Unpublished. 'status' => 0, 'subject' => 'Gail the minky whale', 'entity_id' => $host->id(), @@ -153,54 +157,62 @@ public function testAccessToAdministrativeFields() { ]); $comment3->save(); - foreach ($this->administrativeFields as $field) { + // Generate permutations. + $combinations = [ + 'comment' => [$comment1, $comment2, $comment3], + 'user' => [$comment_admin_user, $comment_enabled_user, $comment_no_edit_user, $comment_disabled_user] + ]; + $permutations = TestBase::generatePermutations($combinations); - // Checks on view operations. - foreach ($test_users as $account) { - $may_view = $comment1->{$field}->access('view', $account); - $this->assertEqual($may_view, $account->hasPermission('access comments'), String::format('Any user may view the field @name.', array('@name' => $field))); + // Check access to administrative fields. + foreach ($this->administrativeFields as $field) { + foreach ($permutations as $set) { + $may_view = $set['comment']->{$field}->access('view', $set['user']); + $may_update = $set['comment']->{$field}->access('edit', $set['user']); + $this->assertEqual($may_view, $set['user']->hasPermission('administer comments') || ($set['comment']->isPublished() && $set['user']->hasPermission('access comments')), String::format('User @user !state view field !field on comment @comment', [ + '@user' => $set['user']->label(), + '!state' => $may_update ? 'can' : 'cannot', + '@comment' => $set['comment']->getSubject(), + '!field' => $field, + ])); + $this->assertEqual($may_update, $set['user']->hasPermission('administer comments'), String::format('User @user !state update field !field on comment @comment', [ + '@user' => $set['user']->label(), + '!state' => $may_update ? 'can' : 'cannot', + '@comment' => $set['comment']->getSubject(), + '!field' => $field, + ])); } - - // Checks on edit operations. - $may_update = $comment1->{$field}->access('edit', $comment_enabled_user); - $this->assertFalse($may_update, String::format('Users with permission "edit own comments" is not allowed to the field @name.', array('@name' => $field))); - $may_update = $comment2->{$field}->access('edit', $comment_enabled_user); - $this->assertFalse($may_update, String::format('Users with permission "edit own comments" is not allowed to the field @name.', array('@name' => $field))); - $may_update = $comment3->{$field}->access('edit', $comment_no_edit_user); - $this->assertFalse($may_update, String::format('Users with permission "post comments" is not allowed to the field @name.', array('@name' => $field))); - $may_update = $comment1->{$field}->access('edit', $comment_disabled_user); - $this->assertFalse($may_update, String::format('Users with no comment permissions is not allowed to edit the field @name.', array('@name' => $field))); - $may_update = $comment2->{$field}->access('edit', $comment_disabled_user); - $this->assertFalse($may_update, String::format('Users not having permission "edit any page content" is not allowed to the field @name.', array('@name' => $field))); - $may_update = $comment1->{$field}->access('edit', $comment_admin_user) && $comment3->status->access('edit', $comment_admin_user); - $this->assertTrue($may_update, String::format('Users with permission "administer comments" may edit @name fields on all comments.', array('@name' => $field))); } - $may_update = $comment2->subject->access('edit', $comment_enabled_user); - $this->assertTrue($may_update, String::format('Users with permission "edit own comments" is allowed to edit the field subject.')); + // Check access to normal field. + foreach ($permutations as $set) { + $may_update = $set['comment']->subject->access('edit', $set['user']); + $this->assertEqual($may_update, $set['user']->hasPermission('administer comments') || ($set['user']->hasPermission('edit own comments') && $set['user']->id() == $set['comment']->getOwnerId()), String::format('User @user !state update field subject on comment @comment', [ + '@user' => $set['user']->label(), + '!state' => $may_update ? 'can' : 'cannot', + '@comment' => $set['comment']->getSubject(), + ])); + } foreach ($this->readOnlyFields as $field) { // Check view operation. foreach ($test_users as $account) { - $may_view = $comment1->{$field}->access('view', $account); - $this->assertEqual($may_view, $account->hasPermission('access comments'), String::format('User @user @type view the field @name.', array( - '@name' => $field, - '@user' => $account->label(), - '@type' => $may_view ? 'may' : 'may not', - ))); - // Only admin should be able to access unpublished comments. - $may_view = $comment3->{$field}->access('view', $account); - $this->assertEqual($may_view, $account->hasPermission('administer comments'), String::format('User @user @type view the field @name.', array( - '@name' => $field, - '@user' => $account->label(), - '@type' => $may_view ? 'may' : 'may not', - ))); - } - - // Check edit operation. - foreach ($test_users as $account) { - $may_view = $comment1->{$field}->access('edit', $account); - $this->assertFalse($may_view, String::format('No user is not allowed to edit the field @name.', array('@name' => $field))); + foreach ($permutations as $set) { + $may_view = $set['comment']->{$field}->access('view', $set['user']); + $may_update = $set['comment']->{$field}->access('edit', $set['user']); + $this->assertEqual($may_view, $set['user']->hasPermission('administer comments') || ($set['comment']->isPublished() && $set['user']->hasPermission('access comments')), String::format('User @user !state view field !field on comment @comment', [ + '@user' => $set['user']->label(), + '!state' => $may_update ? 'can' : 'cannot', + '@comment' => $set['comment']->getSubject(), + '!field' => $field, + ])); + $this->assertFalse($may_update, String::format('User @user !state update field !field on comment @comment', [ + '@user' => $set['user']->label(), + '!state' => $may_update ? 'can' : 'cannot', + '@comment' => $set['comment']->getSubject(), + '!field' => $field, + ])); + } } }