clusev/app/Livewire/Terminal/Index.php

83 lines
2.5 KiB
PHP

<?php
namespace App\Livewire\Terminal;
use App\Models\HostCredential;
use App\Models\TerminalSession;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Str;
use Livewire\Attributes\Layout;
use Livewire\Attributes\On;
use Livewire\Component;
/**
* Host terminal — a real SSH login into the CLUSEV HOST machine, admin-only (manage-fleet). Per-SERVER
* shells live on the server-details page (the "Terminal" tab / App\Livewire\Servers\ServerTerminal).
* On connect it mints a single-use token the xterm.js island uses to open a WebSocket to the terminal
* sidecar; this component never touches the SSH connection or credentials.
*/
#[Layout('layouts.app')]
class Index extends Component
{
public function mount(): void
{
// The host shell is a real login into the Clusev machine — the most dangerous target.
abort_unless(Auth::user()?->can('manage-fleet'), 403);
}
public function title(): string
{
return __('terminal.title');
}
/** Mint a single-use token for the host shell and hand it to the xterm island via an event. */
public function open(): void
{
abort_unless(Auth::user()?->can('manage-fleet'), 403);
// With no host login configured yet, open the setup form instead of minting a dead session.
if (HostCredential::current() === null) {
$this->configureHost();
return;
}
$token = Str::random(48);
TerminalSession::create([
'token' => $token,
'user_id' => Auth::id(),
'kind' => 'host',
'server_id' => null,
'expires_at' => now()->addSeconds(60),
'created_at' => now(),
]);
$this->dispatch('terminal-open', token: $token, title: __('terminal.host_label'));
}
/** Open the modal that stores the Clusev host SSH login. */
public function configureHost(): void
{
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()
{
$host = HostCredential::current();
return view('livewire.terminal.index', [
'hostConfigured' => $host !== null,
'hostTarget' => $host?->username,
])->title($this->title());
}
}