permissionService = $this->createMock(PermissionService::class); $this->policy = new AuditAuthorizationPolicy($this->permissionService); } public static function abilityPermissionProvider(): array { return [ [AuditAuthorizationPolicy::ABILITY_API_AUDIT_VIEW, 'audit.api.view'], [AuditAuthorizationPolicy::ABILITY_API_AUDIT_PURGE, 'audit.api.purge'], [AuditAuthorizationPolicy::ABILITY_SYSTEM_AUDIT_VIEW, 'audit.system.view'], [AuditAuthorizationPolicy::ABILITY_SYSTEM_AUDIT_PURGE, 'audit.system.purge'], [AuditAuthorizationPolicy::ABILITY_IMPORTS_AUDIT_VIEW, 'audit.imports.view'], [AuditAuthorizationPolicy::ABILITY_IMPORTS_AUDIT_PURGE, 'audit.imports.purge'], [AuditAuthorizationPolicy::ABILITY_USER_LIFECYCLE_VIEW, 'audit.user_lifecycle.view'], [AuditAuthorizationPolicy::ABILITY_USER_LIFECYCLE_RESTORE, 'audit.user_lifecycle.restore'], ]; } #[DataProvider('abilityPermissionProvider')] public function testSupportsAllAuditAbilities(string $ability, string $permission): void { self::assertTrue($this->policy->supports($ability)); self::assertNotSame('', $permission); } public function testSupportsRejectsUnknownAbility(): void { self::assertFalse($this->policy->supports('audit.unknown.ability')); } #[DataProvider('abilityPermissionProvider')] public function testAuthorizeUsesMappedPermissionKey(string $ability, string $permission): void { $this->permissionService->expects($this->once()) ->method('userHas') ->with(17, $permission) ->willReturn(true); $decision = $this->policy->authorize($ability, ['actor_user_id' => 17]); self::assertTrue($decision->isAllowed()); } public function testAuthorizeDeniesMissingActorIdWithoutPermissionLookup(): void { $this->permissionService->expects($this->never())->method('userHas'); $decision = $this->policy->authorize(AuditAuthorizationPolicy::ABILITY_API_AUDIT_VIEW, []); self::assertFalse($decision->isAllowed()); self::assertSame(403, $decision->status()); } public function testAuthorizeDeniesUnknownAbilityWithoutPermissionLookup(): void { $this->permissionService->expects($this->never())->method('userHas'); $decision = $this->policy->authorize('audit.unknown.ability', ['actor_user_id' => 17]); self::assertFalse($decision->isAllowed()); self::assertSame(403, $decision->status()); } public function testPolicyPermissionKeysMatchManifestPermissionKeys(): void { $manifest = require dirname(__DIR__, 3) . '/module.php'; $manifestPermissions = is_array($manifest['permissions'] ?? null) ? $manifest['permissions'] : []; $manifestKeys = []; foreach ($manifestPermissions as $permission) { if (is_array($permission) && isset($permission['key'])) { $manifestKeys[] = (string) $permission['key']; } } sort($manifestKeys); $policyKeys = []; foreach (self::abilityPermissionProvider() as $pair) { $policyKeys[] = $pair[1]; } $policyKeys = array_values(array_unique($policyKeys)); sort($policyKeys); self::assertSame($manifestKeys, $policyKeys); } }