Added a whole load of permission & role tests

This commit is contained in:
Dan Brown 2016-03-05 12:09:09 +00:00
parent 8e274a5a84
commit 268db6b1d0
9 changed files with 450 additions and 9 deletions

View File

@ -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');
}

View File

@ -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]);

View File

@ -136,7 +136,7 @@ class BookRepo
*/
public function newFromInput($input)
{
return $this->bookQuery()->fill($input);
return $this->book->newInstance($input);
}
/**

View File

@ -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();
}

View File

@ -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);
}
/**

View File

@ -16,7 +16,7 @@
{{ $activity->getText() }}
@if($activity->entity())
@if($activity->entity)
<a href="{{ $activity->entity->getUrl() }}">{{ $activity->entity->name }}</a>
@endif

View File

@ -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">

View File

@ -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);
}
}

View File

@ -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.
*