user()?->can($kind === 'host' ? 'manage-fleet' : 'operate'), 403); $serverId = null; $label = __('terminal.host_label'); $this->activeKey = 'host'; if ($kind === 'host') { // The host terminal is a real SSH login into the Clusev machine. With no login configured // yet, open the setup form instead of minting a dead session. if (HostCredential::current() === null) { $this->configureHost(); return; } } else { $kind = 'server'; $server = Server::where('uuid', $uuid)->first(); if ($server === null) { return; } $serverId = $server->id; $label = $server->name; $this->activeKey = $server->uuid; } $token = Str::random(48); TerminalSession::create([ 'token' => $token, 'user_id' => Auth::id(), 'kind' => $kind, 'server_id' => $serverId, 'expires_at' => now()->addSeconds(60), 'created_at' => now(), ]); $this->dispatch('terminal-open', token: $token, title: $label); } /** Open the modal that stores the Clusev host SSH login. */ public function configureHost(): void { // Configuring the host SSH login is a fleet-admin action (HostShell::mount re-gates too). abort_unless(auth()->user()?->can('manage-fleet'), 403); $this->dispatch('openModal', component: 'modals.host-shell'); } /** The host-login modal saved/removed — re-render so the tile reflects the new state. */ #[On('hostShellSaved')] public function hostShellSaved(): void { // No state to set; the empty handler simply triggers a re-render. } public function render() { $serverCount = Server::count(); $servers = Server::query() ->when($this->search !== '', fn ($q) => $q->where('name', 'like', '%'.$this->search.'%')) ->orderBy('name') ->get(['uuid', 'name', 'status']); $host = HostCredential::current(); return view('livewire.terminal.index', [ 'servers' => $servers, 'serverCount' => $serverCount, 'showSearch' => $serverCount > self::SEARCH_THRESHOLD, 'hostConfigured' => $host !== null, // The host is always the local machine, so the tile shows just the login user. 'hostTarget' => $host?->username, ])->title($this->title()); } }