]> BookStack Code Mirror - bookstack/blob - tests/Permissions/RestrictionsTest.php
Updated entity restrictions to allow permissions, Not just restrict
[bookstack] / tests / Permissions / RestrictionsTest.php
1 <?php
2
3 class RestrictionsTest extends TestCase
4 {
5     protected $user;
6     protected $viewer;
7
8     public function setUp()
9     {
10         parent::setUp();
11         $this->user = $this->getNewUser();
12         $this->viewer = $this->getViewer();
13     }
14
15     protected function getViewer()
16     {
17         $role = \BookStack\Role::getRole('viewer');
18         $viewer = $this->getNewBlankUser();
19         $viewer->attachRole($role);;
20         return $viewer;
21     }
22
23     /**
24      * Manually set some restrictions on an entity.
25      * @param \BookStack\Entity $entity
26      * @param $actions
27      */
28     protected function setEntityRestrictions(\BookStack\Entity $entity, $actions)
29     {
30         $entity->restricted = true;
31         $entity->restrictions()->delete();
32         $role = $this->user->roles->first();
33         $viewerRole = $this->viewer->roles->first();
34         foreach ($actions as $action) {
35             $entity->restrictions()->create([
36                 'role_id' => $role->id,
37                 'action' => strtolower($action)
38             ]);
39             $entity->restrictions()->create([
40                 'role_id' => $viewerRole->id,
41                 'action' => strtolower($action)
42             ]);
43         }
44         $entity->save();
45         $entity->load('restrictions');
46     }
47
48     public function test_book_view_restriction()
49     {
50         $book = \BookStack\Book::first();
51         $bookPage = $book->pages->first();
52         $bookChapter = $book->chapters->first();
53
54         $bookUrl = $book->getUrl();
55         $this->actingAs($this->user)
56             ->visit($bookUrl)
57             ->seePageIs($bookUrl);
58
59         $this->setEntityRestrictions($book, []);
60
61         $this->forceVisit($bookUrl)
62             ->see('Book not found');
63         $this->forceVisit($bookPage->getUrl())
64             ->see('Book not found');
65         $this->forceVisit($bookChapter->getUrl())
66             ->see('Book not found');
67
68         $this->setEntityRestrictions($book, ['view']);
69
70         $this->visit($bookUrl)
71             ->see($book->name);
72         $this->visit($bookPage->getUrl())
73             ->see($bookPage->name);
74         $this->visit($bookChapter->getUrl())
75             ->see($bookChapter->name);
76     }
77
78     public function test_book_create_restriction()
79     {
80         $book = \BookStack\Book::first();
81
82         $bookUrl = $book->getUrl();
83         $this->actingAs($this->viewer)
84             ->visit($bookUrl)
85             ->dontSeeInElement('.action-buttons', 'New Page')
86             ->dontSeeInElement('.action-buttons', 'New Chapter');
87         $this->actingAs($this->user)
88             ->visit($bookUrl)
89             ->seeInElement('.action-buttons', 'New Page')
90             ->seeInElement('.action-buttons', 'New Chapter');
91
92         $this->setEntityRestrictions($book, ['view', 'delete', 'update']);
93
94         $this->forceVisit($bookUrl . '/chapter/create')
95             ->see('You do not have permission')->seePageIs('/');
96         $this->forceVisit($bookUrl . '/page/create')
97             ->see('You do not have permission')->seePageIs('/');
98         $this->visit($bookUrl)->dontSeeInElement('.action-buttons', 'New Page')
99             ->dontSeeInElement('.action-buttons', 'New Chapter');
100
101         $this->setEntityRestrictions($book, ['view', 'create']);
102
103         $this->visit($bookUrl . '/chapter/create')
104             ->type('test chapter', 'name')
105             ->type('test description for chapter', 'description')
106             ->press('Save Chapter')
107             ->seePageIs($bookUrl . '/chapter/test-chapter');
108         $this->visit($bookUrl . '/page/create')
109             ->type('test page', 'name')
110             ->type('test content', 'html')
111             ->press('Save Page')
112             ->seePageIs($bookUrl . '/page/test-page');
113         $this->visit($bookUrl)->seeInElement('.action-buttons', 'New Page')
114             ->seeInElement('.action-buttons', 'New Chapter');
115     }
116
117     public function test_book_update_restriction()
118     {
119         $book = \BookStack\Book::first();
120         $bookPage = $book->pages->first();
121         $bookChapter = $book->chapters->first();
122
123         $bookUrl = $book->getUrl();
124         $this->actingAs($this->user)
125             ->visit($bookUrl . '/edit')
126             ->see('Edit Book');
127
128         $this->setEntityRestrictions($book, ['view', 'delete']);
129
130         $this->forceVisit($bookUrl . '/edit')
131             ->see('You do not have permission')->seePageIs('/');
132         $this->forceVisit($bookPage->getUrl() . '/edit')
133             ->see('You do not have permission')->seePageIs('/');
134         $this->forceVisit($bookChapter->getUrl() . '/edit')
135             ->see('You do not have permission')->seePageIs('/');
136
137         $this->setEntityRestrictions($book, ['view', 'update']);
138
139         $this->visit($bookUrl . '/edit')
140             ->seePageIs($bookUrl . '/edit');
141         $this->visit($bookPage->getUrl() . '/edit')
142             ->seePageIs($bookPage->getUrl() . '/edit');
143         $this->visit($bookChapter->getUrl() . '/edit')
144             ->see('Edit Chapter');
145     }
146
147     public function test_book_delete_restriction()
148     {
149         $book = \BookStack\Book::first();
150         $bookPage = $book->pages->first();
151         $bookChapter = $book->chapters->first();
152
153         $bookUrl = $book->getUrl();
154         $this->actingAs($this->user)
155             ->visit($bookUrl . '/delete')
156             ->see('Delete Book');
157
158         $this->setEntityRestrictions($book, ['view', 'update']);
159
160         $this->forceVisit($bookUrl . '/delete')
161             ->see('You do not have permission')->seePageIs('/');
162         $this->forceVisit($bookPage->getUrl() . '/delete')
163             ->see('You do not have permission')->seePageIs('/');
164         $this->forceVisit($bookChapter->getUrl() . '/delete')
165             ->see('You do not have permission')->seePageIs('/');
166
167         $this->setEntityRestrictions($book, ['view', 'delete']);
168
169         $this->visit($bookUrl . '/delete')
170             ->seePageIs($bookUrl . '/delete')->see('Delete Book');
171         $this->visit($bookPage->getUrl() . '/delete')
172             ->seePageIs($bookPage->getUrl() . '/delete')->see('Delete Page');
173         $this->visit($bookChapter->getUrl() . '/delete')
174             ->see('Delete Chapter');
175     }
176
177     public function test_chapter_view_restriction()
178     {
179         $chapter = \BookStack\Chapter::first();
180         $chapterPage = $chapter->pages->first();
181
182         $chapterUrl = $chapter->getUrl();
183         $this->actingAs($this->user)
184             ->visit($chapterUrl)
185             ->seePageIs($chapterUrl);
186
187         $this->setEntityRestrictions($chapter, []);
188
189         $this->forceVisit($chapterUrl)
190             ->see('Chapter not found');
191         $this->forceVisit($chapterPage->getUrl())
192             ->see('Page not found');
193
194         $this->setEntityRestrictions($chapter, ['view']);
195
196         $this->visit($chapterUrl)
197             ->see($chapter->name);
198         $this->visit($chapterPage->getUrl())
199             ->see($chapterPage->name);
200     }
201
202     public function test_chapter_create_restriction()
203     {
204         $chapter = \BookStack\Chapter::first();
205
206         $chapterUrl = $chapter->getUrl();
207         $this->actingAs($this->user)
208             ->visit($chapterUrl)
209             ->seeInElement('.action-buttons', 'New Page');
210
211         $this->setEntityRestrictions($chapter, ['view', 'delete', 'update']);
212
213         $this->forceVisit($chapterUrl . '/create-page')
214             ->see('You do not have permission')->seePageIs('/');
215         $this->visit($chapterUrl)->dontSeeInElement('.action-buttons', 'New Page');
216
217         $this->setEntityRestrictions($chapter, ['view', 'create']);
218
219
220         $this->visit($chapterUrl . '/create-page')
221             ->type('test page', 'name')
222             ->type('test content', 'html')
223             ->press('Save Page')
224             ->seePageIs($chapter->book->getUrl() . '/page/test-page');
225         $this->visit($chapterUrl)->seeInElement('.action-buttons', 'New Page');
226     }
227
228     public function test_chapter_update_restriction()
229     {
230         $chapter = \BookStack\Chapter::first();
231         $chapterPage = $chapter->pages->first();
232
233         $chapterUrl = $chapter->getUrl();
234         $this->actingAs($this->user)
235             ->visit($chapterUrl . '/edit')
236             ->see('Edit Chapter');
237
238         $this->setEntityRestrictions($chapter, ['view', 'delete']);
239
240         $this->forceVisit($chapterUrl . '/edit')
241             ->see('You do not have permission')->seePageIs('/');
242         $this->forceVisit($chapterPage->getUrl() . '/edit')
243             ->see('You do not have permission')->seePageIs('/');
244
245         $this->setEntityRestrictions($chapter, ['view', 'update']);
246
247         $this->visit($chapterUrl . '/edit')
248             ->seePageIs($chapterUrl . '/edit')->see('Edit Chapter');
249         $this->visit($chapterPage->getUrl() . '/edit')
250             ->seePageIs($chapterPage->getUrl() . '/edit');
251     }
252
253     public function test_chapter_delete_restriction()
254     {
255         $chapter = \BookStack\Chapter::first();
256         $chapterPage = $chapter->pages->first();
257
258         $chapterUrl = $chapter->getUrl();
259         $this->actingAs($this->user)
260             ->visit($chapterUrl . '/delete')
261             ->see('Delete Chapter');
262
263         $this->setEntityRestrictions($chapter, ['view', 'update']);
264
265         $this->forceVisit($chapterUrl . '/delete')
266             ->see('You do not have permission')->seePageIs('/');
267         $this->forceVisit($chapterPage->getUrl() . '/delete')
268             ->see('You do not have permission')->seePageIs('/');
269
270         $this->setEntityRestrictions($chapter, ['view', 'delete']);
271
272         $this->visit($chapterUrl . '/delete')
273             ->seePageIs($chapterUrl . '/delete')->see('Delete Chapter');
274         $this->visit($chapterPage->getUrl() . '/delete')
275             ->seePageIs($chapterPage->getUrl() . '/delete')->see('Delete Page');
276     }
277
278     public function test_page_view_restriction()
279     {
280         $page = \BookStack\Page::first();
281
282         $pageUrl = $page->getUrl();
283         $this->actingAs($this->user)
284             ->visit($pageUrl)
285             ->seePageIs($pageUrl);
286
287         $this->setEntityRestrictions($page, ['update', 'delete']);
288
289         $this->forceVisit($pageUrl)
290             ->see('Page not found');
291
292         $this->setEntityRestrictions($page, ['view']);
293
294         $this->visit($pageUrl)
295             ->see($page->name);
296     }
297
298     public function test_page_update_restriction()
299     {
300         $page = \BookStack\Chapter::first();
301
302         $pageUrl = $page->getUrl();
303         $this->actingAs($this->user)
304             ->visit($pageUrl . '/edit')
305             ->seeInField('name', $page->name);
306
307         $this->setEntityRestrictions($page, ['view', 'delete']);
308
309         $this->forceVisit($pageUrl . '/edit')
310             ->see('You do not have permission')->seePageIs('/');
311
312         $this->setEntityRestrictions($page, ['view', 'update']);
313
314         $this->visit($pageUrl . '/edit')
315             ->seePageIs($pageUrl . '/edit')->seeInField('name', $page->name);
316     }
317
318     public function test_page_delete_restriction()
319     {
320         $page = \BookStack\Page::first();
321
322         $pageUrl = $page->getUrl();
323         $this->actingAs($this->user)
324             ->visit($pageUrl . '/delete')
325             ->see('Delete Page');
326
327         $this->setEntityRestrictions($page, ['view', 'update']);
328
329         $this->forceVisit($pageUrl . '/delete')
330             ->see('You do not have permission')->seePageIs('/');
331
332         $this->setEntityRestrictions($page, ['view', 'delete']);
333
334         $this->visit($pageUrl . '/delete')
335             ->seePageIs($pageUrl . '/delete')->see('Delete Page');
336     }
337
338     public function test_book_restriction_form()
339     {
340         $book = \BookStack\Book::first();
341         $this->asAdmin()->visit($book->getUrl() . '/permissions')
342             ->see('Book Permissions')
343             ->check('restricted')
344             ->check('restrictions[2][view]')
345             ->press('Save Permissions')
346             ->seeInDatabase('books', ['id' => $book->id, 'restricted' => true])
347             ->seeInDatabase('restrictions', [
348                 'restrictable_id' => $book->id,
349                 'restrictable_type' => 'BookStack\Book',
350                 'role_id' => '2',
351                 'action' => 'view'
352             ]);
353     }
354
355     public function test_chapter_restriction_form()
356     {
357         $chapter = \BookStack\Chapter::first();
358         $this->asAdmin()->visit($chapter->getUrl() . '/permissions')
359             ->see('Chapter Permissions')
360             ->check('restricted')
361             ->check('restrictions[2][update]')
362             ->press('Save Permissions')
363             ->seeInDatabase('chapters', ['id' => $chapter->id, 'restricted' => true])
364             ->seeInDatabase('restrictions', [
365                 'restrictable_id' => $chapter->id,
366                 'restrictable_type' => 'BookStack\Chapter',
367                 'role_id' => '2',
368                 'action' => 'update'
369             ]);
370     }
371
372     public function test_page_restriction_form()
373     {
374         $page = \BookStack\Page::first();
375         $this->asAdmin()->visit($page->getUrl() . '/permissions')
376             ->see('Page Permissions')
377             ->check('restricted')
378             ->check('restrictions[2][delete]')
379             ->press('Save Permissions')
380             ->seeInDatabase('pages', ['id' => $page->id, 'restricted' => true])
381             ->seeInDatabase('restrictions', [
382                 'restrictable_id' => $page->id,
383                 'restrictable_type' => 'BookStack\Page',
384                 'role_id' => '2',
385                 'action' => 'delete'
386             ]);
387     }
388
389     public function test_restricted_pages_not_visible_in_book_navigation_on_pages()
390     {
391         $chapter = \BookStack\Chapter::first();
392         $page = $chapter->pages->first();
393         $page2 = $chapter->pages[2];
394
395         $this->setEntityRestrictions($page, []);
396
397         $this->actingAs($this->user)
398             ->visit($page2->getUrl())
399             ->dontSeeInElement('.sidebar-page-list', $page->name);
400     }
401
402     public function test_restricted_pages_not_visible_in_book_navigation_on_chapters()
403     {
404         $chapter = \BookStack\Chapter::first();
405         $page = $chapter->pages->first();
406
407         $this->setEntityRestrictions($page, []);
408
409         $this->actingAs($this->user)
410             ->visit($chapter->getUrl())
411             ->dontSeeInElement('.sidebar-page-list', $page->name);
412     }
413
414     public function test_restricted_pages_not_visible_on_chapter_pages()
415     {
416         $chapter = \BookStack\Chapter::first();
417         $page = $chapter->pages->first();
418
419         $this->setEntityRestrictions($page, []);
420
421         $this->actingAs($this->user)
422             ->visit($chapter->getUrl())
423             ->dontSee($page->name);
424     }
425
426     public function test_book_create_restriction_override()
427     {
428         $book = \BookStack\Book::first();
429
430         $bookUrl = $book->getUrl();
431         $this->actingAs($this->viewer)
432             ->visit($bookUrl)
433             ->dontSeeInElement('.action-buttons', 'New Page')
434             ->dontSeeInElement('.action-buttons', 'New Chapter');
435
436         $this->setEntityRestrictions($book, ['view', 'delete', 'update']);
437
438         $this->forceVisit($bookUrl . '/chapter/create')
439             ->see('You do not have permission')->seePageIs('/');
440         $this->forceVisit($bookUrl . '/page/create')
441             ->see('You do not have permission')->seePageIs('/');
442         $this->visit($bookUrl)->dontSeeInElement('.action-buttons', 'New Page')
443             ->dontSeeInElement('.action-buttons', 'New Chapter');
444
445         $this->setEntityRestrictions($book, ['view', 'create']);
446
447         $this->visit($bookUrl . '/chapter/create')
448             ->type('test chapter', 'name')
449             ->type('test description for chapter', 'description')
450             ->press('Save Chapter')
451             ->seePageIs($bookUrl . '/chapter/test-chapter');
452         $this->visit($bookUrl . '/page/create')
453             ->type('test page', 'name')
454             ->type('test content', 'html')
455             ->press('Save Page')
456             ->seePageIs($bookUrl . '/page/test-page');
457         $this->visit($bookUrl)->seeInElement('.action-buttons', 'New Page')
458             ->seeInElement('.action-buttons', 'New Chapter');
459     }
460
461     public function test_book_update_restriction_override()
462     {
463         $book = \BookStack\Book::first();
464         $bookPage = $book->pages->first();
465         $bookChapter = $book->chapters->first();
466
467         $bookUrl = $book->getUrl();
468         $this->actingAs($this->viewer)
469             ->visit($bookUrl . '/edit')
470             ->dontSee('Edit Book');
471
472         $this->setEntityRestrictions($book, ['view', 'delete']);
473
474         $this->forceVisit($bookUrl . '/edit')
475             ->see('You do not have permission')->seePageIs('/');
476         $this->forceVisit($bookPage->getUrl() . '/edit')
477             ->see('You do not have permission')->seePageIs('/');
478         $this->forceVisit($bookChapter->getUrl() . '/edit')
479             ->see('You do not have permission')->seePageIs('/');
480
481         $this->setEntityRestrictions($book, ['view', 'update']);
482
483         $this->visit($bookUrl . '/edit')
484             ->seePageIs($bookUrl . '/edit');
485         $this->visit($bookPage->getUrl() . '/edit')
486             ->seePageIs($bookPage->getUrl() . '/edit');
487         $this->visit($bookChapter->getUrl() . '/edit')
488             ->see('Edit Chapter');
489     }
490
491     public function test_book_delete_restriction_override()
492     {
493         $book = \BookStack\Book::first();
494         $bookPage = $book->pages->first();
495         $bookChapter = $book->chapters->first();
496
497         $bookUrl = $book->getUrl();
498         $this->actingAs($this->viewer)
499             ->visit($bookUrl . '/delete')
500             ->dontSee('Delete Book');
501
502         $this->setEntityRestrictions($book, ['view', 'update']);
503
504         $this->forceVisit($bookUrl . '/delete')
505             ->see('You do not have permission')->seePageIs('/');
506         $this->forceVisit($bookPage->getUrl() . '/delete')
507             ->see('You do not have permission')->seePageIs('/');
508         $this->forceVisit($bookChapter->getUrl() . '/delete')
509             ->see('You do not have permission')->seePageIs('/');
510
511         $this->setEntityRestrictions($book, ['view', 'delete']);
512
513         $this->visit($bookUrl . '/delete')
514             ->seePageIs($bookUrl . '/delete')->see('Delete Book');
515         $this->visit($bookPage->getUrl() . '/delete')
516             ->seePageIs($bookPage->getUrl() . '/delete')->see('Delete Page');
517         $this->visit($bookChapter->getUrl() . '/delete')
518             ->see('Delete Chapter');
519     }
520
521 }