X-Git-Url: http://source.bookstackapp.com/bookstack/blobdiff_plain/cd6572b61af2165133468d2562d04dffdca8fca8..refs/pull/2393/head:/tests/Permissions/RestrictionsTest.php diff --git a/tests/Permissions/RestrictionsTest.php b/tests/Permissions/RestrictionsTest.php index cddd3206a..7da00e26e 100644 --- a/tests/Permissions/RestrictionsTest.php +++ b/tests/Permissions/RestrictionsTest.php @@ -1,57 +1,102 @@ -user = $this->getEditor(); $this->viewer = $this->getViewer(); - $this->restrictionService = $this->app[\BookStack\Services\PermissionService::class]; } - protected function getViewer() + protected function setEntityRestrictions(Entity $entity, $actions = [], $roles = []) { - $role = \BookStack\Role::getRole('viewer'); - $viewer = $this->getNewBlankUser(); - $viewer->attachRole($role);; - return $viewer; + $roles = [ + $this->user->roles->first(), + $this->viewer->roles->first(), + ]; + parent::setEntityRestrictions($entity, $actions, $roles); } - /** - * Manually set some permissions on an entity. - * @param \BookStack\Entity $entity - * @param $actions - */ - protected function setEntityRestrictions(\BookStack\Entity $entity, $actions) + public function test_bookshelf_view_restriction() { - $entity->restricted = true; - $entity->permissions()->delete(); - $role = $this->user->roles->first(); - $viewerRole = $this->viewer->roles->first(); - foreach ($actions as $action) { - $entity->permissions()->create([ - 'role_id' => $role->id, - 'action' => strtolower($action) - ]); - $entity->permissions()->create([ - 'role_id' => $viewerRole->id, - 'action' => strtolower($action) - ]); - } - $entity->save(); - $entity->load('permissions'); - $this->restrictionService->buildJointPermissionsForEntity($entity); - $entity->load('jointPermissions'); + $shelf = Bookshelf::first(); + + $this->actingAs($this->user) + ->visit($shelf->getUrl()) + ->seePageIs($shelf->getUrl()); + + $this->setEntityRestrictions($shelf, []); + + $this->forceVisit($shelf->getUrl()) + ->see('Bookshelf not found'); + + $this->setEntityRestrictions($shelf, ['view']); + + $this->visit($shelf->getUrl()) + ->see($shelf->name); + } + + public function test_bookshelf_update_restriction() + { + $shelf = Bookshelf::first(); + + $this->actingAs($this->user) + ->visit($shelf->getUrl('/edit')) + ->see('Edit Book'); + + $this->setEntityRestrictions($shelf, ['view', 'delete']); + + $this->forceVisit($shelf->getUrl('/edit')) + ->see('You do not have permission')->seePageIs('/'); + + $this->setEntityRestrictions($shelf, ['view', 'update']); + + $this->visit($shelf->getUrl('/edit')) + ->seePageIs($shelf->getUrl('/edit')); + } + + public function test_bookshelf_delete_restriction() + { + $shelf = Book::first(); + + $this->actingAs($this->user) + ->visit($shelf->getUrl('/delete')) + ->see('Delete Book'); + + $this->setEntityRestrictions($shelf, ['view', 'update']); + + $this->forceVisit($shelf->getUrl('/delete')) + ->see('You do not have permission')->seePageIs('/'); + + $this->setEntityRestrictions($shelf, ['view', 'delete']); + + $this->visit($shelf->getUrl('/delete')) + ->seePageIs($shelf->getUrl('/delete'))->see('Delete Book'); } public function test_book_view_restriction() { - $book = \BookStack\Book::first(); + $book = Book::first(); $bookPage = $book->pages->first(); $bookChapter = $book->chapters->first(); @@ -81,46 +126,46 @@ class RestrictionsTest extends TestCase public function test_book_create_restriction() { - $book = \BookStack\Book::first(); + $book = Book::first(); $bookUrl = $book->getUrl(); $this->actingAs($this->viewer) ->visit($bookUrl) - ->dontSeeInElement('.action-buttons', 'New Page') - ->dontSeeInElement('.action-buttons', 'New Chapter'); + ->dontSeeInElement('.actions', 'New Page') + ->dontSeeInElement('.actions', 'New Chapter'); $this->actingAs($this->user) ->visit($bookUrl) - ->seeInElement('.action-buttons', 'New Page') - ->seeInElement('.action-buttons', 'New Chapter'); + ->seeInElement('.actions', 'New Page') + ->seeInElement('.actions', 'New Chapter'); $this->setEntityRestrictions($book, ['view', 'delete', 'update']); - $this->forceVisit($bookUrl . '/chapter/create') + $this->forceVisit($bookUrl . '/create-chapter') ->see('You do not have permission')->seePageIs('/'); - $this->forceVisit($bookUrl . '/page/create') + $this->forceVisit($bookUrl . '/create-page') ->see('You do not have permission')->seePageIs('/'); - $this->visit($bookUrl)->dontSeeInElement('.action-buttons', 'New Page') - ->dontSeeInElement('.action-buttons', 'New Chapter'); + $this->visit($bookUrl)->dontSeeInElement('.actions', 'New Page') + ->dontSeeInElement('.actions', 'New Chapter'); $this->setEntityRestrictions($book, ['view', 'create']); - $this->visit($bookUrl . '/chapter/create') + $this->visit($bookUrl . '/create-chapter') ->type('test chapter', 'name') ->type('test description for chapter', 'description') ->press('Save Chapter') ->seePageIs($bookUrl . '/chapter/test-chapter'); - $this->visit($bookUrl . '/page/create') + $this->visit($bookUrl . '/create-page') ->type('test page', 'name') ->type('test content', 'html') ->press('Save Page') ->seePageIs($bookUrl . '/page/test-page'); - $this->visit($bookUrl)->seeInElement('.action-buttons', 'New Page') - ->seeInElement('.action-buttons', 'New Chapter'); + $this->visit($bookUrl)->seeInElement('.actions', 'New Page') + ->seeInElement('.actions', 'New Chapter'); } public function test_book_update_restriction() { - $book = \BookStack\Book::first(); + $book = Book::first(); $bookPage = $book->pages->first(); $bookChapter = $book->chapters->first(); @@ -150,7 +195,7 @@ class RestrictionsTest extends TestCase public function test_book_delete_restriction() { - $book = \BookStack\Book::first(); + $book = Book::first(); $bookPage = $book->pages->first(); $bookChapter = $book->chapters->first(); @@ -180,7 +225,7 @@ class RestrictionsTest extends TestCase public function test_chapter_view_restriction() { - $chapter = \BookStack\Chapter::first(); + $chapter = Chapter::first(); $chapterPage = $chapter->pages->first(); $chapterUrl = $chapter->getUrl(); @@ -205,18 +250,18 @@ class RestrictionsTest extends TestCase public function test_chapter_create_restriction() { - $chapter = \BookStack\Chapter::first(); + $chapter = Chapter::first(); $chapterUrl = $chapter->getUrl(); $this->actingAs($this->user) ->visit($chapterUrl) - ->seeInElement('.action-buttons', 'New Page'); + ->seeInElement('.actions', 'New Page'); $this->setEntityRestrictions($chapter, ['view', 'delete', 'update']); $this->forceVisit($chapterUrl . '/create-page') ->see('You do not have permission')->seePageIs('/'); - $this->visit($chapterUrl)->dontSeeInElement('.action-buttons', 'New Page'); + $this->visit($chapterUrl)->dontSeeInElement('.actions', 'New Page'); $this->setEntityRestrictions($chapter, ['view', 'create']); @@ -226,12 +271,13 @@ class RestrictionsTest extends TestCase ->type('test content', 'html') ->press('Save Page') ->seePageIs($chapter->book->getUrl() . '/page/test-page'); - $this->visit($chapterUrl)->seeInElement('.action-buttons', 'New Page'); + + $this->visit($chapterUrl)->seeInElement('.actions', 'New Page'); } public function test_chapter_update_restriction() { - $chapter = \BookStack\Chapter::first(); + $chapter = Chapter::first(); $chapterPage = $chapter->pages->first(); $chapterUrl = $chapter->getUrl(); @@ -256,7 +302,7 @@ class RestrictionsTest extends TestCase public function test_chapter_delete_restriction() { - $chapter = \BookStack\Chapter::first(); + $chapter = Chapter::first(); $chapterPage = $chapter->pages->first(); $chapterUrl = $chapter->getUrl(); @@ -281,7 +327,7 @@ class RestrictionsTest extends TestCase public function test_page_view_restriction() { - $page = \BookStack\Page::first(); + $page = Page::first(); $pageUrl = $page->getUrl(); $this->actingAs($this->user) @@ -301,7 +347,7 @@ class RestrictionsTest extends TestCase public function test_page_update_restriction() { - $page = \BookStack\Chapter::first(); + $page = Chapter::first(); $pageUrl = $page->getUrl(); $this->actingAs($this->user) @@ -321,7 +367,7 @@ class RestrictionsTest extends TestCase public function test_page_delete_restriction() { - $page = \BookStack\Page::first(); + $page = Page::first(); $pageUrl = $page->getUrl(); $this->actingAs($this->user) @@ -339,9 +385,26 @@ class RestrictionsTest extends TestCase ->seePageIs($pageUrl . '/delete')->see('Delete Page'); } + public function test_bookshelf_restriction_form() + { + $shelf = Bookshelf::first(); + $this->asAdmin()->visit($shelf->getUrl('/permissions')) + ->see('Bookshelf Permissions') + ->check('restricted') + ->check('restrictions[2][view]') + ->press('Save Permissions') + ->seeInDatabase('bookshelves', ['id' => $shelf->id, 'restricted' => true]) + ->seeInDatabase('entity_permissions', [ + 'restrictable_id' => $shelf->id, + 'restrictable_type' => Bookshelf::newModelInstance()->getMorphClass(), + 'role_id' => '2', + 'action' => 'view' + ]); + } + public function test_book_restriction_form() { - $book = \BookStack\Book::first(); + $book = Book::first(); $this->asAdmin()->visit($book->getUrl() . '/permissions') ->see('Book Permissions') ->check('restricted') @@ -350,7 +413,7 @@ class RestrictionsTest extends TestCase ->seeInDatabase('books', ['id' => $book->id, 'restricted' => true]) ->seeInDatabase('entity_permissions', [ 'restrictable_id' => $book->id, - 'restrictable_type' => 'BookStack\Book', + 'restrictable_type' => Book::newModelInstance()->getMorphClass(), 'role_id' => '2', 'action' => 'view' ]); @@ -358,7 +421,7 @@ class RestrictionsTest extends TestCase public function test_chapter_restriction_form() { - $chapter = \BookStack\Chapter::first(); + $chapter = Chapter::first(); $this->asAdmin()->visit($chapter->getUrl() . '/permissions') ->see('Chapter Permissions') ->check('restricted') @@ -367,7 +430,7 @@ class RestrictionsTest extends TestCase ->seeInDatabase('chapters', ['id' => $chapter->id, 'restricted' => true]) ->seeInDatabase('entity_permissions', [ 'restrictable_id' => $chapter->id, - 'restrictable_type' => 'BookStack\Chapter', + 'restrictable_type' => Chapter::newModelInstance()->getMorphClass(), 'role_id' => '2', 'action' => 'update' ]); @@ -375,7 +438,7 @@ class RestrictionsTest extends TestCase public function test_page_restriction_form() { - $page = \BookStack\Page::first(); + $page = Page::first(); $this->asAdmin()->visit($page->getUrl() . '/permissions') ->see('Page Permissions') ->check('restricted') @@ -384,7 +447,7 @@ class RestrictionsTest extends TestCase ->seeInDatabase('pages', ['id' => $page->id, 'restricted' => true]) ->seeInDatabase('entity_permissions', [ 'restrictable_id' => $page->id, - 'restrictable_type' => 'BookStack\Page', + 'restrictable_type' => Page::newModelInstance()->getMorphClass(), 'role_id' => '2', 'action' => 'delete' ]); @@ -392,7 +455,7 @@ class RestrictionsTest extends TestCase public function test_restricted_pages_not_visible_in_book_navigation_on_pages() { - $chapter = \BookStack\Chapter::first(); + $chapter = Chapter::first(); $page = $chapter->pages->first(); $page2 = $chapter->pages[2]; @@ -405,7 +468,7 @@ class RestrictionsTest extends TestCase public function test_restricted_pages_not_visible_in_book_navigation_on_chapters() { - $chapter = \BookStack\Chapter::first(); + $chapter = Chapter::first(); $page = $chapter->pages->first(); $this->setEntityRestrictions($page, []); @@ -417,7 +480,7 @@ class RestrictionsTest extends TestCase public function test_restricted_pages_not_visible_on_chapter_pages() { - $chapter = \BookStack\Chapter::first(); + $chapter = Chapter::first(); $page = $chapter->pages->first(); $this->setEntityRestrictions($page, []); @@ -427,44 +490,82 @@ class RestrictionsTest extends TestCase ->dontSee($page->name); } + public function test_bookshelf_update_restriction_override() + { + $shelf = Bookshelf::first(); + + $this->actingAs($this->viewer) + ->visit($shelf->getUrl('/edit')) + ->dontSee('Edit Book'); + + $this->setEntityRestrictions($shelf, ['view', 'delete']); + + $this->forceVisit($shelf->getUrl('/edit')) + ->see('You do not have permission')->seePageIs('/'); + + $this->setEntityRestrictions($shelf, ['view', 'update']); + + $this->visit($shelf->getUrl('/edit')) + ->seePageIs($shelf->getUrl('/edit')); + } + + public function test_bookshelf_delete_restriction_override() + { + $shelf = Bookshelf::first(); + + $this->actingAs($this->viewer) + ->visit($shelf->getUrl('/delete')) + ->dontSee('Delete Book'); + + $this->setEntityRestrictions($shelf, ['view', 'update']); + + $this->forceVisit($shelf->getUrl('/delete')) + ->see('You do not have permission')->seePageIs('/'); + + $this->setEntityRestrictions($shelf, ['view', 'delete']); + + $this->visit($shelf->getUrl('/delete')) + ->seePageIs($shelf->getUrl('/delete'))->see('Delete Book'); + } + public function test_book_create_restriction_override() { - $book = \BookStack\Book::first(); + $book = Book::first(); $bookUrl = $book->getUrl(); $this->actingAs($this->viewer) ->visit($bookUrl) - ->dontSeeInElement('.action-buttons', 'New Page') - ->dontSeeInElement('.action-buttons', 'New Chapter'); + ->dontSeeInElement('.actions', 'New Page') + ->dontSeeInElement('.actions', 'New Chapter'); $this->setEntityRestrictions($book, ['view', 'delete', 'update']); - $this->forceVisit($bookUrl . '/chapter/create') + $this->forceVisit($bookUrl . '/create-chapter') ->see('You do not have permission')->seePageIs('/'); - $this->forceVisit($bookUrl . '/page/create') + $this->forceVisit($bookUrl . '/create-page') ->see('You do not have permission')->seePageIs('/'); - $this->visit($bookUrl)->dontSeeInElement('.action-buttons', 'New Page') - ->dontSeeInElement('.action-buttons', 'New Chapter'); + $this->visit($bookUrl)->dontSeeInElement('.actions', 'New Page') + ->dontSeeInElement('.actions', 'New Chapter'); $this->setEntityRestrictions($book, ['view', 'create']); - $this->visit($bookUrl . '/chapter/create') + $this->visit($bookUrl . '/create-chapter') ->type('test chapter', 'name') ->type('test description for chapter', 'description') ->press('Save Chapter') ->seePageIs($bookUrl . '/chapter/test-chapter'); - $this->visit($bookUrl . '/page/create') + $this->visit($bookUrl . '/create-page') ->type('test page', 'name') ->type('test content', 'html') ->press('Save Page') ->seePageIs($bookUrl . '/page/test-page'); - $this->visit($bookUrl)->seeInElement('.action-buttons', 'New Page') - ->seeInElement('.action-buttons', 'New Chapter'); + $this->visit($bookUrl)->seeInElement('.actions', 'New Page') + ->seeInElement('.actions', 'New Chapter'); } public function test_book_update_restriction_override() { - $book = \BookStack\Book::first(); + $book = Book::first(); $bookPage = $book->pages->first(); $bookChapter = $book->chapters->first(); @@ -494,7 +595,7 @@ class RestrictionsTest extends TestCase public function test_book_delete_restriction_override() { - $book = \BookStack\Book::first(); + $book = Book::first(); $bookPage = $book->pages->first(); $bookChapter = $book->chapters->first(); @@ -522,4 +623,104 @@ class RestrictionsTest extends TestCase ->see('Delete Chapter'); } + public function test_page_visible_if_has_permissions_when_book_not_visible() + { + $book = Book::first(); + + $this->setEntityRestrictions($book, []); + + $bookChapter = $book->chapters->first(); + $bookPage = $bookChapter->pages->first(); + $this->setEntityRestrictions($bookPage, ['view']); + + $this->actingAs($this->viewer); + $this->get($bookPage->getUrl()); + $this->assertResponseOk(); + $this->see($bookPage->name); + $this->dontSee(substr($book->name, 0, 15)); + $this->dontSee(substr($bookChapter->name, 0, 15)); + } + + public function test_book_sort_view_permission() + { + $firstBook = Book::first(); + $secondBook = Book::find(2); + + $this->setEntityRestrictions($firstBook, ['view', 'update']); + $this->setEntityRestrictions($secondBook, ['view']); + + // Test sort page visibility + $this->actingAs($this->user)->visit($secondBook->getUrl() . '/sort') + ->see('You do not have permission') + ->seePageIs('/'); + + // Check sort page on first book + $this->actingAs($this->user)->visit($firstBook->getUrl() . '/sort'); + } + + public function test_book_sort_permission() { + $firstBook = Book::first(); + $secondBook = Book::find(2); + + $this->setEntityRestrictions($firstBook, ['view', 'update']); + $this->setEntityRestrictions($secondBook, ['view']); + + $firstBookChapter = $this->newChapter(['name' => 'first book chapter'], $firstBook); + $secondBookChapter = $this->newChapter(['name' => 'second book chapter'], $secondBook); + + // Create request data + $reqData = [ + [ + 'id' => $firstBookChapter->id, + 'sort' => 0, + 'parentChapter' => false, + 'type' => 'chapter', + 'book' => $secondBook->id + ] + ]; + + // Move chapter from first book to a second book + $this->actingAs($this->user)->put($firstBook->getUrl() . '/sort', ['sort-tree' => json_encode($reqData)]) + ->followRedirects() + ->see('You do not have permission') + ->seePageIs('/'); + + $reqData = [ + [ + 'id' => $secondBookChapter->id, + 'sort' => 0, + 'parentChapter' => false, + 'type' => 'chapter', + 'book' => $firstBook->id + ] + ]; + + // Move chapter from second book to first book + $this->actingAs($this->user)->put($firstBook->getUrl() . '/sort', ['sort-tree' => json_encode($reqData)]) + ->followRedirects() + ->see('You do not have permission') + ->seePageIs('/'); + } + + public function test_can_create_page_if_chapter_has_permissions_when_book_not_visible() + { + $book = Book::first(); + $this->setEntityRestrictions($book, []); + $bookChapter = $book->chapters->first(); + $this->setEntityRestrictions($bookChapter, ['view']); + + $this->actingAs($this->user)->visit($bookChapter->getUrl()) + ->dontSee('New Page'); + + $this->setEntityRestrictions($bookChapter, ['view', 'create']); + + $this->actingAs($this->user)->visit($bookChapter->getUrl()) + ->click('New Page') + ->seeStatusCode(200) + ->type('test page', 'name') + ->type('test content', 'html') + ->press('Save Page') + ->seePageIs($book->getUrl('/page/test-page')) + ->seeStatusCode(200); + } }