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