BookStack/app/Auth/Permissions/MassEntityPermissionEvaluator.php
Dan Brown 91e613fe60
Shared entity permission logic across both query methods
The runtime userCan() and the JointPermissionBuilder now share much of
the same logic for handling entity permission resolution.
2023-01-23 15:09:03 +00:00

82 lines
2.7 KiB
PHP

<?php
namespace BookStack\Auth\Permissions;
class MassEntityPermissionEvaluator extends EntityPermissionEvaluator
{
/**
* @var SimpleEntityData[]
*/
protected array $entitiesInvolved;
protected array $permissionMapCache;
public function __construct(array $entitiesInvolved, string $action)
{
$this->entitiesInvolved = $entitiesInvolved;
parent::__construct($action);
}
public function evaluateEntityForRole(SimpleEntityData $entity, int $roleId): ?bool
{
$typeIdChain = $this->gatherEntityChainTypeIds($entity);
$relevantPermissions = $this->getPermissionMapByTypeIdForChainAndRole($typeIdChain, $roleId);
$permitsByType = $this->collapseAndCategorisePermissions($typeIdChain, $relevantPermissions);
return $this->evaluatePermitsByType($permitsByType);
}
/**
* @param string[] $typeIdChain
* @return array<string, EntityPermission[]>
*/
protected function getPermissionMapByTypeIdForChainAndRole(array $typeIdChain, int $roleId): array
{
$allPermissions = $this->getPermissionMapByTypeIdAndRoleForAllInvolved();
$relevantPermissions = [];
// Filter down permissions to just those for current typeId
// and current roleID or fallback permissions.
foreach ($typeIdChain as $typeId) {
$relevantPermissions[$typeId] = [
...($allPermissions[$typeId][$roleId] ?? []),
...($allPermissions[$typeId][0] ?? [])
];
}
return $relevantPermissions;
}
/**
* @return array<string, array<int, EntityPermission[]>>
*/
protected function getPermissionMapByTypeIdAndRoleForAllInvolved(): array
{
if (isset($this->permissionMapCache)) {
return $this->permissionMapCache;
}
$entityTypeIdChain = [];
foreach ($this->entitiesInvolved as $entity) {
$entityTypeIdChain[] = $entity->type . ':' . $entity->id;
}
$permissionMap = $this->getPermissionsMapByTypeId($entityTypeIdChain, []);
// Manipulate permission map to also be keyed by roleId.
foreach ($permissionMap as $typeId => $permissions) {
$permissionMap[$typeId] = [];
foreach ($permissions as $permission) {
$roleId = $permission->getRawAttribute('role_id');
if (!isset($permissionMap[$typeId][$roleId])) {
$permissionMap[$typeId][$roleId] = [];
}
$permissionMap[$typeId][$roleId][] = $permission;
}
}
$this->permissionMapCache = $permissionMap;
return $this->permissionMapCache;
}
}