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