X-Git-Url: http://source.bookstackapp.com/bookstack/blobdiff_plain/ee24635e06a8c01d751f80caba47c57f76e8989d..refs/pull/3918/head:/app/Auth/Permissions/JointPermissionBuilder.php diff --git a/app/Auth/Permissions/JointPermissionBuilder.php b/app/Auth/Permissions/JointPermissionBuilder.php index f377eef5c..114cff619 100644 --- a/app/Auth/Permissions/JointPermissionBuilder.php +++ b/app/Auth/Permissions/JointPermissionBuilder.php @@ -22,7 +22,7 @@ class JointPermissionBuilder /** * @var array> */ - protected $entityCache; + protected array $entityCache; /** * Re-generate all entity permission from scratch. @@ -40,7 +40,7 @@ class JointPermissionBuilder }); // Chunk through all bookshelves - Bookshelf::query()->withTrashed()->select(['id', 'restricted', 'owned_by']) + Bookshelf::query()->withTrashed()->select(['id', 'owned_by']) ->chunk(50, function (EloquentCollection $shelves) use ($roles) { $this->createManyJointPermissions($shelves->all(), $roles); }); @@ -92,7 +92,7 @@ class JointPermissionBuilder }); // Chunk through all bookshelves - Bookshelf::query()->select(['id', 'restricted', 'owned_by']) + Bookshelf::query()->select(['id', 'owned_by']) ->chunk(50, function ($shelves) use ($roles) { $this->createManyJointPermissions($shelves->all(), $roles); }); @@ -138,12 +138,12 @@ class JointPermissionBuilder protected function bookFetchQuery(): Builder { return Book::query()->withTrashed() - ->select(['id', 'restricted', 'owned_by'])->with([ + ->select(['id', 'owned_by'])->with([ 'chapters' => function ($query) { - $query->withTrashed()->select(['id', 'restricted', 'owned_by', 'book_id']); + $query->withTrashed()->select(['id', 'owned_by', 'book_id']); }, 'pages' => function ($query) { - $query->withTrashed()->select(['id', 'restricted', 'owned_by', 'book_id', 'chapter_id']); + $query->withTrashed()->select(['id', 'owned_by', 'book_id', 'chapter_id']); }, ]); } @@ -218,7 +218,6 @@ class JointPermissionBuilder $simple = new SimpleEntityData(); $simple->id = $attrs['id']; $simple->type = $entity->getMorphClass(); - $simple->restricted = boolval($attrs['restricted'] ?? 0); $simple->owned_by = $attrs['owned_by'] ?? 0; $simple->book_id = $attrs['book_id'] ?? null; $simple->chapter_id = $attrs['chapter_id'] ?? null; @@ -231,7 +230,7 @@ class JointPermissionBuilder /** * Create & Save entity jointPermissions for many entities and roles. * - * @param Entity[] $entities + * @param Entity[] $originalEntities * @param Role[] $roles */ protected function createManyJointPermissions(array $originalEntities, array $roles) @@ -240,21 +239,14 @@ class JointPermissionBuilder $this->readyEntityCache($entities); $jointPermissions = []; - // Create a mapping of entity restricted statuses - $entityRestrictedMap = []; - foreach ($entities as $entity) { - $entityRestrictedMap[$entity->type . ':' . $entity->id] = $entity->restricted; - } - // Fetch related entity permissions $permissions = $this->getEntityPermissionsForEntities($entities); // Create a mapping of explicit entity permissions $permissionMap = []; foreach ($permissions as $permission) { - $key = $permission->restrictable_type . ':' . $permission->restrictable_id . ':' . $permission->role_id; - $isRestricted = $entityRestrictedMap[$permission->restrictable_type . ':' . $permission->restrictable_id]; - $permissionMap[$key] = $isRestricted; + $key = $permission->entity_type . ':' . $permission->entity_id . ':' . $permission->role_id; + $permissionMap[$key] = $permission->view; } // Create a mapping of role permissions @@ -319,11 +311,10 @@ class JointPermissionBuilder { $idsByType = $this->entitiesToTypeIdMap($entities); $permissionFetch = EntityPermission::query() - ->where('action', '=', 'view') ->where(function (Builder $query) use ($idsByType) { foreach ($idsByType as $type => $ids) { $query->orWhere(function (Builder $query) use ($type, $ids) { - $query->where('restrictable_type', '=', $type)->whereIn('restrictable_id', $ids); + $query->where('entity_type', '=', $type)->whereIn('entity_id', $ids); }); } }); @@ -345,7 +336,7 @@ class JointPermissionBuilder return $this->createJointPermissionDataArray($entity, $roleId, true, true); } - if ($entity->restricted) { + if ($this->entityPermissionsActiveForRole($permissionMap, $entity, $roleId)) { $hasAccess = $this->mapHasActiveRestriction($permissionMap, $entity, $roleId); return $this->createJointPermissionDataArray($entity, $roleId, $hasAccess, $hasAccess); @@ -358,13 +349,14 @@ class JointPermissionBuilder // For chapters and pages, Check if explicit permissions are set on the Book. $book = $this->getBook($entity->book_id); $hasExplicitAccessToParents = $this->mapHasActiveRestriction($permissionMap, $book, $roleId); - $hasPermissiveAccessToParents = !$book->restricted; + $hasPermissiveAccessToParents = !$this->entityPermissionsActiveForRole($permissionMap, $book, $roleId); // For pages with a chapter, Check if explicit permissions are set on the Chapter if ($entity->type === 'page' && $entity->chapter_id !== 0) { $chapter = $this->getChapter($entity->chapter_id); - $hasPermissiveAccessToParents = $hasPermissiveAccessToParents && !$chapter->restricted; - if ($chapter->restricted) { + $chapterRestricted = $this->entityPermissionsActiveForRole($permissionMap, $chapter, $roleId); + $hasPermissiveAccessToParents = $hasPermissiveAccessToParents && !$chapterRestricted; + if ($chapterRestricted) { $hasExplicitAccessToParents = $this->mapHasActiveRestriction($permissionMap, $chapter, $roleId); } } @@ -377,14 +369,25 @@ class JointPermissionBuilder ); } + /** + * Check if entity permissions are defined within the given map, for the given entity and role. + * Checks for the default `role_id=0` backup option as a fallback. + */ + protected function entityPermissionsActiveForRole(array $permissionMap, SimpleEntityData $entity, int $roleId): bool + { + $keyPrefix = $entity->type . ':' . $entity->id . ':'; + return isset($permissionMap[$keyPrefix . $roleId]) || isset($permissionMap[$keyPrefix . '0']); + } + /** * Check for an active restriction in an entity map. */ protected function mapHasActiveRestriction(array $entityMap, SimpleEntityData $entity, int $roleId): bool { - $key = $entity->type . ':' . $entity->id . ':' . $roleId; + $roleKey = $entity->type . ':' . $entity->id . ':' . $roleId; + $defaultKey = $entity->type . ':' . $entity->id . ':0'; - return $entityMap[$key] ?? false; + return $entityMap[$roleKey] ?? $entityMap[$defaultKey] ?? false; } /**