Files
api/services/nginx/app/tests/Unit/Permissions/AllowOwnOrDepartmentAccessForbiddenTest.php
T

93 lines
2.9 KiB
PHP

<?php
app_require('traits/route_t.php');
use traits\route_t;
class AllowOwnOrDepartmentAccessForbiddenHost
{
use route_t;
/** @var array<string, bool> */
public array $permissionsByKey = [];
public bool $ownContext = true;
/** @var array<int, string>|null */
public ?array $lastForbidden = null;
public bool $departmentAccessChecked = false;
public function __construct()
{
// no-op for unit tests
}
public function hasPermission(string|\classes\permission_node $permission, int $customer_number = null): bool
{
$key = is_string($permission) ? $permission : (string)$permission->permission;
return (bool)($this->permissionsByKey[$key] ?? false);
}
public function isOwnCustomerContext(int $targetCustomerNumber): bool
{
return $this->ownContext;
}
public function requireDepartmentAccess(string $department, string|null $permission = null): void
{
$this->departmentAccessChecked = true;
}
protected function emitForbidden(array $permissions): void
{
$normalized = [];
foreach ($permissions as $permission) {
$key = is_string($permission) ? trim($permission) : trim((string)$permission->permission);
if ($key !== '') {
$normalized[] = $key;
}
}
$this->lastForbidden = array_values(array_unique($normalized));
throw new RuntimeException('forbidden');
}
}
it('returns both own and elevated permissions when both are missing', function (): void {
$host = new AllowOwnOrDepartmentAccessForbiddenHost();
$host->permissionsByKey = [
'perm_own' => false,
'perm_other' => false,
];
expect(fn() => $host->allowOwnOrDepartmentAccess('perm_own', 'perm_other', 101, null))
->toThrow(RuntimeException::class, 'forbidden');
expect($host->lastForbidden)->toBe(['perm_own', 'perm_other']);
});
it('returns only elevated permission when own permission exists but own context fails', function (): void {
$host = new AllowOwnOrDepartmentAccessForbiddenHost();
$host->permissionsByKey = [
'perm_own' => true,
'perm_other' => false,
];
$host->ownContext = false;
expect(fn() => $host->allowOwnOrDepartmentAccess('perm_own', 'perm_other', 202, null))
->toThrow(RuntimeException::class, 'forbidden');
expect($host->lastForbidden)->toBe(['perm_other']);
});
it('allows elevated permission path without forbidden and validates department access', function (): void {
$host = new AllowOwnOrDepartmentAccessForbiddenHost();
$host->permissionsByKey = [
'perm_own' => false,
'perm_other' => true,
];
$allowed = $host->allowOwnOrDepartmentAccess('perm_own', 'perm_other', 303, 77);
expect($allowed)->toBeTrue();
expect($host->departmentAccessChecked)->toBeTrue();
expect($host->lastForbidden)->toBeNull();
});