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;
use BookStack\Users\Models\HasCreatorAndUpdater;
use BookStack\Users\Models\HasOwner;
-use BookStack\Users\Models\Role;
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
{
+ public function __construct(
+ protected ?User $user = null
+ ) {
+ }
+
/**
* 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
{
});
}
+ /**
+ * 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.
*/
protected function currentUser(): User
{
- return user();
+ return $this->user ?? user();
}
/**