mirror of
https://github.com/BookStackApp/BookStack.git
synced 2024-10-01 01:36:00 -04:00
Created big scary query to apply permissions via new format
This commit is contained in:
parent
39acbeac68
commit
7330139555
@ -2,7 +2,6 @@
|
||||
|
||||
namespace BookStack\Auth\Permissions;
|
||||
|
||||
use BookStack\Auth\Role;
|
||||
use BookStack\Entities\Models\Book;
|
||||
use BookStack\Entities\Models\BookChild;
|
||||
use BookStack\Entities\Models\Bookshelf;
|
||||
|
@ -183,21 +183,71 @@ class PermissionApplicator
|
||||
* Limit the given entity query so that the query will only
|
||||
* return items that the user has view permission for.
|
||||
*/
|
||||
public function restrictEntityQuery(Builder $query): Builder
|
||||
public function restrictEntityQuery(Builder $query, string $morphClass): Builder
|
||||
{
|
||||
return $query->where(function (Builder $parentQuery) {
|
||||
$parentQuery->whereHas('jointPermissions', function (Builder $permissionQuery) {
|
||||
$permissionQuery->whereIn('role_id', $this->getCurrentUserRoleIds())
|
||||
->where(function (Builder $query) {
|
||||
$this->addJointHasPermissionCheck($query, $this->currentUser()->id);
|
||||
$this->getCurrentUserRoleIds();
|
||||
$this->currentUser()->id;
|
||||
|
||||
$userViewAll = userCan($morphClass . '-view-all');
|
||||
$userViewOwn = userCan($morphClass . '-view-own');
|
||||
|
||||
// TODO - Leave this as the new admin workaround?
|
||||
// Or auto generate collapsed role permissions for admins?
|
||||
if (\user()->hasSystemRole('admin')) {
|
||||
return $query;
|
||||
}
|
||||
|
||||
// Fallback permission join
|
||||
$query->joinSub(function (QueryBuilder $joinQuery) use ($morphClass) {
|
||||
$joinQuery->select(['entity_id'])->selectRaw('max(view) as perms_fallback')
|
||||
->from('entity_permissions_collapsed')
|
||||
->where('entity_type', '=', $morphClass)
|
||||
->whereNull(['role_id', 'user_id'])
|
||||
->groupBy('entity_id');
|
||||
}, 'p_f', 'id', '=', 'p_f.entity_id', 'left');
|
||||
|
||||
// Role permission join
|
||||
$query->joinSub(function (QueryBuilder $joinQuery) use ($morphClass) {
|
||||
$joinQuery->select(['entity_id'])->selectRaw('max(view) as perms_role')
|
||||
->from('entity_permissions_collapsed')
|
||||
->where('entity_type', '=', $morphClass)
|
||||
->whereIn('role_id', $this->getCurrentUserRoleIds())
|
||||
->groupBy('entity_id');
|
||||
}, 'p_r', 'id', '=', 'p_r.entity_id', 'left');
|
||||
|
||||
// User permission join
|
||||
$query->joinSub(function (QueryBuilder $joinQuery) use ($morphClass) {
|
||||
$joinQuery->select(['entity_id'])->selectRaw('max(view) as perms_user')
|
||||
->from('entity_permissions_collapsed')
|
||||
->where('entity_type', '=', $morphClass)
|
||||
->where('user_id', '=', $this->currentUser()->id)
|
||||
->groupBy('entity_id');
|
||||
}, 'p_u', 'id', '=', 'p_u.entity_id', 'left');
|
||||
|
||||
// Where permissions apply
|
||||
$query->where(function (Builder $query) use ($userViewOwn, $userViewAll) {
|
||||
$query->where('perms_user', '=', 1)
|
||||
->orWhere(function (Builder $query) {
|
||||
$query->whereNull('perms_user')->where('perms_role', '=', 1);
|
||||
})->orWhere(function (Builder $query) {
|
||||
$query->whereNull(['perms_user', 'perms_role'])
|
||||
->where('perms_fallback', '=', 1);
|
||||
});
|
||||
})->orWhereHas('jointUserPermissions', function (Builder $query) {
|
||||
$query->where('user_id', '=', $this->currentUser()->id)->where('has_permission', '=', true);
|
||||
|
||||
if ($userViewAll) {
|
||||
$query->orWhere(function (Builder $query) {
|
||||
$query->whereNull(['perms_user', 'perms_role', 'perms_fallback']);
|
||||
});
|
||||
})->whereDoesntHave('jointUserPermissions', function (Builder $query) {
|
||||
$query->where('user_id', '=', $this->currentUser()->id)->where('has_permission', '=', false);
|
||||
} else if ($userViewOwn) {
|
||||
$query->orWhere(function (Builder $query) {
|
||||
$query->whereNull(['perms_user', 'perms_role', 'perms_fallback'])
|
||||
->where('created_by', '=', $this->currentUser()->id);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
return $query;
|
||||
}
|
||||
|
||||
/**
|
||||
* Extend the given page query to ensure draft items are not visible
|
||||
@ -226,6 +276,9 @@ class PermissionApplicator
|
||||
$tableDetails = ['tableName' => $tableName, 'entityIdColumn' => $entityIdColumn, 'entityTypeColumn' => $entityTypeColumn];
|
||||
$pageMorphClass = (new Page())->getMorphClass();
|
||||
|
||||
// TODO;
|
||||
return $query;
|
||||
|
||||
$q = $query->where(function ($query) use ($tableDetails) {
|
||||
$query->whereExists(function ($permissionQuery) use ($tableDetails) {
|
||||
/** @var Builder $permissionQuery */
|
||||
@ -275,6 +328,9 @@ class PermissionApplicator
|
||||
$fullPageIdColumn = $tableName . '.' . $pageIdColumn;
|
||||
$morphClass = (new Page())->getMorphClass();
|
||||
|
||||
// TODO
|
||||
return $query;
|
||||
|
||||
$existsQuery = function ($permissionQuery) use ($fullPageIdColumn, $morphClass) {
|
||||
/** @var Builder $permissionQuery */
|
||||
$permissionQuery->select('joint_permissions.role_id')->from('joint_permissions')
|
||||
|
@ -70,7 +70,7 @@ abstract class Entity extends Model implements Sluggable, Favouritable, Viewable
|
||||
*/
|
||||
public function scopeVisible(Builder $query): Builder
|
||||
{
|
||||
return app()->make(PermissionApplicator::class)->restrictEntityQuery($query);
|
||||
return app()->make(PermissionApplicator::class)->restrictEntityQuery($query, $this->getMorphClass());
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -8,8 +8,11 @@ Tests are categorised by the most specific element involved in the scenario, whe
|
||||
|
||||
- User entity permissions.
|
||||
- Role entity permissions.
|
||||
- Fallback entity permissions.
|
||||
- Role permissions.
|
||||
|
||||
- TODO - Test fallback in the context of the above.
|
||||
|
||||
## General Permission Logical Rules
|
||||
|
||||
The below are some general rules we follow to standardise the behaviour of permissions in the platform:
|
||||
|
Loading…
Reference in New Issue
Block a user