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 public function latest(int $count = 20, int $page = 0): array
{ {
$activityList = $this->permissions $activityList = $this->permissions
->filterRestrictedEntityRelations(Activity::query(), 'activities', 'entity_id', 'entity_type') ->restrictEntityRelationQuery(Activity::query(), 'activities', 'entity_id', 'entity_type')
->orderBy('created_at', 'desc') ->orderBy('created_at', 'desc')
->with(['user', 'entity']) ->with(['user', 'entity'])
->skip($count * $page) ->skip($count * $page)
@ -79,7 +79,7 @@ class ActivityQueries
public function userActivity(User $user, int $count = 20, int $page = 0): array public function userActivity(User $user, int $count = 20, int $page = 0): array
{ {
$activityList = $this->permissions $activityList = $this->permissions
->filterRestrictedEntityRelations(Activity::query(), 'activities', 'entity_id', 'entity_type') ->restrictEntityRelationQuery(Activity::query(), 'activities', 'entity_id', 'entity_type')
->orderBy('created_at', 'desc') ->orderBy('created_at', 'desc')
->where('user_id', '=', $user->id) ->where('user_id', '=', $user->id)
->skip($count * $page) ->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 = $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'); return $query->get(['name'])->pluck('name');
} }
@ -95,7 +95,7 @@ class TagRepo
$query = $query->where('name', '=', $tagName); $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'); 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. * return items that the user has view permission for.
*/ */
public function restrictEntityQuery(Builder $query): Builder public function restrictEntityQuery(Builder $query): Builder
@ -126,7 +126,7 @@ class PermissionApplicator
* Extend the given page query to ensure draft items are not visible * Extend the given page query to ensure draft items are not visible
* unless created by the given user. * unless created by the given user.
*/ */
public function enforceDraftVisibilityOnQuery(Builder $query): Builder public function restrictDraftsOnPageQuery(Builder $query): Builder
{ {
return $query->where(function (Builder $query) { return $query->where(function (Builder $query) {
$query->where('draft', '=', false) $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. * Filter items that have entities set as a polymorphic relation.
* For simplicity, this will not return results attached to draft pages. * For simplicity, this will not return results attached to draft pages.
@ -177,7 +144,7 @@ class PermissionApplicator
* *
* @param Builder|QueryBuilder $query * @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]; $tableDetails = ['tableName' => $tableName, 'entityIdColumn' => $entityIdColumn, 'entityTypeColumn' => $entityTypeColumn];
$pageMorphClass = (new Page())->getMorphClass(); $pageMorphClass = (new Page())->getMorphClass();
@ -207,19 +174,20 @@ class PermissionApplicator
} }
/** /**
* Add conditions to a query to filter the selection to related entities * Add conditions to a query for a model that's a relation of a page, so only the model results
* where view permissions are granted. * 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; $fullPageIdColumn = $tableName . '.' . $pageIdColumn;
$instance = new $entityClass(); $morphClass = (new Page())->getMorphClass();
$morphClass = $instance->getMorphClass();
$existsQuery = function ($permissionQuery) use ($fullEntityIdColumn, $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')
->whereColumn('joint_permissions.entity_id', '=', $fullEntityIdColumn) ->whereColumn('joint_permissions.entity_id', '=', $fullPageIdColumn)
->where('joint_permissions.entity_type', '=', $morphClass) ->where('joint_permissions.entity_type', '=', $morphClass)
->where('joint_permissions.action', '=', 'view') ->where('joint_permissions.action', '=', 'view')
->whereIn('joint_permissions.role_id', $this->getCurrentUserRoleIds()) ->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) $query->whereExists($existsQuery)
->orWhere($fullEntityIdColumn, '=', 0); ->orWhere($fullPageIdColumn, '=', 0);
}); });
if ($instance instanceof Page) { // Prevent visibility of non-owned draft pages
// Prevent visibility of non-owned draft pages $q->whereExists(function (QueryBuilder $query) use ($fullPageIdColumn) {
$q->whereExists(function (QueryBuilder $query) use ($fullEntityIdColumn) { $query->select('id')->from('pages')
$query->select('id')->from('pages') ->whereColumn('pages.id', '=', $fullPageIdColumn)
->whereColumn('pages.id', '=', $fullEntityIdColumn) ->where(function (QueryBuilder $query) {
->where(function (QueryBuilder $query) { $query->where('pages.draft', '=', false)
$query->where('pages.draft', '=', false) ->orWhere('pages.owned_by', '=', $this->currentUser()->id);
->orWhere('pages.owned_by', '=', $this->currentUser()->id); });
}); });
});
}
return $q; return $q;
} }

View File

@ -51,7 +51,7 @@ class Page extends BookChild
*/ */
public function scopeVisible(Builder $query): Builder public function scopeVisible(Builder $query): Builder
{ {
$query = app()->make(PermissionApplicator::class)->enforceDraftVisibilityOnQuery($query); $query = app()->make(PermissionApplicator::class)->restrictDraftsOnPageQuery($query);
return parent::scopeVisible($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) public function run(int $count, int $page, array $filterModels = null)
{ {
$query = $this->permissionService() $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')) ->select('*', 'viewable_id', 'viewable_type', DB::raw('SUM(views) as view_count'))
->groupBy('viewable_id', 'viewable_type') ->groupBy('viewable_id', 'viewable_type')
->orderBy('view_count', 'desc'); ->orderBy('view_count', 'desc');

View File

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

View File

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

View File

@ -161,7 +161,7 @@ class SearchRunner
*/ */
protected function buildQuery(SearchOptions $searchOpts, Entity $entityModelInstance): EloquentBuilder protected function buildQuery(SearchOptions $searchOpts, Entity $entityModelInstance): EloquentBuilder
{ {
$entityQuery = $entityModelInstance->newQuery(); $entityQuery = $entityModelInstance->newQuery()->scopes('visible');
if ($entityModelInstance instanceof Page) { if ($entityModelInstance instanceof Page) {
$entityQuery->select($entityModelInstance::$listAttributes); $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); $permissions = app()->make(PermissionApplicator::class);
return $permissions->filterRelatedEntity( return $permissions->restrictPageRelationQuery(
Page::class,
self::query(), self::query(),
'attachments', 'attachments',
'uploaded_to' 'uploaded_to'

View File

@ -74,7 +74,7 @@ class ImageRepo
} }
// Filter by page access // 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) { if ($whereClause !== null) {
$imageQuery = $imageQuery->where($whereClause); $imageQuery = $imageQuery->where($whereClause);