3 class RolesTest extends TestCase
7 public function setUp()
10 $this->user = $this->getNewBlankUser();
14 * Give the given user some permissions.
15 * @param \BookStack\User $user
16 * @param array $permissions
18 protected function giveUserPermissions(\BookStack\User $user, $permissions = [])
20 $newRole = $this->createNewRole($permissions);
21 $user->attachRole($newRole);
23 $user->permissions(false);
27 * Create a new basic role for testing purposes.
28 * @param array $permissions
31 protected function createNewRole($permissions = [])
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);
39 public function test_admin_can_see_settings()
41 $this->asAdmin()->visit('/settings')->see('Settings');
44 public function test_cannot_delete_admin_role()
46 $adminRole = \BookStack\Role::getRole('admin');
47 $deletePageUrl = '/settings/roles/delete/' . $adminRole->id;
48 $this->asAdmin()->visit($deletePageUrl)
50 ->seePageIs($deletePageUrl)
51 ->see('cannot be deleted');
54 public function test_role_cannot_be_deleted_if_default()
56 $newRole = $this->createNewRole();
57 $this->setSettings(['registration-role' => $newRole->id]);
59 $deletePageUrl = '/settings/roles/delete/' . $newRole->id;
60 $this->asAdmin()->visit($deletePageUrl)
62 ->seePageIs($deletePageUrl)
63 ->see('cannot be deleted');
66 public function test_role_create_update_delete_flow()
68 $testRoleName = 'Test Role';
69 $testRoleDesc = 'a little test description';
70 $testRoleUpdateName = 'An Super Updated role';
73 $this->asAdmin()->visit('/settings')
75 ->seePageIs('/settings/roles')
76 ->click('Add new role')
77 ->type('Test Role', 'display_name')
78 ->type('A little test description', 'description')
80 ->seeInDatabase('roles', ['display_name' => $testRoleName, 'name' => 'test-role', 'description' => $testRoleDesc])
81 ->seePageIs('/settings/roles');
83 $this->asAdmin()->visit('/settings/roles')
85 ->click($testRoleName)
86 ->type($testRoleUpdateName, '#display_name')
88 ->seeInDatabase('roles', ['display_name' => $testRoleUpdateName, 'name' => 'test-role', 'description' => $testRoleDesc])
89 ->seePageIs('/settings/roles');
91 $this->asAdmin()->visit('/settings/roles')
92 ->click($testRoleUpdateName)
93 ->click('Delete Role')
94 ->see($testRoleUpdateName)
96 ->seePageIs('/settings/roles')
97 ->dontSee($testRoleUpdateName);
100 public function test_manage_user_permission()
102 $this->actingAs($this->user)->visit('/')->visit('/settings/users')
104 $this->giveUserPermissions($this->user, ['users-manage']);
105 $this->actingAs($this->user)->visit('/')->visit('/settings/users')
106 ->seePageIs('/settings/users');
109 public function test_user_roles_manage_permission()
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')
119 public function test_settings_manage_permission()
121 $this->actingAs($this->user)->visit('/')->visit('/settings')
123 $this->giveUserPermissions($this->user, ['settings-manage']);
124 $this->actingAs($this->user)->visit('/')->visit('/settings')
125 ->seePageIs('/settings')->press('Save Settings')->see('Settings Saved');
128 public function test_restrictions_manage_all_permission()
130 $page = \BookStack\Page::take(1)->get()->first();
131 $this->actingAs($this->user)->visit($page->getUrl())
132 ->dontSee('Restrict')
133 ->visit($page->getUrl() . '/restrict')
135 $this->giveUserPermissions($this->user, ['restrictions-manage-all']);
136 $this->actingAs($this->user)->visit($page->getUrl())
139 ->see('Page Restrictions')->seePageIs($page->getUrl() . '/restrict');
142 public function test_restrictions_manage_own_permission()
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')
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')
157 $this->giveUserPermissions($this->user, ['restrictions-manage-own']);
159 // Check can't restrict other's content
160 $this->actingAs($this->user)->visit($otherUsersPage->getUrl())
161 ->dontSee('Restrict')
162 ->visit($otherUsersPage->getUrl() . '/restrict')
164 // Check can restrict own content
165 $this->actingAs($this->user)->visit($content['page']->getUrl())
168 ->seePageIs($content['page']->getUrl() . '/restrict');
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
178 private function checkAccessPermission($permission, $accessUrls = [], $visibles = [])
180 foreach ($accessUrls as $url) {
181 $this->actingAs($this->user)->visit('/')->visit($url)
184 foreach ($visibles as $url => $text) {
185 $this->actingAs($this->user)->visit('/')->visit($url)
186 ->dontSeeInElement('.action-buttons',$text);
189 $this->giveUserPermissions($this->user, [$permission]);
191 foreach ($accessUrls as $url) {
192 $this->actingAs($this->user)->visit('/')->visit($url)
195 foreach ($visibles as $url => $text) {
196 $this->actingAs($this->user)->visit('/')->visit($url)
201 public function test_books_create_all_permissions()
203 $this->checkAccessPermission('book-create-all', [
206 '/books' => 'Add new book'
209 $this->visit('/books/create')
210 ->type('test book', 'name')
211 ->type('book desc', 'description')
213 ->seePageIs('/books/test-book');
216 public function test_books_edit_own_permission()
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'
223 $ownBook->getUrl() => 'Edit'
226 $this->visit($otherBook->getUrl())
227 ->dontSeeInElement('.action-buttons', 'Edit')
228 ->visit($otherBook->getUrl() . '/edit')
232 public function test_books_edit_all_permission()
234 $otherBook = \BookStack\Book::take(1)->get()->first();
235 $this->checkAccessPermission('book-update-all', [
236 $otherBook->getUrl() . '/edit'
238 $otherBook->getUrl() => 'Edit'
242 public function test_books_delete_own_permission()
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'
250 $ownBook->getUrl() => 'Delete'
253 $this->visit($otherBook->getUrl())
254 ->dontSeeInElement('.action-buttons', 'Delete')
255 ->visit($otherBook->getUrl() . '/delete')
257 $this->visit($ownBook->getUrl())->visit($ownBook->getUrl() . '/delete')
259 ->seePageIs('/books')
260 ->dontSee($ownBook->name);
263 public function test_books_delete_all_permission()
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'
270 $otherBook->getUrl() => 'Delete'
273 $this->visit($otherBook->getUrl())->visit($otherBook->getUrl() . '/delete')
275 ->seePageIs('/books')
276 ->dontSee($otherBook->name);
279 public function test_chapter_create_own_permissions()
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', [
287 $ownBook->getUrl() => 'New Chapter'
290 $this->visit($baseUrl . '/create')
291 ->type('test chapter', 'name')
292 ->type('chapter desc', 'description')
293 ->press('Save Chapter')
294 ->seePageIs($baseUrl . '/test-chapter');
296 $this->visit($book->getUrl())
297 ->dontSeeInElement('.action-buttons', 'New Chapter')
298 ->visit($book->getUrl() . '/chapter/create')
302 public function test_chapter_create_all_permissions()
304 $book = \BookStack\Book::take(1)->get()->first();
305 $baseUrl = $book->getUrl() . '/chapter';
306 $this->checkAccessPermission('chapter-create-all', [
309 $book->getUrl() => 'New Chapter'
312 $this->visit($baseUrl . '/create')
313 ->type('test chapter', 'name')
314 ->type('chapter desc', 'description')
315 ->press('Save Chapter')
316 ->seePageIs($baseUrl . '/test-chapter');
319 public function test_chapter_edit_own_permission()
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'
326 $ownChapter->getUrl() => 'Edit'
329 $this->visit($otherChapter->getUrl())
330 ->dontSeeInElement('.action-buttons', 'Edit')
331 ->visit($otherChapter->getUrl() . '/edit')
335 public function test_chapter_edit_all_permission()
337 $otherChapter = \BookStack\Chapter::take(1)->get()->first();
338 $this->checkAccessPermission('chapter-update-all', [
339 $otherChapter->getUrl() . '/edit'
341 $otherChapter->getUrl() => 'Edit'
345 public function test_chapter_delete_own_permission()
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'
353 $ownChapter->getUrl() => 'Delete'
356 $bookUrl = $ownChapter->book->getUrl();
357 $this->visit($otherChapter->getUrl())
358 ->dontSeeInElement('.action-buttons', 'Delete')
359 ->visit($otherChapter->getUrl() . '/delete')
361 $this->visit($ownChapter->getUrl())->visit($ownChapter->getUrl() . '/delete')
363 ->seePageIs($bookUrl)
364 ->dontSeeInElement('.book-content', $ownChapter->name);
367 public function test_chapter_delete_all_permission()
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'
374 $otherChapter->getUrl() => 'Delete'
377 $bookUrl = $otherChapter->book->getUrl();
378 $this->visit($otherChapter->getUrl())->visit($otherChapter->getUrl() . '/delete')
380 ->seePageIs($bookUrl)
381 ->dontSeeInElement('.book-content', $otherChapter->name);
384 public function test_page_create_own_permissions()
386 $book = \BookStack\Book::take(1)->get()->first();
387 $chapter = \BookStack\Chapter::take(1)->get()->first();
389 $entities = $this->createEntityChainBelongingToUser($this->user);
390 $ownBook = $entities['book'];
391 $ownChapter = $entities['chapter'];
393 $baseUrl = $ownBook->getUrl() . '/page';
395 $this->checkAccessPermission('page-create-own', [
396 $baseUrl . '/create',
397 $ownChapter->getUrl() . '/create-page'
399 $ownBook->getUrl() => 'New Page',
400 $ownChapter->getUrl() => 'New Page'
403 $this->visit($baseUrl . '/create')
404 ->type('test page', 'name')
405 ->type('page desc', 'html')
407 ->seePageIs($baseUrl . '/test-page');
409 $this->visit($book->getUrl())
410 ->dontSeeInElement('.action-buttons', 'New Page')
411 ->visit($book->getUrl() . '/page/create')
413 $this->visit($chapter->getUrl())
414 ->dontSeeInElement('.action-buttons', 'New Page')
415 ->visit($chapter->getUrl() . '/create-page')
419 public function test_page_create_all_permissions()
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'
428 $book->getUrl() => 'New Page',
429 $chapter->getUrl() => 'New Page'
432 $this->visit($baseUrl . '/create')
433 ->type('test page', 'name')
434 ->type('page desc', 'html')
436 ->seePageIs($baseUrl . '/test-page');
438 $this->visit($chapter->getUrl() . '/create-page')
439 ->type('new test page', 'name')
440 ->type('page desc', 'html')
442 ->seePageIs($baseUrl . '/new-test-page');
445 public function test_page_edit_own_permission()
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'
452 $ownPage->getUrl() => 'Edit'
455 $this->visit($otherPage->getUrl())
456 ->dontSeeInElement('.action-buttons', 'Edit')
457 ->visit($otherPage->getUrl() . '/edit')
461 public function test_page_edit_all_permission()
463 $otherPage = \BookStack\Page::take(1)->get()->first();
464 $this->checkAccessPermission('page-update-all', [
465 $otherPage->getUrl() . '/edit'
467 $otherPage->getUrl() => 'Edit'
471 public function test_page_delete_own_permission()
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'
479 $ownPage->getUrl() => 'Delete'
482 $bookUrl = $ownPage->book->getUrl();
483 $this->visit($otherPage->getUrl())
484 ->dontSeeInElement('.action-buttons', 'Delete')
485 ->visit($otherPage->getUrl() . '/delete')
487 $this->visit($ownPage->getUrl())->visit($ownPage->getUrl() . '/delete')
489 ->seePageIs($bookUrl)
490 ->dontSeeInElement('.book-content', $ownPage->name);
493 public function test_page_delete_all_permission()
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'
500 $otherPage->getUrl() => 'Delete'
503 $bookUrl = $otherPage->book->getUrl();
504 $this->visit($otherPage->getUrl())->visit($otherPage->getUrl() . '/delete')
506 ->seePageIs($bookUrl)
507 ->dontSeeInElement('.book-content', $otherPage->name);