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