]> BookStack Code Mirror - bookstack/blob - tests/RolesTest.php
Added UI components of page autosaving
[bookstack] / tests / 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         $this->checkAccessPermission('page-create-own', [
396             $baseUrl . '/create',
397             $ownChapter->getUrl() . '/create-page'
398         ], [
399             $ownBook->getUrl() => 'New Page',
400             $ownChapter->getUrl() => 'New Page'
401         ]);
402
403         $this->visit($baseUrl . '/create')
404             ->type('test page', 'name')
405             ->type('page desc', 'html')
406             ->press('Save Page')
407             ->seePageIs($baseUrl . '/test-page');
408
409         $this->visit($book->getUrl())
410             ->dontSeeInElement('.action-buttons', 'New Page')
411             ->visit($book->getUrl() . '/page/create')
412             ->seePageIs('/');
413         $this->visit($chapter->getUrl())
414             ->dontSeeInElement('.action-buttons', 'New Page')
415             ->visit($chapter->getUrl() . '/create-page')
416             ->seePageIs('/');
417     }
418
419     public function test_page_create_all_permissions()
420     {
421         $book = \BookStack\Book::take(1)->get()->first();
422         $chapter = \BookStack\Chapter::take(1)->get()->first();
423         $baseUrl = $book->getUrl() . '/page';
424         $this->checkAccessPermission('page-create-all', [
425             $baseUrl . '/create',
426             $chapter->getUrl() . '/create-page'
427         ], [
428             $book->getUrl() => 'New Page',
429             $chapter->getUrl() => 'New Page'
430         ]);
431
432         $this->visit($baseUrl . '/create')
433             ->type('test page', 'name')
434             ->type('page desc', 'html')
435             ->press('Save Page')
436             ->seePageIs($baseUrl . '/test-page');
437
438         $this->visit($chapter->getUrl() . '/create-page')
439             ->type('new test page', 'name')
440             ->type('page desc', 'html')
441             ->press('Save Page')
442             ->seePageIs($baseUrl . '/new-test-page');
443     }
444
445     public function test_page_edit_own_permission()
446     {
447         $otherPage = \BookStack\Page::take(1)->get()->first();
448         $ownPage = $this->createEntityChainBelongingToUser($this->user)['page'];
449         $this->checkAccessPermission('page-update-own', [
450             $ownPage->getUrl() . '/edit'
451         ], [
452             $ownPage->getUrl() => 'Edit'
453         ]);
454
455         $this->visit($otherPage->getUrl())
456             ->dontSeeInElement('.action-buttons', 'Edit')
457             ->visit($otherPage->getUrl() . '/edit')
458             ->seePageIs('/');
459     }
460
461     public function test_page_edit_all_permission()
462     {
463         $otherPage = \BookStack\Page::take(1)->get()->first();
464         $this->checkAccessPermission('page-update-all', [
465             $otherPage->getUrl() . '/edit'
466         ], [
467             $otherPage->getUrl() => 'Edit'
468         ]);
469     }
470
471     public function test_page_delete_own_permission()
472     {
473         $this->giveUserPermissions($this->user, ['page-update-all']);
474         $otherPage = \BookStack\Page::take(1)->get()->first();
475         $ownPage = $this->createEntityChainBelongingToUser($this->user)['page'];
476         $this->checkAccessPermission('page-delete-own', [
477             $ownPage->getUrl() . '/delete'
478         ], [
479             $ownPage->getUrl() => 'Delete'
480         ]);
481
482         $bookUrl = $ownPage->book->getUrl();
483         $this->visit($otherPage->getUrl())
484             ->dontSeeInElement('.action-buttons', 'Delete')
485             ->visit($otherPage->getUrl() . '/delete')
486             ->seePageIs('/');
487         $this->visit($ownPage->getUrl())->visit($ownPage->getUrl() . '/delete')
488             ->press('Confirm')
489             ->seePageIs($bookUrl)
490             ->dontSeeInElement('.book-content', $ownPage->name);
491     }
492
493     public function test_page_delete_all_permission()
494     {
495         $this->giveUserPermissions($this->user, ['page-update-all']);
496         $otherPage = \BookStack\Page::take(1)->get()->first();
497         $this->checkAccessPermission('page-delete-all', [
498             $otherPage->getUrl() . '/delete'
499         ], [
500             $otherPage->getUrl() => 'Delete'
501         ]);
502
503         $bookUrl = $otherPage->book->getUrl();
504         $this->visit($otherPage->getUrl())->visit($otherPage->getUrl() . '/delete')
505             ->press('Confirm')
506             ->seePageIs($bookUrl)
507             ->dontSeeInElement('.book-content', $otherPage->name);
508     }
509
510 }