3 namespace Tests\Permissions;
5 use BookStack\Activity\Models\Comment;
6 use BookStack\Entities\Models\Book;
7 use BookStack\Entities\Models\Bookshelf;
8 use BookStack\Entities\Models\Chapter;
9 use BookStack\Entities\Models\Entity;
10 use BookStack\Entities\Models\Page;
11 use BookStack\Uploads\Image;
12 use BookStack\Users\Models\User;
13 use Illuminate\Testing\TestResponse;
16 class RolePermissionsTest extends TestCase
20 protected function setUp(): void
23 $this->user = $this->users->viewer();
26 public function test_manage_user_permission()
28 $this->actingAs($this->user)->get('/settings/users')->assertRedirect('/');
29 $this->permissions->grantUserRolePermissions($this->user, ['users-manage']);
30 $this->actingAs($this->user)->get('/settings/users')->assertOk();
33 public function test_manage_users_permission_shows_link_in_header_if_does_not_have_settings_manage_permision()
35 $usersLink = 'href="' . url('/settings/users') . '"';
36 $this->actingAs($this->user)->get('/')->assertDontSee($usersLink, false);
37 $this->permissions->grantUserRolePermissions($this->user, ['users-manage']);
38 $this->actingAs($this->user)->get('/')->assertSee($usersLink, false);
39 $this->permissions->grantUserRolePermissions($this->user, ['settings-manage', 'users-manage']);
40 $this->actingAs($this->user)->get('/')->assertDontSee($usersLink, false);
43 public function test_user_cannot_change_email_unless_they_have_manage_users_permission()
45 $originalEmail = $this->user->email;
46 $this->actingAs($this->user);
48 $resp = $this->get('/my-account/profile')->assertOk();
49 $this->withHtml($resp)->assertElementExists('input[name=email][disabled]');
50 $resp->assertSee('Unfortunately you don\'t have permission to change your email address.');
51 $this->put('/my-account/profile', [
52 'name' => 'my_new_name',
55 $this->assertDatabaseHas('users', [
56 'id' => $this->user->id,
57 'email' => $originalEmail,
58 'name' => 'my_new_name',
61 $this->permissions->grantUserRolePermissions($this->user, ['users-manage']);
63 $resp = $this->get('/my-account/profile')->assertOk();
64 $this->withHtml($resp)
65 ->assertElementNotExists('input[name=email][disabled]')
66 ->assertElementExists('input[name=email]');
68 $this->put('/my-account/profile', [
69 'name' => 'my_new_name_2',
73 $this->assertDatabaseHas('users', [
74 'id' => $this->user->id,
76 'name' => 'my_new_name_2',
80 public function test_user_roles_manage_permission()
82 $this->actingAs($this->user)->get('/settings/roles')->assertRedirect('/');
83 $this->get('/settings/roles/1')->assertRedirect('/');
84 $this->permissions->grantUserRolePermissions($this->user, ['user-roles-manage']);
85 $this->actingAs($this->user)->get('/settings/roles')->assertOk();
86 $this->get('/settings/roles/1')
91 public function test_settings_manage_permission()
93 $this->actingAs($this->user)->get('/settings/features')->assertRedirect('/');
94 $this->permissions->grantUserRolePermissions($this->user, ['settings-manage']);
95 $this->get('/settings/features')->assertOk();
97 $resp = $this->post('/settings/features', []);
98 $resp->assertRedirect('/settings/features');
99 $resp = $this->get('/settings/features');
100 $resp->assertSee('Settings successfully updated');
103 public function test_restrictions_manage_all_permission()
105 $page = $this->entities->page();
107 $this->actingAs($this->user)->get($page->getUrl())->assertDontSee('Permissions');
108 $this->get($page->getUrl('/permissions'))->assertRedirect('/');
110 $this->permissions->grantUserRolePermissions($this->user, ['restrictions-manage-all']);
112 $this->actingAs($this->user)->get($page->getUrl())->assertSee('Permissions');
114 $this->get($page->getUrl('/permissions'))
116 ->assertSee('Page Permissions');
119 public function test_restrictions_manage_own_permission()
121 $otherUsersPage = $this->entities->page();
122 $content = $this->entities->createChainBelongingToUser($this->user);
124 // Set a different creator on the page we're checking to ensure
125 // that the owner fields are checked
126 $page = $content['page']; /** @var Page $page */
127 $page->created_by = $otherUsersPage->id;
128 $page->owned_by = $this->user->id;
131 // Check can't restrict other's content
132 $this->actingAs($this->user)->get($otherUsersPage->getUrl())->assertDontSee('Permissions');
133 $this->get($otherUsersPage->getUrl('/permissions'))->assertRedirect('/');
135 // Check can't restrict own content
136 $this->actingAs($this->user)->get($page->getUrl())->assertDontSee('Permissions');
137 $this->get($page->getUrl('/permissions'))->assertRedirect('/');
139 $this->permissions->grantUserRolePermissions($this->user, ['restrictions-manage-own']);
141 // Check can't restrict other's content
142 $this->actingAs($this->user)->get($otherUsersPage->getUrl())->assertDontSee('Permissions');
143 $this->get($otherUsersPage->getUrl('/permissions'))->assertRedirect();
145 // Check can restrict own content
146 $this->actingAs($this->user)->get($page->getUrl())->assertSee('Permissions');
147 $this->get($page->getUrl('/permissions'))->assertOk();
151 * Check a standard entity access permission.
153 private function checkAccessPermission(
155 array $accessUrls = [],
156 array $visibles = [],
157 string $expectedRedirectUri = '/',
159 foreach ($accessUrls as $url) {
160 $this->actingAs($this->user)->get($url)->assertRedirect($expectedRedirectUri);
163 foreach ($visibles as $url => $text) {
164 $resp = $this->actingAs($this->user)->get($url);
165 $this->withHtml($resp)->assertElementNotContains('.action-buttons', $text);
168 $this->permissions->grantUserRolePermissions($this->user, [$permission]);
170 foreach ($accessUrls as $url) {
171 $this->actingAs($this->user)->get($url)->assertOk();
173 foreach ($visibles as $url => $text) {
174 $this->actingAs($this->user)->get($url)->assertSee($text);
178 public function test_bookshelves_create_all_permissions()
180 $this->checkAccessPermission('bookshelf-create-all', [
183 '/shelves' => 'New Shelf',
186 $this->post('/shelves', [
187 'name' => 'test shelf',
188 'description' => 'shelf desc',
189 ])->assertRedirect('/shelves/test-shelf');
192 public function test_bookshelves_edit_own_permission()
194 /** @var Bookshelf $otherShelf */
195 $otherShelf = Bookshelf::query()->first();
196 $ownShelf = $this->entities->newShelf(['name' => 'test-shelf', 'slug' => 'test-shelf']);
197 $ownShelf->forceFill(['owned_by' => $this->user->id, 'updated_by' => $this->user->id])->save();
198 $this->permissions->regenerateForEntity($ownShelf);
200 $this->checkAccessPermission('bookshelf-update-own', [
201 $ownShelf->getUrl('/edit'),
203 $ownShelf->getUrl() => 'Edit',
206 $resp = $this->get($otherShelf->getUrl());
207 $this->withHtml($resp)->assertElementNotContains('.action-buttons', 'Edit');
208 $this->get($otherShelf->getUrl('/edit'))->assertRedirect('/');
211 public function test_bookshelves_edit_all_permission()
213 /** @var Bookshelf $otherShelf */
214 $otherShelf = Bookshelf::query()->first();
215 $this->checkAccessPermission('bookshelf-update-all', [
216 $otherShelf->getUrl('/edit'),
218 $otherShelf->getUrl() => 'Edit',
222 public function test_bookshelves_delete_own_permission()
224 $this->permissions->grantUserRolePermissions($this->user, ['bookshelf-update-all']);
225 /** @var Bookshelf $otherShelf */
226 $otherShelf = Bookshelf::query()->first();
227 $ownShelf = $this->entities->newShelf(['name' => 'test-shelf', 'slug' => 'test-shelf']);
228 $ownShelf->forceFill(['owned_by' => $this->user->id, 'updated_by' => $this->user->id])->save();
229 $this->permissions->regenerateForEntity($ownShelf);
231 $this->checkAccessPermission('bookshelf-delete-own', [
232 $ownShelf->getUrl('/delete'),
234 $ownShelf->getUrl() => 'Delete',
237 $resp = $this->get($otherShelf->getUrl());
238 $this->withHtml($resp)->assertElementNotContains('.action-buttons', 'Delete');
239 $this->get($otherShelf->getUrl('/delete'))->assertRedirect('/');
241 $this->get($ownShelf->getUrl());
242 $this->delete($ownShelf->getUrl())->assertRedirect('/shelves');
243 $this->get('/shelves')->assertDontSee($ownShelf->name);
246 public function test_bookshelves_delete_all_permission()
248 $this->permissions->grantUserRolePermissions($this->user, ['bookshelf-update-all']);
249 /** @var Bookshelf $otherShelf */
250 $otherShelf = Bookshelf::query()->first();
251 $this->checkAccessPermission('bookshelf-delete-all', [
252 $otherShelf->getUrl('/delete'),
254 $otherShelf->getUrl() => 'Delete',
257 $this->delete($otherShelf->getUrl())->assertRedirect('/shelves');
258 $this->get('/shelves')->assertDontSee($otherShelf->name);
261 public function test_books_create_all_permissions()
263 $this->checkAccessPermission('book-create-all', [
266 '/books' => 'Create New Book',
269 $this->post('/books', [
270 'name' => 'test book',
271 'description' => 'book desc',
272 ])->assertRedirect('/books/test-book');
275 public function test_books_edit_own_permission()
277 /** @var Book $otherBook */
278 $otherBook = Book::query()->take(1)->get()->first();
279 $ownBook = $this->entities->createChainBelongingToUser($this->user)['book'];
280 $this->checkAccessPermission('book-update-own', [
281 $ownBook->getUrl() . '/edit',
283 $ownBook->getUrl() => 'Edit',
286 $resp = $this->get($otherBook->getUrl());
287 $this->withHtml($resp)->assertElementNotContains('.action-buttons', 'Edit');
288 $this->get($otherBook->getUrl('/edit'))->assertRedirect('/');
291 public function test_books_edit_all_permission()
293 /** @var Book $otherBook */
294 $otherBook = Book::query()->take(1)->get()->first();
295 $this->checkAccessPermission('book-update-all', [
296 $otherBook->getUrl() . '/edit',
298 $otherBook->getUrl() => 'Edit',
302 public function test_books_delete_own_permission()
304 $this->permissions->grantUserRolePermissions($this->user, ['book-update-all']);
305 /** @var Book $otherBook */
306 $otherBook = Book::query()->take(1)->get()->first();
307 $ownBook = $this->entities->createChainBelongingToUser($this->user)['book'];
308 $this->checkAccessPermission('book-delete-own', [
309 $ownBook->getUrl() . '/delete',
311 $ownBook->getUrl() => 'Delete',
314 $resp = $this->get($otherBook->getUrl());
315 $this->withHtml($resp)->assertElementNotContains('.action-buttons', 'Delete');
316 $this->get($otherBook->getUrl('/delete'))->assertRedirect('/');
317 $this->get($ownBook->getUrl());
318 $this->delete($ownBook->getUrl())->assertRedirect('/books');
319 $this->get('/books')->assertDontSee($ownBook->name);
322 public function test_books_delete_all_permission()
324 $this->permissions->grantUserRolePermissions($this->user, ['book-update-all']);
325 /** @var Book $otherBook */
326 $otherBook = Book::query()->take(1)->get()->first();
327 $this->checkAccessPermission('book-delete-all', [
328 $otherBook->getUrl() . '/delete',
330 $otherBook->getUrl() => 'Delete',
333 $this->get($otherBook->getUrl());
334 $this->delete($otherBook->getUrl())->assertRedirect('/books');
335 $this->get('/books')->assertDontSee($otherBook->name);
338 public function test_chapter_create_own_permissions()
340 /** @var Book $book */
341 $book = Book::query()->take(1)->get()->first();
342 $ownBook = $this->entities->createChainBelongingToUser($this->user)['book'];
343 $this->checkAccessPermission('chapter-create-own', [
344 $ownBook->getUrl('/create-chapter'),
346 $ownBook->getUrl() => 'New Chapter',
349 $this->post($ownBook->getUrl('/create-chapter'), [
350 'name' => 'test chapter',
351 'description' => 'chapter desc',
352 ])->assertRedirect($ownBook->getUrl('/chapter/test-chapter'));
354 $resp = $this->get($book->getUrl());
355 $this->withHtml($resp)->assertElementNotContains('.action-buttons', 'New Chapter');
356 $this->get($book->getUrl('/create-chapter'))->assertRedirect('/');
359 public function test_chapter_create_all_permissions()
361 $book = $this->entities->book();
362 $this->checkAccessPermission('chapter-create-all', [
363 $book->getUrl('/create-chapter'),
365 $book->getUrl() => 'New Chapter',
368 $this->post($book->getUrl('/create-chapter'), [
369 'name' => 'test chapter',
370 'description' => 'chapter desc',
371 ])->assertRedirect($book->getUrl('/chapter/test-chapter'));
374 public function test_chapter_edit_own_permission()
376 /** @var Chapter $otherChapter */
377 $otherChapter = Chapter::query()->first();
378 $ownChapter = $this->entities->createChainBelongingToUser($this->user)['chapter'];
379 $this->checkAccessPermission('chapter-update-own', [
380 $ownChapter->getUrl() . '/edit',
382 $ownChapter->getUrl() => 'Edit',
385 $resp = $this->get($otherChapter->getUrl());
386 $this->withHtml($resp)->assertElementNotContains('.action-buttons', 'Edit');
387 $this->get($otherChapter->getUrl('/edit'))->assertRedirect('/');
390 public function test_chapter_edit_all_permission()
392 /** @var Chapter $otherChapter */
393 $otherChapter = Chapter::query()->take(1)->get()->first();
394 $this->checkAccessPermission('chapter-update-all', [
395 $otherChapter->getUrl() . '/edit',
397 $otherChapter->getUrl() => 'Edit',
401 public function test_chapter_delete_own_permission()
403 $this->permissions->grantUserRolePermissions($this->user, ['chapter-update-all']);
404 /** @var Chapter $otherChapter */
405 $otherChapter = Chapter::query()->first();
406 $ownChapter = $this->entities->createChainBelongingToUser($this->user)['chapter'];
407 $this->checkAccessPermission('chapter-delete-own', [
408 $ownChapter->getUrl() . '/delete',
410 $ownChapter->getUrl() => 'Delete',
413 $bookUrl = $ownChapter->book->getUrl();
414 $resp = $this->get($otherChapter->getUrl());
415 $this->withHtml($resp)->assertElementNotContains('.action-buttons', 'Delete');
416 $this->get($otherChapter->getUrl('/delete'))->assertRedirect('/');
417 $this->get($ownChapter->getUrl());
418 $this->delete($ownChapter->getUrl())->assertRedirect($bookUrl);
419 $resp = $this->get($bookUrl);
420 $this->withHtml($resp)->assertElementNotContains('.book-content', $ownChapter->name);
423 public function test_chapter_delete_all_permission()
425 $this->permissions->grantUserRolePermissions($this->user, ['chapter-update-all']);
426 /** @var Chapter $otherChapter */
427 $otherChapter = Chapter::query()->first();
428 $this->checkAccessPermission('chapter-delete-all', [
429 $otherChapter->getUrl() . '/delete',
431 $otherChapter->getUrl() => 'Delete',
434 $bookUrl = $otherChapter->book->getUrl();
435 $this->get($otherChapter->getUrl());
436 $this->delete($otherChapter->getUrl())->assertRedirect($bookUrl);
437 $resp = $this->get($bookUrl);
438 $this->withHtml($resp)->assertElementNotContains('.book-content', $otherChapter->name);
441 public function test_page_create_own_permissions()
443 $book = $this->entities->book();
444 $chapter = $this->entities->chapter();
446 $entities = $this->entities->createChainBelongingToUser($this->user);
447 $ownBook = $entities['book'];
448 $ownChapter = $entities['chapter'];
450 $createUrl = $ownBook->getUrl('/create-page');
451 $createUrlChapter = $ownChapter->getUrl('/create-page');
452 $accessUrls = [$createUrl, $createUrlChapter];
454 foreach ($accessUrls as $url) {
455 $this->actingAs($this->user)->get($url)->assertRedirect('/');
458 $this->checkAccessPermission('page-create-own', [], [
459 $ownBook->getUrl() => 'New Page',
460 $ownChapter->getUrl() => 'New Page',
463 $this->permissions->grantUserRolePermissions($this->user, ['page-create-own']);
465 foreach ($accessUrls as $index => $url) {
466 $resp = $this->actingAs($this->user)->get($url);
467 $expectedUrl = Page::query()->where('draft', '=', true)->orderBy('id', 'desc')->first()->getUrl();
468 $resp->assertRedirect($expectedUrl);
471 $this->get($createUrl);
472 /** @var Page $draft */
473 $draft = Page::query()->where('draft', '=', true)->orderBy('id', 'desc')->first();
474 $this->post($draft->getUrl(), [
475 'name' => 'test page',
476 'html' => 'page desc',
477 ])->assertRedirect($ownBook->getUrl('/page/test-page'));
479 $resp = $this->get($book->getUrl());
480 $this->withHtml($resp)->assertElementNotContains('.action-buttons', 'New Page');
481 $this->get($book->getUrl('/create-page'))->assertRedirect('/');
483 $resp = $this->get($chapter->getUrl());
484 $this->withHtml($resp)->assertElementNotContains('.action-buttons', 'New Page');
485 $this->get($chapter->getUrl('/create-page'))->assertRedirect('/');
488 public function test_page_create_all_permissions()
490 $book = $this->entities->book();
491 $chapter = $this->entities->chapter();
492 $createUrl = $book->getUrl('/create-page');
494 $createUrlChapter = $chapter->getUrl('/create-page');
495 $accessUrls = [$createUrl, $createUrlChapter];
497 foreach ($accessUrls as $url) {
498 $this->actingAs($this->user)->get($url)->assertRedirect('/');
501 $this->checkAccessPermission('page-create-all', [], [
502 $book->getUrl() => 'New Page',
503 $chapter->getUrl() => 'New Page',
506 $this->permissions->grantUserRolePermissions($this->user, ['page-create-all']);
508 foreach ($accessUrls as $index => $url) {
509 $resp = $this->actingAs($this->user)->get($url);
510 $expectedUrl = Page::query()->where('draft', '=', true)->orderBy('id', 'desc')->first()->getUrl();
511 $resp->assertRedirect($expectedUrl);
514 $this->get($createUrl);
515 /** @var Page $draft */
516 $draft = Page::query()->where('draft', '=', true)->orderByDesc('id')->first();
517 $this->post($draft->getUrl(), [
518 'name' => 'test page',
519 'html' => 'page desc',
520 ])->assertRedirect($book->getUrl('/page/test-page'));
522 $this->get($chapter->getUrl('/create-page'));
523 /** @var Page $draft */
524 $draft = Page::query()->where('draft', '=', true)->orderByDesc('id')->first();
525 $this->post($draft->getUrl(), [
526 'name' => 'new test page',
527 'html' => 'page desc',
528 ])->assertRedirect($book->getUrl('/page/new-test-page'));
531 public function test_page_edit_own_permission()
533 /** @var Page $otherPage */
534 $otherPage = Page::query()->first();
535 $ownPage = $this->entities->createChainBelongingToUser($this->user)['page'];
536 $this->checkAccessPermission('page-update-own', [
537 $ownPage->getUrl() . '/edit',
539 $ownPage->getUrl() => 'Edit',
540 ], $ownPage->getUrl());
542 $resp = $this->get($otherPage->getUrl());
543 $this->withHtml($resp)->assertElementNotContains('.action-buttons', 'Edit');
544 $this->get($otherPage->getUrl() . '/edit')->assertRedirect($otherPage->getUrl());
547 public function test_page_edit_all_permission()
549 /** @var Page $otherPage */
550 $otherPage = Page::query()->first();
551 $this->checkAccessPermission('page-update-all', [
552 $otherPage->getUrl('/edit'),
554 $otherPage->getUrl() => 'Edit',
555 ], $otherPage->getUrl());
558 public function test_page_delete_own_permission()
560 $this->permissions->grantUserRolePermissions($this->user, ['page-update-all']);
561 /** @var Page $otherPage */
562 $otherPage = Page::query()->first();
563 $ownPage = $this->entities->createChainBelongingToUser($this->user)['page'];
564 $this->checkAccessPermission('page-delete-own', [
565 $ownPage->getUrl() . '/delete',
567 $ownPage->getUrl() => 'Delete',
570 $parent = $ownPage->chapter ?? $ownPage->book;
571 $resp = $this->get($otherPage->getUrl());
572 $this->withHtml($resp)->assertElementNotContains('.action-buttons', 'Delete');
573 $this->get($otherPage->getUrl('/delete'))->assertRedirect('/');
574 $this->get($ownPage->getUrl());
575 $this->delete($ownPage->getUrl())->assertRedirect($parent->getUrl());
576 $resp = $this->get($parent->getUrl());
577 $this->withHtml($resp)->assertElementNotContains('.book-content', $ownPage->name);
580 public function test_page_delete_all_permission()
582 $this->permissions->grantUserRolePermissions($this->user, ['page-update-all']);
583 /** @var Page $otherPage */
584 $otherPage = Page::query()->first();
586 $this->checkAccessPermission('page-delete-all', [
587 $otherPage->getUrl() . '/delete',
589 $otherPage->getUrl() => 'Delete',
592 /** @var Entity $parent */
593 $parent = $otherPage->chapter ?? $otherPage->book;
594 $this->get($otherPage->getUrl());
596 $this->delete($otherPage->getUrl())->assertRedirect($parent->getUrl());
597 $this->get($parent->getUrl())->assertDontSee($otherPage->name);
601 public function test_image_delete_own_permission()
603 $this->permissions->grantUserRolePermissions($this->user, ['image-update-all']);
604 $page = $this->entities->page();
605 $image = Image::factory()->create([
606 'uploaded_to' => $page->id,
607 'created_by' => $this->user->id,
608 'updated_by' => $this->user->id,
611 $this->actingAs($this->user)->json('delete', '/images/' . $image->id)->assertStatus(403);
613 $this->permissions->grantUserRolePermissions($this->user, ['image-delete-own']);
615 $this->actingAs($this->user)->json('delete', '/images/' . $image->id)->assertOk();
616 $this->assertDatabaseMissing('images', ['id' => $image->id]);
619 public function test_image_delete_all_permission()
621 $this->permissions->grantUserRolePermissions($this->user, ['image-update-all']);
622 $admin = $this->users->admin();
623 $page = $this->entities->page();
624 $image = Image::factory()->create(['uploaded_to' => $page->id, 'created_by' => $admin->id, 'updated_by' => $admin->id]);
626 $this->actingAs($this->user)->json('delete', '/images/' . $image->id)->assertStatus(403);
628 $this->permissions->grantUserRolePermissions($this->user, ['image-delete-own']);
630 $this->actingAs($this->user)->json('delete', '/images/' . $image->id)->assertStatus(403);
632 $this->permissions->grantUserRolePermissions($this->user, ['image-delete-all']);
634 $this->actingAs($this->user)->json('delete', '/images/' . $image->id)->assertOk();
635 $this->assertDatabaseMissing('images', ['id' => $image->id]);
638 public function test_empty_state_actions_not_visible_without_permission()
640 $admin = $this->users->admin();
642 $book = Book::factory()->create(['created_by' => $admin->id, 'updated_by' => $admin->id]);
643 $this->permissions->regenerateForEntity($book);
644 $this->actingAs($this->users->viewer())->get($book->getUrl())
645 ->assertDontSee('Create a new page')
646 ->assertDontSee('Add a chapter');
649 $chapter = Chapter::factory()->create(['created_by' => $admin->id, 'updated_by' => $admin->id, 'book_id' => $book->id]);
650 $this->permissions->regenerateForEntity($chapter);
651 $this->actingAs($this->users->viewer())->get($chapter->getUrl())
652 ->assertDontSee('Create a new page')
653 ->assertDontSee('Sort the current book');
656 public function test_comment_create_permission()
658 $ownPage = $this->entities->createChainBelongingToUser($this->user)['page'];
660 $this->actingAs($this->user)
661 ->addComment($ownPage)
664 $this->permissions->grantUserRolePermissions($this->user, ['comment-create-all']);
666 $this->actingAs($this->user)
667 ->addComment($ownPage)
671 public function test_comment_update_own_permission()
673 $ownPage = $this->entities->createChainBelongingToUser($this->user)['page'];
674 $this->permissions->grantUserRolePermissions($this->user, ['comment-create-all']);
675 $this->actingAs($this->user)->addComment($ownPage);
676 /** @var Comment $comment */
677 $comment = $ownPage->comments()->latest()->first();
679 // no comment-update-own
680 $this->actingAs($this->user)->updateComment($comment)->assertStatus(403);
682 $this->permissions->grantUserRolePermissions($this->user, ['comment-update-own']);
684 // now has comment-update-own
685 $this->actingAs($this->user)->updateComment($comment)->assertOk();
688 public function test_comment_update_all_permission()
690 /** @var Page $ownPage */
691 $ownPage = $this->entities->createChainBelongingToUser($this->user)['page'];
692 $this->asAdmin()->addComment($ownPage);
693 /** @var Comment $comment */
694 $comment = $ownPage->comments()->latest()->first();
696 // no comment-update-all
697 $this->actingAs($this->user)->updateComment($comment)->assertStatus(403);
699 $this->permissions->grantUserRolePermissions($this->user, ['comment-update-all']);
701 // now has comment-update-all
702 $this->actingAs($this->user)->updateComment($comment)->assertOk();
705 public function test_comment_delete_own_permission()
707 /** @var Page $ownPage */
708 $ownPage = $this->entities->createChainBelongingToUser($this->user)['page'];
709 $this->permissions->grantUserRolePermissions($this->user, ['comment-create-all']);
710 $this->actingAs($this->user)->addComment($ownPage);
712 /** @var Comment $comment */
713 $comment = $ownPage->comments()->latest()->first();
715 // no comment-delete-own
716 $this->actingAs($this->user)->deleteComment($comment)->assertStatus(403);
718 $this->permissions->grantUserRolePermissions($this->user, ['comment-delete-own']);
720 // now has comment-update-own
721 $this->actingAs($this->user)->deleteComment($comment)->assertOk();
724 public function test_comment_delete_all_permission()
726 /** @var Page $ownPage */
727 $ownPage = $this->entities->createChainBelongingToUser($this->user)['page'];
728 $this->asAdmin()->addComment($ownPage);
729 /** @var Comment $comment */
730 $comment = $ownPage->comments()->latest()->first();
732 // no comment-delete-all
733 $this->actingAs($this->user)->deleteComment($comment)->assertStatus(403);
735 $this->permissions->grantUserRolePermissions($this->user, ['comment-delete-all']);
737 // now has comment-delete-all
738 $this->actingAs($this->user)->deleteComment($comment)->assertOk();
741 private function addComment(Page $page): TestResponse
743 return $this->postJson("/comment/$page->id", ['html' => '<p>New comment content</p>']);
746 private function updateComment(Comment $comment): TestResponse
748 return $this->putJson("/comment/{$comment->id}", ['html' => '<p>Updated comment content</p>']);
751 private function deleteComment(Comment $comment): TestResponse
753 return $this->json('DELETE', '/comment/' . $comment->id);