createMock(SettingRepositoryInterface::class); $settings->method('getValue')->willReturnCallback(static function (string $key): ?string { if ($key === 'api_token_max_ttl_days') { return '30'; } return null; }); $settings->expects($this->never())->method('set'); $gateway = new SettingsApiPolicyGateway(new SettingsMetadataGateway($settings)); $this->assertFalse($gateway->setApiTokenDefaultTtlDays(31)); } public function testSetApiTokenMaxTtlDaysUpdatesDefaultWhenNeeded(): void { $settings = $this->createMock(SettingRepositoryInterface::class); $settings->method('getValue')->willReturnCallback(static function (string $key): ?string { if ($key === 'api_token_default_ttl_days') { return '365'; } return null; }); $calls = []; $settings->expects($this->exactly(2)) ->method('set') ->willReturnCallback(static function (string $key, ?string $value, ?string $description) use (&$calls): bool { $calls[] = [$key, $value, $description]; return true; }); $gateway = new SettingsApiPolicyGateway(new SettingsMetadataGateway($settings)); $this->assertTrue($gateway->setApiTokenMaxTtlDays(120)); $this->assertSame( [ ['api_token_default_ttl_days', '120', 'setting.api_token_default_ttl_days'], ['api_token_max_ttl_days', '120', 'setting.api_token_max_ttl_days'], ], $calls ); } public function testSetApiCorsAllowedOriginsRejectsInvalidOrigins(): void { $settings = $this->createMock(SettingRepositoryInterface::class); $settings->expects($this->never())->method('set'); $gateway = new SettingsApiPolicyGateway(new SettingsMetadataGateway($settings)); $this->assertFalse($gateway->setApiCorsAllowedOrigins("https://ok.example\njavascript:alert(1)")); } public function testCorsOriginsRoundtripNormalizesAndDeduplicates(): void { $settings = $this->createMock(SettingRepositoryInterface::class); $stored = null; $settings->expects($this->once()) ->method('set') ->willReturnCallback(static function (string $key, ?string $value) use (&$stored): bool { if ($key === 'api_cors_allowed_origins') { $stored = $value; } return true; }); $settings->method('getValue')->willReturnCallback(static function (string $key) use (&$stored): ?string { if ($key === 'api_cors_allowed_origins') { return $stored; } return null; }); $gateway = new SettingsApiPolicyGateway(new SettingsMetadataGateway($settings)); $this->assertTrue($gateway->setApiCorsAllowedOrigins("https://a.example,https://a.example/\nhttps://b.example:443")); $this->assertSame(['https://a.example', 'https://b.example'], $gateway->getApiCorsAllowedOrigins()); $this->assertSame("https://a.example\nhttps://b.example", $gateway->getApiCorsAllowedOriginsText()); } }