83 lines
2.5 KiB
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());
|
|
}
|
|
}
|