75 lines
2.7 KiB
PHP
75 lines
2.7 KiB
PHP
<?php
|
|
|
|
namespace App\Livewire;
|
|
|
|
use App\Livewire\Concerns\ResolvesCustomer;
|
|
use App\Models\SecurityBlock;
|
|
use Livewire\Attributes\Layout;
|
|
use Livewire\Attributes\On;
|
|
use Livewire\Component;
|
|
|
|
/**
|
|
* Die Sperrliste der eigenen Instanzen — das Ziel, auf das die Mail aus
|
|
* BlockAddress verlinkt (route('portal.security'), siehe deren
|
|
* SecurityBlockMail), und der Ort, an dem ein Kunde eine eigene
|
|
* Fehlalarm-Sperre selbst vorzeitig aufheben kann.
|
|
*/
|
|
#[Layout('layouts.portal-app')]
|
|
class Security extends Component
|
|
{
|
|
use ResolvesCustomer;
|
|
|
|
/**
|
|
* ConfirmReleaseBlock dispatches this back (R23) — das Modal selbst
|
|
* mutiert nichts. Es ist ohne die Middleware dieser Seite erreichbar
|
|
* (R20), deshalb wird hier — wie im Modal auch, aber unabhaengig davon —
|
|
* erneut geprueft, dass die Sperre zu einer Instanz DIESES Kunden
|
|
* gehoert, statt der uebergebenen uuid zu vertrauen. Eine fremde oder
|
|
* eine Host-Sperre (kein instance_id) gibt es hier nie zu sehen.
|
|
*/
|
|
#[On('block-release-confirmed')]
|
|
public function onReleaseConfirmed(string $uuid): void
|
|
{
|
|
$customer = $this->customer();
|
|
|
|
$block = SecurityBlock::query()
|
|
->where('uuid', $uuid)
|
|
->whereHas('instance', fn ($q) => $q->where('customer_id', $customer?->id))
|
|
->first();
|
|
|
|
abort_if($block === null, 403);
|
|
|
|
// Der Datensatz steht in jedem Fall; nur die Firewall kann nachhinken,
|
|
// wenn der Host gerade nicht erreichbar ist. Dann sagen wir das —
|
|
// sonst versucht sich jemand gleich wieder anzumelden und wird
|
|
// wortlos erneut abgewiesen.
|
|
$this->dispatch('notify', message: $block->release(auth()->user())
|
|
? __('security.blocks_released')
|
|
: __('security.blocks_released_pending'));
|
|
}
|
|
|
|
public function render()
|
|
{
|
|
$customer = $this->customer();
|
|
|
|
$blocks = $customer
|
|
? SecurityBlock::query()
|
|
->whereHas('instance', fn ($q) => $q->where('customer_id', $customer->id))
|
|
->orderByDesc('blocked_at')
|
|
->get()
|
|
: collect();
|
|
|
|
// Aktiv/Verlauf wird hier gesplittet, nicht per zweiter Abfrage:
|
|
// scopeActive() prueft dieselben zwei Felder, die die Menge schon in
|
|
// der Hand haelt.
|
|
return view('livewire.security', [
|
|
'active' => $blocks->filter(
|
|
fn (SecurityBlock $b) => $b->released_at === null && $b->expires_at->isFuture()
|
|
)->values(),
|
|
'history' => $blocks->filter(
|
|
fn (SecurityBlock $b) => $b->released_at !== null || $b->expires_at->isPast()
|
|
)->values(),
|
|
]);
|
|
}
|
|
}
|