mirror of
https://github.com/BookStackApp/BookStack.git
synced 2024-10-01 01:36:00 -04:00
Removed role 'name' field from database
The 'name' field was really redundant and caused confusion in the codebase, since the 'Display' name is often used and we have a 'system_name' for the admin and public role. This fixes #2032, Where external auth group matching has confusing behaviour as matching was done against the display_name, if no external_auth field is set, but only roles with a match 'name' field would be considered. This also fixes and error where the role users migration, on role delete, would not actually fire due to mis-matching http body keys. Looks like this has been an issue from the start. Added some testing to cover. Fixes #2211. Also converted phpdoc to typehints in many areas of the reviewed code during the above.
This commit is contained in:
parent
a9f02550f0
commit
5f1ee5fb0e
@ -3,6 +3,8 @@
|
|||||||
use BookStack\Auth\Role;
|
use BookStack\Auth\Role;
|
||||||
use BookStack\Auth\User;
|
use BookStack\Auth\User;
|
||||||
use Illuminate\Database\Eloquent\Builder;
|
use Illuminate\Database\Eloquent\Builder;
|
||||||
|
use Illuminate\Support\Collection;
|
||||||
|
use Illuminate\Support\Facades\DB;
|
||||||
|
|
||||||
class ExternalAuthService
|
class ExternalAuthService
|
||||||
{
|
{
|
||||||
@ -39,22 +41,14 @@ class ExternalAuthService
|
|||||||
/**
|
/**
|
||||||
* Match an array of group names to BookStack system roles.
|
* Match an array of group names to BookStack system roles.
|
||||||
* Formats group names to be lower-case and hyphenated.
|
* Formats group names to be lower-case and hyphenated.
|
||||||
* @param array $groupNames
|
|
||||||
* @return \Illuminate\Support\Collection
|
|
||||||
*/
|
*/
|
||||||
protected function matchGroupsToSystemsRoles(array $groupNames)
|
protected function matchGroupsToSystemsRoles(array $groupNames): Collection
|
||||||
{
|
{
|
||||||
foreach ($groupNames as $i => $groupName) {
|
foreach ($groupNames as $i => $groupName) {
|
||||||
$groupNames[$i] = str_replace(' ', '-', trim(strtolower($groupName)));
|
$groupNames[$i] = str_replace(' ', '-', trim(strtolower($groupName)));
|
||||||
}
|
}
|
||||||
|
|
||||||
$roles = Role::query()->where(function (Builder $query) use ($groupNames) {
|
$roles = Role::query()->get(['id', 'external_auth_id', 'display_name']);
|
||||||
$query->whereIn('name', $groupNames);
|
|
||||||
foreach ($groupNames as $groupName) {
|
|
||||||
$query->orWhere('external_auth_id', 'LIKE', '%' . $groupName . '%');
|
|
||||||
}
|
|
||||||
})->get();
|
|
||||||
|
|
||||||
$matchedRoles = $roles->filter(function (Role $role) use ($groupNames) {
|
$matchedRoles = $roles->filter(function (Role $role) use ($groupNames) {
|
||||||
return $this->roleMatchesGroupNames($role, $groupNames);
|
return $this->roleMatchesGroupNames($role, $groupNames);
|
||||||
});
|
});
|
||||||
|
@ -1,8 +1,9 @@
|
|||||||
<?php namespace BookStack\Auth\Permissions;
|
<?php namespace BookStack\Auth\Permissions;
|
||||||
|
|
||||||
use BookStack\Auth\Permissions;
|
|
||||||
use BookStack\Auth\Role;
|
use BookStack\Auth\Role;
|
||||||
use BookStack\Exceptions\PermissionsException;
|
use BookStack\Exceptions\PermissionsException;
|
||||||
|
use Exception;
|
||||||
|
use Illuminate\Database\Eloquent\Collection;
|
||||||
use Illuminate\Support\Str;
|
use Illuminate\Support\Str;
|
||||||
|
|
||||||
class PermissionsRepo
|
class PermissionsRepo
|
||||||
@ -16,11 +17,8 @@ class PermissionsRepo
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* PermissionsRepo constructor.
|
* PermissionsRepo constructor.
|
||||||
* @param RolePermission $permission
|
|
||||||
* @param Role $role
|
|
||||||
* @param \BookStack\Auth\Permissions\PermissionService $permissionService
|
|
||||||
*/
|
*/
|
||||||
public function __construct(RolePermission $permission, Role $role, Permissions\PermissionService $permissionService)
|
public function __construct(RolePermission $permission, Role $role, PermissionService $permissionService)
|
||||||
{
|
{
|
||||||
$this->permission = $permission;
|
$this->permission = $permission;
|
||||||
$this->role = $role;
|
$this->role = $role;
|
||||||
@ -29,46 +27,34 @@ class PermissionsRepo
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Get all the user roles from the system.
|
* Get all the user roles from the system.
|
||||||
* @return \Illuminate\Database\Eloquent\Collection|static[]
|
|
||||||
*/
|
*/
|
||||||
public function getAllRoles()
|
public function getAllRoles(): Collection
|
||||||
{
|
{
|
||||||
return $this->role->all();
|
return $this->role->all();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get all the roles except for the provided one.
|
* Get all the roles except for the provided one.
|
||||||
* @param Role $role
|
|
||||||
* @return mixed
|
|
||||||
*/
|
*/
|
||||||
public function getAllRolesExcept(Role $role)
|
public function getAllRolesExcept(Role $role): Collection
|
||||||
{
|
{
|
||||||
return $this->role->where('id', '!=', $role->id)->get();
|
return $this->role->where('id', '!=', $role->id)->get();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get a role via its ID.
|
* Get a role via its ID.
|
||||||
* @param $id
|
|
||||||
* @return mixed
|
|
||||||
*/
|
*/
|
||||||
public function getRoleById($id)
|
public function getRoleById($id): Role
|
||||||
{
|
{
|
||||||
return $this->role->findOrFail($id);
|
return $this->role->newQuery()->findOrFail($id);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Save a new role into the system.
|
* Save a new role into the system.
|
||||||
* @param array $roleData
|
|
||||||
* @return Role
|
|
||||||
*/
|
*/
|
||||||
public function saveNewRole($roleData)
|
public function saveNewRole(array $roleData): Role
|
||||||
{
|
{
|
||||||
$role = $this->role->newInstance($roleData);
|
$role = $this->role->newInstance($roleData);
|
||||||
$role->name = str_replace(' ', '-', strtolower($roleData['display_name']));
|
|
||||||
// Prevent duplicate names
|
|
||||||
while ($this->role->where('name', '=', $role->name)->count() > 0) {
|
|
||||||
$role->name .= strtolower(Str::random(2));
|
|
||||||
}
|
|
||||||
$role->save();
|
$role->save();
|
||||||
|
|
||||||
$permissions = isset($roleData['permissions']) ? array_keys($roleData['permissions']) : [];
|
$permissions = isset($roleData['permissions']) ? array_keys($roleData['permissions']) : [];
|
||||||
@ -80,13 +66,11 @@ class PermissionsRepo
|
|||||||
/**
|
/**
|
||||||
* Updates an existing role.
|
* Updates an existing role.
|
||||||
* Ensure Admin role always have core permissions.
|
* Ensure Admin role always have core permissions.
|
||||||
* @param $roleId
|
|
||||||
* @param $roleData
|
|
||||||
* @throws PermissionsException
|
|
||||||
*/
|
*/
|
||||||
public function updateRole($roleId, $roleData)
|
public function updateRole($roleId, array $roleData)
|
||||||
{
|
{
|
||||||
$role = $this->role->findOrFail($roleId);
|
/** @var Role $role */
|
||||||
|
$role = $this->role->newQuery()->findOrFail($roleId);
|
||||||
|
|
||||||
$permissions = isset($roleData['permissions']) ? array_keys($roleData['permissions']) : [];
|
$permissions = isset($roleData['permissions']) ? array_keys($roleData['permissions']) : [];
|
||||||
if ($role->system_name === 'admin') {
|
if ($role->system_name === 'admin') {
|
||||||
@ -108,16 +92,19 @@ class PermissionsRepo
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Assign an list of permission names to an role.
|
* Assign an list of permission names to an role.
|
||||||
* @param Role $role
|
|
||||||
* @param array $permissionNameArray
|
|
||||||
*/
|
*/
|
||||||
public function assignRolePermissions(Role $role, $permissionNameArray = [])
|
public function assignRolePermissions(Role $role, array $permissionNameArray = [])
|
||||||
{
|
{
|
||||||
$permissions = [];
|
$permissions = [];
|
||||||
$permissionNameArray = array_values($permissionNameArray);
|
$permissionNameArray = array_values($permissionNameArray);
|
||||||
if ($permissionNameArray && count($permissionNameArray) > 0) {
|
|
||||||
$permissions = $this->permission->whereIn('name', $permissionNameArray)->pluck('id')->toArray();
|
if ($permissionNameArray) {
|
||||||
|
$permissions = $this->permission->newQuery()
|
||||||
|
->whereIn('name', $permissionNameArray)
|
||||||
|
->pluck('id')
|
||||||
|
->toArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
$role->permissions()->sync($permissions);
|
$role->permissions()->sync($permissions);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -126,13 +113,13 @@ class PermissionsRepo
|
|||||||
* Check it's not an admin role or set as default before deleting.
|
* Check it's not an admin role or set as default before deleting.
|
||||||
* If an migration Role ID is specified the users assign to the current role
|
* If an migration Role ID is specified the users assign to the current role
|
||||||
* will be added to the role of the specified id.
|
* will be added to the role of the specified id.
|
||||||
* @param $roleId
|
|
||||||
* @param $migrateRoleId
|
|
||||||
* @throws PermissionsException
|
* @throws PermissionsException
|
||||||
|
* @throws Exception
|
||||||
*/
|
*/
|
||||||
public function deleteRole($roleId, $migrateRoleId)
|
public function deleteRole($roleId, $migrateRoleId)
|
||||||
{
|
{
|
||||||
$role = $this->role->findOrFail($roleId);
|
/** @var Role $role */
|
||||||
|
$role = $this->role->newQuery()->findOrFail($roleId);
|
||||||
|
|
||||||
// Prevent deleting admin role or default registration role.
|
// Prevent deleting admin role or default registration role.
|
||||||
if ($role->system_name && in_array($role->system_name, $this->systemRoles)) {
|
if ($role->system_name && in_array($role->system_name, $this->systemRoles)) {
|
||||||
@ -142,9 +129,9 @@ class PermissionsRepo
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ($migrateRoleId) {
|
if ($migrateRoleId) {
|
||||||
$newRole = $this->role->find($migrateRoleId);
|
$newRole = $this->role->newQuery()->find($migrateRoleId);
|
||||||
if ($newRole) {
|
if ($newRole) {
|
||||||
$users = $role->users->pluck('id')->toArray();
|
$users = $role->users()->pluck('id')->toArray();
|
||||||
$newRole->users()->sync($users);
|
$newRole->users()->sync($users);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,9 @@
|
|||||||
use BookStack\Auth\Role;
|
use BookStack\Auth\Role;
|
||||||
use BookStack\Model;
|
use BookStack\Model;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @property int $id
|
||||||
|
*/
|
||||||
class RolePermission extends Model
|
class RolePermission extends Model
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
|
@ -3,13 +3,16 @@
|
|||||||
use BookStack\Auth\Permissions\JointPermission;
|
use BookStack\Auth\Permissions\JointPermission;
|
||||||
use BookStack\Auth\Permissions\RolePermission;
|
use BookStack\Auth\Permissions\RolePermission;
|
||||||
use BookStack\Model;
|
use BookStack\Model;
|
||||||
|
use Illuminate\Database\Eloquent\Collection;
|
||||||
|
use Illuminate\Database\Eloquent\Relations\HasMany;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class Role
|
* Class Role
|
||||||
|
* @property int $id
|
||||||
* @property string $display_name
|
* @property string $display_name
|
||||||
* @property string $description
|
* @property string $description
|
||||||
* @property string $external_auth_id
|
* @property string $external_auth_id
|
||||||
* @package BookStack\Auth
|
* @property string $system_name
|
||||||
*/
|
*/
|
||||||
class Role extends Model
|
class Role extends Model
|
||||||
{
|
{
|
||||||
@ -26,9 +29,8 @@ class Role extends Model
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Get all related JointPermissions.
|
* Get all related JointPermissions.
|
||||||
* @return \Illuminate\Database\Eloquent\Relations\HasMany
|
|
||||||
*/
|
*/
|
||||||
public function jointPermissions()
|
public function jointPermissions(): HasMany
|
||||||
{
|
{
|
||||||
return $this->hasMany(JointPermission::class);
|
return $this->hasMany(JointPermission::class);
|
||||||
}
|
}
|
||||||
@ -43,10 +45,8 @@ class Role extends Model
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Check if this role has a permission.
|
* Check if this role has a permission.
|
||||||
* @param $permissionName
|
|
||||||
* @return bool
|
|
||||||
*/
|
*/
|
||||||
public function hasPermission($permissionName)
|
public function hasPermission(string $permissionName): bool
|
||||||
{
|
{
|
||||||
$permissions = $this->getRelationValue('permissions');
|
$permissions = $this->getRelationValue('permissions');
|
||||||
foreach ($permissions as $permission) {
|
foreach ($permissions as $permission) {
|
||||||
@ -59,7 +59,6 @@ class Role extends Model
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Add a permission to this role.
|
* Add a permission to this role.
|
||||||
* @param RolePermission $permission
|
|
||||||
*/
|
*/
|
||||||
public function attachPermission(RolePermission $permission)
|
public function attachPermission(RolePermission $permission)
|
||||||
{
|
{
|
||||||
@ -68,7 +67,6 @@ class Role extends Model
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Detach a single permission from this role.
|
* Detach a single permission from this role.
|
||||||
* @param RolePermission $permission
|
|
||||||
*/
|
*/
|
||||||
public function detachPermission(RolePermission $permission)
|
public function detachPermission(RolePermission $permission)
|
||||||
{
|
{
|
||||||
@ -76,39 +74,33 @@ class Role extends Model
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the role object for the specified role.
|
* Get the role of the specified display name.
|
||||||
* @param $roleName
|
|
||||||
* @return Role
|
|
||||||
*/
|
*/
|
||||||
public static function getRole($roleName)
|
public static function getRole(string $displayName): ?Role
|
||||||
{
|
{
|
||||||
return static::query()->where('name', '=', $roleName)->first();
|
return static::query()->where('display_name', '=', $displayName)->first();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the role object for the specified system role.
|
* Get the role object for the specified system role.
|
||||||
* @param $roleName
|
|
||||||
* @return Role
|
|
||||||
*/
|
*/
|
||||||
public static function getSystemRole($roleName)
|
public static function getSystemRole(string $systemName): ?Role
|
||||||
{
|
{
|
||||||
return static::query()->where('system_name', '=', $roleName)->first();
|
return static::query()->where('system_name', '=', $systemName)->first();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get all visible roles
|
* Get all visible roles
|
||||||
* @return mixed
|
|
||||||
*/
|
*/
|
||||||
public static function visible()
|
public static function visible(): Collection
|
||||||
{
|
{
|
||||||
return static::query()->where('hidden', '=', false)->orderBy('name')->get();
|
return static::query()->where('hidden', '=', false)->orderBy('name')->get();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the roles that can be restricted.
|
* Get the roles that can be restricted.
|
||||||
* @return \Illuminate\Database\Eloquent\Builder[]|\Illuminate\Database\Eloquent\Collection
|
|
||||||
*/
|
*/
|
||||||
public static function restrictable()
|
public static function restrictable(): Collection
|
||||||
{
|
{
|
||||||
return static::query()->where('system_name', '!=', 'admin')->get();
|
return static::query()->where('system_name', '!=', 'admin')->get();
|
||||||
}
|
}
|
||||||
|
@ -101,12 +101,10 @@ class User extends Model implements AuthenticatableContract, CanResetPasswordCon
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Check if the user has a role.
|
* Check if the user has a role.
|
||||||
* @param $role
|
|
||||||
* @return mixed
|
|
||||||
*/
|
*/
|
||||||
public function hasRole($role)
|
public function hasRole($roleId): bool
|
||||||
{
|
{
|
||||||
return $this->roles->pluck('name')->contains($role);
|
return $this->roles->pluck('id')->contains($roleId);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -163,7 +161,6 @@ class User extends Model implements AuthenticatableContract, CanResetPasswordCon
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Attach a role to this user.
|
* Attach a role to this user.
|
||||||
* @param Role $role
|
|
||||||
*/
|
*/
|
||||||
public function attachRole(Role $role)
|
public function attachRole(Role $role)
|
||||||
{
|
{
|
||||||
|
@ -238,7 +238,7 @@ class UserRepo
|
|||||||
*/
|
*/
|
||||||
public function getAllRoles()
|
public function getAllRoles()
|
||||||
{
|
{
|
||||||
return $this->role->newQuery()->orderBy('name', 'asc')->get();
|
return $this->role->newQuery()->orderBy('display_name', 'asc')->get();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -2,7 +2,9 @@
|
|||||||
|
|
||||||
use BookStack\Auth\Permissions\PermissionsRepo;
|
use BookStack\Auth\Permissions\PermissionsRepo;
|
||||||
use BookStack\Exceptions\PermissionsException;
|
use BookStack\Exceptions\PermissionsException;
|
||||||
|
use Exception;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
|
use Illuminate\Validation\ValidationException;
|
||||||
|
|
||||||
class PermissionController extends Controller
|
class PermissionController extends Controller
|
||||||
{
|
{
|
||||||
@ -11,7 +13,6 @@ class PermissionController extends Controller
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* PermissionController constructor.
|
* PermissionController constructor.
|
||||||
* @param \BookStack\Auth\Permissions\PermissionsRepo $permissionsRepo
|
|
||||||
*/
|
*/
|
||||||
public function __construct(PermissionsRepo $permissionsRepo)
|
public function __construct(PermissionsRepo $permissionsRepo)
|
||||||
{
|
{
|
||||||
@ -31,7 +32,6 @@ class PermissionController extends Controller
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Show the form to create a new role
|
* Show the form to create a new role
|
||||||
* @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
|
|
||||||
*/
|
*/
|
||||||
public function createRole()
|
public function createRole()
|
||||||
{
|
{
|
||||||
@ -41,15 +41,13 @@ class PermissionController extends Controller
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Store a new role in the system.
|
* Store a new role in the system.
|
||||||
* @param Request $request
|
|
||||||
* @return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector
|
|
||||||
*/
|
*/
|
||||||
public function storeRole(Request $request)
|
public function storeRole(Request $request)
|
||||||
{
|
{
|
||||||
$this->checkPermission('user-roles-manage');
|
$this->checkPermission('user-roles-manage');
|
||||||
$this->validate($request, [
|
$this->validate($request, [
|
||||||
'display_name' => 'required|min:3|max:200',
|
'display_name' => 'required|min:3|max:180',
|
||||||
'description' => 'max:250'
|
'description' => 'max:180'
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$this->permissionsRepo->saveNewRole($request->all());
|
$this->permissionsRepo->saveNewRole($request->all());
|
||||||
@ -59,11 +57,9 @@ class PermissionController extends Controller
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Show the form for editing a user role.
|
* Show the form for editing a user role.
|
||||||
* @param $id
|
|
||||||
* @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
|
|
||||||
* @throws PermissionsException
|
* @throws PermissionsException
|
||||||
*/
|
*/
|
||||||
public function editRole($id)
|
public function editRole(string $id)
|
||||||
{
|
{
|
||||||
$this->checkPermission('user-roles-manage');
|
$this->checkPermission('user-roles-manage');
|
||||||
$role = $this->permissionsRepo->getRoleById($id);
|
$role = $this->permissionsRepo->getRoleById($id);
|
||||||
@ -75,18 +71,14 @@ class PermissionController extends Controller
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Updates a user role.
|
* Updates a user role.
|
||||||
* @param Request $request
|
* @throws ValidationException
|
||||||
* @param $id
|
|
||||||
* @return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector
|
|
||||||
* @throws PermissionsException
|
|
||||||
* @throws \Illuminate\Validation\ValidationException
|
|
||||||
*/
|
*/
|
||||||
public function updateRole(Request $request, $id)
|
public function updateRole(Request $request, string $id)
|
||||||
{
|
{
|
||||||
$this->checkPermission('user-roles-manage');
|
$this->checkPermission('user-roles-manage');
|
||||||
$this->validate($request, [
|
$this->validate($request, [
|
||||||
'display_name' => 'required|min:3|max:200',
|
'display_name' => 'required|min:3|max:180',
|
||||||
'description' => 'max:250'
|
'description' => 'max:180'
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$this->permissionsRepo->updateRole($id, $request->all());
|
$this->permissionsRepo->updateRole($id, $request->all());
|
||||||
@ -97,10 +89,8 @@ class PermissionController extends Controller
|
|||||||
/**
|
/**
|
||||||
* Show the view to delete a role.
|
* Show the view to delete a role.
|
||||||
* Offers the chance to migrate users.
|
* Offers the chance to migrate users.
|
||||||
* @param $id
|
|
||||||
* @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
|
|
||||||
*/
|
*/
|
||||||
public function showDeleteRole($id)
|
public function showDeleteRole(string $id)
|
||||||
{
|
{
|
||||||
$this->checkPermission('user-roles-manage');
|
$this->checkPermission('user-roles-manage');
|
||||||
$role = $this->permissionsRepo->getRoleById($id);
|
$role = $this->permissionsRepo->getRoleById($id);
|
||||||
@ -113,11 +103,9 @@ class PermissionController extends Controller
|
|||||||
/**
|
/**
|
||||||
* Delete a role from the system,
|
* Delete a role from the system,
|
||||||
* Migrate from a previous role if set.
|
* Migrate from a previous role if set.
|
||||||
* @param Request $request
|
* @throws Exception
|
||||||
* @param $id
|
|
||||||
* @return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector
|
|
||||||
*/
|
*/
|
||||||
public function deleteRole(Request $request, $id)
|
public function deleteRole(Request $request, string $id)
|
||||||
{
|
{
|
||||||
$this->checkPermission('user-roles-manage');
|
$this->checkPermission('user-roles-manage');
|
||||||
|
|
||||||
|
@ -66,8 +66,8 @@ class UserController extends Controller
|
|||||||
{
|
{
|
||||||
$this->checkPermission('users-manage');
|
$this->checkPermission('users-manage');
|
||||||
$validationRules = [
|
$validationRules = [
|
||||||
'name' => 'required',
|
'name' => 'required',
|
||||||
'email' => 'required|email|unique:users,email'
|
'email' => 'required|email|unique:users,email'
|
||||||
];
|
];
|
||||||
|
|
||||||
$authMethod = config('auth.method');
|
$authMethod = config('auth.method');
|
||||||
|
@ -0,0 +1,37 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
use Illuminate\Support\Facades\DB;
|
||||||
|
|
||||||
|
class RemoveRoleNameField extends Migration
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Run the migrations.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function up()
|
||||||
|
{
|
||||||
|
Schema::table('roles', function (Blueprint $table) {
|
||||||
|
$table->dropColumn('name');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reverse the migrations.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function down()
|
||||||
|
{
|
||||||
|
Schema::table('roles', function (Blueprint $table) {
|
||||||
|
$table->string('name')->index();
|
||||||
|
});
|
||||||
|
|
||||||
|
DB::table('roles')->update([
|
||||||
|
"name" => DB::raw("lower(replace(`display_name`, ' ', '-'))"),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
@ -3,10 +3,10 @@
|
|||||||
@foreach($roles as $role)
|
@foreach($roles as $role)
|
||||||
<div>
|
<div>
|
||||||
@include('components.custom-checkbox', [
|
@include('components.custom-checkbox', [
|
||||||
'name' => $name . '[' . str_replace('.', 'DOT', $role->name) . ']',
|
'name' => $name . '[' . strval($role->id) . ']',
|
||||||
'label' => $role->display_name,
|
'label' => $role->display_name,
|
||||||
'value' => $role->id,
|
'value' => $role->id,
|
||||||
'checked' => old($name . '.' . str_replace('.', 'DOT', $role->name)) || (!old('name') && isset($model) && $model->hasRole($role->name))
|
'checked' => old($name . '.' . strval($role->id)) || (!old('name') && isset($model) && $model->hasRole($role->id))
|
||||||
])
|
])
|
||||||
</div>
|
</div>
|
||||||
@endforeach
|
@endforeach
|
||||||
|
@ -231,7 +231,8 @@
|
|||||||
<label for="setting-registration-role">{{ trans('settings.reg_default_role') }}</label>
|
<label for="setting-registration-role">{{ trans('settings.reg_default_role') }}</label>
|
||||||
<select id="setting-registration-role" name="setting-registration-role" @if($errors->has('setting-registration-role')) class="neg" @endif>
|
<select id="setting-registration-role" name="setting-registration-role" @if($errors->has('setting-registration-role')) class="neg" @endif>
|
||||||
@foreach(\BookStack\Auth\Role::all() as $role)
|
@foreach(\BookStack\Auth\Role::all() as $role)
|
||||||
<option value="{{$role->id}}" data-role-name="{{ $role->name }}"
|
<option value="{{$role->id}}"
|
||||||
|
data-system-role-name="{{ $role->system_name ?? '' }}"
|
||||||
@if(setting('registration-role', \BookStack\Auth\Role::first()->id) == $role->id) selected @endif
|
@if(setting('registration-role', \BookStack\Auth\Role::first()->id) == $role->id) selected @endif
|
||||||
>
|
>
|
||||||
{{ $role->display_name }}
|
{{ $role->display_name }}
|
||||||
|
@ -19,7 +19,7 @@
|
|||||||
@if($role->users->count() > 0)
|
@if($role->users->count() > 0)
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<p>{{ trans('settings.role_delete_users_assigned', ['userCount' => $role->users->count()]) }}</p>
|
<p>{{ trans('settings.role_delete_users_assigned', ['userCount' => $role->users->count()]) }}</p>
|
||||||
@include('form.role-select', ['options' => $roles, 'name' => 'migration_role_id'])
|
@include('form.role-select', ['options' => $roles, 'name' => 'migrate_role_id'])
|
||||||
</div>
|
</div>
|
||||||
@endif
|
@endif
|
||||||
|
|
||||||
|
@ -213,13 +213,14 @@ class AuthTest extends BrowserKitTest
|
|||||||
public function test_user_creation()
|
public function test_user_creation()
|
||||||
{
|
{
|
||||||
$user = factory(User::class)->make();
|
$user = factory(User::class)->make();
|
||||||
|
$adminRole = Role::getRole('admin');
|
||||||
|
|
||||||
$this->asAdmin()
|
$this->asAdmin()
|
||||||
->visit('/settings/users')
|
->visit('/settings/users')
|
||||||
->click('Add New User')
|
->click('Add New User')
|
||||||
->type($user->name, '#name')
|
->type($user->name, '#name')
|
||||||
->type($user->email, '#email')
|
->type($user->email, '#email')
|
||||||
->check('roles[admin]')
|
->check("roles[{$adminRole->id}]")
|
||||||
->type($user->password, '#password')
|
->type($user->password, '#password')
|
||||||
->type($user->password, '#password-confirm')
|
->type($user->password, '#password-confirm')
|
||||||
->press('Save')
|
->press('Save')
|
||||||
|
@ -237,9 +237,9 @@ class LdapTest extends BrowserKitTest
|
|||||||
|
|
||||||
public function test_login_maps_roles_and_retains_existing_roles()
|
public function test_login_maps_roles_and_retains_existing_roles()
|
||||||
{
|
{
|
||||||
$roleToReceive = factory(Role::class)->create(['name' => 'ldaptester', 'display_name' => 'LdapTester']);
|
$roleToReceive = factory(Role::class)->create(['display_name' => 'LdapTester']);
|
||||||
$roleToReceive2 = factory(Role::class)->create(['name' => 'ldaptester-second', 'display_name' => 'LdapTester Second']);
|
$roleToReceive2 = factory(Role::class)->create(['display_name' => 'LdapTester Second']);
|
||||||
$existingRole = factory(Role::class)->create(['name' => 'ldaptester-existing']);
|
$existingRole = factory(Role::class)->create(['display_name' => 'ldaptester-existing']);
|
||||||
$this->mockUser->forceFill(['external_auth_id' => $this->mockUser->name])->save();
|
$this->mockUser->forceFill(['external_auth_id' => $this->mockUser->name])->save();
|
||||||
$this->mockUser->attachRole($existingRole);
|
$this->mockUser->attachRole($existingRole);
|
||||||
|
|
||||||
@ -283,8 +283,8 @@ class LdapTest extends BrowserKitTest
|
|||||||
|
|
||||||
public function test_login_maps_roles_and_removes_old_roles_if_set()
|
public function test_login_maps_roles_and_removes_old_roles_if_set()
|
||||||
{
|
{
|
||||||
$roleToReceive = factory(Role::class)->create(['name' => 'ldaptester', 'display_name' => 'LdapTester']);
|
$roleToReceive = factory(Role::class)->create(['display_name' => 'LdapTester']);
|
||||||
$existingRole = factory(Role::class)->create(['name' => 'ldaptester-existing']);
|
$existingRole = factory(Role::class)->create(['display_name' => 'ldaptester-existing']);
|
||||||
$this->mockUser->forceFill(['external_auth_id' => $this->mockUser->name])->save();
|
$this->mockUser->forceFill(['external_auth_id' => $this->mockUser->name])->save();
|
||||||
$this->mockUser->attachRole($existingRole);
|
$this->mockUser->attachRole($existingRole);
|
||||||
|
|
||||||
@ -323,15 +323,15 @@ class LdapTest extends BrowserKitTest
|
|||||||
|
|
||||||
public function test_external_auth_id_visible_in_roles_page_when_ldap_active()
|
public function test_external_auth_id_visible_in_roles_page_when_ldap_active()
|
||||||
{
|
{
|
||||||
$role = factory(Role::class)->create(['name' => 'ldaptester', 'external_auth_id' => 'ex-auth-a, test-second-param']);
|
$role = factory(Role::class)->create(['display_name' => 'ldaptester', 'external_auth_id' => 'ex-auth-a, test-second-param']);
|
||||||
$this->asAdmin()->visit('/settings/roles/' . $role->id)
|
$this->asAdmin()->visit('/settings/roles/' . $role->id)
|
||||||
->see('ex-auth-a');
|
->see('ex-auth-a');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function test_login_maps_roles_using_external_auth_ids_if_set()
|
public function test_login_maps_roles_using_external_auth_ids_if_set()
|
||||||
{
|
{
|
||||||
$roleToReceive = factory(Role::class)->create(['name' => 'ldaptester', 'external_auth_id' => 'test-second-param, ex-auth-a']);
|
$roleToReceive = factory(Role::class)->create(['display_name' => 'ldaptester', 'external_auth_id' => 'test-second-param, ex-auth-a']);
|
||||||
$roleToNotReceive = factory(Role::class)->create(['name' => 'ldaptester-not-receive', 'display_name' => 'ex-auth-a', 'external_auth_id' => 'test-second-param']);
|
$roleToNotReceive = factory(Role::class)->create(['display_name' => 'ex-auth-a', 'external_auth_id' => 'test-second-param']);
|
||||||
|
|
||||||
app('config')->set([
|
app('config')->set([
|
||||||
'services.ldap.user_to_groups' => true,
|
'services.ldap.user_to_groups' => true,
|
||||||
@ -368,8 +368,8 @@ class LdapTest extends BrowserKitTest
|
|||||||
|
|
||||||
public function test_login_group_mapping_does_not_conflict_with_default_role()
|
public function test_login_group_mapping_does_not_conflict_with_default_role()
|
||||||
{
|
{
|
||||||
$roleToReceive = factory(Role::class)->create(['name' => 'ldaptester', 'display_name' => 'LdapTester']);
|
$roleToReceive = factory(Role::class)->create(['display_name' => 'LdapTester']);
|
||||||
$roleToReceive2 = factory(Role::class)->create(['name' => 'ldaptester-second', 'display_name' => 'LdapTester Second']);
|
$roleToReceive2 = factory(Role::class)->create(['display_name' => 'LdapTester Second']);
|
||||||
$this->mockUser->forceFill(['external_auth_id' => $this->mockUser->name])->save();
|
$this->mockUser->forceFill(['external_auth_id' => $this->mockUser->name])->save();
|
||||||
|
|
||||||
setting()->put('registration-role', $roleToReceive->id);
|
setting()->put('registration-role', $roleToReceive->id);
|
||||||
|
@ -57,7 +57,7 @@ class RolesTest extends BrowserKitTest
|
|||||||
->type('Test Role', 'display_name')
|
->type('Test Role', 'display_name')
|
||||||
->type('A little test description', 'description')
|
->type('A little test description', 'description')
|
||||||
->press('Save Role')
|
->press('Save Role')
|
||||||
->seeInDatabase('roles', ['display_name' => $testRoleName, 'name' => 'test-role', 'description' => $testRoleDesc])
|
->seeInDatabase('roles', ['display_name' => $testRoleName, 'description' => $testRoleDesc])
|
||||||
->seePageIs('/settings/roles');
|
->seePageIs('/settings/roles');
|
||||||
// Updating
|
// Updating
|
||||||
$this->asAdmin()->visit('/settings/roles')
|
$this->asAdmin()->visit('/settings/roles')
|
||||||
@ -65,7 +65,7 @@ class RolesTest extends BrowserKitTest
|
|||||||
->click($testRoleName)
|
->click($testRoleName)
|
||||||
->type($testRoleUpdateName, '#display_name')
|
->type($testRoleUpdateName, '#display_name')
|
||||||
->press('Save Role')
|
->press('Save Role')
|
||||||
->seeInDatabase('roles', ['display_name' => $testRoleUpdateName, 'name' => 'test-role', 'description' => $testRoleDesc])
|
->seeInDatabase('roles', ['display_name' => $testRoleUpdateName, 'description' => $testRoleDesc])
|
||||||
->seePageIs('/settings/roles');
|
->seePageIs('/settings/roles');
|
||||||
// Deleting
|
// Deleting
|
||||||
$this->asAdmin()->visit('/settings/roles')
|
$this->asAdmin()->visit('/settings/roles')
|
||||||
@ -99,6 +99,25 @@ class RolesTest extends BrowserKitTest
|
|||||||
$this->see('This user is the only user assigned to the administrator role');
|
$this->see('This user is the only user assigned to the administrator role');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function test_migrate_users_on_delete_works()
|
||||||
|
{
|
||||||
|
$roleA = Role::query()->create(['display_name' => 'Delete Test A']);
|
||||||
|
$roleB = Role::query()->create(['display_name' => 'Delete Test B']);
|
||||||
|
$this->user->attachRole($roleB);
|
||||||
|
|
||||||
|
$this->assertCount(0, $roleA->users()->get());
|
||||||
|
$this->assertCount(1, $roleB->users()->get());
|
||||||
|
|
||||||
|
$deletePage = $this->asAdmin()->get("/settings/roles/delete/{$roleB->id}");
|
||||||
|
$deletePage->seeElement('select[name=migrate_role_id]');
|
||||||
|
$this->asAdmin()->delete("/settings/roles/delete/{$roleB->id}", [
|
||||||
|
'migrate_role_id' => $roleA->id,
|
||||||
|
]);
|
||||||
|
|
||||||
|
$this->assertCount(1, $roleA->users()->get());
|
||||||
|
$this->assertEquals($this->user->id, $roleA->users()->first()->id);
|
||||||
|
}
|
||||||
|
|
||||||
public function test_manage_user_permission()
|
public function test_manage_user_permission()
|
||||||
{
|
{
|
||||||
$this->actingAs($this->user)->visit('/settings/users')
|
$this->actingAs($this->user)->visit('/settings/users')
|
||||||
@ -667,9 +686,11 @@ class RolesTest extends BrowserKitTest
|
|||||||
public function test_public_role_visible_in_user_edit_screen()
|
public function test_public_role_visible_in_user_edit_screen()
|
||||||
{
|
{
|
||||||
$user = \BookStack\Auth\User::first();
|
$user = \BookStack\Auth\User::first();
|
||||||
|
$adminRole = Role::getSystemRole('admin');
|
||||||
|
$publicRole = Role::getSystemRole('public');
|
||||||
$this->asAdmin()->visit('/settings/users/' . $user->id)
|
$this->asAdmin()->visit('/settings/users/' . $user->id)
|
||||||
->seeElement('[name="roles[admin]"]')
|
->seeElement('[name="roles['.$adminRole->id.']"]')
|
||||||
->seeElement('[name="roles[public]"]');
|
->seeElement('[name="roles['.$publicRole->id.']"]');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function test_public_role_visible_in_role_listing()
|
public function test_public_role_visible_in_role_listing()
|
||||||
@ -682,9 +703,8 @@ class RolesTest extends BrowserKitTest
|
|||||||
public function test_public_role_visible_in_default_role_setting()
|
public function test_public_role_visible_in_default_role_setting()
|
||||||
{
|
{
|
||||||
$this->asAdmin()->visit('/settings')
|
$this->asAdmin()->visit('/settings')
|
||||||
->seeElement('[data-role-name="admin"]')
|
->seeElement('[data-system-role-name="admin"]')
|
||||||
->seeElement('[data-role-name="public"]');
|
->seeElement('[data-system-role-name="public"]');
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function test_public_role_not_deleteable()
|
public function test_public_role_not_deleteable()
|
||||||
|
Loading…
Reference in New Issue
Block a user