85 lines
2.9 KiB
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'));
|
|
}
|
|
}
|