]> BookStack Code Mirror - bookstack/blob - tests/Permissions/RestrictionsTest.php
Adds overflow:auto to popup content to allow it to scroll in lower res.
[bookstack] / tests / Permissions / RestrictionsTest.php
1 <?php namespace Tests;
2
3 use BookStack\Book;
4 use BookStack\Services\PermissionService;
5 use BookStack\User;
6
7 class RestrictionsTest extends BrowserKitTest
8 {
9
10     /**
11      * @var User
12      */
13     protected $user;
14
15     /**
16      * @var User
17      */
18     protected $viewer;
19
20     /**
21      * @var PermissionService
22      */
23     protected $permissionService;
24
25     public function setUp()
26     {
27         parent::setUp();
28         $this->user = $this->getEditor();
29         $this->viewer = $this->getViewer();
30         $this->permissionService = $this->app[PermissionService::class];
31     }
32
33     /**
34      * Manually set some permissions on an entity.
35      * @param \BookStack\Entity $entity
36      * @param $actions
37      */
38     protected function setEntityRestrictions(\BookStack\Entity $entity, $actions)
39     {
40         $entity->restricted = true;
41         $entity->permissions()->delete();
42
43         $role = $this->user->roles->first();
44         $viewerRole = $this->viewer->roles->first();
45
46         $permissions = [];
47         foreach ($actions as $action) {
48             $permissions[] = [
49                 'role_id' => $role->id,
50                 'action' => strtolower($action)
51             ];
52             $permissions[] = [
53                 'role_id' => $viewerRole->id,
54                 'action' => strtolower($action)
55             ];
56         }
57         $entity->permissions()->createMany($permissions);
58
59         $entity->save();
60         $entity->load('permissions');
61         $this->permissionService->buildJointPermissionsForEntity($entity);
62         $entity->load('jointPermissions');
63     }
64
65     public function test_book_view_restriction()
66     {
67         $book = Book::first();
68         $bookPage = $book->pages->first();
69         $bookChapter = $book->chapters->first();
70
71         $bookUrl = $book->getUrl();
72         $this->actingAs($this->user)
73             ->visit($bookUrl)
74             ->seePageIs($bookUrl);
75
76         $this->setEntityRestrictions($book, []);
77
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');
84
85         $this->setEntityRestrictions($book, ['view']);
86
87         $this->visit($bookUrl)
88             ->see($book->name);
89         $this->visit($bookPage->getUrl())
90             ->see($bookPage->name);
91         $this->visit($bookChapter->getUrl())
92             ->see($bookChapter->name);
93     }
94
95     public function test_book_create_restriction()
96     {
97         $book = Book::first();
98
99         $bookUrl = $book->getUrl();
100         $this->actingAs($this->viewer)
101             ->visit($bookUrl)
102             ->dontSeeInElement('.action-buttons', 'New Page')
103             ->dontSeeInElement('.action-buttons', 'New Chapter');
104         $this->actingAs($this->user)
105             ->visit($bookUrl)
106             ->seeInElement('.action-buttons', 'New Page')
107             ->seeInElement('.action-buttons', 'New Chapter');
108
109         $this->setEntityRestrictions($book, ['view', 'delete', 'update']);
110
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');
117
118         $this->setEntityRestrictions($book, ['view', 'create']);
119
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')
128             ->press('Save Page')
129             ->seePageIs($bookUrl . '/page/test-page');
130         $this->visit($bookUrl)->seeInElement('.action-buttons', 'New Page')
131             ->seeInElement('.action-buttons', 'New Chapter');
132     }
133
134     public function test_book_update_restriction()
135     {
136         $book = Book::first();
137         $bookPage = $book->pages->first();
138         $bookChapter = $book->chapters->first();
139
140         $bookUrl = $book->getUrl();
141         $this->actingAs($this->user)
142             ->visit($bookUrl . '/edit')
143             ->see('Edit Book');
144
145         $this->setEntityRestrictions($book, ['view', 'delete']);
146
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('/');
153
154         $this->setEntityRestrictions($book, ['view', 'update']);
155
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');
162     }
163
164     public function test_book_delete_restriction()
165     {
166         $book = Book::first();
167         $bookPage = $book->pages->first();
168         $bookChapter = $book->chapters->first();
169
170         $bookUrl = $book->getUrl();
171         $this->actingAs($this->user)
172             ->visit($bookUrl . '/delete')
173             ->see('Delete Book');
174
175         $this->setEntityRestrictions($book, ['view', 'update']);
176
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('/');
183
184         $this->setEntityRestrictions($book, ['view', 'delete']);
185
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');
192     }
193
194     public function test_chapter_view_restriction()
195     {
196         $chapter = \BookStack\Chapter::first();
197         $chapterPage = $chapter->pages->first();
198
199         $chapterUrl = $chapter->getUrl();
200         $this->actingAs($this->user)
201             ->visit($chapterUrl)
202             ->seePageIs($chapterUrl);
203
204         $this->setEntityRestrictions($chapter, []);
205
206         $this->forceVisit($chapterUrl)
207             ->see('Chapter not found');
208         $this->forceVisit($chapterPage->getUrl())
209             ->see('Page not found');
210
211         $this->setEntityRestrictions($chapter, ['view']);
212
213         $this->visit($chapterUrl)
214             ->see($chapter->name);
215         $this->visit($chapterPage->getUrl())
216             ->see($chapterPage->name);
217     }
218
219     public function test_chapter_create_restriction()
220     {
221         $chapter = \BookStack\Chapter::first();
222
223         $chapterUrl = $chapter->getUrl();
224         $this->actingAs($this->user)
225             ->visit($chapterUrl)
226             ->seeInElement('.action-buttons', 'New Page');
227
228         $this->setEntityRestrictions($chapter, ['view', 'delete', 'update']);
229
230         $this->forceVisit($chapterUrl . '/create-page')
231             ->see('You do not have permission')->seePageIs('/');
232         $this->visit($chapterUrl)->dontSeeInElement('.action-buttons', 'New Page');
233
234         $this->setEntityRestrictions($chapter, ['view', 'create']);
235
236
237         $this->visit($chapterUrl . '/create-page')
238             ->type('test page', 'name')
239             ->type('test content', 'html')
240             ->press('Save Page')
241             ->seePageIs($chapter->book->getUrl() . '/page/test-page');
242
243         $this->visit($chapterUrl)->seeInElement('.action-buttons', 'New Page');
244     }
245
246     public function test_chapter_update_restriction()
247     {
248         $chapter = \BookStack\Chapter::first();
249         $chapterPage = $chapter->pages->first();
250
251         $chapterUrl = $chapter->getUrl();
252         $this->actingAs($this->user)
253             ->visit($chapterUrl . '/edit')
254             ->see('Edit Chapter');
255
256         $this->setEntityRestrictions($chapter, ['view', 'delete']);
257
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('/');
262
263         $this->setEntityRestrictions($chapter, ['view', 'update']);
264
265         $this->visit($chapterUrl . '/edit')
266             ->seePageIs($chapterUrl . '/edit')->see('Edit Chapter');
267         $this->visit($chapterPage->getUrl() . '/edit')
268             ->seePageIs($chapterPage->getUrl() . '/edit');
269     }
270
271     public function test_chapter_delete_restriction()
272     {
273         $chapter = \BookStack\Chapter::first();
274         $chapterPage = $chapter->pages->first();
275
276         $chapterUrl = $chapter->getUrl();
277         $this->actingAs($this->user)
278             ->visit($chapterUrl . '/delete')
279             ->see('Delete Chapter');
280
281         $this->setEntityRestrictions($chapter, ['view', 'update']);
282
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('/');
287
288         $this->setEntityRestrictions($chapter, ['view', 'delete']);
289
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');
294     }
295
296     public function test_page_view_restriction()
297     {
298         $page = \BookStack\Page::first();
299
300         $pageUrl = $page->getUrl();
301         $this->actingAs($this->user)
302             ->visit($pageUrl)
303             ->seePageIs($pageUrl);
304
305         $this->setEntityRestrictions($page, ['update', 'delete']);
306
307         $this->forceVisit($pageUrl)
308             ->see('Page not found');
309
310         $this->setEntityRestrictions($page, ['view']);
311
312         $this->visit($pageUrl)
313             ->see($page->name);
314     }
315
316     public function test_page_update_restriction()
317     {
318         $page = \BookStack\Chapter::first();
319
320         $pageUrl = $page->getUrl();
321         $this->actingAs($this->user)
322             ->visit($pageUrl . '/edit')
323             ->seeInField('name', $page->name);
324
325         $this->setEntityRestrictions($page, ['view', 'delete']);
326
327         $this->forceVisit($pageUrl . '/edit')
328             ->see('You do not have permission')->seePageIs('/');
329
330         $this->setEntityRestrictions($page, ['view', 'update']);
331
332         $this->visit($pageUrl . '/edit')
333             ->seePageIs($pageUrl . '/edit')->seeInField('name', $page->name);
334     }
335
336     public function test_page_delete_restriction()
337     {
338         $page = \BookStack\Page::first();
339
340         $pageUrl = $page->getUrl();
341         $this->actingAs($this->user)
342             ->visit($pageUrl . '/delete')
343             ->see('Delete Page');
344
345         $this->setEntityRestrictions($page, ['view', 'update']);
346
347         $this->forceVisit($pageUrl . '/delete')
348             ->see('You do not have permission')->seePageIs('/');
349
350         $this->setEntityRestrictions($page, ['view', 'delete']);
351
352         $this->visit($pageUrl . '/delete')
353             ->seePageIs($pageUrl . '/delete')->see('Delete Page');
354     }
355
356     public function test_book_restriction_form()
357     {
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',
368                 'role_id' => '2',
369                 'action' => 'view'
370             ]);
371     }
372
373     public function test_chapter_restriction_form()
374     {
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',
385                 'role_id' => '2',
386                 'action' => 'update'
387             ]);
388     }
389
390     public function test_page_restriction_form()
391     {
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',
402                 'role_id' => '2',
403                 'action' => 'delete'
404             ]);
405     }
406
407     public function test_restricted_pages_not_visible_in_book_navigation_on_pages()
408     {
409         $chapter = \BookStack\Chapter::first();
410         $page = $chapter->pages->first();
411         $page2 = $chapter->pages[2];
412
413         $this->setEntityRestrictions($page, []);
414
415         $this->actingAs($this->user)
416             ->visit($page2->getUrl())
417             ->dontSeeInElement('.sidebar-page-list', $page->name);
418     }
419
420     public function test_restricted_pages_not_visible_in_book_navigation_on_chapters()
421     {
422         $chapter = \BookStack\Chapter::first();
423         $page = $chapter->pages->first();
424
425         $this->setEntityRestrictions($page, []);
426
427         $this->actingAs($this->user)
428             ->visit($chapter->getUrl())
429             ->dontSeeInElement('.sidebar-page-list', $page->name);
430     }
431
432     public function test_restricted_pages_not_visible_on_chapter_pages()
433     {
434         $chapter = \BookStack\Chapter::first();
435         $page = $chapter->pages->first();
436
437         $this->setEntityRestrictions($page, []);
438
439         $this->actingAs($this->user)
440             ->visit($chapter->getUrl())
441             ->dontSee($page->name);
442     }
443
444     public function test_book_create_restriction_override()
445     {
446         $book = Book::first();
447
448         $bookUrl = $book->getUrl();
449         $this->actingAs($this->viewer)
450             ->visit($bookUrl)
451             ->dontSeeInElement('.action-buttons', 'New Page')
452             ->dontSeeInElement('.action-buttons', 'New Chapter');
453
454         $this->setEntityRestrictions($book, ['view', 'delete', 'update']);
455
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');
462
463         $this->setEntityRestrictions($book, ['view', 'create']);
464
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')
473             ->press('Save Page')
474             ->seePageIs($bookUrl . '/page/test-page');
475         $this->visit($bookUrl)->seeInElement('.action-buttons', 'New Page')
476             ->seeInElement('.action-buttons', 'New Chapter');
477     }
478
479     public function test_book_update_restriction_override()
480     {
481         $book = Book::first();
482         $bookPage = $book->pages->first();
483         $bookChapter = $book->chapters->first();
484
485         $bookUrl = $book->getUrl();
486         $this->actingAs($this->viewer)
487             ->visit($bookUrl . '/edit')
488             ->dontSee('Edit Book');
489
490         $this->setEntityRestrictions($book, ['view', 'delete']);
491
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('/');
498
499         $this->setEntityRestrictions($book, ['view', 'update']);
500
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');
507     }
508
509     public function test_book_delete_restriction_override()
510     {
511         $book = Book::first();
512         $bookPage = $book->pages->first();
513         $bookChapter = $book->chapters->first();
514
515         $bookUrl = $book->getUrl();
516         $this->actingAs($this->viewer)
517             ->visit($bookUrl . '/delete')
518             ->dontSee('Delete Book');
519
520         $this->setEntityRestrictions($book, ['view', 'update']);
521
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('/');
528
529         $this->setEntityRestrictions($book, ['view', 'delete']);
530
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');
537     }
538
539     public function test_page_visible_if_has_permissions_when_book_not_visible()
540     {
541         $book = Book::first();
542
543         $this->setEntityRestrictions($book, []);
544
545         $bookChapter = $book->chapters->first();
546         $bookPage = $bookChapter->pages->first();
547         $this->setEntityRestrictions($bookPage, ['view']);
548
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));
555     }
556
557 }