100 lines
3.0 KiB
PHP
100 lines
3.0 KiB
PHP
<?php
|
|
|
|
namespace App\Livewire\Audit;
|
|
|
|
use App\Models\AuditEvent;
|
|
use App\Models\Setting;
|
|
use Illuminate\Support\Collection;
|
|
use Illuminate\Support\Facades\Auth;
|
|
use Livewire\Attributes\Layout;
|
|
use Livewire\Component;
|
|
|
|
#[Layout('layouts.app')]
|
|
class Index extends Component
|
|
{
|
|
/** Freitext-Filter über Akteur / Aktion / Ziel / Server. */
|
|
public string $q = '';
|
|
|
|
/**
|
|
* Aufbewahrungsdauer in Tagen (Formularfeld). Leer/0 = unbegrenzt; ein
|
|
* positiver Wert N löscht beim täglichen Prune Einträge älter als N Tage.
|
|
*/
|
|
public ?string $retentionDays = null;
|
|
|
|
public function mount(): void
|
|
{
|
|
// Empty/0 means "keep forever" — surface that as a blank field, not "0".
|
|
$stored = (int) Setting::get('audit_retention_days', '0');
|
|
$this->retentionDays = $stored > 0 ? (string) $stored : null;
|
|
}
|
|
|
|
/** Persist the retention policy, audit the change and notify the operator. */
|
|
public function saveRetention(): void
|
|
{
|
|
$validated = $this->validate([
|
|
'retentionDays' => ['nullable', 'integer', 'min:1', 'max:3650'],
|
|
]);
|
|
|
|
$days = $validated['retentionDays'] !== null && $validated['retentionDays'] !== ''
|
|
? (int) $validated['retentionDays']
|
|
: 0;
|
|
|
|
Setting::put('audit_retention_days', $days > 0 ? (string) $days : null);
|
|
$this->retentionDays = $days > 0 ? (string) $days : null;
|
|
|
|
AuditEvent::create([
|
|
'user_id' => Auth::id(),
|
|
'actor' => Auth::user()?->name ?? 'system',
|
|
'action' => 'audit.retention_set',
|
|
'target' => 'audit_retention_days='.$days,
|
|
'ip' => request()->ip(),
|
|
]);
|
|
|
|
$this->dispatch('notify', message: __('audit.retention_saved_notify'));
|
|
}
|
|
|
|
/** Effective retention in days (0 = unlimited) for the policy summary. */
|
|
protected function retentionPolicy(): int
|
|
{
|
|
return $this->retentionDays !== null && $this->retentionDays !== ''
|
|
? (int) $this->retentionDays
|
|
: 0;
|
|
}
|
|
|
|
/**
|
|
* Letzte Audit-Ereignisse, optional gefiltert. Echte Daten aus der DB;
|
|
* die Filterung läuft im Speicher über die geladenen 50 Einträge.
|
|
*/
|
|
protected function events(): Collection
|
|
{
|
|
$events = AuditEvent::with('server')->latest()->limit(50)->get();
|
|
|
|
$needle = trim($this->q);
|
|
|
|
if ($needle === '') {
|
|
return $events;
|
|
}
|
|
|
|
$needle = mb_strtolower($needle);
|
|
|
|
return $events->filter(function (AuditEvent $e) use ($needle): bool {
|
|
$haystack = mb_strtolower(implode(' ', array_filter([
|
|
$e->actor,
|
|
$e->action,
|
|
$e->target,
|
|
$e->server?->name,
|
|
])));
|
|
|
|
return str_contains($haystack, $needle);
|
|
})->values();
|
|
}
|
|
|
|
public function render()
|
|
{
|
|
return view('livewire.audit.index', [
|
|
'events' => $this->events(),
|
|
'retentionPolicy' => $this->retentionPolicy(),
|
|
])->title(__('audit.title'));
|
|
}
|
|
}
|