]> BookStack Code Mirror - bookstack/blob - tests/Permissions/RolesTest.php
Merge branch 'master' of git://github.com/osmansorkar/BookStack into osmansorkar...
[bookstack] / tests / Permissions / RolesTest.php
1 <?php namespace Tests\Permissions;
2
3 use BookStack\Entities\Bookshelf;
4 use BookStack\Entities\Page;
5 use BookStack\Auth\Permissions\PermissionsRepo;
6 use BookStack\Auth\Role;
7 use Laravel\BrowserKitTesting\HttpException;
8 use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
9 use Tests\BrowserKitTest;
10
11 class RolesTest extends BrowserKitTest
12 {
13     protected $user;
14
15     public function setUp(): void
16     {
17         parent::setUp();
18         $this->user = $this->getViewer();
19     }
20
21     public function test_admin_can_see_settings()
22     {
23         $this->asAdmin()->visit('/settings')->see('Settings');
24     }
25
26     public function test_cannot_delete_admin_role()
27     {
28         $adminRole = \BookStack\Auth\Role::getRole('admin');
29         $deletePageUrl = '/settings/roles/delete/' . $adminRole->id;
30         $this->asAdmin()->visit($deletePageUrl)
31             ->press('Confirm')
32             ->seePageIs($deletePageUrl)
33             ->see('cannot be deleted');
34     }
35
36     public function test_role_cannot_be_deleted_if_default()
37     {
38         $newRole = $this->createNewRole();
39         $this->setSettings(['registration-role' => $newRole->id]);
40
41         $deletePageUrl = '/settings/roles/delete/' . $newRole->id;
42         $this->asAdmin()->visit($deletePageUrl)
43             ->press('Confirm')
44             ->seePageIs($deletePageUrl)
45             ->see('cannot be deleted');
46     }
47
48     public function test_role_create_update_delete_flow()
49     {
50         $testRoleName = 'Test Role';
51         $testRoleDesc = 'a little test description';
52         $testRoleUpdateName = 'An Super Updated role';
53
54         // Creation
55         $this->asAdmin()->visit('/settings')
56             ->click('Roles')
57             ->seePageIs('/settings/roles')
58             ->click('Create New Role')
59             ->type('Test Role', 'display_name')
60             ->type('A little test description', 'description')
61             ->press('Save Role')
62             ->seeInDatabase('roles', ['display_name' => $testRoleName, 'name' => 'test-role', 'description' => $testRoleDesc])
63             ->seePageIs('/settings/roles');
64         // Updating
65         $this->asAdmin()->visit('/settings/roles')
66             ->see($testRoleDesc)
67             ->click($testRoleName)
68             ->type($testRoleUpdateName, '#display_name')
69             ->press('Save Role')
70             ->seeInDatabase('roles', ['display_name' => $testRoleUpdateName, 'name' => 'test-role', 'description' => $testRoleDesc])
71             ->seePageIs('/settings/roles');
72         // Deleting
73         $this->asAdmin()->visit('/settings/roles')
74             ->click($testRoleUpdateName)
75             ->click('Delete Role')
76             ->see($testRoleUpdateName)
77             ->press('Confirm')
78             ->seePageIs('/settings/roles')
79             ->dontSee($testRoleUpdateName);
80     }
81
82     public function test_admin_role_cannot_be_removed_if_last_admin()
83     {
84         $adminRole = Role::where('system_name', '=', 'admin')->first();
85         $adminUser = $this->getAdmin();
86         $adminRole->users()->where('id', '!=', $adminUser->id)->delete();
87         $this->assertEquals($adminRole->users()->count(), 1);
88
89         $viewerRole = $this->getViewer()->roles()->first();
90
91         $editUrl = '/settings/users/' . $adminUser->id;
92         $this->actingAs($adminUser)->put($editUrl, [
93             'name' => $adminUser->name,
94             'email' => $adminUser->email,
95             'roles' => [
96                 'viewer' => strval($viewerRole->id),
97             ]
98         ])->followRedirects();
99
100         $this->seePageIs($editUrl);
101         $this->see('This user is the only user assigned to the administrator role');
102     }
103
104     public function test_manage_user_permission()
105     {
106         $this->actingAs($this->user)->visit('/settings/users')
107             ->seePageIs('/');
108         $this->giveUserPermissions($this->user, ['users-manage']);
109         $this->actingAs($this->user)->visit('/settings/users')
110             ->seePageIs('/settings/users');
111     }
112
113     public function test_manage_users_permission_shows_link_in_header_if_does_not_have_settings_manage_permision()
114     {
115         $usersLink = 'href="'.url('/settings/users') . '"';
116         $this->actingAs($this->user)->visit('/')->dontSee($usersLink);
117         $this->giveUserPermissions($this->user, ['users-manage']);
118         $this->actingAs($this->user)->visit('/')->see($usersLink);
119         $this->giveUserPermissions($this->user, ['settings-manage', 'users-manage']);
120         $this->actingAs($this->user)->visit('/')->dontSee($usersLink);
121     }
122
123     public function test_user_cannot_change_email_unless_they_have_manage_users_permission()
124     {
125         $userProfileUrl = '/settings/users/' . $this->user->id;
126         $originalEmail = $this->user->email;
127         $this->actingAs($this->user);
128
129         $this->visit($userProfileUrl)
130             ->assertResponseOk()
131             ->seeElement('input[name=email][disabled]');
132         $this->put($userProfileUrl, [
133             'name' => 'my_new_name',
134             'email' => '[email protected]',
135         ]);
136         $this->seeInDatabase('users', [
137             'id' => $this->user->id,
138             'email' => $originalEmail,
139             'name' => 'my_new_name',
140         ]);
141
142         $this->giveUserPermissions($this->user, ['users-manage']);
143
144         $this->visit($userProfileUrl)
145             ->assertResponseOk()
146             ->dontSeeElement('input[name=email][disabled]')
147             ->seeElement('input[name=email]');
148         $this->put($userProfileUrl, [
149             'name' => 'my_new_name_2',
150             'email' => '[email protected]',
151         ]);
152
153         $this->seeInDatabase('users', [
154             'id' => $this->user->id,
155             'email' => '[email protected]',
156             'name' => 'my_new_name_2',
157         ]);
158     }
159
160     public function test_user_roles_manage_permission()
161     {
162         $this->actingAs($this->user)->visit('/settings/roles')
163             ->seePageIs('/')->visit('/settings/roles/1')->seePageIs('/');
164         $this->giveUserPermissions($this->user, ['user-roles-manage']);
165         $this->actingAs($this->user)->visit('/settings/roles')
166             ->seePageIs('/settings/roles')->click('Admin')
167             ->see('Edit Role');
168     }
169
170     public function test_settings_manage_permission()
171     {
172         $this->actingAs($this->user)->visit('/settings')
173             ->seePageIs('/');
174         $this->giveUserPermissions($this->user, ['settings-manage']);
175         $this->actingAs($this->user)->visit('/settings')
176             ->seePageIs('/settings')->press('Save Settings')->see('Settings Saved');
177     }
178
179     public function test_restrictions_manage_all_permission()
180     {
181         $page = \BookStack\Entities\Page::take(1)->get()->first();
182         $this->actingAs($this->user)->visit($page->getUrl())
183             ->dontSee('Permissions')
184             ->visit($page->getUrl() . '/permissions')
185             ->seePageIs('/');
186         $this->giveUserPermissions($this->user, ['restrictions-manage-all']);
187         $this->actingAs($this->user)->visit($page->getUrl())
188             ->see('Permissions')
189             ->click('Permissions')
190             ->see('Page Permissions')->seePageIs($page->getUrl() . '/permissions');
191     }
192
193     public function test_restrictions_manage_own_permission()
194     {
195         $otherUsersPage = \BookStack\Entities\Page::first();
196         $content = $this->createEntityChainBelongingToUser($this->user);
197         // Check can't restrict other's content
198         $this->actingAs($this->user)->visit($otherUsersPage->getUrl())
199             ->dontSee('Permissions')
200             ->visit($otherUsersPage->getUrl() . '/permissions')
201             ->seePageIs('/');
202         // Check can't restrict own content
203         $this->actingAs($this->user)->visit($content['page']->getUrl())
204             ->dontSee('Permissions')
205             ->visit($content['page']->getUrl() . '/permissions')
206             ->seePageIs('/');
207
208         $this->giveUserPermissions($this->user, ['restrictions-manage-own']);
209
210         // Check can't restrict other's content
211         $this->actingAs($this->user)->visit($otherUsersPage->getUrl())
212             ->dontSee('Permissions')
213             ->visit($otherUsersPage->getUrl() . '/permissions')
214             ->seePageIs('/');
215         // Check can restrict own content
216         $this->actingAs($this->user)->visit($content['page']->getUrl())
217             ->see('Permissions')
218             ->click('Permissions')
219             ->seePageIs($content['page']->getUrl() . '/permissions');
220     }
221
222     /**
223      * Check a standard entity access permission
224      * @param string $permission
225      * @param array $accessUrls Urls that are only accessible after having the permission
226      * @param array $visibles Check this text, In the buttons toolbar, is only visible with the permission
227      */
228     private function checkAccessPermission($permission, $accessUrls = [], $visibles = [])
229     {
230         foreach ($accessUrls as $url) {
231             $this->actingAs($this->user)->visit($url)
232                 ->seePageIs('/');
233         }
234         foreach ($visibles as $url => $text) {
235             $this->actingAs($this->user)->visit($url)
236                 ->dontSeeInElement('.action-buttons',$text);
237         }
238
239         $this->giveUserPermissions($this->user, [$permission]);
240
241         foreach ($accessUrls as $url) {
242             $this->actingAs($this->user)->visit($url)
243                 ->seePageIs($url);
244         }
245         foreach ($visibles as $url => $text) {
246             $this->actingAs($this->user)->visit($url)
247                 ->see($text);
248         }
249     }
250
251     public function test_bookshelves_create_all_permissions()
252     {
253         $this->checkAccessPermission('bookshelf-create-all', [
254             '/create-shelf'
255         ], [
256             '/shelves' => 'New Shelf'
257         ]);
258
259         $this->visit('/create-shelf')
260             ->type('test shelf', 'name')
261             ->type('shelf desc', 'description')
262             ->press('Save Shelf')
263             ->seePageIs('/shelves/test-shelf');
264     }
265
266     public function test_bookshelves_edit_own_permission()
267     {
268         $otherShelf = Bookshelf::first();
269         $ownShelf = $this->newShelf(['name' => 'test-shelf', 'slug' => 'test-shelf']);
270         $ownShelf->forceFill(['created_by' => $this->user->id, 'updated_by' => $this->user->id])->save();
271         $this->regenEntityPermissions($ownShelf);
272
273         $this->checkAccessPermission('bookshelf-update-own', [
274             $ownShelf->getUrl('/edit')
275         ], [
276             $ownShelf->getUrl() => 'Edit'
277         ]);
278
279         $this->visit($otherShelf->getUrl())
280             ->dontSeeInElement('.action-buttons', 'Edit')
281             ->visit($otherShelf->getUrl('/edit'))
282             ->seePageIs('/');
283     }
284
285     public function test_bookshelves_edit_all_permission()
286     {
287         $otherShelf = \BookStack\Entities\Bookshelf::first();
288         $this->checkAccessPermission('bookshelf-update-all', [
289             $otherShelf->getUrl('/edit')
290         ], [
291             $otherShelf->getUrl() => 'Edit'
292         ]);
293     }
294
295     public function test_bookshelves_delete_own_permission()
296     {
297         $this->giveUserPermissions($this->user, ['bookshelf-update-all']);
298         $otherShelf = \BookStack\Entities\Bookshelf::first();
299         $ownShelf = $this->newShelf(['name' => 'test-shelf', 'slug' => 'test-shelf']);
300         $ownShelf->forceFill(['created_by' => $this->user->id, 'updated_by' => $this->user->id])->save();
301         $this->regenEntityPermissions($ownShelf);
302
303         $this->checkAccessPermission('bookshelf-delete-own', [
304             $ownShelf->getUrl('/delete')
305         ], [
306             $ownShelf->getUrl() => 'Delete'
307         ]);
308
309         $this->visit($otherShelf->getUrl())
310             ->dontSeeInElement('.action-buttons', 'Delete')
311             ->visit($otherShelf->getUrl('/delete'))
312             ->seePageIs('/');
313         $this->visit($ownShelf->getUrl())->visit($ownShelf->getUrl('/delete'))
314             ->press('Confirm')
315             ->seePageIs('/shelves')
316             ->dontSee($ownShelf->name);
317     }
318
319     public function test_bookshelves_delete_all_permission()
320     {
321         $this->giveUserPermissions($this->user, ['bookshelf-update-all']);
322         $otherShelf = \BookStack\Entities\Bookshelf::first();
323         $this->checkAccessPermission('bookshelf-delete-all', [
324             $otherShelf->getUrl('/delete')
325         ], [
326             $otherShelf->getUrl() => 'Delete'
327         ]);
328
329         $this->visit($otherShelf->getUrl())->visit($otherShelf->getUrl('/delete'))
330             ->press('Confirm')
331             ->seePageIs('/shelves')
332             ->dontSee($otherShelf->name);
333     }
334
335     public function test_books_create_all_permissions()
336     {
337         $this->checkAccessPermission('book-create-all', [
338             '/create-book'
339         ], [
340             '/books' => 'Create New Book'
341         ]);
342
343         $this->visit('/create-book')
344             ->type('test book', 'name')
345             ->type('book desc', 'description')
346             ->press('Save Book')
347             ->seePageIs('/books/test-book');
348     }
349
350     public function test_books_edit_own_permission()
351     {
352         $otherBook = \BookStack\Entities\Book::take(1)->get()->first();
353         $ownBook = $this->createEntityChainBelongingToUser($this->user)['book'];
354         $this->checkAccessPermission('book-update-own', [
355             $ownBook->getUrl() . '/edit'
356         ], [
357             $ownBook->getUrl() => 'Edit'
358         ]);
359
360         $this->visit($otherBook->getUrl())
361             ->dontSeeInElement('.action-buttons', 'Edit')
362             ->visit($otherBook->getUrl() . '/edit')
363             ->seePageIs('/');
364     }
365
366     public function test_books_edit_all_permission()
367     {
368         $otherBook = \BookStack\Entities\Book::take(1)->get()->first();
369         $this->checkAccessPermission('book-update-all', [
370             $otherBook->getUrl() . '/edit'
371         ], [
372             $otherBook->getUrl() => 'Edit'
373         ]);
374     }
375
376     public function test_books_delete_own_permission()
377     {
378         $this->giveUserPermissions($this->user, ['book-update-all']);
379         $otherBook = \BookStack\Entities\Book::take(1)->get()->first();
380         $ownBook = $this->createEntityChainBelongingToUser($this->user)['book'];
381         $this->checkAccessPermission('book-delete-own', [
382             $ownBook->getUrl() . '/delete'
383         ], [
384             $ownBook->getUrl() => 'Delete'
385         ]);
386
387         $this->visit($otherBook->getUrl())
388             ->dontSeeInElement('.action-buttons', 'Delete')
389             ->visit($otherBook->getUrl() . '/delete')
390             ->seePageIs('/');
391         $this->visit($ownBook->getUrl())->visit($ownBook->getUrl() . '/delete')
392             ->press('Confirm')
393             ->seePageIs('/books')
394             ->dontSee($ownBook->name);
395     }
396
397     public function test_books_delete_all_permission()
398     {
399         $this->giveUserPermissions($this->user, ['book-update-all']);
400         $otherBook = \BookStack\Entities\Book::take(1)->get()->first();
401         $this->checkAccessPermission('book-delete-all', [
402             $otherBook->getUrl() . '/delete'
403         ], [
404             $otherBook->getUrl() => 'Delete'
405         ]);
406
407         $this->visit($otherBook->getUrl())->visit($otherBook->getUrl() . '/delete')
408             ->press('Confirm')
409             ->seePageIs('/books')
410             ->dontSee($otherBook->name);
411     }
412
413     public function test_chapter_create_own_permissions()
414     {
415         $book = \BookStack\Entities\Book::take(1)->get()->first();
416         $ownBook = $this->createEntityChainBelongingToUser($this->user)['book'];
417         $this->checkAccessPermission('chapter-create-own', [
418             $ownBook->getUrl('/create-chapter')
419         ], [
420             $ownBook->getUrl() => 'New Chapter'
421         ]);
422
423         $this->visit($ownBook->getUrl('/create-chapter'))
424             ->type('test chapter', 'name')
425             ->type('chapter desc', 'description')
426             ->press('Save Chapter')
427             ->seePageIs($ownBook->getUrl('/chapter/test-chapter'));
428
429         $this->visit($book->getUrl())
430             ->dontSeeInElement('.action-buttons', 'New Chapter')
431             ->visit($book->getUrl('/create-chapter'))
432             ->seePageIs('/');
433     }
434
435     public function test_chapter_create_all_permissions()
436     {
437         $book = \BookStack\Entities\Book::take(1)->get()->first();
438         $this->checkAccessPermission('chapter-create-all', [
439             $book->getUrl('/create-chapter')
440         ], [
441             $book->getUrl() => 'New Chapter'
442         ]);
443
444         $this->visit($book->getUrl('/create-chapter'))
445             ->type('test chapter', 'name')
446             ->type('chapter desc', 'description')
447             ->press('Save Chapter')
448             ->seePageIs($book->getUrl('/chapter/test-chapter'));
449     }
450
451     public function test_chapter_edit_own_permission()
452     {
453         $otherChapter = \BookStack\Entities\Chapter::take(1)->get()->first();
454         $ownChapter = $this->createEntityChainBelongingToUser($this->user)['chapter'];
455         $this->checkAccessPermission('chapter-update-own', [
456             $ownChapter->getUrl() . '/edit'
457         ], [
458             $ownChapter->getUrl() => 'Edit'
459         ]);
460
461         $this->visit($otherChapter->getUrl())
462             ->dontSeeInElement('.action-buttons', 'Edit')
463             ->visit($otherChapter->getUrl() . '/edit')
464             ->seePageIs('/');
465     }
466
467     public function test_chapter_edit_all_permission()
468     {
469         $otherChapter = \BookStack\Entities\Chapter::take(1)->get()->first();
470         $this->checkAccessPermission('chapter-update-all', [
471             $otherChapter->getUrl() . '/edit'
472         ], [
473             $otherChapter->getUrl() => 'Edit'
474         ]);
475     }
476
477     public function test_chapter_delete_own_permission()
478     {
479         $this->giveUserPermissions($this->user, ['chapter-update-all']);
480         $otherChapter = \BookStack\Entities\Chapter::take(1)->get()->first();
481         $ownChapter = $this->createEntityChainBelongingToUser($this->user)['chapter'];
482         $this->checkAccessPermission('chapter-delete-own', [
483             $ownChapter->getUrl() . '/delete'
484         ], [
485             $ownChapter->getUrl() => 'Delete'
486         ]);
487
488         $bookUrl = $ownChapter->book->getUrl();
489         $this->visit($otherChapter->getUrl())
490             ->dontSeeInElement('.action-buttons', 'Delete')
491             ->visit($otherChapter->getUrl() . '/delete')
492             ->seePageIs('/');
493         $this->visit($ownChapter->getUrl())->visit($ownChapter->getUrl() . '/delete')
494             ->press('Confirm')
495             ->seePageIs($bookUrl)
496             ->dontSeeInElement('.book-content', $ownChapter->name);
497     }
498
499     public function test_chapter_delete_all_permission()
500     {
501         $this->giveUserPermissions($this->user, ['chapter-update-all']);
502         $otherChapter = \BookStack\Entities\Chapter::take(1)->get()->first();
503         $this->checkAccessPermission('chapter-delete-all', [
504             $otherChapter->getUrl() . '/delete'
505         ], [
506             $otherChapter->getUrl() => 'Delete'
507         ]);
508
509         $bookUrl = $otherChapter->book->getUrl();
510         $this->visit($otherChapter->getUrl())->visit($otherChapter->getUrl() . '/delete')
511             ->press('Confirm')
512             ->seePageIs($bookUrl)
513             ->dontSeeInElement('.book-content', $otherChapter->name);
514     }
515
516     public function test_page_create_own_permissions()
517     {
518         $book = \BookStack\Entities\Book::first();
519         $chapter = \BookStack\Entities\Chapter::first();
520
521         $entities = $this->createEntityChainBelongingToUser($this->user);
522         $ownBook = $entities['book'];
523         $ownChapter = $entities['chapter'];
524
525         $createUrl = $ownBook->getUrl('/create-page');
526         $createUrlChapter = $ownChapter->getUrl('/create-page');
527         $accessUrls = [$createUrl, $createUrlChapter];
528
529         foreach ($accessUrls as $url) {
530             $this->actingAs($this->user)->visit($url)
531                 ->seePageIs('/');
532         }
533
534         $this->checkAccessPermission('page-create-own', [], [
535             $ownBook->getUrl() => 'New Page',
536             $ownChapter->getUrl() => 'New Page'
537         ]);
538
539         $this->giveUserPermissions($this->user, ['page-create-own']);
540
541         foreach ($accessUrls as $index => $url) {
542             $this->actingAs($this->user)->visit($url);
543             $expectedUrl = \BookStack\Entities\Page::where('draft', '=', true)->orderBy('id', 'desc')->first()->getUrl();
544             $this->seePageIs($expectedUrl);
545         }
546
547         $this->visit($createUrl)
548             ->type('test page', 'name')
549             ->type('page desc', 'html')
550             ->press('Save Page')
551             ->seePageIs($ownBook->getUrl('/page/test-page'));
552
553         $this->visit($book->getUrl())
554             ->dontSeeInElement('.action-buttons', 'New Page')
555             ->visit($book->getUrl() . '/create-page')
556             ->seePageIs('/');
557         $this->visit($chapter->getUrl())
558             ->dontSeeInElement('.action-buttons', 'New Page')
559             ->visit($chapter->getUrl() . '/create-page')
560             ->seePageIs('/');
561     }
562
563     public function test_page_create_all_permissions()
564     {
565         $book = \BookStack\Entities\Book::take(1)->get()->first();
566         $chapter = \BookStack\Entities\Chapter::take(1)->get()->first();
567         $baseUrl = $book->getUrl() . '/page';
568         $createUrl = $book->getUrl('/create-page');
569
570         $createUrlChapter = $chapter->getUrl('/create-page');
571         $accessUrls = [$createUrl, $createUrlChapter];
572
573         foreach ($accessUrls as $url) {
574             $this->actingAs($this->user)->visit($url)
575                 ->seePageIs('/');
576         }
577
578         $this->checkAccessPermission('page-create-all', [], [
579             $book->getUrl() => 'New Page',
580             $chapter->getUrl() => 'New Page'
581         ]);
582
583         $this->giveUserPermissions($this->user, ['page-create-all']);
584
585         foreach ($accessUrls as $index => $url) {
586             $this->actingAs($this->user)->visit($url);
587             $expectedUrl = \BookStack\Entities\Page::where('draft', '=', true)->orderBy('id', 'desc')->first()->getUrl();
588             $this->seePageIs($expectedUrl);
589         }
590
591         $this->visit($createUrl)
592             ->type('test page', 'name')
593             ->type('page desc', 'html')
594             ->press('Save Page')
595             ->seePageIs($book->getUrl('/page/test-page'));
596
597         $this->visit($chapter->getUrl('/create-page'))
598             ->type('new test page', 'name')
599             ->type('page desc', 'html')
600             ->press('Save Page')
601             ->seePageIs($book->getUrl('/page/new-test-page'));
602     }
603
604     public function test_page_edit_own_permission()
605     {
606         $otherPage = \BookStack\Entities\Page::take(1)->get()->first();
607         $ownPage = $this->createEntityChainBelongingToUser($this->user)['page'];
608         $this->checkAccessPermission('page-update-own', [
609             $ownPage->getUrl() . '/edit'
610         ], [
611             $ownPage->getUrl() => 'Edit'
612         ]);
613
614         $this->visit($otherPage->getUrl())
615             ->dontSeeInElement('.action-buttons', 'Edit')
616             ->visit($otherPage->getUrl() . '/edit')
617             ->seePageIs('/');
618     }
619
620     public function test_page_edit_all_permission()
621     {
622         $otherPage = \BookStack\Entities\Page::take(1)->get()->first();
623         $this->checkAccessPermission('page-update-all', [
624             $otherPage->getUrl() . '/edit'
625         ], [
626             $otherPage->getUrl() => 'Edit'
627         ]);
628     }
629
630     public function test_page_delete_own_permission()
631     {
632         $this->giveUserPermissions($this->user, ['page-update-all']);
633         $otherPage = \BookStack\Entities\Page::take(1)->get()->first();
634         $ownPage = $this->createEntityChainBelongingToUser($this->user)['page'];
635         $this->checkAccessPermission('page-delete-own', [
636             $ownPage->getUrl() . '/delete'
637         ], [
638             $ownPage->getUrl() => 'Delete'
639         ]);
640
641         $parent = $ownPage->chapter ?? $ownPage->book;
642         $this->visit($otherPage->getUrl())
643             ->dontSeeInElement('.action-buttons', 'Delete')
644             ->visit($otherPage->getUrl() . '/delete')
645             ->seePageIs('/');
646         $this->visit($ownPage->getUrl())->visit($ownPage->getUrl() . '/delete')
647             ->press('Confirm')
648             ->seePageIs($parent->getUrl())
649             ->dontSeeInElement('.book-content', $ownPage->name);
650     }
651
652     public function test_page_delete_all_permission()
653     {
654         $this->giveUserPermissions($this->user, ['page-update-all']);
655         $otherPage = \BookStack\Entities\Page::take(1)->get()->first();
656         $this->checkAccessPermission('page-delete-all', [
657             $otherPage->getUrl() . '/delete'
658         ], [
659             $otherPage->getUrl() => 'Delete'
660         ]);
661
662         $parent = $otherPage->chapter ?? $otherPage->book;
663         $this->visit($otherPage->getUrl())->visit($otherPage->getUrl() . '/delete')
664             ->press('Confirm')
665             ->seePageIs($parent->getUrl())
666             ->dontSeeInElement('.book-content', $otherPage->name);
667     }
668
669     public function test_public_role_visible_in_user_edit_screen()
670     {
671         $user = \BookStack\Auth\User::first();
672         $this->asAdmin()->visit('/settings/users/' . $user->id)
673             ->seeElement('[name="roles[admin]"]')
674             ->seeElement('[name="roles[public]"]');
675     }
676
677     public function test_public_role_visible_in_role_listing()
678     {
679         $this->asAdmin()->visit('/settings/roles')
680             ->see('Admin')
681             ->see('Public');
682     }
683
684     public function test_public_role_visible_in_default_role_setting()
685     {
686         $this->asAdmin()->visit('/settings')
687             ->seeElement('[data-role-name="admin"]')
688             ->seeElement('[data-role-name="public"]');
689
690     }
691
692     public function test_public_role_not_deleteable()
693     {
694         $this->asAdmin()->visit('/settings/roles')
695             ->click('Public')
696             ->see('Edit Role')
697             ->click('Delete Role')
698             ->press('Confirm')
699             ->see('Delete Role')
700             ->see('Cannot be deleted');
701     }
702
703     public function test_image_delete_own_permission()
704     {
705         $this->giveUserPermissions($this->user, ['image-update-all']);
706         $page = \BookStack\Entities\Page::first();
707         $image = factory(\BookStack\Uploads\Image::class)->create(['uploaded_to' => $page->id, 'created_by' => $this->user->id, 'updated_by' => $this->user->id]);
708
709         $this->actingAs($this->user)->json('delete', '/images/' . $image->id)
710             ->seeStatusCode(403);
711
712         $this->giveUserPermissions($this->user, ['image-delete-own']);
713
714         $this->actingAs($this->user)->json('delete', '/images/' . $image->id)
715             ->seeStatusCode(200)
716             ->dontSeeInDatabase('images', ['id' => $image->id]);
717     }
718
719     public function test_image_delete_all_permission()
720     {
721         $this->giveUserPermissions($this->user, ['image-update-all']);
722         $admin = $this->getAdmin();
723         $page = \BookStack\Entities\Page::first();
724         $image = factory(\BookStack\Uploads\Image::class)->create(['uploaded_to' => $page->id, 'created_by' => $admin->id, 'updated_by' => $admin->id]);
725
726         $this->actingAs($this->user)->json('delete', '/images/' . $image->id)
727             ->seeStatusCode(403);
728
729         $this->giveUserPermissions($this->user, ['image-delete-own']);
730
731         $this->actingAs($this->user)->json('delete', '/images/' . $image->id)
732             ->seeStatusCode(403);
733
734         $this->giveUserPermissions($this->user, ['image-delete-all']);
735
736         $this->actingAs($this->user)->json('delete', '/images/' . $image->id)
737             ->seeStatusCode(200)
738             ->dontSeeInDatabase('images', ['id' => $image->id]);
739     }
740
741     public function test_role_permission_removal()
742     {
743         // To cover issue fixed in f99c8ff99aee9beb8c692f36d4b84dc6e651e50a.
744         $page = Page::first();
745         $viewerRole = \BookStack\Auth\Role::getRole('viewer');
746         $viewer = $this->getViewer();
747         $this->actingAs($viewer)->visit($page->getUrl())->assertResponseStatus(200);
748
749         $this->asAdmin()->put('/settings/roles/' . $viewerRole->id, [
750             'display_name' => $viewerRole->display_name,
751             'description' => $viewerRole->description,
752             'permission' => []
753         ])->assertResponseStatus(302);
754
755         $this->expectException(HttpException::class);
756         $this->actingAs($viewer)->visit($page->getUrl())->assertResponseStatus(404);
757     }
758
759     public function test_empty_state_actions_not_visible_without_permission()
760     {
761         $admin = $this->getAdmin();
762         // Book links
763         $book = factory(\BookStack\Entities\Book::class)->create(['created_by' => $admin->id, 'updated_by' => $admin->id]);
764         $this->updateEntityPermissions($book);
765         $this->actingAs($this->getViewer())->visit($book->getUrl())
766             ->dontSee('Create a new page')
767             ->dontSee('Add a chapter');
768
769         // Chapter links
770         $chapter = factory(\BookStack\Entities\Chapter::class)->create(['created_by' => $admin->id, 'updated_by' => $admin->id, 'book_id' => $book->id]);
771         $this->updateEntityPermissions($chapter);
772         $this->actingAs($this->getViewer())->visit($chapter->getUrl())
773             ->dontSee('Create a new page')
774             ->dontSee('Sort the current book');
775     }
776
777     public function test_comment_create_permission () {
778         $ownPage = $this->createEntityChainBelongingToUser($this->user)['page'];
779
780         $this->actingAs($this->user)->addComment($ownPage);
781
782         $this->assertResponseStatus(403);
783
784         $this->giveUserPermissions($this->user, ['comment-create-all']);
785
786         $this->actingAs($this->user)->addComment($ownPage);
787         $this->assertResponseStatus(200);
788     }
789
790
791     public function test_comment_update_own_permission () {
792         $ownPage = $this->createEntityChainBelongingToUser($this->user)['page'];
793         $this->giveUserPermissions($this->user, ['comment-create-all']);
794         $commentId = $this->actingAs($this->user)->addComment($ownPage);
795
796         // no comment-update-own
797         $this->actingAs($this->user)->updateComment($commentId);
798         $this->assertResponseStatus(403);
799
800         $this->giveUserPermissions($this->user, ['comment-update-own']);
801
802         // now has comment-update-own
803         $this->actingAs($this->user)->updateComment($commentId);
804         $this->assertResponseStatus(200);
805     }
806
807     public function test_comment_update_all_permission () {
808         $ownPage = $this->createEntityChainBelongingToUser($this->user)['page'];
809         $commentId = $this->asAdmin()->addComment($ownPage);
810
811         // no comment-update-all
812         $this->actingAs($this->user)->updateComment($commentId);
813         $this->assertResponseStatus(403);
814
815         $this->giveUserPermissions($this->user, ['comment-update-all']);
816
817         // now has comment-update-all
818         $this->actingAs($this->user)->updateComment($commentId);
819         $this->assertResponseStatus(200);
820     }
821
822     public function test_comment_delete_own_permission () {
823         $ownPage = $this->createEntityChainBelongingToUser($this->user)['page'];
824         $this->giveUserPermissions($this->user, ['comment-create-all']);
825         $commentId = $this->actingAs($this->user)->addComment($ownPage);
826
827         // no comment-delete-own
828         $this->actingAs($this->user)->deleteComment($commentId);
829         $this->assertResponseStatus(403);
830
831         $this->giveUserPermissions($this->user, ['comment-delete-own']);
832
833         // now has comment-update-own
834         $this->actingAs($this->user)->deleteComment($commentId);
835         $this->assertResponseStatus(200);
836     }
837
838     public function test_comment_delete_all_permission () {
839         $ownPage = $this->createEntityChainBelongingToUser($this->user)['page'];
840         $commentId = $this->asAdmin()->addComment($ownPage);
841
842         // no comment-delete-all
843         $this->actingAs($this->user)->deleteComment($commentId);
844         $this->assertResponseStatus(403);
845
846         $this->giveUserPermissions($this->user, ['comment-delete-all']);
847
848         // now has comment-delete-all
849         $this->actingAs($this->user)->deleteComment($commentId);
850         $this->assertResponseStatus(200);
851     }
852
853     private function addComment($page) {
854         $comment = factory(\BookStack\Actions\Comment::class)->make();
855         $url = "/ajax/page/$page->id/comment";
856         $request = [
857             'text' => $comment->text,
858             'html' => $comment->html
859         ];
860
861         $this->postJson($url, $request);
862         $comment = $page->comments()->first();
863         return $comment === null ? null : $comment->id;
864     }
865
866     private function updateComment($commentId) {
867         $comment = factory(\BookStack\Actions\Comment::class)->make();
868         $url = "/ajax/comment/$commentId";
869         $request = [
870             'text' => $comment->text,
871             'html' => $comment->html
872         ];
873
874         return $this->putJson($url, $request);
875     }
876
877     private function deleteComment($commentId) {
878          $url = '/ajax/comment/' . $commentId;
879          return $this->json('DELETE', $url);
880     }
881
882 }