mirror of
https://github.com/BookStackApp/BookStack.git
synced 2025-08-07 23:03:00 +03:00
Created big scary query to apply permissions via new format
This commit is contained in:
@@ -2,7 +2,6 @@
|
|||||||
|
|
||||||
namespace BookStack\Auth\Permissions;
|
namespace BookStack\Auth\Permissions;
|
||||||
|
|
||||||
use BookStack\Auth\Role;
|
|
||||||
use BookStack\Entities\Models\Book;
|
use BookStack\Entities\Models\Book;
|
||||||
use BookStack\Entities\Models\BookChild;
|
use BookStack\Entities\Models\BookChild;
|
||||||
use BookStack\Entities\Models\Bookshelf;
|
use BookStack\Entities\Models\Bookshelf;
|
||||||
|
@@ -183,20 +183,70 @@ class PermissionApplicator
|
|||||||
* Limit the given entity query so that the query will only
|
* Limit the given entity query so that the query will only
|
||||||
* return items that the user has view permission for.
|
* 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) {
|
$this->getCurrentUserRoleIds();
|
||||||
$parentQuery->whereHas('jointPermissions', function (Builder $permissionQuery) {
|
$this->currentUser()->id;
|
||||||
$permissionQuery->whereIn('role_id', $this->getCurrentUserRoleIds())
|
|
||||||
->where(function (Builder $query) {
|
$userViewAll = userCan($morphClass . '-view-all');
|
||||||
$this->addJointHasPermissionCheck($query, $this->currentUser()->id);
|
$userViewOwn = userCan($morphClass . '-view-own');
|
||||||
});
|
|
||||||
})->orWhereHas('jointUserPermissions', function (Builder $query) {
|
// TODO - Leave this as the new admin workaround?
|
||||||
$query->where('user_id', '=', $this->currentUser()->id)->where('has_permission', '=', true);
|
// Or auto generate collapsed role permissions for admins?
|
||||||
});
|
if (\user()->hasSystemRole('admin')) {
|
||||||
})->whereDoesntHave('jointUserPermissions', function (Builder $query) {
|
return $query;
|
||||||
$query->where('user_id', '=', $this->currentUser()->id)->where('has_permission', '=', false);
|
}
|
||||||
|
|
||||||
|
// 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);
|
||||||
|
});
|
||||||
|
|
||||||
|
if ($userViewAll) {
|
||||||
|
$query->orWhere(function (Builder $query) {
|
||||||
|
$query->whereNull(['perms_user', 'perms_role', 'perms_fallback']);
|
||||||
|
});
|
||||||
|
} else if ($userViewOwn) {
|
||||||
|
$query->orWhere(function (Builder $query) {
|
||||||
|
$query->whereNull(['perms_user', 'perms_role', 'perms_fallback'])
|
||||||
|
->where('created_by', '=', $this->currentUser()->id);
|
||||||
|
});
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
return $query;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -226,6 +276,9 @@ class PermissionApplicator
|
|||||||
$tableDetails = ['tableName' => $tableName, 'entityIdColumn' => $entityIdColumn, 'entityTypeColumn' => $entityTypeColumn];
|
$tableDetails = ['tableName' => $tableName, 'entityIdColumn' => $entityIdColumn, 'entityTypeColumn' => $entityTypeColumn];
|
||||||
$pageMorphClass = (new Page())->getMorphClass();
|
$pageMorphClass = (new Page())->getMorphClass();
|
||||||
|
|
||||||
|
// TODO;
|
||||||
|
return $query;
|
||||||
|
|
||||||
$q = $query->where(function ($query) use ($tableDetails) {
|
$q = $query->where(function ($query) use ($tableDetails) {
|
||||||
$query->whereExists(function ($permissionQuery) use ($tableDetails) {
|
$query->whereExists(function ($permissionQuery) use ($tableDetails) {
|
||||||
/** @var Builder $permissionQuery */
|
/** @var Builder $permissionQuery */
|
||||||
@@ -275,6 +328,9 @@ class PermissionApplicator
|
|||||||
$fullPageIdColumn = $tableName . '.' . $pageIdColumn;
|
$fullPageIdColumn = $tableName . '.' . $pageIdColumn;
|
||||||
$morphClass = (new Page())->getMorphClass();
|
$morphClass = (new Page())->getMorphClass();
|
||||||
|
|
||||||
|
// TODO
|
||||||
|
return $query;
|
||||||
|
|
||||||
$existsQuery = function ($permissionQuery) use ($fullPageIdColumn, $morphClass) {
|
$existsQuery = function ($permissionQuery) use ($fullPageIdColumn, $morphClass) {
|
||||||
/** @var Builder $permissionQuery */
|
/** @var Builder $permissionQuery */
|
||||||
$permissionQuery->select('joint_permissions.role_id')->from('joint_permissions')
|
$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
|
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.
|
- User entity permissions.
|
||||||
- Role entity permissions.
|
- Role entity permissions.
|
||||||
|
- Fallback entity permissions.
|
||||||
- Role permissions.
|
- Role permissions.
|
||||||
|
|
||||||
|
- TODO - Test fallback in the context of the above.
|
||||||
|
|
||||||
## General Permission Logical Rules
|
## General Permission Logical Rules
|
||||||
|
|
||||||
The below are some general rules we follow to standardise the behaviour of permissions in the platform:
|
The below are some general rules we follow to standardise the behaviour of permissions in the platform:
|
||||||
|
Reference in New Issue
Block a user