1
0
mirror of https://github.com/BookStackApp/BookStack.git synced 2024-11-24 03:42:32 +01:00

Aligned permission applicator method names

Also removed lesser used function, that was mostly a duplicate of an
existing function, and only used for search.
This commit is contained in:
Dan Brown 2022-07-16 19:54:25 +01:00
parent f459a68535
commit afe1a04239
No known key found for this signature in database
GPG Key ID: 46D9F943C24A2EF9
10 changed files with 36 additions and 71 deletions

View File

@ -26,7 +26,7 @@ class ActivityQueries
public function latest(int $count = 20, int $page = 0): array
{
$activityList = $this->permissions
->filterRestrictedEntityRelations(Activity::query(), 'activities', 'entity_id', 'entity_type')
->restrictEntityRelationQuery(Activity::query(), 'activities', 'entity_id', 'entity_type')
->orderBy('created_at', 'desc')
->with(['user', 'entity'])
->skip($count * $page)
@ -79,7 +79,7 @@ class ActivityQueries
public function userActivity(User $user, int $count = 20, int $page = 0): array
{
$activityList = $this->permissions
->filterRestrictedEntityRelations(Activity::query(), 'activities', 'entity_id', 'entity_type')
->restrictEntityRelationQuery(Activity::query(), 'activities', 'entity_id', 'entity_type')
->orderBy('created_at', 'desc')
->where('user_id', '=', $user->id)
->skip($count * $page)

View File

@ -50,7 +50,7 @@ class TagRepo
});
}
return $this->permissions->filterRestrictedEntityRelations($query, 'tags', 'entity_id', 'entity_type');
return $this->permissions->restrictEntityRelationQuery($query, 'tags', 'entity_id', 'entity_type');
}
/**
@ -69,7 +69,7 @@ class TagRepo
$query = $query->orderBy('count', 'desc')->take(50);
}
$query = $this->permissions->filterRestrictedEntityRelations($query, 'tags', 'entity_id', 'entity_type');
$query = $this->permissions->restrictEntityRelationQuery($query, 'tags', 'entity_id', 'entity_type');
return $query->get(['name'])->pluck('name');
}
@ -95,7 +95,7 @@ class TagRepo
$query = $query->where('name', '=', $tagName);
}
$query = $this->permissions->filterRestrictedEntityRelations($query, 'tags', 'entity_id', 'entity_type');
$query = $this->permissions->restrictEntityRelationQuery($query, 'tags', 'entity_id', 'entity_type');
return $query->get(['value'])->pluck('value');
}

View File

@ -105,7 +105,7 @@ class PermissionApplicator
}
/**
* Limited 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.
*/
public function restrictEntityQuery(Builder $query): Builder
@ -126,7 +126,7 @@ class PermissionApplicator
* Extend the given page query to ensure draft items are not visible
* unless created by the given user.
*/
public function enforceDraftVisibilityOnQuery(Builder $query): Builder
public function restrictDraftsOnPageQuery(Builder $query): Builder
{
return $query->where(function (Builder $query) {
$query->where('draft', '=', false)
@ -137,39 +137,6 @@ class PermissionApplicator
});
}
/**
* Add restrictions for a generic entity.
*/
public function enforceEntityRestrictions(Entity $entity, Builder $query): Builder
{
if ($entity instanceof Page) {
// Prevent drafts being visible to others.
$this->enforceDraftVisibilityOnQuery($query);
}
return $this->entityRestrictionQuery($query);
}
/**
* The general query filter to remove all entities
* that the current user does not have access to.
*/
protected function entityRestrictionQuery(Builder $query): Builder
{
$q = $query->where(function ($parentQuery) {
$parentQuery->whereHas('jointPermissions', function ($permissionQuery) {
$permissionQuery->whereIn('role_id', $this->getCurrentUserRoleIds())
// TODO - Delete line once only views
->where('action', '=', 'view')
->where(function (Builder $query) {
$this->addJointHasPermissionCheck($query, $this->currentUser()->id);
});
});
});
return $q;
}
/**
* Filter items that have entities set as a polymorphic relation.
* For simplicity, this will not return results attached to draft pages.
@ -177,7 +144,7 @@ class PermissionApplicator
*
* @param Builder|QueryBuilder $query
*/
public function filterRestrictedEntityRelations($query, string $tableName, string $entityIdColumn, string $entityTypeColumn)
public function restrictEntityRelationQuery($query, string $tableName, string $entityIdColumn, string $entityTypeColumn)
{
$tableDetails = ['tableName' => $tableName, 'entityIdColumn' => $entityIdColumn, 'entityTypeColumn' => $entityTypeColumn];
$pageMorphClass = (new Page())->getMorphClass();
@ -207,19 +174,20 @@ class PermissionApplicator
}
/**
* Add conditions to a query to filter the selection to related entities
* where view permissions are granted.
* Add conditions to a query for a model that's a relation of a page, so only the model results
* on visible pages are returned by the query.
* Is effectively the same as "restrictEntityRelationQuery" but takes into account page drafts
* while not expecting a polymorphic relation, Just a simpler one-page-to-many-relations set-up.
*/
public function filterRelatedEntity(string $entityClass, Builder $query, string $tableName, string $entityIdColumn): Builder
public function restrictPageRelationQuery(Builder $query, string $tableName, string $pageIdColumn): Builder
{
$fullEntityIdColumn = $tableName . '.' . $entityIdColumn;
$instance = new $entityClass();
$morphClass = $instance->getMorphClass();
$fullPageIdColumn = $tableName . '.' . $pageIdColumn;
$morphClass = (new Page())->getMorphClass();
$existsQuery = function ($permissionQuery) use ($fullEntityIdColumn, $morphClass) {
$existsQuery = function ($permissionQuery) use ($fullPageIdColumn, $morphClass) {
/** @var Builder $permissionQuery */
$permissionQuery->select('joint_permissions.role_id')->from('joint_permissions')
->whereColumn('joint_permissions.entity_id', '=', $fullEntityIdColumn)
->whereColumn('joint_permissions.entity_id', '=', $fullPageIdColumn)
->where('joint_permissions.entity_type', '=', $morphClass)
->where('joint_permissions.action', '=', 'view')
->whereIn('joint_permissions.role_id', $this->getCurrentUserRoleIds())
@ -228,22 +196,20 @@ class PermissionApplicator
});
};
$q = $query->where(function ($query) use ($existsQuery, $fullEntityIdColumn) {
$q = $query->where(function ($query) use ($existsQuery, $fullPageIdColumn) {
$query->whereExists($existsQuery)
->orWhere($fullEntityIdColumn, '=', 0);
->orWhere($fullPageIdColumn, '=', 0);
});
if ($instance instanceof Page) {
// Prevent visibility of non-owned draft pages
$q->whereExists(function (QueryBuilder $query) use ($fullEntityIdColumn) {
$query->select('id')->from('pages')
->whereColumn('pages.id', '=', $fullEntityIdColumn)
->where(function (QueryBuilder $query) {
$query->where('pages.draft', '=', false)
->orWhere('pages.owned_by', '=', $this->currentUser()->id);
});
});
}
// Prevent visibility of non-owned draft pages
$q->whereExists(function (QueryBuilder $query) use ($fullPageIdColumn) {
$query->select('id')->from('pages')
->whereColumn('pages.id', '=', $fullPageIdColumn)
->where(function (QueryBuilder $query) {
$query->where('pages.draft', '=', false)
->orWhere('pages.owned_by', '=', $this->currentUser()->id);
});
});
return $q;
}

View File

@ -51,7 +51,7 @@ class Page extends BookChild
*/
public function scopeVisible(Builder $query): Builder
{
$query = app()->make(PermissionApplicator::class)->enforceDraftVisibilityOnQuery($query);
$query = app()->make(PermissionApplicator::class)->restrictDraftsOnPageQuery($query);
return parent::scopeVisible($query);
}

View File

@ -10,7 +10,7 @@ class Popular extends EntityQuery
public function run(int $count, int $page, array $filterModels = null)
{
$query = $this->permissionService()
->filterRestrictedEntityRelations(View::query(), 'views', 'viewable_id', 'viewable_type')
->restrictEntityRelationQuery(View::query(), 'views', 'viewable_id', 'viewable_type')
->select('*', 'viewable_id', 'viewable_type', DB::raw('SUM(views) as view_count'))
->groupBy('viewable_id', 'viewable_type')
->orderBy('view_count', 'desc');

View File

@ -14,7 +14,7 @@ class RecentlyViewed extends EntityQuery
return collect();
}
$query = $this->permissionService()->filterRestrictedEntityRelations(
$query = $this->permissionService()->restrictEntityRelationQuery(
View::query(),
'views',
'viewable_id',

View File

@ -15,7 +15,7 @@ class TopFavourites extends EntityQuery
}
$query = $this->permissionService()
->filterRestrictedEntityRelations(Favourite::query(), 'favourites', 'favouritable_id', 'favouritable_type')
->restrictEntityRelationQuery(Favourite::query(), 'favourites', 'favouritable_id', 'favouritable_type')
->select('favourites.*')
->leftJoin('views', function (JoinClause $join) {
$join->on('favourites.favouritable_id', '=', 'views.viewable_id');

View File

@ -161,7 +161,7 @@ class SearchRunner
*/
protected function buildQuery(SearchOptions $searchOpts, Entity $entityModelInstance): EloquentBuilder
{
$entityQuery = $entityModelInstance->newQuery();
$entityQuery = $entityModelInstance->newQuery()->scopes('visible');
if ($entityModelInstance instanceof Page) {
$entityQuery->select($entityModelInstance::$listAttributes);
@ -193,7 +193,7 @@ class SearchRunner
}
}
return $this->permissions->enforceEntityRestrictions($entityModelInstance, $entityQuery);
return $entityQuery;
}
/**

View File

@ -91,8 +91,7 @@ class Attachment extends Model
{
$permissions = app()->make(PermissionApplicator::class);
return $permissions->filterRelatedEntity(
Page::class,
return $permissions->restrictPageRelationQuery(
self::query(),
'attachments',
'uploaded_to'

View File

@ -74,7 +74,7 @@ class ImageRepo
}
// Filter by page access
$imageQuery = $this->permissions->filterRelatedEntity(Page::class, $imageQuery, 'images', 'uploaded_to');
$imageQuery = $this->permissions->restrictPageRelationQuery($imageQuery, 'images', 'uploaded_to');
if ($whereClause !== null) {
$imageQuery = $imageQuery->where($whereClause);