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