105 lines
3.4 KiB
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,
|
||
|
|
]);
|
||
|
|
}
|
||
|
|
}
|