CluPilotCloud/app/Livewire/Admin/ReissueTakeover.php

115 lines
4.3 KiB
PHP

<?php
namespace App\Livewire\Admin;
use App\Models\Host;
use App\Support\HostEnrolment;
use App\Support\HostTakeoverCommand;
use LivewireUI\Modal\ModalComponent;
/**
* Stellt die Übernahme-Befehlszeile für einen bestehenden Host neu aus.
*
* Es gab sie bis hierher genau EINMAL: auf der Seite direkt nach dem Anlegen.
* Wer sie dort nicht kopierte — oder wem sie wegbrach, wie beim
* WireGuard-Fehler bis 1.3.80 — hatte danach einen Host in der Liste, für den
* es keinen Weg zu einer Befehlszeile mehr gab. Ein zweites Anlegen scheitert
* an der eindeutigen IP, also blieb nur Entfernen und von vorn.
*
* `HostTakeoverCommand` behauptet in seinem Kopfkommentar, die Zeile werde „an
* zwei Stellen gezeigt (beim Anlegen und beim Neuausstellen eines Codes)". Das
* Zweite gab es nie — ein Kommentar, der eine Absicht beschreibt und wie eine
* Beschreibung des Gebauten klingt.
*
* Bestätigt wird VOR dem Ausstellen (R23), denn der bisherige Code wird dabei
* wertlos: eine Maschine, die gerade im Rettungssystem arbeitet, verlöre ihren
* Ausweis mitten im Lauf.
*/
class ReissueTakeover extends ModalComponent
{
public string $uuid;
public string $name = '';
/** Null, solange nur gefragt wird. Gesetzt heißt: ausgestellt, hier steht sie. */
public ?string $command = null;
/** Gesetzt, wenn nicht ausgestellt wurde — und warum. */
public ?string $refusal = null;
/**
* Nur vor der Übernahme: angelegt, mitten in der Übernahme, gescheitert.
*
* Für einen laufenden Host wäre eine neue Befehlszeile kein Angebot,
* sondern eine Falle: sie setzt die Maschine neu auf.
*
* `disabled` gehört NICHT dazu, obwohl es danach aussieht (Codex P1).
* Es ist der Wartungszustand eines längst laufenden Hosts —
* `HostDetail::toggleMaintenance()` schaltet aktiv → disabled, um ihn aus
* der Platzierung zu nehmen. Wer einen Host zum Warten stilllegt, bekäme
* sonst einen Knopf angeboten, der seine Produktionsmaschine neu aufsetzt.
*/
public const ELIGIBLE = ['pending', 'onboarding', 'error'];
/**
* Eine Stelle für die Bedingung, gefragt von der Ansicht UND von `issue()`.
*
* Zwei Fassungen davon liefen auseinander, sobald jemand eine ändert — und
* die, die dann noch gilt, ist die in der Ansicht, also gar keine.
*/
public static function eligible(Host $host): bool
{
return in_array($host->status, self::ELIGIBLE, true);
}
public function mount(string $uuid): void
{
$this->uuid = $uuid;
$this->name = Host::query()->where('uuid', $uuid)->value('name') ?? '';
}
/**
* Ein Modal ist ohne die Route-Middleware der Seite erreichbar (R20) und
* prüft die Berechtigung deshalb selbst — hier besonders, weil in der
* Antwort ein privater WireGuard-Schlüssel steht.
*/
public function issue(): void
{
$this->authorize('hosts.manage');
$host = Host::query()->where('uuid', $this->uuid)->firstOrFail();
// Der Knopf steht nur bei passendem Zustand — aber ein Modal, das offen
// blieb, während der Host aktiv wurde, ruft diese Methode trotzdem, und
// eine Livewire-Methode ist ohnehin von außen aufrufbar. Die
// Sichtbarkeit eines Knopfes ist keine Prüfung (Codex P1): sonst
// tauschte das hier den Schlüssel einer laufenden Maschine und schnitte
// sie aus dem Tunnel.
if (! self::eligible($host)) {
$this->refusal = __('hosts.reissue.not_eligible');
return;
}
// Dieselbe Prüfung wie in der Ansicht, aus demselben Grund (Codex P2).
// Sonst wird ein gültiger Code entwertet und dafür eine Zeile
// ausgegeben, der die Tunnel-Angaben fehlen — genau die kaputte Zeile,
// vor der die Warnung daneben steht.
if (HostTakeoverCommand::missingSettings() !== []) {
$this->refusal = __('hosts.takeover.missing_title');
return;
}
$this->refusal = null;
$this->command = HostTakeoverCommand::for($host, HostEnrolment::issueWithKeys($host));
}
public function render()
{
return view('livewire.admin.reissue-takeover', [
'missingSettings' => HostTakeoverCommand::missingSettings(),
]);
}
}