]> BookStack Code Mirror - bookstack/blob - tests/Permissions/EntityPermissionsTest.php
e88909dba16ef25f8455398b270e0657d64cd4aa
[bookstack] / tests / Permissions / EntityPermissionsTest.php
1 <?php
2
3 namespace Tests\Permissions;
4
5 use BookStack\Auth\User;
6 use BookStack\Entities\Models\Book;
7 use BookStack\Entities\Models\Bookshelf;
8 use BookStack\Entities\Models\Chapter;
9 use BookStack\Entities\Models\Entity;
10 use BookStack\Entities\Models\Page;
11 use Illuminate\Support\Str;
12 use Tests\TestCase;
13
14 class EntityPermissionsTest extends TestCase
15 {
16     protected User $user;
17     protected User $viewer;
18
19     protected function setUp(): void
20     {
21         parent::setUp();
22         $this->user = $this->getEditor();
23         $this->viewer = $this->getViewer();
24     }
25
26     protected function setRestrictionsForTestRoles(Entity $entity, array $actions = [])
27     {
28         $roles = [
29             $this->user->roles->first(),
30             $this->viewer->roles->first(),
31         ];
32         $this->entities->setPermissions($entity, $actions, $roles);
33     }
34
35     public function test_bookshelf_view_restriction()
36     {
37         $shelf = $this->entities->shelf();
38
39         $this->actingAs($this->user)
40             ->get($shelf->getUrl())
41             ->assertStatus(200);
42
43         $this->setRestrictionsForTestRoles($shelf, []);
44
45         $this->followingRedirects()->get($shelf->getUrl())
46             ->assertSee('Shelf not found');
47
48         $this->setRestrictionsForTestRoles($shelf, ['view']);
49
50         $this->get($shelf->getUrl())
51             ->assertSee($shelf->name);
52     }
53
54     public function test_bookshelf_update_restriction()
55     {
56         $shelf = $this->entities->shelf();
57
58         $this->actingAs($this->user)
59             ->get($shelf->getUrl('/edit'))
60             ->assertSee('Edit Shelf');
61
62         $this->setRestrictionsForTestRoles($shelf, ['view', 'delete']);
63
64         $resp = $this->get($shelf->getUrl('/edit'))
65             ->assertRedirect('/');
66         $this->followRedirects($resp)->assertSee('You do not have permission');
67
68         $this->setRestrictionsForTestRoles($shelf, ['view', 'update']);
69
70         $this->get($shelf->getUrl('/edit'))
71             ->assertOk();
72     }
73
74     public function test_bookshelf_delete_restriction()
75     {
76         $shelf = $this->entities->shelf();
77
78         $this->actingAs($this->user)
79             ->get($shelf->getUrl('/delete'))
80             ->assertSee('Delete Shelf');
81
82         $this->setRestrictionsForTestRoles($shelf, ['view', 'update']);
83
84         $this->get($shelf->getUrl('/delete'))->assertRedirect('/');
85         $this->get('/')->assertSee('You do not have permission');
86
87         $this->setRestrictionsForTestRoles($shelf, ['view', 'delete']);
88
89         $this->get($shelf->getUrl('/delete'))
90             ->assertOk()
91             ->assertSee('Delete Shelf');
92     }
93
94     public function test_book_view_restriction()
95     {
96         $book = $this->entities->book();
97         $bookPage = $book->pages->first();
98         $bookChapter = $book->chapters->first();
99
100         $bookUrl = $book->getUrl();
101         $this->actingAs($this->user)
102             ->get($bookUrl)
103             ->assertOk();
104
105         $this->setRestrictionsForTestRoles($book, []);
106
107         $this->followingRedirects()->get($bookUrl)
108             ->assertSee('Book not found');
109         $this->followingRedirects()->get($bookPage->getUrl())
110             ->assertSee('Page not found');
111         $this->followingRedirects()->get($bookChapter->getUrl())
112             ->assertSee('Chapter not found');
113
114         $this->setRestrictionsForTestRoles($book, ['view']);
115
116         $this->get($bookUrl)
117             ->assertSee($book->name);
118         $this->get($bookPage->getUrl())
119             ->assertSee($bookPage->name);
120         $this->get($bookChapter->getUrl())
121             ->assertSee($bookChapter->name);
122     }
123
124     public function test_book_create_restriction()
125     {
126         $book = $this->entities->book();
127
128         $bookUrl = $book->getUrl();
129         $resp = $this->actingAs($this->viewer)->get($bookUrl);
130         $this->withHtml($resp)->assertElementNotContains('.actions', 'New Page')
131             ->assertElementNotContains('.actions', 'New Chapter');
132         $resp = $this->actingAs($this->user)->get($bookUrl);
133         $this->withHtml($resp)->assertElementContains('.actions', 'New Page')
134             ->assertElementContains('.actions', 'New Chapter');
135
136         $this->setRestrictionsForTestRoles($book, ['view', 'delete', 'update']);
137
138         $this->get($bookUrl . '/create-chapter')->assertRedirect('/');
139         $this->get('/')->assertSee('You do not have permission');
140
141         $this->get($bookUrl . '/create-page')->assertRedirect('/');
142         $this->get('/')->assertSee('You do not have permission');
143
144         $resp = $this->get($bookUrl);
145         $this->withHtml($resp)->assertElementNotContains('.actions', 'New Page')
146             ->assertElementNotContains('.actions', 'New Chapter');
147
148         $this->setRestrictionsForTestRoles($book, ['view', 'create']);
149
150         $resp = $this->post($book->getUrl('/create-chapter'), [
151             'name'        => 'test chapter',
152             'description' => 'desc',
153         ]);
154         $resp->assertRedirect($book->getUrl('/chapter/test-chapter'));
155
156         $this->get($book->getUrl('/create-page'));
157         /** @var Page $page */
158         $page = Page::query()->where('draft', '=', true)->orderBy('id', 'desc')->first();
159         $resp = $this->post($page->getUrl(), [
160             'name' => 'test page',
161             'html' => 'test content',
162         ]);
163         $resp->assertRedirect($book->getUrl('/page/test-page'));
164
165         $resp = $this->get($bookUrl);
166         $this->withHtml($resp)->assertElementContains('.actions', 'New Page')
167             ->assertElementContains('.actions', 'New Chapter');
168     }
169
170     public function test_book_update_restriction()
171     {
172         $book = $this->entities->book();
173         $bookPage = $book->pages->first();
174         $bookChapter = $book->chapters->first();
175
176         $bookUrl = $book->getUrl();
177         $this->actingAs($this->user)
178             ->get($bookUrl . '/edit')
179             ->assertSee('Edit Book');
180
181         $this->setRestrictionsForTestRoles($book, ['view', 'delete']);
182
183         $this->get($bookUrl . '/edit')->assertRedirect('/');
184         $this->get('/')->assertSee('You do not have permission');
185         $this->get($bookPage->getUrl() . '/edit')->assertRedirect('/');
186         $this->get('/')->assertSee('You do not have permission');
187         $this->get($bookChapter->getUrl() . '/edit')->assertRedirect('/');
188         $this->get('/')->assertSee('You do not have permission');
189
190         $this->setRestrictionsForTestRoles($book, ['view', 'update']);
191
192         $this->get($bookUrl . '/edit')->assertOk();
193         $this->get($bookPage->getUrl() . '/edit')->assertOk();
194         $this->get($bookChapter->getUrl() . '/edit')->assertSee('Edit Chapter');
195     }
196
197     public function test_book_delete_restriction()
198     {
199         $book = $this->entities->book();
200         $bookPage = $book->pages->first();
201         $bookChapter = $book->chapters->first();
202
203         $bookUrl = $book->getUrl();
204         $this->actingAs($this->user)->get($bookUrl . '/delete')
205             ->assertSee('Delete Book');
206
207         $this->setRestrictionsForTestRoles($book, ['view', 'update']);
208
209         $this->get($bookUrl . '/delete')->assertRedirect('/');
210         $this->get('/')->assertSee('You do not have permission');
211         $this->get($bookPage->getUrl() . '/delete')->assertRedirect('/');
212         $this->get('/')->assertSee('You do not have permission');
213         $this->get($bookChapter->getUrl() . '/delete')->assertRedirect('/');
214         $this->get('/')->assertSee('You do not have permission');
215
216         $this->setRestrictionsForTestRoles($book, ['view', 'delete']);
217
218         $this->get($bookUrl . '/delete')->assertOk()->assertSee('Delete Book');
219         $this->get($bookPage->getUrl('/delete'))->assertOk()->assertSee('Delete Page');
220         $this->get($bookChapter->getUrl('/delete'))->assertSee('Delete Chapter');
221     }
222
223     public function test_chapter_view_restriction()
224     {
225         $chapter = $this->entities->chapter();
226         $chapterPage = $chapter->pages->first();
227
228         $chapterUrl = $chapter->getUrl();
229         $this->actingAs($this->user)->get($chapterUrl)->assertOk();
230
231         $this->setRestrictionsForTestRoles($chapter, []);
232
233         $this->followingRedirects()->get($chapterUrl)->assertSee('Chapter not found');
234         $this->followingRedirects()->get($chapterPage->getUrl())->assertSee('Page not found');
235
236         $this->setRestrictionsForTestRoles($chapter, ['view']);
237
238         $this->get($chapterUrl)->assertSee($chapter->name);
239         $this->get($chapterPage->getUrl())->assertSee($chapterPage->name);
240     }
241
242     public function test_chapter_create_restriction()
243     {
244         $chapter = $this->entities->chapter();
245
246         $chapterUrl = $chapter->getUrl();
247         $resp = $this->actingAs($this->user)->get($chapterUrl);
248         $this->withHtml($resp)->assertElementContains('.actions', 'New Page');
249
250         $this->setRestrictionsForTestRoles($chapter, ['view', 'delete', 'update']);
251
252         $this->get($chapterUrl . '/create-page')->assertRedirect('/');
253         $this->get('/')->assertSee('You do not have permission');
254         $this->withHtml($this->get($chapterUrl))->assertElementNotContains('.actions', 'New Page');
255
256         $this->setRestrictionsForTestRoles($chapter, ['view', 'create']);
257
258         $this->get($chapter->getUrl('/create-page'));
259         /** @var Page $page */
260         $page = Page::query()->where('draft', '=', true)->orderBy('id', 'desc')->first();
261         $resp = $this->post($page->getUrl(), [
262             'name' => 'test page',
263             'html' => 'test content',
264         ]);
265         $resp->assertRedirect($chapter->book->getUrl('/page/test-page'));
266
267         $this->withHtml($this->get($chapterUrl))->assertElementContains('.actions', 'New Page');
268     }
269
270     public function test_chapter_update_restriction()
271     {
272         $chapter = $this->entities->chapter();
273         $chapterPage = $chapter->pages->first();
274
275         $chapterUrl = $chapter->getUrl();
276         $this->actingAs($this->user)->get($chapterUrl . '/edit')
277             ->assertSee('Edit Chapter');
278
279         $this->setRestrictionsForTestRoles($chapter, ['view', 'delete']);
280
281         $this->get($chapterUrl . '/edit')->assertRedirect('/');
282         $this->get('/')->assertSee('You do not have permission');
283         $this->get($chapterPage->getUrl() . '/edit')->assertRedirect('/');
284         $this->get('/')->assertSee('You do not have permission');
285
286         $this->setRestrictionsForTestRoles($chapter, ['view', 'update']);
287
288         $this->get($chapterUrl . '/edit')->assertOk()->assertSee('Edit Chapter');
289         $this->get($chapterPage->getUrl() . '/edit')->assertOk();
290     }
291
292     public function test_chapter_delete_restriction()
293     {
294         $chapter = $this->entities->chapter();
295         $chapterPage = $chapter->pages->first();
296
297         $chapterUrl = $chapter->getUrl();
298         $this->actingAs($this->user)
299             ->get($chapterUrl . '/delete')
300             ->assertSee('Delete Chapter');
301
302         $this->setRestrictionsForTestRoles($chapter, ['view', 'update']);
303
304         $this->get($chapterUrl . '/delete')->assertRedirect('/');
305         $this->get('/')->assertSee('You do not have permission');
306         $this->get($chapterPage->getUrl() . '/delete')->assertRedirect('/');
307         $this->get('/')->assertSee('You do not have permission');
308
309         $this->setRestrictionsForTestRoles($chapter, ['view', 'delete']);
310
311         $this->get($chapterUrl . '/delete')->assertOk()->assertSee('Delete Chapter');
312         $this->get($chapterPage->getUrl() . '/delete')->assertOk()->assertSee('Delete Page');
313     }
314
315     public function test_page_view_restriction()
316     {
317         $page = $this->entities->page();
318
319         $pageUrl = $page->getUrl();
320         $this->actingAs($this->user)->get($pageUrl)->assertOk();
321
322         $this->setRestrictionsForTestRoles($page, ['update', 'delete']);
323
324         $this->get($pageUrl)->assertSee('Page not found');
325
326         $this->setRestrictionsForTestRoles($page, ['view']);
327
328         $this->get($pageUrl)->assertSee($page->name);
329     }
330
331     public function test_page_update_restriction()
332     {
333         $page = $this->entities->page();
334
335         $pageUrl = $page->getUrl();
336         $resp = $this->actingAs($this->user)
337             ->get($pageUrl . '/edit');
338         $this->withHtml($resp)->assertElementExists('input[name="name"][value="' . $page->name . '"]');
339
340         $this->setRestrictionsForTestRoles($page, ['view', 'delete']);
341
342         $this->get($pageUrl . '/edit')->assertRedirect('/');
343         $this->get('/')->assertSee('You do not have permission');
344
345         $this->setRestrictionsForTestRoles($page, ['view', 'update']);
346
347         $resp = $this->get($pageUrl . '/edit')
348             ->assertOk();
349         $this->withHtml($resp)->assertElementExists('input[name="name"][value="' . $page->name . '"]');
350     }
351
352     public function test_page_delete_restriction()
353     {
354         $page = $this->entities->page();
355
356         $pageUrl = $page->getUrl();
357         $this->actingAs($this->user)
358             ->get($pageUrl . '/delete')
359             ->assertSee('Delete Page');
360
361         $this->setRestrictionsForTestRoles($page, ['view', 'update']);
362
363         $this->get($pageUrl . '/delete')->assertRedirect('/');
364         $this->get('/')->assertSee('You do not have permission');
365
366         $this->setRestrictionsForTestRoles($page, ['view', 'delete']);
367
368         $this->get($pageUrl . '/delete')->assertOk()->assertSee('Delete Page');
369     }
370
371     protected function entityRestrictionFormTest(string $model, string $title, string $permission, string $roleId)
372     {
373         /** @var Entity $modelInstance */
374         $modelInstance = $model::query()->first();
375         $this->asAdmin()->get($modelInstance->getUrl('/permissions'))
376             ->assertSee($title);
377
378         $this->put($modelInstance->getUrl('/permissions'), [
379             'restrictions' => [
380                 $roleId => [
381                     $permission => 'true',
382                 ],
383             ],
384         ]);
385
386         $this->assertDatabaseHas($modelInstance->getTable(), ['id' => $modelInstance->id, 'restricted' => true]);
387         $this->assertDatabaseHas('entity_permissions', [
388             'restrictable_id'   => $modelInstance->id,
389             'restrictable_type' => $modelInstance->getMorphClass(),
390             'role_id'           => $roleId,
391             'action'            => $permission,
392         ]);
393     }
394
395     public function test_bookshelf_restriction_form()
396     {
397         $this->entityRestrictionFormTest(Bookshelf::class, 'Shelf Permissions', 'view', '2');
398     }
399
400     public function test_book_restriction_form()
401     {
402         $this->entityRestrictionFormTest(Book::class, 'Book Permissions', 'view', '2');
403     }
404
405     public function test_chapter_restriction_form()
406     {
407         $this->entityRestrictionFormTest(Chapter::class, 'Chapter Permissions', 'update', '2');
408     }
409
410     public function test_page_restriction_form()
411     {
412         $this->entityRestrictionFormTest(Page::class, 'Page Permissions', 'delete', '2');
413     }
414
415     public function test_restricted_pages_not_visible_in_book_navigation_on_pages()
416     {
417         $chapter = $this->entities->chapter();
418         $page = $chapter->pages->first();
419         $page2 = $chapter->pages[2];
420
421         $this->setRestrictionsForTestRoles($page, []);
422
423         $resp = $this->actingAs($this->user)->get($page2->getUrl());
424         $this->withHtml($resp)->assertElementNotContains('.sidebar-page-list', $page->name);
425     }
426
427     public function test_restricted_pages_not_visible_in_book_navigation_on_chapters()
428     {
429         $chapter = $this->entities->chapter();
430         $page = $chapter->pages->first();
431
432         $this->setRestrictionsForTestRoles($page, []);
433
434         $resp = $this->actingAs($this->user)->get($chapter->getUrl());
435         $this->withHtml($resp)->assertElementNotContains('.sidebar-page-list', $page->name);
436     }
437
438     public function test_restricted_pages_not_visible_on_chapter_pages()
439     {
440         $chapter = $this->entities->chapter();
441         $page = $chapter->pages->first();
442
443         $this->setRestrictionsForTestRoles($page, []);
444
445         $this->actingAs($this->user)
446             ->get($chapter->getUrl())
447             ->assertDontSee($page->name);
448     }
449
450     public function test_restricted_chapter_pages_not_visible_on_book_page()
451     {
452         $chapter = $this->entities->chapter();
453         $this->actingAs($this->user)
454             ->get($chapter->book->getUrl())
455             ->assertSee($chapter->pages->first()->name);
456
457         foreach ($chapter->pages as $page) {
458             $this->setRestrictionsForTestRoles($page, []);
459         }
460
461         $this->actingAs($this->user)
462             ->get($chapter->book->getUrl())
463             ->assertDontSee($chapter->pages->first()->name);
464     }
465
466     public function test_bookshelf_update_restriction_override()
467     {
468         $shelf = $this->entities->shelf();
469
470         $this->actingAs($this->viewer)
471             ->get($shelf->getUrl('/edit'))
472             ->assertDontSee('Edit Book');
473
474         $this->setRestrictionsForTestRoles($shelf, ['view', 'delete']);
475
476         $this->get($shelf->getUrl('/edit'))->assertRedirect('/');
477         $this->get('/')->assertSee('You do not have permission');
478
479         $this->setRestrictionsForTestRoles($shelf, ['view', 'update']);
480
481         $this->get($shelf->getUrl('/edit'))->assertOk();
482     }
483
484     public function test_bookshelf_delete_restriction_override()
485     {
486         $shelf = $this->entities->shelf();
487
488         $this->actingAs($this->viewer)
489             ->get($shelf->getUrl('/delete'))
490             ->assertDontSee('Delete Book');
491
492         $this->setRestrictionsForTestRoles($shelf, ['view', 'update']);
493
494         $this->get($shelf->getUrl('/delete'))->assertRedirect('/');
495         $this->get('/')->assertSee('You do not have permission');
496
497         $this->setRestrictionsForTestRoles($shelf, ['view', 'delete']);
498
499         $this->get($shelf->getUrl('/delete'))->assertOk()->assertSee('Delete Shelf');
500     }
501
502     public function test_book_create_restriction_override()
503     {
504         $book = $this->entities->book();
505
506         $bookUrl = $book->getUrl();
507         $resp = $this->actingAs($this->viewer)->get($bookUrl);
508         $this->withHtml($resp)->assertElementNotContains('.actions', 'New Page')
509             ->assertElementNotContains('.actions', 'New Chapter');
510
511         $this->setRestrictionsForTestRoles($book, ['view', 'delete', 'update']);
512
513         $this->get($bookUrl . '/create-chapter')->assertRedirect('/');
514         $this->get('/')->assertSee('You do not have permission');
515         $this->get($bookUrl . '/create-page')->assertRedirect('/');
516         $this->get('/')->assertSee('You do not have permission');
517         $resp = $this->get($bookUrl);
518         $this->withHtml($resp)->assertElementNotContains('.actions', 'New Page')
519             ->assertElementNotContains('.actions', 'New Chapter');
520
521         $this->setRestrictionsForTestRoles($book, ['view', 'create']);
522
523         $resp = $this->post($book->getUrl('/create-chapter'), [
524             'name'        => 'test chapter',
525             'description' => 'test desc',
526         ]);
527         $resp->assertRedirect($book->getUrl('/chapter/test-chapter'));
528
529         $this->get($book->getUrl('/create-page'));
530         /** @var Page $page */
531         $page = Page::query()->where('draft', '=', true)->orderByDesc('id')->first();
532         $resp = $this->post($page->getUrl(), [
533             'name' => 'test page',
534             'html' => 'test desc',
535         ]);
536         $resp->assertRedirect($book->getUrl('/page/test-page'));
537
538         $resp = $this->get($bookUrl);
539         $this->withHtml($resp)->assertElementContains('.actions', 'New Page')
540             ->assertElementContains('.actions', 'New Chapter');
541     }
542
543     public function test_book_update_restriction_override()
544     {
545         $book = $this->entities->book();
546         $bookPage = $book->pages->first();
547         $bookChapter = $book->chapters->first();
548
549         $bookUrl = $book->getUrl();
550         $this->actingAs($this->viewer)->get($bookUrl . '/edit')
551             ->assertDontSee('Edit Book');
552
553         $this->setRestrictionsForTestRoles($book, ['view', 'delete']);
554
555         $this->get($bookUrl . '/edit')->assertRedirect('/');
556         $this->get('/')->assertSee('You do not have permission');
557         $this->get($bookPage->getUrl() . '/edit')->assertRedirect('/');
558         $this->get('/')->assertSee('You do not have permission');
559         $this->get($bookChapter->getUrl() . '/edit')->assertRedirect('/');
560         $this->get('/')->assertSee('You do not have permission');
561
562         $this->setRestrictionsForTestRoles($book, ['view', 'update']);
563
564         $this->get($bookUrl . '/edit')->assertOk();
565         $this->get($bookPage->getUrl() . '/edit')->assertOk();
566         $this->get($bookChapter->getUrl() . '/edit')->assertSee('Edit Chapter');
567     }
568
569     public function test_book_delete_restriction_override()
570     {
571         $book = $this->entities->book();
572         $bookPage = $book->pages->first();
573         $bookChapter = $book->chapters->first();
574
575         $bookUrl = $book->getUrl();
576         $this->actingAs($this->viewer)
577             ->get($bookUrl . '/delete')
578             ->assertDontSee('Delete Book');
579
580         $this->setRestrictionsForTestRoles($book, ['view', 'update']);
581
582         $this->get($bookUrl . '/delete')->assertRedirect('/');
583         $this->get('/')->assertSee('You do not have permission');
584         $this->get($bookPage->getUrl() . '/delete')->assertRedirect('/');
585         $this->get('/')->assertSee('You do not have permission');
586         $this->get($bookChapter->getUrl() . '/delete')->assertRedirect('/');
587         $this->get('/')->assertSee('You do not have permission');
588
589         $this->setRestrictionsForTestRoles($book, ['view', 'delete']);
590
591         $this->get($bookUrl . '/delete')->assertOk()->assertSee('Delete Book');
592         $this->get($bookPage->getUrl() . '/delete')->assertOk()->assertSee('Delete Page');
593         $this->get($bookChapter->getUrl() . '/delete')->assertSee('Delete Chapter');
594     }
595
596     public function test_page_visible_if_has_permissions_when_book_not_visible()
597     {
598         $book = $this->entities->book();
599         $bookChapter = $book->chapters->first();
600         $bookPage = $bookChapter->pages->first();
601
602         foreach ([$book, $bookChapter, $bookPage] as $entity) {
603             $entity->name = Str::random(24);
604             $entity->save();
605         }
606
607         $this->setRestrictionsForTestRoles($book, []);
608         $this->setRestrictionsForTestRoles($bookPage, ['view']);
609
610         $this->actingAs($this->viewer);
611         $resp = $this->get($bookPage->getUrl());
612         $resp->assertOk();
613         $resp->assertSee($bookPage->name);
614         $resp->assertDontSee(substr($book->name, 0, 15));
615         $resp->assertDontSee(substr($bookChapter->name, 0, 15));
616     }
617
618     public function test_book_sort_view_permission()
619     {
620         /** @var Book $firstBook */
621         $firstBook = Book::query()->first();
622         /** @var Book $secondBook */
623         $secondBook = Book::query()->find(2);
624
625         $this->setRestrictionsForTestRoles($firstBook, ['view', 'update']);
626         $this->setRestrictionsForTestRoles($secondBook, ['view']);
627
628         // Test sort page visibility
629         $this->actingAs($this->user)->get($secondBook->getUrl('/sort'))->assertRedirect('/');
630         $this->get('/')->assertSee('You do not have permission');
631
632         // Check sort page on first book
633         $this->actingAs($this->user)->get($firstBook->getUrl('/sort'));
634     }
635
636     public function test_can_create_page_if_chapter_has_permissions_when_book_not_visible()
637     {
638         $book = $this->entities->book();
639         $this->setRestrictionsForTestRoles($book, []);
640         $bookChapter = $book->chapters->first();
641         $this->setRestrictionsForTestRoles($bookChapter, ['view']);
642
643         $this->actingAs($this->user)->get($bookChapter->getUrl())
644             ->assertDontSee('New Page');
645
646         $this->setRestrictionsForTestRoles($bookChapter, ['view', 'create']);
647
648         $this->get($bookChapter->getUrl('/create-page'));
649         /** @var Page $page */
650         $page = Page::query()->where('draft', '=', true)->orderByDesc('id')->first();
651         $resp = $this->post($page->getUrl(), [
652             'name' => 'test page',
653             'html' => 'test content',
654         ]);
655         $resp->assertRedirect($book->getUrl('/page/test-page'));
656     }
657 }