mirror of
https://github.com/BookStackApp/BookStack.git
synced 2025-04-09 23:07:50 +00:00
Added a whole load of permission & role tests
This commit is contained in:
parent
8e274a5a84
commit
268db6b1d0
9 changed files with 450 additions and 9 deletions
app
resources/views
tests
|
@ -15,10 +15,10 @@ class Activity extends Model
|
|||
|
||||
/**
|
||||
* Get the entity for this activity.
|
||||
* @return bool
|
||||
*/
|
||||
public function entity()
|
||||
{
|
||||
if ($this->entity_type === '') $this->entity_type = null;
|
||||
return $this->morphTo('entity');
|
||||
}
|
||||
|
||||
|
|
|
@ -35,6 +35,7 @@ class UserController extends Controller
|
|||
*/
|
||||
public function index()
|
||||
{
|
||||
$this->checkPermission('users-manage');
|
||||
$users = $this->userRepo->getAllUsers();
|
||||
$this->setPageTitle('Users');
|
||||
return view('users/index', ['users' => $users]);
|
||||
|
|
|
@ -136,7 +136,7 @@ class BookRepo
|
|||
*/
|
||||
public function newFromInput($input)
|
||||
{
|
||||
return $this->bookQuery()->fill($input);
|
||||
return $this->book->newInstance($input);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -101,6 +101,7 @@ class PermissionsRepo
|
|||
public function assignRolePermissions(Role $role, $permissionNameArray = [])
|
||||
{
|
||||
$permissions = [];
|
||||
$permissionNameArray = array_values($permissionNameArray);
|
||||
if ($permissionNameArray && count($permissionNameArray) > 0) {
|
||||
$permissions = $this->permission->whereIn('name', $permissionNameArray)->pluck('id')->toArray();
|
||||
}
|
||||
|
|
|
@ -67,11 +67,12 @@ class User extends Model implements AuthenticatableContract, CanResetPasswordCon
|
|||
|
||||
/**
|
||||
* Get all permissions belonging to a the current user.
|
||||
* @param bool $cache
|
||||
* @return \Illuminate\Database\Eloquent\Relations\HasManyThrough
|
||||
*/
|
||||
public function permissions()
|
||||
public function permissions($cache = true)
|
||||
{
|
||||
if(isset($this->permissions)) return $this->permissions;
|
||||
if(isset($this->permissions) && $cache) return $this->permissions;
|
||||
$this->load('roles.permissions');
|
||||
$permissions = $this->roles->map(function($role) {
|
||||
return $role->permissions;
|
||||
|
@ -106,7 +107,7 @@ class User extends Model implements AuthenticatableContract, CanResetPasswordCon
|
|||
*/
|
||||
public function attachRoleId($id)
|
||||
{
|
||||
$this->roles()->attach([$id]);
|
||||
$this->roles()->attach($id);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
|
||||
{{ $activity->getText() }}
|
||||
|
||||
@if($activity->entity())
|
||||
@if($activity->entity)
|
||||
<a href="{{ $activity->entity->getUrl() }}">{{ $activity->entity->name }}</a>
|
||||
@endif
|
||||
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
<label> @include('settings/roles/checkbox', ['permission' => 'users-manage']) Manage users</label>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<label>@include('settings/roles/checkbox', ['permission' => 'user-roles-manage']) Manage user roles & Permissions</label>
|
||||
<label>@include('settings/roles/checkbox', ['permission' => 'user-roles-manage']) Manage user roles</label>
|
||||
</div>
|
||||
</div>
|
||||
<hr class="even">
|
||||
|
|
|
@ -7,16 +7,33 @@ class RolesTest extends TestCase
|
|||
public function setUp()
|
||||
{
|
||||
parent::setUp();
|
||||
$this->user = $this->getNewBlankUser();
|
||||
}
|
||||
|
||||
/**
|
||||
* Give the given user some permissions.
|
||||
* @param \BookStack\User $user
|
||||
* @param array $permissions
|
||||
*/
|
||||
protected function giveUserPermissions(\BookStack\User $user, $permissions = [])
|
||||
{
|
||||
$newRole = $this->createNewRole($permissions);
|
||||
$user->attachRole($newRole);
|
||||
$user->load('roles');
|
||||
$user->permissions(false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new basic role for testing purposes.
|
||||
* @param array $permissions
|
||||
* @return static
|
||||
*/
|
||||
protected function createNewRole()
|
||||
protected function createNewRole($permissions = [])
|
||||
{
|
||||
$permissionRepo = app('BookStack\Repos\PermissionsRepo');
|
||||
return $permissionRepo->saveNewRole(factory(\BookStack\Role::class)->make()->toArray());
|
||||
$roleData = factory(\BookStack\Role::class)->make()->toArray();
|
||||
$roleData['permissions'] = array_flip($permissions);
|
||||
return $permissionRepo->saveNewRole($roleData);
|
||||
}
|
||||
|
||||
public function test_admin_can_see_settings()
|
||||
|
@ -80,4 +97,414 @@ class RolesTest extends TestCase
|
|||
->dontSee($testRoleUpdateName);
|
||||
}
|
||||
|
||||
public function test_manage_user_permission()
|
||||
{
|
||||
$this->actingAs($this->user)->visit('/')->visit('/settings/users')
|
||||
->seePageIs('/');
|
||||
$this->giveUserPermissions($this->user, ['users-manage']);
|
||||
$this->actingAs($this->user)->visit('/')->visit('/settings/users')
|
||||
->seePageIs('/settings/users');
|
||||
}
|
||||
|
||||
public function test_user_roles_manage_permission()
|
||||
{
|
||||
$this->actingAs($this->user)->visit('/')->visit('/settings/roles')
|
||||
->seePageIs('/')->visit('/settings/roles/1')->seePageIs('/');
|
||||
$this->giveUserPermissions($this->user, ['user-roles-manage']);
|
||||
$this->actingAs($this->user)->visit('/settings/roles')
|
||||
->seePageIs('/settings/roles')->click('Admin')
|
||||
->see('Edit Role');
|
||||
}
|
||||
|
||||
public function test_settings_manage_permission()
|
||||
{
|
||||
$this->actingAs($this->user)->visit('/')->visit('/settings')
|
||||
->seePageIs('/');
|
||||
$this->giveUserPermissions($this->user, ['settings-manage']);
|
||||
$this->actingAs($this->user)->visit('/')->visit('/settings')
|
||||
->seePageIs('/settings')->press('Save Settings')->see('Settings Saved');
|
||||
}
|
||||
|
||||
public function test_restrictions_manage_all_permission()
|
||||
{
|
||||
$page = \BookStack\Page::take(1)->get()->first();
|
||||
$this->actingAs($this->user)->visit($page->getUrl())
|
||||
->dontSee('Restrict')
|
||||
->visit($page->getUrl() . '/restrict')
|
||||
->seePageIs('/');
|
||||
$this->giveUserPermissions($this->user, ['restrictions-manage-all']);
|
||||
$this->actingAs($this->user)->visit($page->getUrl())
|
||||
->see('Restrict')
|
||||
->click('Restrict')
|
||||
->see('Page Restrictions')->seePageIs($page->getUrl() . '/restrict');
|
||||
}
|
||||
|
||||
public function test_restrictions_manage_own_permission()
|
||||
{
|
||||
$otherUsersPage = \BookStack\Page::take(1)->get()->first();
|
||||
$content = $this->createEntityChainBelongingToUser($this->user);
|
||||
// Check can't restrict other's content
|
||||
$this->actingAs($this->user)->visit($otherUsersPage->getUrl())
|
||||
->dontSee('Restrict')
|
||||
->visit($otherUsersPage->getUrl() . '/restrict')
|
||||
->seePageIs('/');
|
||||
// Check can't restrict own content
|
||||
$this->actingAs($this->user)->visit($content['page']->getUrl())
|
||||
->dontSee('Restrict')
|
||||
->visit($content['page']->getUrl() . '/restrict')
|
||||
->seePageIs('/');
|
||||
|
||||
$this->giveUserPermissions($this->user, ['restrictions-manage-own']);
|
||||
|
||||
// Check can't restrict other's content
|
||||
$this->actingAs($this->user)->visit($otherUsersPage->getUrl())
|
||||
->dontSee('Restrict')
|
||||
->visit($otherUsersPage->getUrl() . '/restrict')
|
||||
->seePageIs('/');
|
||||
// Check can restrict own content
|
||||
$this->actingAs($this->user)->visit($content['page']->getUrl())
|
||||
->see('Restrict')
|
||||
->click('Restrict')
|
||||
->seePageIs($content['page']->getUrl() . '/restrict');
|
||||
}
|
||||
|
||||
/**
|
||||
* Check a standard entity access permission
|
||||
* @param string $permission
|
||||
* @param array $accessUrls Urls that are only accessible after having the permission
|
||||
* @param array $visibles Check this text, In the buttons toolbar, is only visible with the permission
|
||||
* @param null $callback
|
||||
*/
|
||||
private function checkAccessPermission($permission, $accessUrls = [], $visibles = [])
|
||||
{
|
||||
foreach ($accessUrls as $url) {
|
||||
$this->actingAs($this->user)->visit('/')->visit($url)
|
||||
->seePageIs('/');
|
||||
}
|
||||
foreach ($visibles as $url => $text) {
|
||||
$this->actingAs($this->user)->visit('/')->visit($url)
|
||||
->dontSeeInElement('.action-buttons',$text);
|
||||
}
|
||||
|
||||
$this->giveUserPermissions($this->user, [$permission]);
|
||||
|
||||
foreach ($accessUrls as $url) {
|
||||
$this->actingAs($this->user)->visit('/')->visit($url)
|
||||
->seePageIs($url);
|
||||
}
|
||||
foreach ($visibles as $url => $text) {
|
||||
$this->actingAs($this->user)->visit('/')->visit($url)
|
||||
->see($text);
|
||||
}
|
||||
}
|
||||
|
||||
public function test_books_create_all_permissions()
|
||||
{
|
||||
$this->checkAccessPermission('book-create-all', [
|
||||
'/books/create'
|
||||
], [
|
||||
'/books' => 'Add new book'
|
||||
]);
|
||||
|
||||
$this->visit('/books/create')
|
||||
->type('test book', 'name')
|
||||
->type('book desc', 'description')
|
||||
->press('Save Book')
|
||||
->seePageIs('/books/test-book');
|
||||
}
|
||||
|
||||
public function test_books_edit_own_permission()
|
||||
{
|
||||
$otherBook = \BookStack\Book::take(1)->get()->first();
|
||||
$ownBook = $this->createEntityChainBelongingToUser($this->user)['book'];
|
||||
$this->checkAccessPermission('book-update-own', [
|
||||
$ownBook->getUrl() . '/edit'
|
||||
], [
|
||||
$ownBook->getUrl() => 'Edit'
|
||||
]);
|
||||
|
||||
$this->visit($otherBook->getUrl())
|
||||
->dontSeeInElement('.action-buttons', 'Edit')
|
||||
->visit($otherBook->getUrl() . '/edit')
|
||||
->seePageIs('/');
|
||||
}
|
||||
|
||||
public function test_books_edit_all_permission()
|
||||
{
|
||||
$otherBook = \BookStack\Book::take(1)->get()->first();
|
||||
$this->checkAccessPermission('book-update-all', [
|
||||
$otherBook->getUrl() . '/edit'
|
||||
], [
|
||||
$otherBook->getUrl() => 'Edit'
|
||||
]);
|
||||
}
|
||||
|
||||
public function test_books_delete_own_permission()
|
||||
{
|
||||
$this->giveUserPermissions($this->user, ['book-update-all']);
|
||||
$otherBook = \BookStack\Book::take(1)->get()->first();
|
||||
$ownBook = $this->createEntityChainBelongingToUser($this->user)['book'];
|
||||
$this->checkAccessPermission('book-delete-own', [
|
||||
$ownBook->getUrl() . '/delete'
|
||||
], [
|
||||
$ownBook->getUrl() => 'Delete'
|
||||
]);
|
||||
|
||||
$this->visit($otherBook->getUrl())
|
||||
->dontSeeInElement('.action-buttons', 'Delete')
|
||||
->visit($otherBook->getUrl() . '/delete')
|
||||
->seePageIs('/');
|
||||
$this->visit($ownBook->getUrl())->visit($ownBook->getUrl() . '/delete')
|
||||
->press('Confirm')
|
||||
->seePageIs('/books')
|
||||
->dontSee($ownBook->name);
|
||||
}
|
||||
|
||||
public function test_books_delete_all_permission()
|
||||
{
|
||||
$this->giveUserPermissions($this->user, ['book-update-all']);
|
||||
$otherBook = \BookStack\Book::take(1)->get()->first();
|
||||
$this->checkAccessPermission('book-delete-all', [
|
||||
$otherBook->getUrl() . '/delete'
|
||||
], [
|
||||
$otherBook->getUrl() => 'Delete'
|
||||
]);
|
||||
|
||||
$this->visit($otherBook->getUrl())->visit($otherBook->getUrl() . '/delete')
|
||||
->press('Confirm')
|
||||
->seePageIs('/books')
|
||||
->dontSee($otherBook->name);
|
||||
}
|
||||
|
||||
public function test_chapter_create_own_permissions()
|
||||
{
|
||||
$book = \BookStack\Book::take(1)->get()->first();
|
||||
$ownBook = $this->createEntityChainBelongingToUser($this->user)['book'];
|
||||
$baseUrl = $ownBook->getUrl() . '/chapter';
|
||||
$this->checkAccessPermission('chapter-create-own', [
|
||||
$baseUrl . '/create'
|
||||
], [
|
||||
$ownBook->getUrl() => 'New Chapter'
|
||||
]);
|
||||
|
||||
$this->visit($baseUrl . '/create')
|
||||
->type('test chapter', 'name')
|
||||
->type('chapter desc', 'description')
|
||||
->press('Save Chapter')
|
||||
->seePageIs($baseUrl . '/test-chapter');
|
||||
|
||||
$this->visit($book->getUrl())
|
||||
->dontSeeInElement('.action-buttons', 'New Chapter')
|
||||
->visit($book->getUrl() . '/chapter/create')
|
||||
->seePageIs('/');
|
||||
}
|
||||
|
||||
public function test_chapter_create_all_permissions()
|
||||
{
|
||||
$book = \BookStack\Book::take(1)->get()->first();
|
||||
$baseUrl = $book->getUrl() . '/chapter';
|
||||
$this->checkAccessPermission('chapter-create-all', [
|
||||
$baseUrl . '/create'
|
||||
], [
|
||||
$book->getUrl() => 'New Chapter'
|
||||
]);
|
||||
|
||||
$this->visit($baseUrl . '/create')
|
||||
->type('test chapter', 'name')
|
||||
->type('chapter desc', 'description')
|
||||
->press('Save Chapter')
|
||||
->seePageIs($baseUrl . '/test-chapter');
|
||||
}
|
||||
|
||||
public function test_chapter_edit_own_permission()
|
||||
{
|
||||
$otherChapter = \BookStack\Chapter::take(1)->get()->first();
|
||||
$ownChapter = $this->createEntityChainBelongingToUser($this->user)['chapter'];
|
||||
$this->checkAccessPermission('chapter-update-own', [
|
||||
$ownChapter->getUrl() . '/edit'
|
||||
], [
|
||||
$ownChapter->getUrl() => 'Edit'
|
||||
]);
|
||||
|
||||
$this->visit($otherChapter->getUrl())
|
||||
->dontSeeInElement('.action-buttons', 'Edit')
|
||||
->visit($otherChapter->getUrl() . '/edit')
|
||||
->seePageIs('/');
|
||||
}
|
||||
|
||||
public function test_chapter_edit_all_permission()
|
||||
{
|
||||
$otherChapter = \BookStack\Chapter::take(1)->get()->first();
|
||||
$this->checkAccessPermission('chapter-update-all', [
|
||||
$otherChapter->getUrl() . '/edit'
|
||||
], [
|
||||
$otherChapter->getUrl() => 'Edit'
|
||||
]);
|
||||
}
|
||||
|
||||
public function test_chapter_delete_own_permission()
|
||||
{
|
||||
$this->giveUserPermissions($this->user, ['chapter-update-all']);
|
||||
$otherChapter = \BookStack\Chapter::take(1)->get()->first();
|
||||
$ownChapter = $this->createEntityChainBelongingToUser($this->user)['chapter'];
|
||||
$this->checkAccessPermission('chapter-delete-own', [
|
||||
$ownChapter->getUrl() . '/delete'
|
||||
], [
|
||||
$ownChapter->getUrl() => 'Delete'
|
||||
]);
|
||||
|
||||
$bookUrl = $ownChapter->book->getUrl();
|
||||
$this->visit($otherChapter->getUrl())
|
||||
->dontSeeInElement('.action-buttons', 'Delete')
|
||||
->visit($otherChapter->getUrl() . '/delete')
|
||||
->seePageIs('/');
|
||||
$this->visit($ownChapter->getUrl())->visit($ownChapter->getUrl() . '/delete')
|
||||
->press('Confirm')
|
||||
->seePageIs($bookUrl)
|
||||
->dontSeeInElement('.book-content', $ownChapter->name);
|
||||
}
|
||||
|
||||
public function test_chapter_delete_all_permission()
|
||||
{
|
||||
$this->giveUserPermissions($this->user, ['chapter-update-all']);
|
||||
$otherChapter = \BookStack\Chapter::take(1)->get()->first();
|
||||
$this->checkAccessPermission('chapter-delete-all', [
|
||||
$otherChapter->getUrl() . '/delete'
|
||||
], [
|
||||
$otherChapter->getUrl() => 'Delete'
|
||||
]);
|
||||
|
||||
$bookUrl = $otherChapter->book->getUrl();
|
||||
$this->visit($otherChapter->getUrl())->visit($otherChapter->getUrl() . '/delete')
|
||||
->press('Confirm')
|
||||
->seePageIs($bookUrl)
|
||||
->dontSeeInElement('.book-content', $otherChapter->name);
|
||||
}
|
||||
|
||||
public function test_page_create_own_permissions()
|
||||
{
|
||||
$book = \BookStack\Book::take(1)->get()->first();
|
||||
$chapter = \BookStack\Chapter::take(1)->get()->first();
|
||||
|
||||
$entities = $this->createEntityChainBelongingToUser($this->user);
|
||||
$ownBook = $entities['book'];
|
||||
$ownChapter = $entities['chapter'];
|
||||
|
||||
$baseUrl = $ownBook->getUrl() . '/page';
|
||||
|
||||
$this->checkAccessPermission('page-create-own', [
|
||||
$baseUrl . '/create',
|
||||
$ownChapter->getUrl() . '/create-page'
|
||||
], [
|
||||
$ownBook->getUrl() => 'New Page',
|
||||
$ownChapter->getUrl() => 'New Page'
|
||||
]);
|
||||
|
||||
$this->visit($baseUrl . '/create')
|
||||
->type('test page', 'name')
|
||||
->type('page desc', 'html')
|
||||
->press('Save Page')
|
||||
->seePageIs($baseUrl . '/test-page');
|
||||
|
||||
$this->visit($book->getUrl())
|
||||
->dontSeeInElement('.action-buttons', 'New Page')
|
||||
->visit($book->getUrl() . '/page/create')
|
||||
->seePageIs('/');
|
||||
$this->visit($chapter->getUrl())
|
||||
->dontSeeInElement('.action-buttons', 'New Page')
|
||||
->visit($chapter->getUrl() . '/create-page')
|
||||
->seePageIs('/');
|
||||
}
|
||||
|
||||
public function test_page_create_all_permissions()
|
||||
{
|
||||
$book = \BookStack\Book::take(1)->get()->first();
|
||||
$chapter = \BookStack\Chapter::take(1)->get()->first();
|
||||
$baseUrl = $book->getUrl() . '/page';
|
||||
$this->checkAccessPermission('page-create-all', [
|
||||
$baseUrl . '/create',
|
||||
$chapter->getUrl() . '/create-page'
|
||||
], [
|
||||
$book->getUrl() => 'New Page',
|
||||
$chapter->getUrl() => 'New Page'
|
||||
]);
|
||||
|
||||
$this->visit($baseUrl . '/create')
|
||||
->type('test page', 'name')
|
||||
->type('page desc', 'html')
|
||||
->press('Save Page')
|
||||
->seePageIs($baseUrl . '/test-page');
|
||||
|
||||
$this->visit($chapter->getUrl() . '/create-page')
|
||||
->type('new test page', 'name')
|
||||
->type('page desc', 'html')
|
||||
->press('Save Page')
|
||||
->seePageIs($baseUrl . '/new-test-page');
|
||||
}
|
||||
|
||||
public function test_page_edit_own_permission()
|
||||
{
|
||||
$otherPage = \BookStack\Page::take(1)->get()->first();
|
||||
$ownPage = $this->createEntityChainBelongingToUser($this->user)['page'];
|
||||
$this->checkAccessPermission('page-update-own', [
|
||||
$ownPage->getUrl() . '/edit'
|
||||
], [
|
||||
$ownPage->getUrl() => 'Edit'
|
||||
]);
|
||||
|
||||
$this->visit($otherPage->getUrl())
|
||||
->dontSeeInElement('.action-buttons', 'Edit')
|
||||
->visit($otherPage->getUrl() . '/edit')
|
||||
->seePageIs('/');
|
||||
}
|
||||
|
||||
public function test_page_edit_all_permission()
|
||||
{
|
||||
$otherPage = \BookStack\Page::take(1)->get()->first();
|
||||
$this->checkAccessPermission('page-update-all', [
|
||||
$otherPage->getUrl() . '/edit'
|
||||
], [
|
||||
$otherPage->getUrl() => 'Edit'
|
||||
]);
|
||||
}
|
||||
|
||||
public function test_page_delete_own_permission()
|
||||
{
|
||||
$this->giveUserPermissions($this->user, ['page-update-all']);
|
||||
$otherPage = \BookStack\Page::take(1)->get()->first();
|
||||
$ownPage = $this->createEntityChainBelongingToUser($this->user)['page'];
|
||||
$this->checkAccessPermission('page-delete-own', [
|
||||
$ownPage->getUrl() . '/delete'
|
||||
], [
|
||||
$ownPage->getUrl() => 'Delete'
|
||||
]);
|
||||
|
||||
$bookUrl = $ownPage->book->getUrl();
|
||||
$this->visit($otherPage->getUrl())
|
||||
->dontSeeInElement('.action-buttons', 'Delete')
|
||||
->visit($otherPage->getUrl() . '/delete')
|
||||
->seePageIs('/');
|
||||
$this->visit($ownPage->getUrl())->visit($ownPage->getUrl() . '/delete')
|
||||
->press('Confirm')
|
||||
->seePageIs($bookUrl)
|
||||
->dontSeeInElement('.book-content', $ownPage->name);
|
||||
}
|
||||
|
||||
public function test_page_delete_all_permission()
|
||||
{
|
||||
$this->giveUserPermissions($this->user, ['page-update-all']);
|
||||
$otherPage = \BookStack\Page::take(1)->get()->first();
|
||||
$this->checkAccessPermission('page-delete-all', [
|
||||
$otherPage->getUrl() . '/delete'
|
||||
], [
|
||||
$otherPage->getUrl() => 'Delete'
|
||||
]);
|
||||
|
||||
$bookUrl = $otherPage->book->getUrl();
|
||||
$this->visit($otherPage->getUrl())->visit($otherPage->getUrl() . '/delete')
|
||||
->press('Confirm')
|
||||
->seePageIs($bookUrl)
|
||||
->dontSeeInElement('.book-content', $otherPage->name);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -84,6 +84,17 @@ class TestCase extends Illuminate\Foundation\Testing\TestCase
|
|||
return $user;
|
||||
}
|
||||
|
||||
/**
|
||||
* Quick way to create a new user without any permissions
|
||||
* @param array $attributes
|
||||
* @return mixed
|
||||
*/
|
||||
protected function getNewBlankUser($attributes = [])
|
||||
{
|
||||
$user = factory(\BookStack\User::class)->create($attributes);
|
||||
return $user;
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert that a given string is seen inside an element.
|
||||
*
|
||||
|
|
Loading…
Add table
Reference in a new issue