]> BookStack Code Mirror - bookstack/blob - tests/Permissions/RolesTest.php
Added basic system tests for markdown editor, Added extra test helpers
[bookstack] / tests / Permissions / RolesTest.php
1 <?php
2
3 class RolesTest extends TestCase
4 {
5     protected $user;
6
7     public function setUp()
8     {
9         parent::setUp();
10         $this->user = $this->getNewBlankUser();
11     }
12
13     /**
14      * Give the given user some permissions.
15      * @param \BookStack\User $user
16      * @param array $permissions
17      */
18     protected function giveUserPermissions(\BookStack\User $user, $permissions = [])
19     {
20         $newRole = $this->createNewRole($permissions);
21         $user->attachRole($newRole);
22         $user->load('roles');
23         $user->permissions(false);
24     }
25
26     /**
27      * Create a new basic role for testing purposes.
28      * @param array $permissions
29      * @return static
30      */
31     protected function createNewRole($permissions = [])
32     {
33         $permissionRepo = app('BookStack\Repos\PermissionsRepo');
34         $roleData = factory(\BookStack\Role::class)->make()->toArray();
35         $roleData['permissions'] = array_flip($permissions);
36         return $permissionRepo->saveNewRole($roleData);
37     }
38
39     public function test_admin_can_see_settings()
40     {
41         $this->asAdmin()->visit('/settings')->see('Settings');
42     }
43
44     public function test_cannot_delete_admin_role()
45     {
46         $adminRole = \BookStack\Role::getRole('admin');
47         $deletePageUrl = '/settings/roles/delete/' . $adminRole->id;
48         $this->asAdmin()->visit($deletePageUrl)
49             ->press('Confirm')
50             ->seePageIs($deletePageUrl)
51             ->see('cannot be deleted');
52     }
53
54     public function test_role_cannot_be_deleted_if_default()
55     {
56         $newRole = $this->createNewRole();
57         $this->setSettings(['registration-role' => $newRole->id]);
58
59         $deletePageUrl = '/settings/roles/delete/' . $newRole->id;
60         $this->asAdmin()->visit($deletePageUrl)
61             ->press('Confirm')
62             ->seePageIs($deletePageUrl)
63             ->see('cannot be deleted');
64     }
65
66     public function test_role_create_update_delete_flow()
67     {
68         $testRoleName = 'Test Role';
69         $testRoleDesc = 'a little test description';
70         $testRoleUpdateName = 'An Super Updated role';
71
72         // Creation
73         $this->asAdmin()->visit('/settings')
74             ->click('Roles')
75             ->seePageIs('/settings/roles')
76             ->click('Add new role')
77             ->type('Test Role', 'display_name')
78             ->type('A little test description', 'description')
79             ->press('Save Role')
80             ->seeInDatabase('roles', ['display_name' => $testRoleName, 'name' => 'test-role', 'description' => $testRoleDesc])
81             ->seePageIs('/settings/roles');
82         // Updating
83         $this->asAdmin()->visit('/settings/roles')
84             ->see($testRoleDesc)
85             ->click($testRoleName)
86             ->type($testRoleUpdateName, '#display_name')
87             ->press('Save Role')
88             ->seeInDatabase('roles', ['display_name' => $testRoleUpdateName, 'name' => 'test-role', 'description' => $testRoleDesc])
89             ->seePageIs('/settings/roles');
90         // Deleting
91         $this->asAdmin()->visit('/settings/roles')
92             ->click($testRoleUpdateName)
93             ->click('Delete Role')
94             ->see($testRoleUpdateName)
95             ->press('Confirm')
96             ->seePageIs('/settings/roles')
97             ->dontSee($testRoleUpdateName);
98     }
99
100     public function test_manage_user_permission()
101     {
102         $this->actingAs($this->user)->visit('/')->visit('/settings/users')
103             ->seePageIs('/');
104         $this->giveUserPermissions($this->user, ['users-manage']);
105         $this->actingAs($this->user)->visit('/')->visit('/settings/users')
106             ->seePageIs('/settings/users');
107     }
108
109     public function test_user_roles_manage_permission()
110     {
111         $this->actingAs($this->user)->visit('/')->visit('/settings/roles')
112             ->seePageIs('/')->visit('/settings/roles/1')->seePageIs('/');
113         $this->giveUserPermissions($this->user, ['user-roles-manage']);
114         $this->actingAs($this->user)->visit('/settings/roles')
115             ->seePageIs('/settings/roles')->click('Admin')
116             ->see('Edit Role');
117     }
118
119     public function test_settings_manage_permission()
120     {
121         $this->actingAs($this->user)->visit('/')->visit('/settings')
122             ->seePageIs('/');
123         $this->giveUserPermissions($this->user, ['settings-manage']);
124         $this->actingAs($this->user)->visit('/')->visit('/settings')
125             ->seePageIs('/settings')->press('Save Settings')->see('Settings Saved');
126     }
127
128     public function test_restrictions_manage_all_permission()
129     {
130         $page = \BookStack\Page::take(1)->get()->first();
131         $this->actingAs($this->user)->visit($page->getUrl())
132             ->dontSee('Restrict')
133             ->visit($page->getUrl() . '/restrict')
134             ->seePageIs('/');
135         $this->giveUserPermissions($this->user, ['restrictions-manage-all']);
136         $this->actingAs($this->user)->visit($page->getUrl())
137             ->see('Restrict')
138             ->click('Restrict')
139             ->see('Page Restrictions')->seePageIs($page->getUrl() . '/restrict');
140     }
141
142     public function test_restrictions_manage_own_permission()
143     {
144         $otherUsersPage = \BookStack\Page::take(1)->get()->first();
145         $content = $this->createEntityChainBelongingToUser($this->user);
146         // Check can't restrict other's content
147         $this->actingAs($this->user)->visit($otherUsersPage->getUrl())
148             ->dontSee('Restrict')
149             ->visit($otherUsersPage->getUrl() . '/restrict')
150             ->seePageIs('/');
151         // Check can't restrict own content
152         $this->actingAs($this->user)->visit($content['page']->getUrl())
153             ->dontSee('Restrict')
154             ->visit($content['page']->getUrl() . '/restrict')
155             ->seePageIs('/');
156
157         $this->giveUserPermissions($this->user, ['restrictions-manage-own']);
158
159         // Check can't restrict other's content
160         $this->actingAs($this->user)->visit($otherUsersPage->getUrl())
161             ->dontSee('Restrict')
162             ->visit($otherUsersPage->getUrl() . '/restrict')
163             ->seePageIs('/');
164         // Check can restrict own content
165         $this->actingAs($this->user)->visit($content['page']->getUrl())
166             ->see('Restrict')
167             ->click('Restrict')
168             ->seePageIs($content['page']->getUrl() . '/restrict');
169     }
170
171     /**
172      * Check a standard entity access permission
173      * @param string $permission
174      * @param array $accessUrls Urls that are only accessible after having the permission
175      * @param array $visibles Check this text, In the buttons toolbar, is only visible with the permission
176      * @param null $callback
177      */
178     private function checkAccessPermission($permission, $accessUrls = [], $visibles = [])
179     {
180         foreach ($accessUrls as $url) {
181             $this->actingAs($this->user)->visit('/')->visit($url)
182                 ->seePageIs('/');
183         }
184         foreach ($visibles as $url => $text) {
185             $this->actingAs($this->user)->visit('/')->visit($url)
186                 ->dontSeeInElement('.action-buttons',$text);
187         }
188
189         $this->giveUserPermissions($this->user, [$permission]);
190
191         foreach ($accessUrls as $url) {
192             $this->actingAs($this->user)->visit('/')->visit($url)
193                 ->seePageIs($url);
194         }
195         foreach ($visibles as $url => $text) {
196             $this->actingAs($this->user)->visit('/')->visit($url)
197                 ->see($text);
198         }
199     }
200
201     public function test_books_create_all_permissions()
202     {
203         $this->checkAccessPermission('book-create-all', [
204             '/books/create'
205         ], [
206             '/books' => 'Add new book'
207         ]);
208
209         $this->visit('/books/create')
210             ->type('test book', 'name')
211             ->type('book desc', 'description')
212             ->press('Save Book')
213             ->seePageIs('/books/test-book');
214     }
215
216     public function test_books_edit_own_permission()
217     {
218         $otherBook = \BookStack\Book::take(1)->get()->first();
219         $ownBook = $this->createEntityChainBelongingToUser($this->user)['book'];
220         $this->checkAccessPermission('book-update-own', [
221             $ownBook->getUrl() . '/edit'
222         ], [
223             $ownBook->getUrl() => 'Edit'
224         ]);
225
226         $this->visit($otherBook->getUrl())
227             ->dontSeeInElement('.action-buttons', 'Edit')
228             ->visit($otherBook->getUrl() . '/edit')
229             ->seePageIs('/');
230     }
231
232     public function test_books_edit_all_permission()
233     {
234         $otherBook = \BookStack\Book::take(1)->get()->first();
235         $this->checkAccessPermission('book-update-all', [
236             $otherBook->getUrl() . '/edit'
237         ], [
238             $otherBook->getUrl() => 'Edit'
239         ]);
240     }
241
242     public function test_books_delete_own_permission()
243     {
244         $this->giveUserPermissions($this->user, ['book-update-all']);
245         $otherBook = \BookStack\Book::take(1)->get()->first();
246         $ownBook = $this->createEntityChainBelongingToUser($this->user)['book'];
247         $this->checkAccessPermission('book-delete-own', [
248             $ownBook->getUrl() . '/delete'
249         ], [
250             $ownBook->getUrl() => 'Delete'
251         ]);
252
253         $this->visit($otherBook->getUrl())
254             ->dontSeeInElement('.action-buttons', 'Delete')
255             ->visit($otherBook->getUrl() . '/delete')
256             ->seePageIs('/');
257         $this->visit($ownBook->getUrl())->visit($ownBook->getUrl() . '/delete')
258             ->press('Confirm')
259             ->seePageIs('/books')
260             ->dontSee($ownBook->name);
261     }
262
263     public function test_books_delete_all_permission()
264     {
265         $this->giveUserPermissions($this->user, ['book-update-all']);
266         $otherBook = \BookStack\Book::take(1)->get()->first();
267         $this->checkAccessPermission('book-delete-all', [
268             $otherBook->getUrl() . '/delete'
269         ], [
270             $otherBook->getUrl() => 'Delete'
271         ]);
272
273         $this->visit($otherBook->getUrl())->visit($otherBook->getUrl() . '/delete')
274             ->press('Confirm')
275             ->seePageIs('/books')
276             ->dontSee($otherBook->name);
277     }
278
279     public function test_chapter_create_own_permissions()
280     {
281         $book = \BookStack\Book::take(1)->get()->first();
282         $ownBook = $this->createEntityChainBelongingToUser($this->user)['book'];
283         $baseUrl = $ownBook->getUrl() . '/chapter';
284         $this->checkAccessPermission('chapter-create-own', [
285             $baseUrl . '/create'
286         ], [
287             $ownBook->getUrl() => 'New Chapter'
288         ]);
289
290         $this->visit($baseUrl . '/create')
291             ->type('test chapter', 'name')
292             ->type('chapter desc', 'description')
293             ->press('Save Chapter')
294             ->seePageIs($baseUrl . '/test-chapter');
295
296         $this->visit($book->getUrl())
297             ->dontSeeInElement('.action-buttons', 'New Chapter')
298             ->visit($book->getUrl() . '/chapter/create')
299             ->seePageIs('/');
300     }
301
302     public function test_chapter_create_all_permissions()
303     {
304         $book = \BookStack\Book::take(1)->get()->first();
305         $baseUrl = $book->getUrl() . '/chapter';
306         $this->checkAccessPermission('chapter-create-all', [
307             $baseUrl . '/create'
308         ], [
309             $book->getUrl() => 'New Chapter'
310         ]);
311
312         $this->visit($baseUrl . '/create')
313             ->type('test chapter', 'name')
314             ->type('chapter desc', 'description')
315             ->press('Save Chapter')
316             ->seePageIs($baseUrl . '/test-chapter');
317     }
318
319     public function test_chapter_edit_own_permission()
320     {
321         $otherChapter = \BookStack\Chapter::take(1)->get()->first();
322         $ownChapter = $this->createEntityChainBelongingToUser($this->user)['chapter'];
323         $this->checkAccessPermission('chapter-update-own', [
324             $ownChapter->getUrl() . '/edit'
325         ], [
326             $ownChapter->getUrl() => 'Edit'
327         ]);
328
329         $this->visit($otherChapter->getUrl())
330             ->dontSeeInElement('.action-buttons', 'Edit')
331             ->visit($otherChapter->getUrl() . '/edit')
332             ->seePageIs('/');
333     }
334
335     public function test_chapter_edit_all_permission()
336     {
337         $otherChapter = \BookStack\Chapter::take(1)->get()->first();
338         $this->checkAccessPermission('chapter-update-all', [
339             $otherChapter->getUrl() . '/edit'
340         ], [
341             $otherChapter->getUrl() => 'Edit'
342         ]);
343     }
344
345     public function test_chapter_delete_own_permission()
346     {
347         $this->giveUserPermissions($this->user, ['chapter-update-all']);
348         $otherChapter = \BookStack\Chapter::take(1)->get()->first();
349         $ownChapter = $this->createEntityChainBelongingToUser($this->user)['chapter'];
350         $this->checkAccessPermission('chapter-delete-own', [
351             $ownChapter->getUrl() . '/delete'
352         ], [
353             $ownChapter->getUrl() => 'Delete'
354         ]);
355
356         $bookUrl = $ownChapter->book->getUrl();
357         $this->visit($otherChapter->getUrl())
358             ->dontSeeInElement('.action-buttons', 'Delete')
359             ->visit($otherChapter->getUrl() . '/delete')
360             ->seePageIs('/');
361         $this->visit($ownChapter->getUrl())->visit($ownChapter->getUrl() . '/delete')
362             ->press('Confirm')
363             ->seePageIs($bookUrl)
364             ->dontSeeInElement('.book-content', $ownChapter->name);
365     }
366
367     public function test_chapter_delete_all_permission()
368     {
369         $this->giveUserPermissions($this->user, ['chapter-update-all']);
370         $otherChapter = \BookStack\Chapter::take(1)->get()->first();
371         $this->checkAccessPermission('chapter-delete-all', [
372             $otherChapter->getUrl() . '/delete'
373         ], [
374             $otherChapter->getUrl() => 'Delete'
375         ]);
376
377         $bookUrl = $otherChapter->book->getUrl();
378         $this->visit($otherChapter->getUrl())->visit($otherChapter->getUrl() . '/delete')
379             ->press('Confirm')
380             ->seePageIs($bookUrl)
381             ->dontSeeInElement('.book-content', $otherChapter->name);
382     }
383
384     public function test_page_create_own_permissions()
385     {
386         $book = \BookStack\Book::take(1)->get()->first();
387         $chapter = \BookStack\Chapter::take(1)->get()->first();
388
389         $entities = $this->createEntityChainBelongingToUser($this->user);
390         $ownBook = $entities['book'];
391         $ownChapter = $entities['chapter'];
392
393         $baseUrl = $ownBook->getUrl() . '/page';
394
395         $createUrl = $baseUrl . '/create';
396         $createUrlChapter = $ownChapter->getUrl() . '/create-page';
397         $accessUrls = [$createUrl, $createUrlChapter];
398
399         foreach ($accessUrls as $url) {
400             $this->actingAs($this->user)->visit('/')->visit($url)
401                 ->seePageIs('/');
402         }
403
404         $this->checkAccessPermission('page-create-own', [], [
405             $ownBook->getUrl() => 'New Page',
406             $ownChapter->getUrl() => 'New Page'
407         ]);
408
409         $this->giveUserPermissions($this->user, ['page-create-own']);
410
411         foreach ($accessUrls as $index => $url) {
412             $this->actingAs($this->user)->visit('/')->visit($url);
413             $expectedUrl = \BookStack\Page::where('draft', '=', true)->orderBy('id', 'desc')->first()->getUrl();
414             $this->seePageIs($expectedUrl);
415         }
416
417         $this->visit($baseUrl . '/create')
418             ->type('test page', 'name')
419             ->type('page desc', 'html')
420             ->press('Save Page')
421             ->seePageIs($baseUrl . '/test-page');
422
423         $this->visit($book->getUrl())
424             ->dontSeeInElement('.action-buttons', 'New Page')
425             ->visit($book->getUrl() . '/page/create')
426             ->seePageIs('/');
427         $this->visit($chapter->getUrl())
428             ->dontSeeInElement('.action-buttons', 'New Page')
429             ->visit($chapter->getUrl() . '/create-page')
430             ->seePageIs('/');
431     }
432
433     public function test_page_create_all_permissions()
434     {
435         $book = \BookStack\Book::take(1)->get()->first();
436         $chapter = \BookStack\Chapter::take(1)->get()->first();
437         $baseUrl = $book->getUrl() . '/page';
438         $createUrl = $baseUrl . '/create';
439
440         $createUrlChapter = $chapter->getUrl() . '/create-page';
441         $accessUrls = [$createUrl, $createUrlChapter];
442
443         foreach ($accessUrls as $url) {
444             $this->actingAs($this->user)->visit('/')->visit($url)
445                 ->seePageIs('/');
446         }
447
448         $this->checkAccessPermission('page-create-all', [], [
449             $book->getUrl() => 'New Page',
450             $chapter->getUrl() => 'New Page'
451         ]);
452
453         $this->giveUserPermissions($this->user, ['page-create-all']);
454
455         foreach ($accessUrls as $index => $url) {
456             $this->actingAs($this->user)->visit('/')->visit($url);
457             $expectedUrl = \BookStack\Page::where('draft', '=', true)->orderBy('id', 'desc')->first()->getUrl();
458             $this->seePageIs($expectedUrl);
459         }
460
461         $this->visit($baseUrl . '/create')
462             ->type('test page', 'name')
463             ->type('page desc', 'html')
464             ->press('Save Page')
465             ->seePageIs($baseUrl . '/test-page');
466
467         $this->visit($chapter->getUrl() . '/create-page')
468             ->type('new test page', 'name')
469             ->type('page desc', 'html')
470             ->press('Save Page')
471             ->seePageIs($baseUrl . '/new-test-page');
472     }
473
474     public function test_page_edit_own_permission()
475     {
476         $otherPage = \BookStack\Page::take(1)->get()->first();
477         $ownPage = $this->createEntityChainBelongingToUser($this->user)['page'];
478         $this->checkAccessPermission('page-update-own', [
479             $ownPage->getUrl() . '/edit'
480         ], [
481             $ownPage->getUrl() => 'Edit'
482         ]);
483
484         $this->visit($otherPage->getUrl())
485             ->dontSeeInElement('.action-buttons', 'Edit')
486             ->visit($otherPage->getUrl() . '/edit')
487             ->seePageIs('/');
488     }
489
490     public function test_page_edit_all_permission()
491     {
492         $otherPage = \BookStack\Page::take(1)->get()->first();
493         $this->checkAccessPermission('page-update-all', [
494             $otherPage->getUrl() . '/edit'
495         ], [
496             $otherPage->getUrl() => 'Edit'
497         ]);
498     }
499
500     public function test_page_delete_own_permission()
501     {
502         $this->giveUserPermissions($this->user, ['page-update-all']);
503         $otherPage = \BookStack\Page::take(1)->get()->first();
504         $ownPage = $this->createEntityChainBelongingToUser($this->user)['page'];
505         $this->checkAccessPermission('page-delete-own', [
506             $ownPage->getUrl() . '/delete'
507         ], [
508             $ownPage->getUrl() => 'Delete'
509         ]);
510
511         $bookUrl = $ownPage->book->getUrl();
512         $this->visit($otherPage->getUrl())
513             ->dontSeeInElement('.action-buttons', 'Delete')
514             ->visit($otherPage->getUrl() . '/delete')
515             ->seePageIs('/');
516         $this->visit($ownPage->getUrl())->visit($ownPage->getUrl() . '/delete')
517             ->press('Confirm')
518             ->seePageIs($bookUrl)
519             ->dontSeeInElement('.book-content', $ownPage->name);
520     }
521
522     public function test_page_delete_all_permission()
523     {
524         $this->giveUserPermissions($this->user, ['page-update-all']);
525         $otherPage = \BookStack\Page::take(1)->get()->first();
526         $this->checkAccessPermission('page-delete-all', [
527             $otherPage->getUrl() . '/delete'
528         ], [
529             $otherPage->getUrl() => 'Delete'
530         ]);
531
532         $bookUrl = $otherPage->book->getUrl();
533         $this->visit($otherPage->getUrl())->visit($otherPage->getUrl() . '/delete')
534             ->press('Confirm')
535             ->seePageIs($bookUrl)
536             ->dontSeeInElement('.book-content', $otherPage->name);
537     }
538
539 }