user()?->can('manage-fleet'), 403); $this->serverId = $serverId; $server = Server::find($serverId); if (! $server) { $this->error = __('common.server_not_found'); return; } $this->serverName = $server->name; try { $this->unsupportedReason = $maintenance->updateSupport($server); $this->supported = $this->unsupportedReason === null; $this->pending = $this->supported ? $maintenance->pendingUpdates($server) : null; } catch (Throwable $e) { $this->error = $e->getMessage(); } } public static function modalMaxWidth(): string { return 'lg'; } public function upgrade(MaintenanceService $maintenance): void { // Re-gate on upgrade: refuse a demoted user / hand-crafted /livewire/update after mount. abort_unless(auth()->user()?->can('manage-fleet'), 403); if ($this->error !== null || $this->done || ! $this->supported) { return; } $server = Server::find($this->serverId); if (! $server) { $this->error = __('common.server_not_found'); return; } try { $result = $maintenance->applyUpgrades($server); } catch (Throwable $e) { $this->done = true; $this->ok = false; $this->output = $e->getMessage(); $this->dispatch('notify', message: __('modals.system_update.notify_failed')); return; } $this->done = true; $this->ok = $result['ok']; // On success we surface a clean German line, not the raw apt log; on failure // the trimmed error tail helps the operator diagnose. $this->output = $this->ok ? '' : $result['output']; AuditEvent::create([ 'user_id' => Auth::id(), 'server_id' => $server->id, 'actor' => Auth::user()?->name ?? 'system', 'action' => 'system.package_upgrade', 'target' => $server->name.($this->ok ? '' : ' '.__('modals.system_update.audit_failed_suffix')), 'ip' => request()->ip(), ]); if ($this->ok) { $this->pending = 0; $this->dispatch('notify', message: __('modals.system_update.notify_updated')); } else { $this->dispatch('notify', message: __('modals.system_update.notify_failed')); } } public function render() { return view('livewire.modals.system-update'); } }