mirror of
https://github.com/BookStackApp/BookStack.git
synced 2025-05-30 20:51:57 +08:00
Added restriction tests and fixed any bugs in the process
Also updated many styles within areas affected by the new permission and roles system.
This commit is contained in:
407
tests/RestrictionsTest.php
Normal file
407
tests/RestrictionsTest.php
Normal file
@ -0,0 +1,407 @@
|
||||
<?php
|
||||
|
||||
class RestrictionsTest extends TestCase
|
||||
{
|
||||
protected $user;
|
||||
|
||||
public function setUp()
|
||||
{
|
||||
parent::setUp();
|
||||
$this->user = $this->getNewUser();
|
||||
}
|
||||
|
||||
/**
|
||||
* Manually set some restrictions on an entity.
|
||||
* @param \BookStack\Entity $entity
|
||||
* @param $actions
|
||||
*/
|
||||
protected function setEntityRestrictions(\BookStack\Entity $entity, $actions)
|
||||
{
|
||||
$entity->restricted = true;
|
||||
$entity->restrictions()->delete();
|
||||
$role = $this->user->roles->first();
|
||||
foreach ($actions as $action) {
|
||||
$entity->restrictions()->create([
|
||||
'role_id' => $role->id,
|
||||
'action' => strtolower($action)
|
||||
]);
|
||||
}
|
||||
$entity->save();
|
||||
$entity->load('restrictions');
|
||||
}
|
||||
|
||||
public function test_book_view_restriction()
|
||||
{
|
||||
$book = \BookStack\Book::first();
|
||||
$bookPage = $book->pages->first();
|
||||
$bookChapter = $book->chapters->first();
|
||||
|
||||
$bookUrl = $book->getUrl();
|
||||
$this->actingAs($this->user)
|
||||
->visit($bookUrl)
|
||||
->seePageIs($bookUrl);
|
||||
|
||||
$this->setEntityRestrictions($book, []);
|
||||
|
||||
$this->forceVisit($bookUrl)
|
||||
->see('Book not found');
|
||||
$this->forceVisit($bookPage->getUrl())
|
||||
->see('Book not found');
|
||||
$this->forceVisit($bookChapter->getUrl())
|
||||
->see('Book not found');
|
||||
|
||||
$this->setEntityRestrictions($book, ['view']);
|
||||
|
||||
$this->visit($bookUrl)
|
||||
->see($book->name);
|
||||
$this->visit($bookPage->getUrl())
|
||||
->see($bookPage->name);
|
||||
$this->visit($bookChapter->getUrl())
|
||||
->see($bookChapter->name);
|
||||
}
|
||||
|
||||
public function test_book_create_restriction()
|
||||
{
|
||||
$book = \BookStack\Book::first();
|
||||
|
||||
$bookUrl = $book->getUrl();
|
||||
$this->actingAs($this->user)
|
||||
->visit($bookUrl)
|
||||
->seeInElement('.action-buttons', 'New Page')
|
||||
->seeInElement('.action-buttons', 'New Chapter');
|
||||
|
||||
$this->setEntityRestrictions($book, ['view', 'delete', 'update']);
|
||||
|
||||
$this->forceVisit($bookUrl . '/chapter/create')
|
||||
->see('You do not have permission')->seePageIs('/');
|
||||
$this->forceVisit($bookUrl . '/page/create')
|
||||
->see('You do not have permission')->seePageIs('/');
|
||||
$this->visit($bookUrl)->dontSeeInElement('.action-buttons', 'New Page')
|
||||
->dontSeeInElement('.action-buttons', 'New Chapter');
|
||||
|
||||
$this->setEntityRestrictions($book, ['view', 'create']);
|
||||
|
||||
$this->visit($bookUrl . '/chapter/create')
|
||||
->type('test chapter', 'name')
|
||||
->type('test description for chapter', 'description')
|
||||
->press('Save Chapter')
|
||||
->seePageIs($bookUrl . '/chapter/test-chapter');
|
||||
$this->visit($bookUrl . '/page/create')
|
||||
->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');
|
||||
}
|
||||
|
||||
public function test_book_update_restriction()
|
||||
{
|
||||
$book = \BookStack\Book::first();
|
||||
$bookPage = $book->pages->first();
|
||||
$bookChapter = $book->chapters->first();
|
||||
|
||||
$bookUrl = $book->getUrl();
|
||||
$this->actingAs($this->user)
|
||||
->visit($bookUrl . '/edit')
|
||||
->see('Edit Book');
|
||||
|
||||
$this->setEntityRestrictions($book, ['view', 'delete']);
|
||||
|
||||
$this->forceVisit($bookUrl . '/edit')
|
||||
->see('You do not have permission')->seePageIs('/');
|
||||
$this->forceVisit($bookPage->getUrl() . '/edit')
|
||||
->see('You do not have permission')->seePageIs('/');
|
||||
$this->forceVisit($bookChapter->getUrl() . '/edit')
|
||||
->see('You do not have permission')->seePageIs('/');
|
||||
|
||||
$this->setEntityRestrictions($book, ['view', 'update']);
|
||||
|
||||
$this->visit($bookUrl . '/edit')
|
||||
->seePageIs($bookUrl . '/edit');
|
||||
$this->visit($bookPage->getUrl() . '/edit')
|
||||
->seePageIs($bookPage->getUrl() . '/edit');
|
||||
$this->visit($bookChapter->getUrl() . '/edit')
|
||||
->see('Edit Chapter');
|
||||
}
|
||||
|
||||
public function test_book_delete_restriction()
|
||||
{
|
||||
$book = \BookStack\Book::first();
|
||||
$bookPage = $book->pages->first();
|
||||
$bookChapter = $book->chapters->first();
|
||||
|
||||
$bookUrl = $book->getUrl();
|
||||
$this->actingAs($this->user)
|
||||
->visit($bookUrl . '/delete')
|
||||
->see('Delete Book');
|
||||
|
||||
$this->setEntityRestrictions($book, ['view', 'update']);
|
||||
|
||||
$this->forceVisit($bookUrl . '/delete')
|
||||
->see('You do not have permission')->seePageIs('/');
|
||||
$this->forceVisit($bookPage->getUrl() . '/delete')
|
||||
->see('You do not have permission')->seePageIs('/');
|
||||
$this->forceVisit($bookChapter->getUrl() . '/delete')
|
||||
->see('You do not have permission')->seePageIs('/');
|
||||
|
||||
$this->setEntityRestrictions($book, ['view', 'delete']);
|
||||
|
||||
$this->visit($bookUrl . '/delete')
|
||||
->seePageIs($bookUrl . '/delete')->see('Delete Book');
|
||||
$this->visit($bookPage->getUrl() . '/delete')
|
||||
->seePageIs($bookPage->getUrl() . '/delete')->see('Delete Page');
|
||||
$this->visit($bookChapter->getUrl() . '/delete')
|
||||
->see('Delete Chapter');
|
||||
}
|
||||
|
||||
public function test_chapter_view_restriction()
|
||||
{
|
||||
$chapter = \BookStack\Chapter::first();
|
||||
$chapterPage = $chapter->pages->first();
|
||||
|
||||
$chapterUrl = $chapter->getUrl();
|
||||
$this->actingAs($this->user)
|
||||
->visit($chapterUrl)
|
||||
->seePageIs($chapterUrl);
|
||||
|
||||
$this->setEntityRestrictions($chapter, []);
|
||||
|
||||
$this->forceVisit($chapterUrl)
|
||||
->see('Chapter not found');
|
||||
$this->forceVisit($chapterPage->getUrl())
|
||||
->see('Page not found');
|
||||
|
||||
$this->setEntityRestrictions($chapter, ['view']);
|
||||
|
||||
$this->visit($chapterUrl)
|
||||
->see($chapter->name);
|
||||
$this->visit($chapterPage->getUrl())
|
||||
->see($chapterPage->name);
|
||||
}
|
||||
|
||||
public function test_chapter_create_restriction()
|
||||
{
|
||||
$chapter = \BookStack\Chapter::first();
|
||||
|
||||
$chapterUrl = $chapter->getUrl();
|
||||
$this->actingAs($this->user)
|
||||
->visit($chapterUrl)
|
||||
->seeInElement('.action-buttons', '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->setEntityRestrictions($chapter, ['view', 'create']);
|
||||
|
||||
|
||||
$this->visit($chapterUrl . '/create-page')
|
||||
->type('test page', 'name')
|
||||
->type('test content', 'html')
|
||||
->press('Save Page')
|
||||
->seePageIs($chapter->book->getUrl() . '/page/test-page');
|
||||
$this->visit($chapterUrl)->seeInElement('.action-buttons', 'New Page');
|
||||
}
|
||||
|
||||
public function test_chapter_update_restriction()
|
||||
{
|
||||
$chapter = \BookStack\Chapter::first();
|
||||
$chapterPage = $chapter->pages->first();
|
||||
|
||||
$chapterUrl = $chapter->getUrl();
|
||||
$this->actingAs($this->user)
|
||||
->visit($chapterUrl . '/edit')
|
||||
->see('Edit Chapter');
|
||||
|
||||
$this->setEntityRestrictions($chapter, ['view', 'delete']);
|
||||
|
||||
$this->forceVisit($chapterUrl . '/edit')
|
||||
->see('You do not have permission')->seePageIs('/');
|
||||
$this->forceVisit($chapterPage->getUrl() . '/edit')
|
||||
->see('You do not have permission')->seePageIs('/');
|
||||
|
||||
$this->setEntityRestrictions($chapter, ['view', 'update']);
|
||||
|
||||
$this->visit($chapterUrl . '/edit')
|
||||
->seePageIs($chapterUrl . '/edit')->see('Edit Chapter');
|
||||
$this->visit($chapterPage->getUrl() . '/edit')
|
||||
->seePageIs($chapterPage->getUrl() . '/edit');
|
||||
}
|
||||
|
||||
public function test_chapter_delete_restriction()
|
||||
{
|
||||
$chapter = \BookStack\Chapter::first();
|
||||
$chapterPage = $chapter->pages->first();
|
||||
|
||||
$chapterUrl = $chapter->getUrl();
|
||||
$this->actingAs($this->user)
|
||||
->visit($chapterUrl . '/delete')
|
||||
->see('Delete Chapter');
|
||||
|
||||
$this->setEntityRestrictions($chapter, ['view', 'update']);
|
||||
|
||||
$this->forceVisit($chapterUrl . '/delete')
|
||||
->see('You do not have permission')->seePageIs('/');
|
||||
$this->forceVisit($chapterPage->getUrl() . '/delete')
|
||||
->see('You do not have permission')->seePageIs('/');
|
||||
|
||||
$this->setEntityRestrictions($chapter, ['view', 'delete']);
|
||||
|
||||
$this->visit($chapterUrl . '/delete')
|
||||
->seePageIs($chapterUrl . '/delete')->see('Delete Chapter');
|
||||
$this->visit($chapterPage->getUrl() . '/delete')
|
||||
->seePageIs($chapterPage->getUrl() . '/delete')->see('Delete Page');
|
||||
}
|
||||
|
||||
public function test_page_view_restriction()
|
||||
{
|
||||
$page = \BookStack\Page::first();
|
||||
|
||||
$pageUrl = $page->getUrl();
|
||||
$this->actingAs($this->user)
|
||||
->visit($pageUrl)
|
||||
->seePageIs($pageUrl);
|
||||
|
||||
$this->setEntityRestrictions($page, ['update', 'delete']);
|
||||
|
||||
$this->forceVisit($pageUrl)
|
||||
->see('Page not found');
|
||||
|
||||
$this->setEntityRestrictions($page, ['view']);
|
||||
|
||||
$this->visit($pageUrl)
|
||||
->see($page->name);
|
||||
}
|
||||
|
||||
public function test_page_update_restriction()
|
||||
{
|
||||
$page = \BookStack\Chapter::first();
|
||||
|
||||
$pageUrl = $page->getUrl();
|
||||
$this->actingAs($this->user)
|
||||
->visit($pageUrl . '/edit')
|
||||
->seeInField('name', $page->name);
|
||||
|
||||
$this->setEntityRestrictions($page, ['view', 'delete']);
|
||||
|
||||
$this->forceVisit($pageUrl . '/edit')
|
||||
->see('You do not have permission')->seePageIs('/');
|
||||
|
||||
$this->setEntityRestrictions($page, ['view', 'update']);
|
||||
|
||||
$this->visit($pageUrl . '/edit')
|
||||
->seePageIs($pageUrl . '/edit')->seeInField('name', $page->name);
|
||||
}
|
||||
|
||||
public function test_page_delete_restriction()
|
||||
{
|
||||
$page = \BookStack\Page::first();
|
||||
|
||||
$pageUrl = $page->getUrl();
|
||||
$this->actingAs($this->user)
|
||||
->visit($pageUrl . '/delete')
|
||||
->see('Delete Page');
|
||||
|
||||
$this->setEntityRestrictions($page, ['view', 'update']);
|
||||
|
||||
$this->forceVisit($pageUrl . '/delete')
|
||||
->see('You do not have permission')->seePageIs('/');
|
||||
|
||||
$this->setEntityRestrictions($page, ['view', 'delete']);
|
||||
|
||||
$this->visit($pageUrl . '/delete')
|
||||
->seePageIs($pageUrl . '/delete')->see('Delete Page');
|
||||
}
|
||||
|
||||
public function test_book_restriction_form()
|
||||
{
|
||||
$book = \BookStack\Book::first();
|
||||
$this->asAdmin()->visit($book->getUrl() . '/restrict')
|
||||
->see('Book Restrictions')
|
||||
->check('restricted')
|
||||
->check('restrictions[2][view]')
|
||||
->press('Save Restrictions')
|
||||
->seeInDatabase('books', ['id' => $book->id, 'restricted' => true])
|
||||
->seeInDatabase('restrictions', [
|
||||
'restrictable_id' => $book->id,
|
||||
'restrictable_type' => 'BookStack\Book',
|
||||
'role_id' => '2',
|
||||
'action' => 'view'
|
||||
]);
|
||||
}
|
||||
|
||||
public function test_chapter_restriction_form()
|
||||
{
|
||||
$chapter = \BookStack\Chapter::first();
|
||||
$this->asAdmin()->visit($chapter->getUrl() . '/restrict')
|
||||
->see('Chapter Restrictions')
|
||||
->check('restricted')
|
||||
->check('restrictions[2][update]')
|
||||
->press('Save Restrictions')
|
||||
->seeInDatabase('chapters', ['id' => $chapter->id, 'restricted' => true])
|
||||
->seeInDatabase('restrictions', [
|
||||
'restrictable_id' => $chapter->id,
|
||||
'restrictable_type' => 'BookStack\Chapter',
|
||||
'role_id' => '2',
|
||||
'action' => 'update'
|
||||
]);
|
||||
}
|
||||
|
||||
public function test_page_restriction_form()
|
||||
{
|
||||
$page = \BookStack\Page::first();
|
||||
$this->asAdmin()->visit($page->getUrl() . '/restrict')
|
||||
->see('Page Restrictions')
|
||||
->check('restricted')
|
||||
->check('restrictions[2][delete]')
|
||||
->press('Save Restrictions')
|
||||
->seeInDatabase('pages', ['id' => $page->id, 'restricted' => true])
|
||||
->seeInDatabase('restrictions', [
|
||||
'restrictable_id' => $page->id,
|
||||
'restrictable_type' => 'BookStack\Page',
|
||||
'role_id' => '2',
|
||||
'action' => 'delete'
|
||||
]);
|
||||
}
|
||||
|
||||
public function test_restricted_pages_not_visible_in_book_navigation_on_pages()
|
||||
{
|
||||
$chapter = \BookStack\Chapter::first();
|
||||
$page = $chapter->pages->first();
|
||||
$page2 = $chapter->pages[2];
|
||||
|
||||
$this->setEntityRestrictions($page, []);
|
||||
|
||||
$this->actingAs($this->user)
|
||||
->visit($page2->getUrl())
|
||||
->dontSeeInElement('.sidebar-page-list', $page->name);
|
||||
}
|
||||
|
||||
public function test_restricted_pages_not_visible_in_book_navigation_on_chapters()
|
||||
{
|
||||
$chapter = \BookStack\Chapter::first();
|
||||
$page = $chapter->pages->first();
|
||||
|
||||
$this->setEntityRestrictions($page, []);
|
||||
|
||||
$this->actingAs($this->user)
|
||||
->visit($chapter->getUrl())
|
||||
->dontSeeInElement('.sidebar-page-list', $page->name);
|
||||
}
|
||||
|
||||
public function test_restricted_pages_not_visible_on_chapter_pages()
|
||||
{
|
||||
$chapter = \BookStack\Chapter::first();
|
||||
$page = $chapter->pages->first();
|
||||
|
||||
$this->setEntityRestrictions($page, []);
|
||||
|
||||
$this->actingAs($this->user)
|
||||
->visit($chapter->getUrl())
|
||||
->dontSee($page->name);
|
||||
}
|
||||
|
||||
}
|
@ -1,6 +1,7 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Foundation\Testing\DatabaseTransactions;
|
||||
use Symfony\Component\DomCrawler\Crawler;
|
||||
|
||||
class TestCase extends Illuminate\Foundation\Testing\TestCase
|
||||
{
|
||||
@ -122,6 +123,40 @@ class TestCase extends Illuminate\Foundation\Testing\TestCase
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert that the current page matches a given URI.
|
||||
*
|
||||
* @param string $uri
|
||||
* @return $this
|
||||
*/
|
||||
protected function seePageUrlIs($uri)
|
||||
{
|
||||
$this->assertEquals(
|
||||
$uri, $this->currentUri, "Did not land on expected page [{$uri}].\n"
|
||||
);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Do a forced visit that does not error out on exception.
|
||||
* @param string $uri
|
||||
* @param array $parameters
|
||||
* @param array $cookies
|
||||
* @param array $files
|
||||
* @return $this
|
||||
*/
|
||||
protected function forceVisit($uri, $parameters = [], $cookies = [], $files = [])
|
||||
{
|
||||
$method = 'GET';
|
||||
$uri = $this->prepareUrlForRequest($uri);
|
||||
$this->call($method, $uri, $parameters, $cookies, $files);
|
||||
$this->clearInputs()->followRedirects();
|
||||
$this->currentUri = $this->app->make('request')->fullUrl();
|
||||
$this->crawler = new Crawler($this->response->getContent(), $uri);
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Click the text within the selected element.
|
||||
* @param $parentElement
|
||||
|
Reference in New Issue
Block a user