Files
server/core/lib/Service/FirewallSettingsService.php
T
2026-08-05 23:56:28 -04:00

77 lines
2.4 KiB
PHP

<?php
declare(strict_types=1);
namespace KTXC\Service;
use KTXC\Models\Tenant\TenantConfiguration;
use KTXF\Event\EventDispatcherInterface;
use KTXC\Security\Event\FirewallSettingsUpdatedEvent;
final class FirewallSettingsService
{
public function __construct(
private readonly TenantService $tenants,
private readonly EventDispatcherInterface $events,
) {
}
public function update(
string $tenantId,
bool $enabled,
int $maxAuthFailures,
int $authFailureWindow,
int $autoBlockDuration,
string $reason,
?string $actorId
): ?array {
$reason = trim($reason);
if ($reason === '' || strlen($reason) > 1000) {
throw new \InvalidArgumentException('A change reason containing 1-1000 bytes is required.');
}
self::bounded($maxAuthFailures, 1, 1000, 'Maximum authentication failures');
self::bounded($authFailureWindow, 1, 86400, 'Authentication failure window');
self::bounded($autoBlockDuration, 1, 31536000, 'Automatic block duration');
$tenant = $this->tenants->fetchById($tenantId);
if ($tenant === null) {
return null;
}
$previous = $tenant->getConfiguration()->firewall()->jsonSerialize();
$current = [
'enabled' => $enabled,
'maxAuthFailures' => $maxAuthFailures,
'authFailureWindow' => $authFailureWindow,
'autoBlockDuration' => $autoBlockDuration,
];
$configuration = (new TenantConfiguration())->jsonDeserialize([
...$tenant->getConfiguration()->jsonSerialize(),
'firewall' => $current,
]);
$tenant->setConfiguration($configuration);
$this->tenants->deposit($tenant);
$event = new FirewallSettingsUpdatedEvent(
changeReason: $reason,
previous: $previous,
current: $current,
tenantId: $tenantId,
actorId: $actorId,
changeOrigin: FirewallRuleManager::ORIGIN_MANUAL,
);
$this->events->dispatch($event);
return $current;
}
private static function bounded(int $value, int $minimum, int $maximum, string $label): void
{
if ($value < $minimum || $value > $maximum) {
throw new \InvalidArgumentException(
"{$label} must be between {$minimum} and {$maximum}."
);
}
}
}