1 <?php namespace Tests\Permissions;
3 use BookStack\Entities\Bookshelf;
4 use BookStack\Entities\Page;
5 use BookStack\Auth\Role;
6 use Laravel\BrowserKitTesting\HttpException;
7 use Tests\BrowserKitTest;
9 class RolesTest extends BrowserKitTest
13 public function setUp(): void
16 $this->user = $this->getViewer();
19 public function test_admin_can_see_settings()
21 $this->asAdmin()->visit('/settings')->see('Settings');
24 public function test_cannot_delete_admin_role()
26 $adminRole = \BookStack\Auth\Role::getRole('admin');
27 $deletePageUrl = '/settings/roles/delete/' . $adminRole->id;
28 $this->asAdmin()->visit($deletePageUrl)
30 ->seePageIs($deletePageUrl)
31 ->see('cannot be deleted');
34 public function test_role_cannot_be_deleted_if_default()
36 $newRole = $this->createNewRole();
37 $this->setSettings(['registration-role' => $newRole->id]);
39 $deletePageUrl = '/settings/roles/delete/' . $newRole->id;
40 $this->asAdmin()->visit($deletePageUrl)
42 ->seePageIs($deletePageUrl)
43 ->see('cannot be deleted');
46 public function test_role_create_update_delete_flow()
48 $testRoleName = 'Test Role';
49 $testRoleDesc = 'a little test description';
50 $testRoleUpdateName = 'An Super Updated role';
53 $this->asAdmin()->visit('/settings')
55 ->seePageIs('/settings/roles')
56 ->click('Create New Role')
57 ->type('Test Role', 'display_name')
58 ->type('A little test description', 'description')
60 ->seeInDatabase('roles', ['display_name' => $testRoleName, 'description' => $testRoleDesc])
61 ->seePageIs('/settings/roles');
63 $this->asAdmin()->visit('/settings/roles')
65 ->click($testRoleName)
66 ->type($testRoleUpdateName, '#display_name')
68 ->seeInDatabase('roles', ['display_name' => $testRoleUpdateName, 'description' => $testRoleDesc])
69 ->seePageIs('/settings/roles');
71 $this->asAdmin()->visit('/settings/roles')
72 ->click($testRoleUpdateName)
73 ->click('Delete Role')
74 ->see($testRoleUpdateName)
76 ->seePageIs('/settings/roles')
77 ->dontSee($testRoleUpdateName);
80 public function test_admin_role_cannot_be_removed_if_last_admin()
82 $adminRole = Role::where('system_name', '=', 'admin')->first();
83 $adminUser = $this->getAdmin();
84 $adminRole->users()->where('id', '!=', $adminUser->id)->delete();
85 $this->assertEquals($adminRole->users()->count(), 1);
87 $viewerRole = $this->getViewer()->roles()->first();
89 $editUrl = '/settings/users/' . $adminUser->id;
90 $this->actingAs($adminUser)->put($editUrl, [
91 'name' => $adminUser->name,
92 'email' => $adminUser->email,
94 'viewer' => strval($viewerRole->id),
96 ])->followRedirects();
98 $this->seePageIs($editUrl);
99 $this->see('This user is the only user assigned to the administrator role');
102 public function test_migrate_users_on_delete_works()
104 $roleA = Role::query()->create(['display_name' => 'Delete Test A']);
105 $roleB = Role::query()->create(['display_name' => 'Delete Test B']);
106 $this->user->attachRole($roleB);
108 $this->assertCount(0, $roleA->users()->get());
109 $this->assertCount(1, $roleB->users()->get());
111 $deletePage = $this->asAdmin()->get("/settings/roles/delete/{$roleB->id}");
112 $deletePage->seeElement('select[name=migrate_role_id]');
113 $this->asAdmin()->delete("/settings/roles/delete/{$roleB->id}", [
114 'migrate_role_id' => $roleA->id,
117 $this->assertCount(1, $roleA->users()->get());
118 $this->assertEquals($this->user->id, $roleA->users()->first()->id);
121 public function test_manage_user_permission()
123 $this->actingAs($this->user)->visit('/settings/users')
125 $this->giveUserPermissions($this->user, ['users-manage']);
126 $this->actingAs($this->user)->visit('/settings/users')
127 ->seePageIs('/settings/users');
130 public function test_manage_users_permission_shows_link_in_header_if_does_not_have_settings_manage_permision()
132 $usersLink = 'href="'.url('/settings/users') . '"';
133 $this->actingAs($this->user)->visit('/')->dontSee($usersLink);
134 $this->giveUserPermissions($this->user, ['users-manage']);
135 $this->actingAs($this->user)->visit('/')->see($usersLink);
136 $this->giveUserPermissions($this->user, ['settings-manage', 'users-manage']);
137 $this->actingAs($this->user)->visit('/')->dontSee($usersLink);
140 public function test_user_cannot_change_email_unless_they_have_manage_users_permission()
142 $userProfileUrl = '/settings/users/' . $this->user->id;
143 $originalEmail = $this->user->email;
144 $this->actingAs($this->user);
146 $this->visit($userProfileUrl)
148 ->seeElement('input[name=email][disabled]');
149 $this->put($userProfileUrl, [
150 'name' => 'my_new_name',
153 $this->seeInDatabase('users', [
154 'id' => $this->user->id,
155 'email' => $originalEmail,
156 'name' => 'my_new_name',
159 $this->giveUserPermissions($this->user, ['users-manage']);
161 $this->visit($userProfileUrl)
163 ->dontSeeElement('input[name=email][disabled]')
164 ->seeElement('input[name=email]');
165 $this->put($userProfileUrl, [
166 'name' => 'my_new_name_2',
170 $this->seeInDatabase('users', [
171 'id' => $this->user->id,
173 'name' => 'my_new_name_2',
177 public function test_user_roles_manage_permission()
179 $this->actingAs($this->user)->visit('/settings/roles')
180 ->seePageIs('/')->visit('/settings/roles/1')->seePageIs('/');
181 $this->giveUserPermissions($this->user, ['user-roles-manage']);
182 $this->actingAs($this->user)->visit('/settings/roles')
183 ->seePageIs('/settings/roles')->click('Admin')
187 public function test_settings_manage_permission()
189 $this->actingAs($this->user)->visit('/settings')
191 $this->giveUserPermissions($this->user, ['settings-manage']);
192 $this->actingAs($this->user)->visit('/settings')
193 ->seePageIs('/settings')->press('Save Settings')->see('Settings Saved');
196 public function test_restrictions_manage_all_permission()
198 $page = \BookStack\Entities\Page::take(1)->get()->first();
199 $this->actingAs($this->user)->visit($page->getUrl())
200 ->dontSee('Permissions')
201 ->visit($page->getUrl() . '/permissions')
203 $this->giveUserPermissions($this->user, ['restrictions-manage-all']);
204 $this->actingAs($this->user)->visit($page->getUrl())
206 ->click('Permissions')
207 ->see('Page Permissions')->seePageIs($page->getUrl() . '/permissions');
210 public function test_restrictions_manage_own_permission()
212 $otherUsersPage = \BookStack\Entities\Page::first();
213 $content = $this->createEntityChainBelongingToUser($this->user);
214 // Check can't restrict other's content
215 $this->actingAs($this->user)->visit($otherUsersPage->getUrl())
216 ->dontSee('Permissions')
217 ->visit($otherUsersPage->getUrl() . '/permissions')
219 // Check can't restrict own content
220 $this->actingAs($this->user)->visit($content['page']->getUrl())
221 ->dontSee('Permissions')
222 ->visit($content['page']->getUrl() . '/permissions')
225 $this->giveUserPermissions($this->user, ['restrictions-manage-own']);
227 // Check can't restrict other's content
228 $this->actingAs($this->user)->visit($otherUsersPage->getUrl())
229 ->dontSee('Permissions')
230 ->visit($otherUsersPage->getUrl() . '/permissions')
232 // Check can restrict own content
233 $this->actingAs($this->user)->visit($content['page']->getUrl())
235 ->click('Permissions')
236 ->seePageIs($content['page']->getUrl() . '/permissions');
240 * Check a standard entity access permission
241 * @param string $permission
242 * @param array $accessUrls Urls that are only accessible after having the permission
243 * @param array $visibles Check this text, In the buttons toolbar, is only visible with the permission
245 private function checkAccessPermission($permission, $accessUrls = [], $visibles = [])
247 foreach ($accessUrls as $url) {
248 $this->actingAs($this->user)->visit($url)
251 foreach ($visibles as $url => $text) {
252 $this->actingAs($this->user)->visit($url)
253 ->dontSeeInElement('.action-buttons',$text);
256 $this->giveUserPermissions($this->user, [$permission]);
258 foreach ($accessUrls as $url) {
259 $this->actingAs($this->user)->visit($url)
262 foreach ($visibles as $url => $text) {
263 $this->actingAs($this->user)->visit($url)
268 public function test_bookshelves_create_all_permissions()
270 $this->checkAccessPermission('bookshelf-create-all', [
273 '/shelves' => 'New Shelf'
276 $this->visit('/create-shelf')
277 ->type('test shelf', 'name')
278 ->type('shelf desc', 'description')
279 ->press('Save Shelf')
280 ->seePageIs('/shelves/test-shelf');
283 public function test_bookshelves_edit_own_permission()
285 $otherShelf = Bookshelf::first();
286 $ownShelf = $this->newShelf(['name' => 'test-shelf', 'slug' => 'test-shelf']);
287 $ownShelf->forceFill(['created_by' => $this->user->id, 'updated_by' => $this->user->id])->save();
288 $this->regenEntityPermissions($ownShelf);
290 $this->checkAccessPermission('bookshelf-update-own', [
291 $ownShelf->getUrl('/edit')
293 $ownShelf->getUrl() => 'Edit'
296 $this->visit($otherShelf->getUrl())
297 ->dontSeeInElement('.action-buttons', 'Edit')
298 ->visit($otherShelf->getUrl('/edit'))
302 public function test_bookshelves_edit_all_permission()
304 $otherShelf = \BookStack\Entities\Bookshelf::first();
305 $this->checkAccessPermission('bookshelf-update-all', [
306 $otherShelf->getUrl('/edit')
308 $otherShelf->getUrl() => 'Edit'
312 public function test_bookshelves_delete_own_permission()
314 $this->giveUserPermissions($this->user, ['bookshelf-update-all']);
315 $otherShelf = \BookStack\Entities\Bookshelf::first();
316 $ownShelf = $this->newShelf(['name' => 'test-shelf', 'slug' => 'test-shelf']);
317 $ownShelf->forceFill(['created_by' => $this->user->id, 'updated_by' => $this->user->id])->save();
318 $this->regenEntityPermissions($ownShelf);
320 $this->checkAccessPermission('bookshelf-delete-own', [
321 $ownShelf->getUrl('/delete')
323 $ownShelf->getUrl() => 'Delete'
326 $this->visit($otherShelf->getUrl())
327 ->dontSeeInElement('.action-buttons', 'Delete')
328 ->visit($otherShelf->getUrl('/delete'))
330 $this->visit($ownShelf->getUrl())->visit($ownShelf->getUrl('/delete'))
332 ->seePageIs('/shelves')
333 ->dontSee($ownShelf->name);
336 public function test_bookshelves_delete_all_permission()
338 $this->giveUserPermissions($this->user, ['bookshelf-update-all']);
339 $otherShelf = \BookStack\Entities\Bookshelf::first();
340 $this->checkAccessPermission('bookshelf-delete-all', [
341 $otherShelf->getUrl('/delete')
343 $otherShelf->getUrl() => 'Delete'
346 $this->visit($otherShelf->getUrl())->visit($otherShelf->getUrl('/delete'))
348 ->seePageIs('/shelves')
349 ->dontSee($otherShelf->name);
352 public function test_books_create_all_permissions()
354 $this->checkAccessPermission('book-create-all', [
357 '/books' => 'Create New Book'
360 $this->visit('/create-book')
361 ->type('test book', 'name')
362 ->type('book desc', 'description')
364 ->seePageIs('/books/test-book');
367 public function test_books_edit_own_permission()
369 $otherBook = \BookStack\Entities\Book::take(1)->get()->first();
370 $ownBook = $this->createEntityChainBelongingToUser($this->user)['book'];
371 $this->checkAccessPermission('book-update-own', [
372 $ownBook->getUrl() . '/edit'
374 $ownBook->getUrl() => 'Edit'
377 $this->visit($otherBook->getUrl())
378 ->dontSeeInElement('.action-buttons', 'Edit')
379 ->visit($otherBook->getUrl() . '/edit')
383 public function test_books_edit_all_permission()
385 $otherBook = \BookStack\Entities\Book::take(1)->get()->first();
386 $this->checkAccessPermission('book-update-all', [
387 $otherBook->getUrl() . '/edit'
389 $otherBook->getUrl() => 'Edit'
393 public function test_books_delete_own_permission()
395 $this->giveUserPermissions($this->user, ['book-update-all']);
396 $otherBook = \BookStack\Entities\Book::take(1)->get()->first();
397 $ownBook = $this->createEntityChainBelongingToUser($this->user)['book'];
398 $this->checkAccessPermission('book-delete-own', [
399 $ownBook->getUrl() . '/delete'
401 $ownBook->getUrl() => 'Delete'
404 $this->visit($otherBook->getUrl())
405 ->dontSeeInElement('.action-buttons', 'Delete')
406 ->visit($otherBook->getUrl() . '/delete')
408 $this->visit($ownBook->getUrl())->visit($ownBook->getUrl() . '/delete')
410 ->seePageIs('/books')
411 ->dontSee($ownBook->name);
414 public function test_books_delete_all_permission()
416 $this->giveUserPermissions($this->user, ['book-update-all']);
417 $otherBook = \BookStack\Entities\Book::take(1)->get()->first();
418 $this->checkAccessPermission('book-delete-all', [
419 $otherBook->getUrl() . '/delete'
421 $otherBook->getUrl() => 'Delete'
424 $this->visit($otherBook->getUrl())->visit($otherBook->getUrl() . '/delete')
426 ->seePageIs('/books')
427 ->dontSee($otherBook->name);
430 public function test_chapter_create_own_permissions()
432 $book = \BookStack\Entities\Book::take(1)->get()->first();
433 $ownBook = $this->createEntityChainBelongingToUser($this->user)['book'];
434 $this->checkAccessPermission('chapter-create-own', [
435 $ownBook->getUrl('/create-chapter')
437 $ownBook->getUrl() => 'New Chapter'
440 $this->visit($ownBook->getUrl('/create-chapter'))
441 ->type('test chapter', 'name')
442 ->type('chapter desc', 'description')
443 ->press('Save Chapter')
444 ->seePageIs($ownBook->getUrl('/chapter/test-chapter'));
446 $this->visit($book->getUrl())
447 ->dontSeeInElement('.action-buttons', 'New Chapter')
448 ->visit($book->getUrl('/create-chapter'))
452 public function test_chapter_create_all_permissions()
454 $book = \BookStack\Entities\Book::take(1)->get()->first();
455 $this->checkAccessPermission('chapter-create-all', [
456 $book->getUrl('/create-chapter')
458 $book->getUrl() => 'New Chapter'
461 $this->visit($book->getUrl('/create-chapter'))
462 ->type('test chapter', 'name')
463 ->type('chapter desc', 'description')
464 ->press('Save Chapter')
465 ->seePageIs($book->getUrl('/chapter/test-chapter'));
468 public function test_chapter_edit_own_permission()
470 $otherChapter = \BookStack\Entities\Chapter::take(1)->get()->first();
471 $ownChapter = $this->createEntityChainBelongingToUser($this->user)['chapter'];
472 $this->checkAccessPermission('chapter-update-own', [
473 $ownChapter->getUrl() . '/edit'
475 $ownChapter->getUrl() => 'Edit'
478 $this->visit($otherChapter->getUrl())
479 ->dontSeeInElement('.action-buttons', 'Edit')
480 ->visit($otherChapter->getUrl() . '/edit')
484 public function test_chapter_edit_all_permission()
486 $otherChapter = \BookStack\Entities\Chapter::take(1)->get()->first();
487 $this->checkAccessPermission('chapter-update-all', [
488 $otherChapter->getUrl() . '/edit'
490 $otherChapter->getUrl() => 'Edit'
494 public function test_chapter_delete_own_permission()
496 $this->giveUserPermissions($this->user, ['chapter-update-all']);
497 $otherChapter = \BookStack\Entities\Chapter::take(1)->get()->first();
498 $ownChapter = $this->createEntityChainBelongingToUser($this->user)['chapter'];
499 $this->checkAccessPermission('chapter-delete-own', [
500 $ownChapter->getUrl() . '/delete'
502 $ownChapter->getUrl() => 'Delete'
505 $bookUrl = $ownChapter->book->getUrl();
506 $this->visit($otherChapter->getUrl())
507 ->dontSeeInElement('.action-buttons', 'Delete')
508 ->visit($otherChapter->getUrl() . '/delete')
510 $this->visit($ownChapter->getUrl())->visit($ownChapter->getUrl() . '/delete')
512 ->seePageIs($bookUrl)
513 ->dontSeeInElement('.book-content', $ownChapter->name);
516 public function test_chapter_delete_all_permission()
518 $this->giveUserPermissions($this->user, ['chapter-update-all']);
519 $otherChapter = \BookStack\Entities\Chapter::take(1)->get()->first();
520 $this->checkAccessPermission('chapter-delete-all', [
521 $otherChapter->getUrl() . '/delete'
523 $otherChapter->getUrl() => 'Delete'
526 $bookUrl = $otherChapter->book->getUrl();
527 $this->visit($otherChapter->getUrl())->visit($otherChapter->getUrl() . '/delete')
529 ->seePageIs($bookUrl)
530 ->dontSeeInElement('.book-content', $otherChapter->name);
533 public function test_page_create_own_permissions()
535 $book = \BookStack\Entities\Book::first();
536 $chapter = \BookStack\Entities\Chapter::first();
538 $entities = $this->createEntityChainBelongingToUser($this->user);
539 $ownBook = $entities['book'];
540 $ownChapter = $entities['chapter'];
542 $createUrl = $ownBook->getUrl('/create-page');
543 $createUrlChapter = $ownChapter->getUrl('/create-page');
544 $accessUrls = [$createUrl, $createUrlChapter];
546 foreach ($accessUrls as $url) {
547 $this->actingAs($this->user)->visit($url)
551 $this->checkAccessPermission('page-create-own', [], [
552 $ownBook->getUrl() => 'New Page',
553 $ownChapter->getUrl() => 'New Page'
556 $this->giveUserPermissions($this->user, ['page-create-own']);
558 foreach ($accessUrls as $index => $url) {
559 $this->actingAs($this->user)->visit($url);
560 $expectedUrl = \BookStack\Entities\Page::where('draft', '=', true)->orderBy('id', 'desc')->first()->getUrl();
561 $this->seePageIs($expectedUrl);
564 $this->visit($createUrl)
565 ->type('test page', 'name')
566 ->type('page desc', 'html')
568 ->seePageIs($ownBook->getUrl('/page/test-page'));
570 $this->visit($book->getUrl())
571 ->dontSeeInElement('.action-buttons', 'New Page')
572 ->visit($book->getUrl() . '/create-page')
574 $this->visit($chapter->getUrl())
575 ->dontSeeInElement('.action-buttons', 'New Page')
576 ->visit($chapter->getUrl() . '/create-page')
580 public function test_page_create_all_permissions()
582 $book = \BookStack\Entities\Book::take(1)->get()->first();
583 $chapter = \BookStack\Entities\Chapter::take(1)->get()->first();
584 $baseUrl = $book->getUrl() . '/page';
585 $createUrl = $book->getUrl('/create-page');
587 $createUrlChapter = $chapter->getUrl('/create-page');
588 $accessUrls = [$createUrl, $createUrlChapter];
590 foreach ($accessUrls as $url) {
591 $this->actingAs($this->user)->visit($url)
595 $this->checkAccessPermission('page-create-all', [], [
596 $book->getUrl() => 'New Page',
597 $chapter->getUrl() => 'New Page'
600 $this->giveUserPermissions($this->user, ['page-create-all']);
602 foreach ($accessUrls as $index => $url) {
603 $this->actingAs($this->user)->visit($url);
604 $expectedUrl = \BookStack\Entities\Page::where('draft', '=', true)->orderBy('id', 'desc')->first()->getUrl();
605 $this->seePageIs($expectedUrl);
608 $this->visit($createUrl)
609 ->type('test page', 'name')
610 ->type('page desc', 'html')
612 ->seePageIs($book->getUrl('/page/test-page'));
614 $this->visit($chapter->getUrl('/create-page'))
615 ->type('new test page', 'name')
616 ->type('page desc', 'html')
618 ->seePageIs($book->getUrl('/page/new-test-page'));
621 public function test_page_edit_own_permission()
623 $otherPage = \BookStack\Entities\Page::take(1)->get()->first();
624 $ownPage = $this->createEntityChainBelongingToUser($this->user)['page'];
625 $this->checkAccessPermission('page-update-own', [
626 $ownPage->getUrl() . '/edit'
628 $ownPage->getUrl() => 'Edit'
631 $this->visit($otherPage->getUrl())
632 ->dontSeeInElement('.action-buttons', 'Edit')
633 ->visit($otherPage->getUrl() . '/edit')
637 public function test_page_edit_all_permission()
639 $otherPage = \BookStack\Entities\Page::take(1)->get()->first();
640 $this->checkAccessPermission('page-update-all', [
641 $otherPage->getUrl() . '/edit'
643 $otherPage->getUrl() => 'Edit'
647 public function test_page_delete_own_permission()
649 $this->giveUserPermissions($this->user, ['page-update-all']);
650 $otherPage = \BookStack\Entities\Page::take(1)->get()->first();
651 $ownPage = $this->createEntityChainBelongingToUser($this->user)['page'];
652 $this->checkAccessPermission('page-delete-own', [
653 $ownPage->getUrl() . '/delete'
655 $ownPage->getUrl() => 'Delete'
658 $parent = $ownPage->chapter ?? $ownPage->book;
659 $this->visit($otherPage->getUrl())
660 ->dontSeeInElement('.action-buttons', 'Delete')
661 ->visit($otherPage->getUrl() . '/delete')
663 $this->visit($ownPage->getUrl())->visit($ownPage->getUrl() . '/delete')
665 ->seePageIs($parent->getUrl())
666 ->dontSeeInElement('.book-content', $ownPage->name);
669 public function test_page_delete_all_permission()
671 $this->giveUserPermissions($this->user, ['page-update-all']);
672 $otherPage = \BookStack\Entities\Page::take(1)->get()->first();
673 $this->checkAccessPermission('page-delete-all', [
674 $otherPage->getUrl() . '/delete'
676 $otherPage->getUrl() => 'Delete'
679 $parent = $otherPage->chapter ?? $otherPage->book;
680 $this->visit($otherPage->getUrl())->visit($otherPage->getUrl() . '/delete')
682 ->seePageIs($parent->getUrl())
683 ->dontSeeInElement('.book-content', $otherPage->name);
686 public function test_public_role_visible_in_user_edit_screen()
688 $user = \BookStack\Auth\User::first();
689 $adminRole = Role::getSystemRole('admin');
690 $publicRole = Role::getSystemRole('public');
691 $this->asAdmin()->visit('/settings/users/' . $user->id)
692 ->seeElement('[name="roles['.$adminRole->id.']"]')
693 ->seeElement('[name="roles['.$publicRole->id.']"]');
696 public function test_public_role_visible_in_role_listing()
698 $this->asAdmin()->visit('/settings/roles')
703 public function test_public_role_visible_in_default_role_setting()
705 $this->asAdmin()->visit('/settings')
706 ->seeElement('[data-system-role-name="admin"]')
707 ->seeElement('[data-system-role-name="public"]');
710 public function test_public_role_not_deleteable()
712 $this->asAdmin()->visit('/settings/roles')
715 ->click('Delete Role')
718 ->see('Cannot be deleted');
721 public function test_image_delete_own_permission()
723 $this->giveUserPermissions($this->user, ['image-update-all']);
724 $page = \BookStack\Entities\Page::first();
725 $image = factory(\BookStack\Uploads\Image::class)->create(['uploaded_to' => $page->id, 'created_by' => $this->user->id, 'updated_by' => $this->user->id]);
727 $this->actingAs($this->user)->json('delete', '/images/' . $image->id)
728 ->seeStatusCode(403);
730 $this->giveUserPermissions($this->user, ['image-delete-own']);
732 $this->actingAs($this->user)->json('delete', '/images/' . $image->id)
734 ->dontSeeInDatabase('images', ['id' => $image->id]);
737 public function test_image_delete_all_permission()
739 $this->giveUserPermissions($this->user, ['image-update-all']);
740 $admin = $this->getAdmin();
741 $page = \BookStack\Entities\Page::first();
742 $image = factory(\BookStack\Uploads\Image::class)->create(['uploaded_to' => $page->id, 'created_by' => $admin->id, 'updated_by' => $admin->id]);
744 $this->actingAs($this->user)->json('delete', '/images/' . $image->id)
745 ->seeStatusCode(403);
747 $this->giveUserPermissions($this->user, ['image-delete-own']);
749 $this->actingAs($this->user)->json('delete', '/images/' . $image->id)
750 ->seeStatusCode(403);
752 $this->giveUserPermissions($this->user, ['image-delete-all']);
754 $this->actingAs($this->user)->json('delete', '/images/' . $image->id)
756 ->dontSeeInDatabase('images', ['id' => $image->id]);
759 public function test_role_permission_removal()
761 // To cover issue fixed in f99c8ff99aee9beb8c692f36d4b84dc6e651e50a.
762 $page = Page::first();
763 $viewerRole = \BookStack\Auth\Role::getRole('viewer');
764 $viewer = $this->getViewer();
765 $this->actingAs($viewer)->visit($page->getUrl())->assertResponseStatus(200);
767 $this->asAdmin()->put('/settings/roles/' . $viewerRole->id, [
768 'display_name' => $viewerRole->display_name,
769 'description' => $viewerRole->description,
771 ])->assertResponseStatus(302);
773 $this->expectException(HttpException::class);
774 $this->actingAs($viewer)->visit($page->getUrl())->assertResponseStatus(404);
777 public function test_empty_state_actions_not_visible_without_permission()
779 $admin = $this->getAdmin();
781 $book = factory(\BookStack\Entities\Book::class)->create(['created_by' => $admin->id, 'updated_by' => $admin->id]);
782 $this->updateEntityPermissions($book);
783 $this->actingAs($this->getViewer())->visit($book->getUrl())
784 ->dontSee('Create a new page')
785 ->dontSee('Add a chapter');
788 $chapter = factory(\BookStack\Entities\Chapter::class)->create(['created_by' => $admin->id, 'updated_by' => $admin->id, 'book_id' => $book->id]);
789 $this->updateEntityPermissions($chapter);
790 $this->actingAs($this->getViewer())->visit($chapter->getUrl())
791 ->dontSee('Create a new page')
792 ->dontSee('Sort the current book');
795 public function test_comment_create_permission () {
796 $ownPage = $this->createEntityChainBelongingToUser($this->user)['page'];
798 $this->actingAs($this->user)->addComment($ownPage);
800 $this->assertResponseStatus(403);
802 $this->giveUserPermissions($this->user, ['comment-create-all']);
804 $this->actingAs($this->user)->addComment($ownPage);
805 $this->assertResponseStatus(200);
809 public function test_comment_update_own_permission () {
810 $ownPage = $this->createEntityChainBelongingToUser($this->user)['page'];
811 $this->giveUserPermissions($this->user, ['comment-create-all']);
812 $commentId = $this->actingAs($this->user)->addComment($ownPage);
814 // no comment-update-own
815 $this->actingAs($this->user)->updateComment($commentId);
816 $this->assertResponseStatus(403);
818 $this->giveUserPermissions($this->user, ['comment-update-own']);
820 // now has comment-update-own
821 $this->actingAs($this->user)->updateComment($commentId);
822 $this->assertResponseStatus(200);
825 public function test_comment_update_all_permission () {
826 $ownPage = $this->createEntityChainBelongingToUser($this->user)['page'];
827 $commentId = $this->asAdmin()->addComment($ownPage);
829 // no comment-update-all
830 $this->actingAs($this->user)->updateComment($commentId);
831 $this->assertResponseStatus(403);
833 $this->giveUserPermissions($this->user, ['comment-update-all']);
835 // now has comment-update-all
836 $this->actingAs($this->user)->updateComment($commentId);
837 $this->assertResponseStatus(200);
840 public function test_comment_delete_own_permission () {
841 $ownPage = $this->createEntityChainBelongingToUser($this->user)['page'];
842 $this->giveUserPermissions($this->user, ['comment-create-all']);
843 $commentId = $this->actingAs($this->user)->addComment($ownPage);
845 // no comment-delete-own
846 $this->actingAs($this->user)->deleteComment($commentId);
847 $this->assertResponseStatus(403);
849 $this->giveUserPermissions($this->user, ['comment-delete-own']);
851 // now has comment-update-own
852 $this->actingAs($this->user)->deleteComment($commentId);
853 $this->assertResponseStatus(200);
856 public function test_comment_delete_all_permission () {
857 $ownPage = $this->createEntityChainBelongingToUser($this->user)['page'];
858 $commentId = $this->asAdmin()->addComment($ownPage);
860 // no comment-delete-all
861 $this->actingAs($this->user)->deleteComment($commentId);
862 $this->assertResponseStatus(403);
864 $this->giveUserPermissions($this->user, ['comment-delete-all']);
866 // now has comment-delete-all
867 $this->actingAs($this->user)->deleteComment($commentId);
868 $this->assertResponseStatus(200);
871 private function addComment($page) {
872 $comment = factory(\BookStack\Actions\Comment::class)->make();
873 $url = "/comment/$page->id";
875 'text' => $comment->text,
876 'html' => $comment->html
879 $this->postJson($url, $request);
880 $comment = $page->comments()->first();
881 return $comment === null ? null : $comment->id;
884 private function updateComment($commentId) {
885 $comment = factory(\BookStack\Actions\Comment::class)->make();
886 $url = "/comment/$commentId";
888 'text' => $comment->text,
889 'html' => $comment->html
892 return $this->putJson($url, $request);
895 private function deleteComment($commentId) {
896 $url = '/comment/' . $commentId;
897 return $this->json('DELETE', $url);