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