CluPilotCloud/app/Livewire/Admin/ServerTerminal.php

85 lines
2.9 KiB
PHP

<?php
namespace App\Livewire\Admin;
use App\Http\Middleware\RestrictConsoleNetwork;
use App\Models\Operator;
use App\Services\Terminal\ServerTicket;
use Livewire\Attributes\Layout;
use Livewire\Component;
use Throwable;
/**
* Eine Root-Sitzung auf dem CluPilot-Server selbst, im eigenen Fenster.
*
* Dieselbe Bühne wie beim Host-Terminal, dieselbe Brücke, dasselbe Ticket —
* und eine Tür, die enger ist, weil dahinter mehr liegt. Ein Host-Terminal
* reicht auf eine Maschine; dieses reicht auf Datenbank, Tresor, DNS-Token und
* jede Kundeninstanz.
*
* DIE REIHENFOLGE IN mount() IST DIE FUNKTION:
*
* 1. `server.terminal` — eine eigene Fähigkeit, nicht `hosts.manage`.
* 2. Das Netz. Und zwar OHNE `RestrictConsoleNetwork::isRestricted()` zu
* fragen: dieser Schalter darf die Konsole öffnen, aber nicht diese Tür.
* Wer ihn aus gutem Grund umlegt — ausgesperrt, muss von unterwegs ran —,
* öffnete sonst still auch eine Root-Schale ins Herz der Anlage.
* 3. Erst dann die Frage, ob überhaupt eine Sitzung entstehen kann.
*
* Und wie beim Host-Terminal: DIESE SEITE WIRFT NIE. Ein Terminalfenster, das
* mit Laravels Fehlerseite aufgeht — Klassenname, Dateipfad, Zeilennummer —,
* ist ein Bruch mitten im Produkt.
*
* Kein Routenparameter, also auch nicht die Falle, die den Host-Ableger eine
* Umbenennung gekostet hat (Livewires ImplicitRouteBinding). Hier gibt es
* nichts nachzuschlagen: der Server ist der, auf dem das hier läuft.
*/
#[Layout('layouts.bare')]
class ServerTerminal extends Component
{
public string $ticket = '';
/**
* Warum hier kein Terminal entstehen kann — ein Merkwort, oder leer, wenn
* nichts im Weg steht.
*/
public string $problem = '';
public function mount(): void
{
$this->authorize('server.terminal');
if (! RestrictConsoleNetwork::allows((string) request()->ip())) {
$this->problem = 'off_network';
return;
}
/** @var Operator $operator */
$operator = auth('operator')->user();
// Der Fangzaun liegt um BEIDE Schritte, nicht nur um das Ausstellen.
// `blocker()` liest den Tresor und eine Datei — beides kann auf eine
// Weise scheitern, mit der niemand gerechnet hat, und ein Wurf dort
// wäre genau die Laravel-Fehlerseite, die dieses Fenster nie zeigen
// soll. Die Antwort ist dieselbe wie beim Ausstellen: eine gestaltete
// Seite, ohne Versprechen, woran es lag.
try {
$this->problem = ServerTicket::blocker() ?? '';
if ($this->problem === '') {
$this->ticket = ServerTicket::issue($operator);
}
} catch (Throwable $e) {
report($e);
$this->problem = 'unknown';
}
}
public function render()
{
return view('livewire.admin.server-terminal')
->title(__('server.terminal.window_title'));
}
}