Files
breadcrumb-the-shire/tests/Service/Access/AccessPolicyFactoryModuleResolverTest.php

105 lines
3.4 KiB
PHP

<?php
namespace MintyPHP\Tests\Service\Access;
use MintyPHP\App\AppContainer;
use MintyPHP\App\Module\ModuleClassResolver;
use MintyPHP\App\Module\ModuleRegistry;
use MintyPHP\Service\Access\AccessPolicyFactory;
use MintyPHP\Service\Access\AuthorizationDecision;
use MintyPHP\Service\Access\AuthorizationPolicyInterface;
use MintyPHP\Service\Access\PermissionService;
use MintyPHP\Service\Tenant\TenantScopeService;
use PHPUnit\Framework\TestCase;
final class AccessPolicyFactoryModuleResolverTest extends TestCase
{
public function testModulePolicyWithMultipleDependenciesIsResolvedViaContainer(): void
{
$fixturesDir = sys_get_temp_dir() . '/access-policy-factory-' . uniqid('', true);
$moduleDir = $fixturesDir . '/mod-policy';
mkdir($moduleDir, 0777, true);
file_put_contents(
$moduleDir . '/module.php',
'<?php return ' . var_export([
'id' => 'mod-policy',
'authorization_policies' => [TestMultiDependencyPolicy::class],
], true) . ';'
);
try {
$registry = ModuleRegistry::boot($fixturesDir, ['mod-policy']);
$permissionService = $this->createMock(PermissionService::class);
$tenantScopeService = $this->createMock(TenantScopeService::class);
$dependency = new TestPolicyDependency();
$container = new AppContainer();
$container->set(
TestMultiDependencyPolicy::class,
static fn () => new TestMultiDependencyPolicy($permissionService, $dependency)
);
$factory = new AccessPolicyFactory(
$permissionService,
$tenantScopeService,
$registry,
static fn (string $class): ?object => ModuleClassResolver::resolve($container, $class)
);
$authorizationService = $factory->createAuthorizationService();
$decision = $authorizationService->authorize(TestMultiDependencyPolicy::ABILITY, [
'actor_user_id' => 7,
]);
self::assertTrue($decision->isAllowed());
self::assertSame('container', $decision->attribute('resolver'));
} finally {
@unlink($moduleDir . '/module.php');
@rmdir($moduleDir);
@rmdir($fixturesDir);
}
}
}
final class TestPolicyDependency
{
public function value(): string
{
return 'container';
}
}
final class TestMultiDependencyPolicy implements AuthorizationPolicyInterface
{
public const ABILITY = 'module.multi.dep';
public function __construct(
private readonly PermissionService $permissionService,
private readonly TestPolicyDependency $dependency
) {
}
public function supports(string $ability): bool
{
return $ability === self::ABILITY;
}
public function authorize(string $ability, array $context = []): AuthorizationDecision
{
if ($ability !== self::ABILITY) {
return AuthorizationDecision::deny(500, 'authorization_ability_not_supported');
}
if ((int) ($context['actor_user_id'] ?? 0) <= 0) {
return AuthorizationDecision::deny(403, 'forbidden');
}
return AuthorizationDecision::allow([
'resolver' => $this->dependency->value(),
'permission_service' => $this->permissionService::class,
]);
}
}