c17f247dff0b6df2dd39fb8d3a97f1a1b582e0a3
[yaffs-website] / web / core / modules / comment / tests / src / Kernel / CommentFieldAccessTest.php
1 <?php
2
3 namespace Drupal\Tests\comment\Kernel;
4
5 use Drupal\comment\Entity\Comment;
6 use Drupal\comment\Entity\CommentType;
7 use Drupal\comment\Tests\CommentTestTrait;
8 use Drupal\Component\Render\FormattableMarkup;
9 use Drupal\Core\Session\AnonymousUserSession;
10 use Drupal\entity_test\Entity\EntityTest;
11 use Drupal\field\Entity\FieldConfig;
12 use Drupal\KernelTests\Core\Entity\EntityKernelTestBase;
13 use Drupal\Tests\Traits\Core\GeneratePermutationsTrait;
14 use Drupal\user\Entity\Role;
15 use Drupal\user\RoleInterface;
16
17 /**
18  * Tests comment field level access.
19  *
20  * @group comment
21  * @group Access
22  */
23 class CommentFieldAccessTest extends EntityKernelTestBase {
24
25   use CommentTestTrait;
26   use GeneratePermutationsTrait;
27
28   /**
29    * Modules to install.
30    *
31    * @var array
32    */
33   public static $modules = ['comment', 'entity_test', 'user'];
34
35   /**
36    * Fields that only users with administer comments permissions can change.
37    *
38    * @var array
39    */
40   protected $administrativeFields = [
41     'uid',
42     'status',
43     'created',
44   ];
45
46   /**
47    * These fields are automatically managed and can not be changed by any user.
48    *
49    * @var array
50    */
51   protected $readOnlyFields = [
52     'changed',
53     'hostname',
54     'cid',
55     'thread',
56   ];
57
58   /**
59    * These fields can be edited on create only.
60    *
61    * @var array
62    */
63   protected $createOnlyFields = [
64     'uuid',
65     'pid',
66     'comment_type',
67     'entity_id',
68     'entity_type',
69     'field_name',
70   ];
71
72   /**
73    * These fields can only be edited by the admin or anonymous users if allowed.
74    *
75    * @var array
76    */
77   protected $contactFields = [
78     'name',
79     'mail',
80     'homepage',
81   ];
82
83   /**
84    * {@inheritdoc}
85    */
86   protected function setUp() {
87     parent::setUp();
88     $this->installConfig(['user', 'comment']);
89     $this->installSchema('comment', ['comment_entity_statistics']);
90   }
91
92   /**
93    * Test permissions on comment fields.
94    */
95   public function testAccessToAdministrativeFields() {
96     // Create a comment type.
97     $comment_type = CommentType::create([
98       'id' => 'comment',
99       'label' => 'Default comments',
100       'description' => 'Default comment field',
101       'target_entity_type_id' => 'entity_test',
102     ]);
103     $comment_type->save();
104
105     // Create a comment against a test entity.
106     $host = EntityTest::create();
107     $host->save();
108
109     // An administrator user. No user exists yet, ensure that the first user
110     // does not have UID 1.
111     $comment_admin_user = $this->createUser(['uid' => 2, 'name' => 'admin'], [
112       'administer comments',
113       'access comments',
114     ]);
115
116     // Two comment enabled users, one with edit access.
117     $comment_enabled_user = $this->createUser(['name' => 'enabled'], [
118       'post comments',
119       'skip comment approval',
120       'edit own comments',
121       'access comments',
122     ]);
123     $comment_no_edit_user = $this->createUser(['name' => 'no edit'], [
124       'post comments',
125       'skip comment approval',
126       'access comments',
127     ]);
128
129     // An unprivileged user.
130     $comment_disabled_user = $this->createUser(['name' => 'disabled'], ['access content']);
131
132     $role = Role::load(RoleInterface::ANONYMOUS_ID);
133     $role->grantPermission('post comments')
134       ->save();
135
136     $anonymous_user = new AnonymousUserSession();
137
138     // Add two fields.
139     $this->addDefaultCommentField('entity_test', 'entity_test', 'comment');
140     $this->addDefaultCommentField('entity_test', 'entity_test', 'comment_other');
141
142     // Change the second field's anonymous contact setting.
143     $instance = FieldConfig::loadByName('entity_test', 'entity_test', 'comment_other');
144     // Default is 'May not contact', for this field - they may contact.
145     $instance->setSetting('anonymous', COMMENT_ANONYMOUS_MAY_CONTACT);
146     $instance->save();
147
148     // Create three "Comments". One is owned by our edit-enabled user.
149     $comment1 = Comment::create([
150       'entity_type' => 'entity_test',
151       'name' => 'Tony',
152       'hostname' => 'magic.example.com',
153       'mail' => 'tonythemagicalpony@example.com',
154       'subject' => 'Bruce the Mesopotamian moose',
155       'entity_id' => $host->id(),
156       'comment_type' => 'comment',
157       'field_name' => 'comment',
158       'pid' => 0,
159       'uid' => 0,
160       'status' => 1,
161     ]);
162     $comment1->save();
163     $comment2 = Comment::create([
164       'entity_type' => 'entity_test',
165       'hostname' => 'magic.example.com',
166       'subject' => 'Brian the messed up lion',
167       'entity_id' => $host->id(),
168       'comment_type' => 'comment',
169       'field_name' => 'comment',
170       'status' => 1,
171       'pid' => 0,
172       'uid' => $comment_enabled_user->id(),
173     ]);
174     $comment2->save();
175     $comment3 = Comment::create([
176       'entity_type' => 'entity_test',
177       'hostname' => 'magic.example.com',
178       // Unpublished.
179       'status' => 0,
180       'subject' => 'Gail the minky whale',
181       'entity_id' => $host->id(),
182       'comment_type' => 'comment',
183       'field_name' => 'comment_other',
184       'pid' => $comment2->id(),
185       'uid' => $comment_no_edit_user->id(),
186     ]);
187     $comment3->save();
188     // Note we intentionally don't save this comment so it remains 'new'.
189     $comment4 = Comment::create([
190       'entity_type' => 'entity_test',
191       'hostname' => 'magic.example.com',
192       // Unpublished.
193       'status' => 0,
194       'subject' => 'Daniel the Cocker-Spaniel',
195       'entity_id' => $host->id(),
196       'comment_type' => 'comment',
197       'field_name' => 'comment_other',
198       'pid' => 0,
199       'uid' => $anonymous_user->id(),
200     ]);
201
202     // Generate permutations.
203     $combinations = [
204       'comment' => [$comment1, $comment2, $comment3, $comment4],
205       'user' => [$comment_admin_user, $comment_enabled_user, $comment_no_edit_user, $comment_disabled_user, $anonymous_user],
206     ];
207     $permutations = $this->generatePermutations($combinations);
208
209     // Check access to administrative fields.
210     foreach ($this->administrativeFields as $field) {
211       foreach ($permutations as $set) {
212         $may_view = $set['comment']->{$field}->access('view', $set['user']);
213         $may_update = $set['comment']->{$field}->access('edit', $set['user']);
214         $this->assertTrue($may_view, new FormattableMarkup('User @user can view field @field on comment @comment', [
215           '@user' => $set['user']->getUsername(),
216           '@comment' => $set['comment']->getSubject(),
217           '@field' => $field,
218         ]));
219         $this->assertEqual($may_update, $set['user']->hasPermission('administer comments'), new FormattableMarkup('User @user @state update field @field on comment @comment', [
220           '@user' => $set['user']->getUsername(),
221           '@state' => $may_update ? 'can' : 'cannot',
222           '@comment' => $set['comment']->getSubject(),
223           '@field' => $field,
224         ]));
225       }
226     }
227
228     // Check access to normal field.
229     foreach ($permutations as $set) {
230       $may_update = $set['comment']->access('update', $set['user']) && $set['comment']->subject->access('edit', $set['user']);
231       $this->assertEqual($may_update, $set['user']->hasPermission('administer comments') || ($set['user']->hasPermission('edit own comments') && $set['user']->id() == $set['comment']->getOwnerId()), new FormattableMarkup('User @user @state update field subject on comment @comment', [
232         '@user' => $set['user']->getUsername(),
233         '@state' => $may_update ? 'can' : 'cannot',
234         '@comment' => $set['comment']->getSubject(),
235       ]));
236     }
237
238     // Check read-only fields.
239     foreach ($this->readOnlyFields as $field) {
240       // Check view operation.
241       foreach ($permutations as $set) {
242         $may_view = $set['comment']->{$field}->access('view', $set['user']);
243         $may_update = $set['comment']->{$field}->access('edit', $set['user']);
244         // Nobody has access to view the hostname field.
245         if ($field === 'hostname') {
246           $view_access = FALSE;
247           $state = 'cannot';
248         }
249         else {
250           $view_access = TRUE;
251           $state = 'can';
252         }
253         $this->assertEqual($may_view, $view_access, new FormattableMarkup('User @user @state view field @field on comment @comment', [
254           '@user' => $set['user']->getUsername(),
255           '@comment' => $set['comment']->getSubject(),
256           '@field' => $field,
257           '@state' => $state,
258         ]));
259         $this->assertFalse($may_update, new FormattableMarkup('User @user @state update field @field on comment @comment', [
260           '@user' => $set['user']->getUsername(),
261           '@state' => $may_update ? 'can' : 'cannot',
262           '@comment' => $set['comment']->getSubject(),
263           '@field' => $field,
264         ]));
265       }
266     }
267
268     // Check create-only fields.
269     foreach ($this->createOnlyFields as $field) {
270       // Check view operation.
271       foreach ($permutations as $set) {
272         $may_view = $set['comment']->{$field}->access('view', $set['user']);
273         $may_update = $set['comment']->{$field}->access('edit', $set['user']);
274         $this->assertEqual($may_view, TRUE, new FormattableMarkup('User @user can view field @field on comment @comment', [
275           '@user' => $set['user']->getUsername(),
276           '@comment' => $set['comment']->getSubject(),
277           '@field' => $field,
278         ]));
279         $this->assertEqual($may_update, $set['user']->hasPermission('post comments') && $set['comment']->isNew(), new FormattableMarkup('User @user @state update field @field on comment @comment', [
280           '@user' => $set['user']->getUsername(),
281           '@state' => $may_update ? 'can' : 'cannot',
282           '@comment' => $set['comment']->getSubject(),
283           '@field' => $field,
284         ]));
285       }
286     }
287
288     // Check contact fields.
289     foreach ($this->contactFields as $field) {
290       // Check view operation.
291       foreach ($permutations as $set) {
292         $may_update = $set['comment']->{$field}->access('edit', $set['user']);
293         // To edit the 'mail' or 'name' field, either the user has the
294         // "administer comments" permissions or the user is anonymous and
295         // adding a new comment using a field that allows contact details.
296         $this->assertEqual($may_update, $set['user']->hasPermission('administer comments') || (
297             $set['user']->isAnonymous() &&
298             $set['comment']->isNew() &&
299             $set['user']->hasPermission('post comments') &&
300             $set['comment']->getFieldName() == 'comment_other'
301           ), new FormattableMarkup('User @user @state update field @field on comment @comment', [
302           '@user' => $set['user']->getUsername(),
303           '@state' => $may_update ? 'can' : 'cannot',
304           '@comment' => $set['comment']->getSubject(),
305           '@field' => $field,
306         ]));
307       }
308     }
309     foreach ($permutations as $set) {
310       // Check no view-access to mail field for other than admin.
311       $may_view = $set['comment']->mail->access('view', $set['user']);
312       $this->assertEqual($may_view, $set['user']->hasPermission('administer comments'));
313     }
314   }
315
316 }