serverId = $serverId; $this->tool = $tool === 'firewalld' ? 'firewalld' : 'ufw'; } public static function modalMaxWidth(): string { return 'lg'; } public function save(FirewallService $firewall): void { $this->error = null; $server = Server::find($this->serverId); if (! $server) { $this->error = __('common.server_not_found'); return; } $port = trim($this->port) !== '' ? (int) $this->port : null; try { $res = $firewall->addRule($server, $this->action, $this->proto, $port, $this->from); } catch (Throwable $e) { $this->error = $e->getMessage(); return; } if (! $res['ok']) { $this->error = $res['output'] !== '' ? $res['output'] : __('modals.firewall_rule.error_add_failed'); return; } AuditEvent::create([ 'user_id' => Auth::id(), 'server_id' => $server->id, 'actor' => Auth::user()?->name ?? 'system', 'action' => 'firewall.rule_add', 'target' => $server->name.' · '.$this->summary($port), 'ip' => request()->ip(), ]); $this->dispatch('firewallChanged'); $this->dispatch('notify', message: __('modals.firewall_rule.notify_added')); $this->closeModal(); } /** Short human summary of the rule for the audit log. */ private function summary(?int $port): string { if ($this->tool === 'firewalld') { return __('modals.firewall_rule.summary_port_opened', [ 'port' => (string) $port, 'proto' => $this->proto === 'udp' ? 'udp' : 'tcp', ]); } $parts = [$this->action]; if ($port !== null) { $parts[] = $port.($this->proto !== 'any' ? '/'.$this->proto : ''); } if (trim($this->from) !== '') { $parts[] = __('modals.firewall_rule.summary_from', ['source' => trim($this->from)]); } return implode(' ', $parts); } public function render() { return view('livewire.modals.firewall-rule'); } }