X-Git-Url: http://source.bookstackapp.com/bookstack/blobdiff_plain/fef433a9cb1ae8c0daf2444e16e590cd9df114aa..refs/pull/5681/head:/app/Permissions/PermissionApplicator.php diff --git a/app/Permissions/PermissionApplicator.php b/app/Permissions/PermissionApplicator.php index a796bdaee..ce4a543fd 100644 --- a/app/Permissions/PermissionApplicator.php +++ b/app/Permissions/PermissionApplicator.php @@ -3,6 +3,7 @@ namespace BookStack\Permissions; use BookStack\App\Model; +use BookStack\Entities\EntityProvider; use BookStack\Entities\Models\Entity; use BookStack\Entities\Models\Page; use BookStack\Permissions\Models\EntityPermission; @@ -11,6 +12,7 @@ use BookStack\Users\Models\HasOwner; use BookStack\Users\Models\User; use Illuminate\Database\Eloquent\Builder; use Illuminate\Database\Query\Builder as QueryBuilder; +use Illuminate\Database\Query\JoinClause; use InvalidArgumentException; class PermissionApplicator @@ -23,7 +25,7 @@ class PermissionApplicator /** * Checks if an entity has a restriction set upon it. * - * @param HasCreatorAndUpdater|HasOwner $ownable + * @param Model&(HasCreatorAndUpdater|HasOwner) $ownable */ public function checkOwnableUserAccess(Model $ownable, string $permission): bool { @@ -147,6 +149,41 @@ class PermissionApplicator }); } + /** + * Filter out items that have related entity relations where + * the entity is marked as deleted. + */ + public function filterDeletedFromEntityRelationQuery(Builder $query, string $tableName, string $entityIdColumn, string $entityTypeColumn): Builder + { + $tableDetails = ['tableName' => $tableName, 'entityIdColumn' => $entityIdColumn, 'entityTypeColumn' => $entityTypeColumn]; + $entityProvider = new EntityProvider(); + + $joinQuery = function ($query) use ($entityProvider) { + $first = true; + foreach ($entityProvider->all() as $entity) { + /** @var Builder $query */ + $entityQuery = function ($query) use ($entity) { + $query->select(['id', 'deleted_at']) + ->selectRaw("'{$entity->getMorphClass()}' as type") + ->from($entity->getTable()) + ->whereNotNull('deleted_at'); + }; + + if ($first) { + $entityQuery($query); + $first = false; + } else { + $query->union($entityQuery); + } + } + }; + + return $query->leftJoinSub($joinQuery, 'deletions', function (JoinClause $join) use ($tableDetails) { + $join->on($tableDetails['tableName'] . '.' . $tableDetails['entityIdColumn'], '=', 'deletions.id') + ->on($tableDetails['tableName'] . '.' . $tableDetails['entityTypeColumn'], '=', 'deletions.type'); + })->whereNull('deletions.deleted_at'); + } + /** * 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.