serverId = $serverId; $server = Server::find($serverId); if (! $server) { $this->error = 'Server nicht gefunden.'; return; } $this->serverName = $server->name; try { $current = $maintenance->readFail2ban($server); $this->bantime = $current['bantime']; $this->maxretry = $current['maxretry']; $this->findtime = $current['findtime']; $this->loaded = true; } catch (Throwable $e) { $this->error = $e->getMessage(); } } public static function modalMaxWidth(): string { return 'lg'; } public function save(MaintenanceService $maintenance): void { // Never overwrite the remote policy with defaults the operator never saw — // saving is only allowed once the current values were read successfully. if (! $this->loaded) { $this->error = 'Aktuelle Konfiguration konnte nicht gelesen werden — Speichern ist gesperrt.'; return; } $this->error = null; // fail2ban duration grammar: a number (seconds) optionally with a unit // (s/m/h/d/w/mo/y), space-separated composites, or -1 for a permanent ban. $duration = ['required', 'string', 'max:40', 'regex:/^(?:-1|\d+(?:\.\d+)?\s*(?:s|m|h|d|w|mo|y)?(?:\s+\d+(?:\.\d+)?\s*(?:s|m|h|d|w|mo|y)?)*)$/i']; $validated = $this->validate([ 'bantime' => $duration, 'maxretry' => ['required', 'integer', 'min:1', 'max:100'], 'findtime' => $duration, ], [ 'bantime.regex' => 'Ungültige Dauer (z. B. 600, 10m, 1h, -1 für dauerhaft).', 'findtime.regex' => 'Ungültige Dauer (z. B. 600, 10m, 1h).', ], [ 'bantime' => 'Sperrdauer', 'maxretry' => 'Max. Fehlversuche', 'findtime' => 'Zeitfenster', ]); $server = Server::find($this->serverId); if (! $server) { $this->error = 'Server nicht gefunden.'; return; } try { // Values are already validated/clamped to the allowed ranges above. $result = $maintenance->writeFail2ban( $server, (string) $validated['bantime'], (int) $validated['maxretry'], (string) $validated['findtime'], ); } catch (Throwable $e) { $this->error = $e->getMessage(); return; } if (! $result['ok']) { $this->error = 'Speichern fehlgeschlagen. '.$result['output']; return; } AuditEvent::create([ 'user_id' => Auth::id(), 'server_id' => $server->id, 'actor' => Auth::user()?->name ?? 'system', 'action' => 'fail2ban.configure', 'target' => $server->name.' · bantime '.$validated['bantime'].', maxretry '.$validated['maxretry'], 'ip' => request()->ip(), ]); $this->dispatch('hardeningApplied'); $this->dispatch('notify', message: 'fail2ban konfiguriert.'); $this->closeModal(); } public function render() { return view('livewire.modals.fail2ban-config'); } }