3 class RestrictionsTest extends BrowserKitTest
7 protected $restrictionService;
9 public function setUp()
12 $this->user = $this->getEditor();
13 $this->viewer = $this->getViewer();
14 $this->restrictionService = $this->app[\BookStack\Services\PermissionService::class];
17 protected function getViewer()
19 $role = \BookStack\Role::getRole('viewer');
20 $viewer = $this->getNewBlankUser();
21 $viewer->attachRole($role);;
26 * Manually set some permissions on an entity.
27 * @param \BookStack\Entity $entity
30 protected function setEntityRestrictions(\BookStack\Entity $entity, $actions)
32 $entity->restricted = true;
33 $entity->permissions()->delete();
34 $role = $this->user->roles->first();
35 $viewerRole = $this->viewer->roles->first();
36 foreach ($actions as $action) {
37 $entity->permissions()->create([
38 'role_id' => $role->id,
39 'action' => strtolower($action)
41 $entity->permissions()->create([
42 'role_id' => $viewerRole->id,
43 'action' => strtolower($action)
47 $entity->load('permissions');
48 $this->restrictionService->buildJointPermissionsForEntity($entity);
49 $entity->load('jointPermissions');
52 public function test_book_view_restriction()
54 $book = \BookStack\Book::first();
55 $bookPage = $book->pages->first();
56 $bookChapter = $book->chapters->first();
58 $bookUrl = $book->getUrl();
59 $this->actingAs($this->user)
61 ->seePageIs($bookUrl);
63 $this->setEntityRestrictions($book, []);
65 $this->forceVisit($bookUrl)
66 ->see('Book not found');
67 $this->forceVisit($bookPage->getUrl())
68 ->see('Page not found');
69 $this->forceVisit($bookChapter->getUrl())
70 ->see('Chapter not found');
72 $this->setEntityRestrictions($book, ['view']);
74 $this->visit($bookUrl)
76 $this->visit($bookPage->getUrl())
77 ->see($bookPage->name);
78 $this->visit($bookChapter->getUrl())
79 ->see($bookChapter->name);
82 public function test_book_create_restriction()
84 $book = \BookStack\Book::first();
86 $bookUrl = $book->getUrl();
87 $this->actingAs($this->viewer)
89 ->dontSeeInElement('.action-buttons', 'New Page')
90 ->dontSeeInElement('.action-buttons', 'New Chapter');
91 $this->actingAs($this->user)
93 ->seeInElement('.action-buttons', 'New Page')
94 ->seeInElement('.action-buttons', 'New Chapter');
96 $this->setEntityRestrictions($book, ['view', 'delete', 'update']);
98 $this->forceVisit($bookUrl . '/chapter/create')
99 ->see('You do not have permission')->seePageIs('/');
100 $this->forceVisit($bookUrl . '/page/create')
101 ->see('You do not have permission')->seePageIs('/');
102 $this->visit($bookUrl)->dontSeeInElement('.action-buttons', 'New Page')
103 ->dontSeeInElement('.action-buttons', 'New Chapter');
105 $this->setEntityRestrictions($book, ['view', 'create']);
107 $this->visit($bookUrl . '/chapter/create')
108 ->type('test chapter', 'name')
109 ->type('test description for chapter', 'description')
110 ->press('Save Chapter')
111 ->seePageIs($bookUrl . '/chapter/test-chapter');
112 $this->visit($bookUrl . '/page/create')
113 ->type('test page', 'name')
114 ->type('test content', 'html')
116 ->seePageIs($bookUrl . '/page/test-page');
117 $this->visit($bookUrl)->seeInElement('.action-buttons', 'New Page')
118 ->seeInElement('.action-buttons', 'New Chapter');
121 public function test_book_update_restriction()
123 $book = \BookStack\Book::first();
124 $bookPage = $book->pages->first();
125 $bookChapter = $book->chapters->first();
127 $bookUrl = $book->getUrl();
128 $this->actingAs($this->user)
129 ->visit($bookUrl . '/edit')
132 $this->setEntityRestrictions($book, ['view', 'delete']);
134 $this->forceVisit($bookUrl . '/edit')
135 ->see('You do not have permission')->seePageIs('/');
136 $this->forceVisit($bookPage->getUrl() . '/edit')
137 ->see('You do not have permission')->seePageIs('/');
138 $this->forceVisit($bookChapter->getUrl() . '/edit')
139 ->see('You do not have permission')->seePageIs('/');
141 $this->setEntityRestrictions($book, ['view', 'update']);
143 $this->visit($bookUrl . '/edit')
144 ->seePageIs($bookUrl . '/edit');
145 $this->visit($bookPage->getUrl() . '/edit')
146 ->seePageIs($bookPage->getUrl() . '/edit');
147 $this->visit($bookChapter->getUrl() . '/edit')
148 ->see('Edit Chapter');
151 public function test_book_delete_restriction()
153 $book = \BookStack\Book::first();
154 $bookPage = $book->pages->first();
155 $bookChapter = $book->chapters->first();
157 $bookUrl = $book->getUrl();
158 $this->actingAs($this->user)
159 ->visit($bookUrl . '/delete')
160 ->see('Delete Book');
162 $this->setEntityRestrictions($book, ['view', 'update']);
164 $this->forceVisit($bookUrl . '/delete')
165 ->see('You do not have permission')->seePageIs('/');
166 $this->forceVisit($bookPage->getUrl() . '/delete')
167 ->see('You do not have permission')->seePageIs('/');
168 $this->forceVisit($bookChapter->getUrl() . '/delete')
169 ->see('You do not have permission')->seePageIs('/');
171 $this->setEntityRestrictions($book, ['view', 'delete']);
173 $this->visit($bookUrl . '/delete')
174 ->seePageIs($bookUrl . '/delete')->see('Delete Book');
175 $this->visit($bookPage->getUrl() . '/delete')
176 ->seePageIs($bookPage->getUrl() . '/delete')->see('Delete Page');
177 $this->visit($bookChapter->getUrl() . '/delete')
178 ->see('Delete Chapter');
181 public function test_chapter_view_restriction()
183 $chapter = \BookStack\Chapter::first();
184 $chapterPage = $chapter->pages->first();
186 $chapterUrl = $chapter->getUrl();
187 $this->actingAs($this->user)
189 ->seePageIs($chapterUrl);
191 $this->setEntityRestrictions($chapter, []);
193 $this->forceVisit($chapterUrl)
194 ->see('Chapter not found');
195 $this->forceVisit($chapterPage->getUrl())
196 ->see('Page not found');
198 $this->setEntityRestrictions($chapter, ['view']);
200 $this->visit($chapterUrl)
201 ->see($chapter->name);
202 $this->visit($chapterPage->getUrl())
203 ->see($chapterPage->name);
206 public function test_chapter_create_restriction()
208 $chapter = \BookStack\Chapter::first();
210 $chapterUrl = $chapter->getUrl();
211 $this->actingAs($this->user)
213 ->seeInElement('.action-buttons', 'New Page');
215 $this->setEntityRestrictions($chapter, ['view', 'delete', 'update']);
217 $this->forceVisit($chapterUrl . '/create-page')
218 ->see('You do not have permission')->seePageIs('/');
219 $this->visit($chapterUrl)->dontSeeInElement('.action-buttons', 'New Page');
221 $this->setEntityRestrictions($chapter, ['view', 'create']);
224 $this->visit($chapterUrl . '/create-page')
225 ->type('test page', 'name')
226 ->type('test content', 'html')
228 ->seePageIs($chapter->book->getUrl() . '/page/test-page');
230 $this->visit($chapterUrl)->seeInElement('.action-buttons', 'New Page');
233 public function test_chapter_update_restriction()
235 $chapter = \BookStack\Chapter::first();
236 $chapterPage = $chapter->pages->first();
238 $chapterUrl = $chapter->getUrl();
239 $this->actingAs($this->user)
240 ->visit($chapterUrl . '/edit')
241 ->see('Edit Chapter');
243 $this->setEntityRestrictions($chapter, ['view', 'delete']);
245 $this->forceVisit($chapterUrl . '/edit')
246 ->see('You do not have permission')->seePageIs('/');
247 $this->forceVisit($chapterPage->getUrl() . '/edit')
248 ->see('You do not have permission')->seePageIs('/');
250 $this->setEntityRestrictions($chapter, ['view', 'update']);
252 $this->visit($chapterUrl . '/edit')
253 ->seePageIs($chapterUrl . '/edit')->see('Edit Chapter');
254 $this->visit($chapterPage->getUrl() . '/edit')
255 ->seePageIs($chapterPage->getUrl() . '/edit');
258 public function test_chapter_delete_restriction()
260 $chapter = \BookStack\Chapter::first();
261 $chapterPage = $chapter->pages->first();
263 $chapterUrl = $chapter->getUrl();
264 $this->actingAs($this->user)
265 ->visit($chapterUrl . '/delete')
266 ->see('Delete Chapter');
268 $this->setEntityRestrictions($chapter, ['view', 'update']);
270 $this->forceVisit($chapterUrl . '/delete')
271 ->see('You do not have permission')->seePageIs('/');
272 $this->forceVisit($chapterPage->getUrl() . '/delete')
273 ->see('You do not have permission')->seePageIs('/');
275 $this->setEntityRestrictions($chapter, ['view', 'delete']);
277 $this->visit($chapterUrl . '/delete')
278 ->seePageIs($chapterUrl . '/delete')->see('Delete Chapter');
279 $this->visit($chapterPage->getUrl() . '/delete')
280 ->seePageIs($chapterPage->getUrl() . '/delete')->see('Delete Page');
283 public function test_page_view_restriction()
285 $page = \BookStack\Page::first();
287 $pageUrl = $page->getUrl();
288 $this->actingAs($this->user)
290 ->seePageIs($pageUrl);
292 $this->setEntityRestrictions($page, ['update', 'delete']);
294 $this->forceVisit($pageUrl)
295 ->see('Page not found');
297 $this->setEntityRestrictions($page, ['view']);
299 $this->visit($pageUrl)
303 public function test_page_update_restriction()
305 $page = \BookStack\Chapter::first();
307 $pageUrl = $page->getUrl();
308 $this->actingAs($this->user)
309 ->visit($pageUrl . '/edit')
310 ->seeInField('name', $page->name);
312 $this->setEntityRestrictions($page, ['view', 'delete']);
314 $this->forceVisit($pageUrl . '/edit')
315 ->see('You do not have permission')->seePageIs('/');
317 $this->setEntityRestrictions($page, ['view', 'update']);
319 $this->visit($pageUrl . '/edit')
320 ->seePageIs($pageUrl . '/edit')->seeInField('name', $page->name);
323 public function test_page_delete_restriction()
325 $page = \BookStack\Page::first();
327 $pageUrl = $page->getUrl();
328 $this->actingAs($this->user)
329 ->visit($pageUrl . '/delete')
330 ->see('Delete Page');
332 $this->setEntityRestrictions($page, ['view', 'update']);
334 $this->forceVisit($pageUrl . '/delete')
335 ->see('You do not have permission')->seePageIs('/');
337 $this->setEntityRestrictions($page, ['view', 'delete']);
339 $this->visit($pageUrl . '/delete')
340 ->seePageIs($pageUrl . '/delete')->see('Delete Page');
343 public function test_book_restriction_form()
345 $book = \BookStack\Book::first();
346 $this->asAdmin()->visit($book->getUrl() . '/permissions')
347 ->see('Book Permissions')
348 ->check('restricted')
349 ->check('restrictions[2][view]')
350 ->press('Save Permissions')
351 ->seeInDatabase('books', ['id' => $book->id, 'restricted' => true])
352 ->seeInDatabase('entity_permissions', [
353 'restrictable_id' => $book->id,
354 'restrictable_type' => 'BookStack\Book',
360 public function test_chapter_restriction_form()
362 $chapter = \BookStack\Chapter::first();
363 $this->asAdmin()->visit($chapter->getUrl() . '/permissions')
364 ->see('Chapter Permissions')
365 ->check('restricted')
366 ->check('restrictions[2][update]')
367 ->press('Save Permissions')
368 ->seeInDatabase('chapters', ['id' => $chapter->id, 'restricted' => true])
369 ->seeInDatabase('entity_permissions', [
370 'restrictable_id' => $chapter->id,
371 'restrictable_type' => 'BookStack\Chapter',
377 public function test_page_restriction_form()
379 $page = \BookStack\Page::first();
380 $this->asAdmin()->visit($page->getUrl() . '/permissions')
381 ->see('Page Permissions')
382 ->check('restricted')
383 ->check('restrictions[2][delete]')
384 ->press('Save Permissions')
385 ->seeInDatabase('pages', ['id' => $page->id, 'restricted' => true])
386 ->seeInDatabase('entity_permissions', [
387 'restrictable_id' => $page->id,
388 'restrictable_type' => 'BookStack\Page',
394 public function test_restricted_pages_not_visible_in_book_navigation_on_pages()
396 $chapter = \BookStack\Chapter::first();
397 $page = $chapter->pages->first();
398 $page2 = $chapter->pages[2];
400 $this->setEntityRestrictions($page, []);
402 $this->actingAs($this->user)
403 ->visit($page2->getUrl())
404 ->dontSeeInElement('.sidebar-page-list', $page->name);
407 public function test_restricted_pages_not_visible_in_book_navigation_on_chapters()
409 $chapter = \BookStack\Chapter::first();
410 $page = $chapter->pages->first();
412 $this->setEntityRestrictions($page, []);
414 $this->actingAs($this->user)
415 ->visit($chapter->getUrl())
416 ->dontSeeInElement('.sidebar-page-list', $page->name);
419 public function test_restricted_pages_not_visible_on_chapter_pages()
421 $chapter = \BookStack\Chapter::first();
422 $page = $chapter->pages->first();
424 $this->setEntityRestrictions($page, []);
426 $this->actingAs($this->user)
427 ->visit($chapter->getUrl())
428 ->dontSee($page->name);
431 public function test_book_create_restriction_override()
433 $book = \BookStack\Book::first();
435 $bookUrl = $book->getUrl();
436 $this->actingAs($this->viewer)
438 ->dontSeeInElement('.action-buttons', 'New Page')
439 ->dontSeeInElement('.action-buttons', 'New Chapter');
441 $this->setEntityRestrictions($book, ['view', 'delete', 'update']);
443 $this->forceVisit($bookUrl . '/chapter/create')
444 ->see('You do not have permission')->seePageIs('/');
445 $this->forceVisit($bookUrl . '/page/create')
446 ->see('You do not have permission')->seePageIs('/');
447 $this->visit($bookUrl)->dontSeeInElement('.action-buttons', 'New Page')
448 ->dontSeeInElement('.action-buttons', 'New Chapter');
450 $this->setEntityRestrictions($book, ['view', 'create']);
452 $this->visit($bookUrl . '/chapter/create')
453 ->type('test chapter', 'name')
454 ->type('test description for chapter', 'description')
455 ->press('Save Chapter')
456 ->seePageIs($bookUrl . '/chapter/test-chapter');
457 $this->visit($bookUrl . '/page/create')
458 ->type('test page', 'name')
459 ->type('test content', 'html')
461 ->seePageIs($bookUrl . '/page/test-page');
462 $this->visit($bookUrl)->seeInElement('.action-buttons', 'New Page')
463 ->seeInElement('.action-buttons', 'New Chapter');
466 public function test_book_update_restriction_override()
468 $book = \BookStack\Book::first();
469 $bookPage = $book->pages->first();
470 $bookChapter = $book->chapters->first();
472 $bookUrl = $book->getUrl();
473 $this->actingAs($this->viewer)
474 ->visit($bookUrl . '/edit')
475 ->dontSee('Edit Book');
477 $this->setEntityRestrictions($book, ['view', 'delete']);
479 $this->forceVisit($bookUrl . '/edit')
480 ->see('You do not have permission')->seePageIs('/');
481 $this->forceVisit($bookPage->getUrl() . '/edit')
482 ->see('You do not have permission')->seePageIs('/');
483 $this->forceVisit($bookChapter->getUrl() . '/edit')
484 ->see('You do not have permission')->seePageIs('/');
486 $this->setEntityRestrictions($book, ['view', 'update']);
488 $this->visit($bookUrl . '/edit')
489 ->seePageIs($bookUrl . '/edit');
490 $this->visit($bookPage->getUrl() . '/edit')
491 ->seePageIs($bookPage->getUrl() . '/edit');
492 $this->visit($bookChapter->getUrl() . '/edit')
493 ->see('Edit Chapter');
496 public function test_book_delete_restriction_override()
498 $book = \BookStack\Book::first();
499 $bookPage = $book->pages->first();
500 $bookChapter = $book->chapters->first();
502 $bookUrl = $book->getUrl();
503 $this->actingAs($this->viewer)
504 ->visit($bookUrl . '/delete')
505 ->dontSee('Delete Book');
507 $this->setEntityRestrictions($book, ['view', 'update']);
509 $this->forceVisit($bookUrl . '/delete')
510 ->see('You do not have permission')->seePageIs('/');
511 $this->forceVisit($bookPage->getUrl() . '/delete')
512 ->see('You do not have permission')->seePageIs('/');
513 $this->forceVisit($bookChapter->getUrl() . '/delete')
514 ->see('You do not have permission')->seePageIs('/');
516 $this->setEntityRestrictions($book, ['view', 'delete']);
518 $this->visit($bookUrl . '/delete')
519 ->seePageIs($bookUrl . '/delete')->see('Delete Book');
520 $this->visit($bookPage->getUrl() . '/delete')
521 ->seePageIs($bookPage->getUrl() . '/delete')->see('Delete Page');
522 $this->visit($bookChapter->getUrl() . '/delete')
523 ->see('Delete Chapter');
526 public function test_page_visible_if_has_permissions_when_book_not_visible()
528 $book = \BookStack\Book::first();
529 $bookChapter = $book->chapters->first();
530 $bookPage = $bookChapter->pages->first();
532 $this->setEntityRestrictions($book, []);
533 $this->setEntityRestrictions($bookPage, ['view']);
535 $this->actingAs($this->viewer);
536 $this->get($bookPage->getUrl());
537 $this->assertResponseOk();
538 $this->see($bookPage->name);
539 $this->dontSee(substr($book->name, 0, 15));
540 $this->dontSee(substr($bookChapter->name, 0, 15));