4 use BookStack\Services\PermissionService;
7 class RestrictionsTest extends BrowserKitTest
21 * @var PermissionService
23 protected $permissionService;
25 public function setUp()
28 $this->user = $this->getEditor();
29 $this->viewer = $this->getViewer();
30 $this->permissionService = $this->app[PermissionService::class];
34 * Manually set some permissions on an entity.
35 * @param \BookStack\Entity $entity
38 protected function setEntityRestrictions(\BookStack\Entity $entity, $actions)
40 $entity->restricted = true;
41 $entity->permissions()->delete();
43 $role = $this->user->roles->first();
44 $viewerRole = $this->viewer->roles->first();
47 foreach ($actions as $action) {
49 'role_id' => $role->id,
50 'action' => strtolower($action)
53 'role_id' => $viewerRole->id,
54 'action' => strtolower($action)
57 $entity->permissions()->createMany($permissions);
60 $entity->load('permissions');
61 $this->permissionService->buildJointPermissionsForEntity($entity);
62 $entity->load('jointPermissions');
65 public function test_book_view_restriction()
67 $book = Book::first();
68 $bookPage = $book->pages->first();
69 $bookChapter = $book->chapters->first();
71 $bookUrl = $book->getUrl();
72 $this->actingAs($this->user)
74 ->seePageIs($bookUrl);
76 $this->setEntityRestrictions($book, []);
78 $this->forceVisit($bookUrl)
79 ->see('Book not found');
80 $this->forceVisit($bookPage->getUrl())
81 ->see('Page not found');
82 $this->forceVisit($bookChapter->getUrl())
83 ->see('Chapter not found');
85 $this->setEntityRestrictions($book, ['view']);
87 $this->visit($bookUrl)
89 $this->visit($bookPage->getUrl())
90 ->see($bookPage->name);
91 $this->visit($bookChapter->getUrl())
92 ->see($bookChapter->name);
95 public function test_book_create_restriction()
97 $book = Book::first();
99 $bookUrl = $book->getUrl();
100 $this->actingAs($this->viewer)
102 ->dontSeeInElement('.action-buttons', 'New Page')
103 ->dontSeeInElement('.action-buttons', 'New Chapter');
104 $this->actingAs($this->user)
106 ->seeInElement('.action-buttons', 'New Page')
107 ->seeInElement('.action-buttons', 'New Chapter');
109 $this->setEntityRestrictions($book, ['view', 'delete', 'update']);
111 $this->forceVisit($bookUrl . '/chapter/create')
112 ->see('You do not have permission')->seePageIs('/');
113 $this->forceVisit($bookUrl . '/page/create')
114 ->see('You do not have permission')->seePageIs('/');
115 $this->visit($bookUrl)->dontSeeInElement('.action-buttons', 'New Page')
116 ->dontSeeInElement('.action-buttons', 'New Chapter');
118 $this->setEntityRestrictions($book, ['view', 'create']);
120 $this->visit($bookUrl . '/chapter/create')
121 ->type('test chapter', 'name')
122 ->type('test description for chapter', 'description')
123 ->press('Save Chapter')
124 ->seePageIs($bookUrl . '/chapter/test-chapter');
125 $this->visit($bookUrl . '/page/create')
126 ->type('test page', 'name')
127 ->type('test content', 'html')
129 ->seePageIs($bookUrl . '/page/test-page');
130 $this->visit($bookUrl)->seeInElement('.action-buttons', 'New Page')
131 ->seeInElement('.action-buttons', 'New Chapter');
134 public function test_book_update_restriction()
136 $book = Book::first();
137 $bookPage = $book->pages->first();
138 $bookChapter = $book->chapters->first();
140 $bookUrl = $book->getUrl();
141 $this->actingAs($this->user)
142 ->visit($bookUrl . '/edit')
145 $this->setEntityRestrictions($book, ['view', 'delete']);
147 $this->forceVisit($bookUrl . '/edit')
148 ->see('You do not have permission')->seePageIs('/');
149 $this->forceVisit($bookPage->getUrl() . '/edit')
150 ->see('You do not have permission')->seePageIs('/');
151 $this->forceVisit($bookChapter->getUrl() . '/edit')
152 ->see('You do not have permission')->seePageIs('/');
154 $this->setEntityRestrictions($book, ['view', 'update']);
156 $this->visit($bookUrl . '/edit')
157 ->seePageIs($bookUrl . '/edit');
158 $this->visit($bookPage->getUrl() . '/edit')
159 ->seePageIs($bookPage->getUrl() . '/edit');
160 $this->visit($bookChapter->getUrl() . '/edit')
161 ->see('Edit Chapter');
164 public function test_book_delete_restriction()
166 $book = Book::first();
167 $bookPage = $book->pages->first();
168 $bookChapter = $book->chapters->first();
170 $bookUrl = $book->getUrl();
171 $this->actingAs($this->user)
172 ->visit($bookUrl . '/delete')
173 ->see('Delete Book');
175 $this->setEntityRestrictions($book, ['view', 'update']);
177 $this->forceVisit($bookUrl . '/delete')
178 ->see('You do not have permission')->seePageIs('/');
179 $this->forceVisit($bookPage->getUrl() . '/delete')
180 ->see('You do not have permission')->seePageIs('/');
181 $this->forceVisit($bookChapter->getUrl() . '/delete')
182 ->see('You do not have permission')->seePageIs('/');
184 $this->setEntityRestrictions($book, ['view', 'delete']);
186 $this->visit($bookUrl . '/delete')
187 ->seePageIs($bookUrl . '/delete')->see('Delete Book');
188 $this->visit($bookPage->getUrl() . '/delete')
189 ->seePageIs($bookPage->getUrl() . '/delete')->see('Delete Page');
190 $this->visit($bookChapter->getUrl() . '/delete')
191 ->see('Delete Chapter');
194 public function test_chapter_view_restriction()
196 $chapter = \BookStack\Chapter::first();
197 $chapterPage = $chapter->pages->first();
199 $chapterUrl = $chapter->getUrl();
200 $this->actingAs($this->user)
202 ->seePageIs($chapterUrl);
204 $this->setEntityRestrictions($chapter, []);
206 $this->forceVisit($chapterUrl)
207 ->see('Chapter not found');
208 $this->forceVisit($chapterPage->getUrl())
209 ->see('Page not found');
211 $this->setEntityRestrictions($chapter, ['view']);
213 $this->visit($chapterUrl)
214 ->see($chapter->name);
215 $this->visit($chapterPage->getUrl())
216 ->see($chapterPage->name);
219 public function test_chapter_create_restriction()
221 $chapter = \BookStack\Chapter::first();
223 $chapterUrl = $chapter->getUrl();
224 $this->actingAs($this->user)
226 ->seeInElement('.action-buttons', 'New Page');
228 $this->setEntityRestrictions($chapter, ['view', 'delete', 'update']);
230 $this->forceVisit($chapterUrl . '/create-page')
231 ->see('You do not have permission')->seePageIs('/');
232 $this->visit($chapterUrl)->dontSeeInElement('.action-buttons', 'New Page');
234 $this->setEntityRestrictions($chapter, ['view', 'create']);
237 $this->visit($chapterUrl . '/create-page')
238 ->type('test page', 'name')
239 ->type('test content', 'html')
241 ->seePageIs($chapter->book->getUrl() . '/page/test-page');
243 $this->visit($chapterUrl)->seeInElement('.action-buttons', 'New Page');
246 public function test_chapter_update_restriction()
248 $chapter = \BookStack\Chapter::first();
249 $chapterPage = $chapter->pages->first();
251 $chapterUrl = $chapter->getUrl();
252 $this->actingAs($this->user)
253 ->visit($chapterUrl . '/edit')
254 ->see('Edit Chapter');
256 $this->setEntityRestrictions($chapter, ['view', 'delete']);
258 $this->forceVisit($chapterUrl . '/edit')
259 ->see('You do not have permission')->seePageIs('/');
260 $this->forceVisit($chapterPage->getUrl() . '/edit')
261 ->see('You do not have permission')->seePageIs('/');
263 $this->setEntityRestrictions($chapter, ['view', 'update']);
265 $this->visit($chapterUrl . '/edit')
266 ->seePageIs($chapterUrl . '/edit')->see('Edit Chapter');
267 $this->visit($chapterPage->getUrl() . '/edit')
268 ->seePageIs($chapterPage->getUrl() . '/edit');
271 public function test_chapter_delete_restriction()
273 $chapter = \BookStack\Chapter::first();
274 $chapterPage = $chapter->pages->first();
276 $chapterUrl = $chapter->getUrl();
277 $this->actingAs($this->user)
278 ->visit($chapterUrl . '/delete')
279 ->see('Delete Chapter');
281 $this->setEntityRestrictions($chapter, ['view', 'update']);
283 $this->forceVisit($chapterUrl . '/delete')
284 ->see('You do not have permission')->seePageIs('/');
285 $this->forceVisit($chapterPage->getUrl() . '/delete')
286 ->see('You do not have permission')->seePageIs('/');
288 $this->setEntityRestrictions($chapter, ['view', 'delete']);
290 $this->visit($chapterUrl . '/delete')
291 ->seePageIs($chapterUrl . '/delete')->see('Delete Chapter');
292 $this->visit($chapterPage->getUrl() . '/delete')
293 ->seePageIs($chapterPage->getUrl() . '/delete')->see('Delete Page');
296 public function test_page_view_restriction()
298 $page = \BookStack\Page::first();
300 $pageUrl = $page->getUrl();
301 $this->actingAs($this->user)
303 ->seePageIs($pageUrl);
305 $this->setEntityRestrictions($page, ['update', 'delete']);
307 $this->forceVisit($pageUrl)
308 ->see('Page not found');
310 $this->setEntityRestrictions($page, ['view']);
312 $this->visit($pageUrl)
316 public function test_page_update_restriction()
318 $page = \BookStack\Chapter::first();
320 $pageUrl = $page->getUrl();
321 $this->actingAs($this->user)
322 ->visit($pageUrl . '/edit')
323 ->seeInField('name', $page->name);
325 $this->setEntityRestrictions($page, ['view', 'delete']);
327 $this->forceVisit($pageUrl . '/edit')
328 ->see('You do not have permission')->seePageIs('/');
330 $this->setEntityRestrictions($page, ['view', 'update']);
332 $this->visit($pageUrl . '/edit')
333 ->seePageIs($pageUrl . '/edit')->seeInField('name', $page->name);
336 public function test_page_delete_restriction()
338 $page = \BookStack\Page::first();
340 $pageUrl = $page->getUrl();
341 $this->actingAs($this->user)
342 ->visit($pageUrl . '/delete')
343 ->see('Delete Page');
345 $this->setEntityRestrictions($page, ['view', 'update']);
347 $this->forceVisit($pageUrl . '/delete')
348 ->see('You do not have permission')->seePageIs('/');
350 $this->setEntityRestrictions($page, ['view', 'delete']);
352 $this->visit($pageUrl . '/delete')
353 ->seePageIs($pageUrl . '/delete')->see('Delete Page');
356 public function test_book_restriction_form()
358 $book = Book::first();
359 $this->asAdmin()->visit($book->getUrl() . '/permissions')
360 ->see('Book Permissions')
361 ->check('restricted')
362 ->check('restrictions[2][view]')
363 ->press('Save Permissions')
364 ->seeInDatabase('books', ['id' => $book->id, 'restricted' => true])
365 ->seeInDatabase('entity_permissions', [
366 'restrictable_id' => $book->id,
367 'restrictable_type' => 'BookStack\Book',
373 public function test_chapter_restriction_form()
375 $chapter = \BookStack\Chapter::first();
376 $this->asAdmin()->visit($chapter->getUrl() . '/permissions')
377 ->see('Chapter Permissions')
378 ->check('restricted')
379 ->check('restrictions[2][update]')
380 ->press('Save Permissions')
381 ->seeInDatabase('chapters', ['id' => $chapter->id, 'restricted' => true])
382 ->seeInDatabase('entity_permissions', [
383 'restrictable_id' => $chapter->id,
384 'restrictable_type' => 'BookStack\Chapter',
390 public function test_page_restriction_form()
392 $page = \BookStack\Page::first();
393 $this->asAdmin()->visit($page->getUrl() . '/permissions')
394 ->see('Page Permissions')
395 ->check('restricted')
396 ->check('restrictions[2][delete]')
397 ->press('Save Permissions')
398 ->seeInDatabase('pages', ['id' => $page->id, 'restricted' => true])
399 ->seeInDatabase('entity_permissions', [
400 'restrictable_id' => $page->id,
401 'restrictable_type' => 'BookStack\Page',
407 public function test_restricted_pages_not_visible_in_book_navigation_on_pages()
409 $chapter = \BookStack\Chapter::first();
410 $page = $chapter->pages->first();
411 $page2 = $chapter->pages[2];
413 $this->setEntityRestrictions($page, []);
415 $this->actingAs($this->user)
416 ->visit($page2->getUrl())
417 ->dontSeeInElement('.sidebar-page-list', $page->name);
420 public function test_restricted_pages_not_visible_in_book_navigation_on_chapters()
422 $chapter = \BookStack\Chapter::first();
423 $page = $chapter->pages->first();
425 $this->setEntityRestrictions($page, []);
427 $this->actingAs($this->user)
428 ->visit($chapter->getUrl())
429 ->dontSeeInElement('.sidebar-page-list', $page->name);
432 public function test_restricted_pages_not_visible_on_chapter_pages()
434 $chapter = \BookStack\Chapter::first();
435 $page = $chapter->pages->first();
437 $this->setEntityRestrictions($page, []);
439 $this->actingAs($this->user)
440 ->visit($chapter->getUrl())
441 ->dontSee($page->name);
444 public function test_book_create_restriction_override()
446 $book = Book::first();
448 $bookUrl = $book->getUrl();
449 $this->actingAs($this->viewer)
451 ->dontSeeInElement('.action-buttons', 'New Page')
452 ->dontSeeInElement('.action-buttons', 'New Chapter');
454 $this->setEntityRestrictions($book, ['view', 'delete', 'update']);
456 $this->forceVisit($bookUrl . '/chapter/create')
457 ->see('You do not have permission')->seePageIs('/');
458 $this->forceVisit($bookUrl . '/page/create')
459 ->see('You do not have permission')->seePageIs('/');
460 $this->visit($bookUrl)->dontSeeInElement('.action-buttons', 'New Page')
461 ->dontSeeInElement('.action-buttons', 'New Chapter');
463 $this->setEntityRestrictions($book, ['view', 'create']);
465 $this->visit($bookUrl . '/chapter/create')
466 ->type('test chapter', 'name')
467 ->type('test description for chapter', 'description')
468 ->press('Save Chapter')
469 ->seePageIs($bookUrl . '/chapter/test-chapter');
470 $this->visit($bookUrl . '/page/create')
471 ->type('test page', 'name')
472 ->type('test content', 'html')
474 ->seePageIs($bookUrl . '/page/test-page');
475 $this->visit($bookUrl)->seeInElement('.action-buttons', 'New Page')
476 ->seeInElement('.action-buttons', 'New Chapter');
479 public function test_book_update_restriction_override()
481 $book = Book::first();
482 $bookPage = $book->pages->first();
483 $bookChapter = $book->chapters->first();
485 $bookUrl = $book->getUrl();
486 $this->actingAs($this->viewer)
487 ->visit($bookUrl . '/edit')
488 ->dontSee('Edit Book');
490 $this->setEntityRestrictions($book, ['view', 'delete']);
492 $this->forceVisit($bookUrl . '/edit')
493 ->see('You do not have permission')->seePageIs('/');
494 $this->forceVisit($bookPage->getUrl() . '/edit')
495 ->see('You do not have permission')->seePageIs('/');
496 $this->forceVisit($bookChapter->getUrl() . '/edit')
497 ->see('You do not have permission')->seePageIs('/');
499 $this->setEntityRestrictions($book, ['view', 'update']);
501 $this->visit($bookUrl . '/edit')
502 ->seePageIs($bookUrl . '/edit');
503 $this->visit($bookPage->getUrl() . '/edit')
504 ->seePageIs($bookPage->getUrl() . '/edit');
505 $this->visit($bookChapter->getUrl() . '/edit')
506 ->see('Edit Chapter');
509 public function test_book_delete_restriction_override()
511 $book = Book::first();
512 $bookPage = $book->pages->first();
513 $bookChapter = $book->chapters->first();
515 $bookUrl = $book->getUrl();
516 $this->actingAs($this->viewer)
517 ->visit($bookUrl . '/delete')
518 ->dontSee('Delete Book');
520 $this->setEntityRestrictions($book, ['view', 'update']);
522 $this->forceVisit($bookUrl . '/delete')
523 ->see('You do not have permission')->seePageIs('/');
524 $this->forceVisit($bookPage->getUrl() . '/delete')
525 ->see('You do not have permission')->seePageIs('/');
526 $this->forceVisit($bookChapter->getUrl() . '/delete')
527 ->see('You do not have permission')->seePageIs('/');
529 $this->setEntityRestrictions($book, ['view', 'delete']);
531 $this->visit($bookUrl . '/delete')
532 ->seePageIs($bookUrl . '/delete')->see('Delete Book');
533 $this->visit($bookPage->getUrl() . '/delete')
534 ->seePageIs($bookPage->getUrl() . '/delete')->see('Delete Page');
535 $this->visit($bookChapter->getUrl() . '/delete')
536 ->see('Delete Chapter');
539 public function test_page_visible_if_has_permissions_when_book_not_visible()
541 $book = Book::first();
543 $this->setEntityRestrictions($book, []);
545 $bookChapter = $book->chapters->first();
546 $bookPage = $bookChapter->pages->first();
547 $this->setEntityRestrictions($bookPage, ['view']);
549 $this->actingAs($this->viewer);
550 $this->get($bookPage->getUrl());
551 $this->assertResponseOk();
552 $this->see($bookPage->name);
553 $this->dontSee(substr($book->name, 0, 15));
554 $this->dontSee(substr($bookChapter->name, 0, 15));