clusev/app/Livewire/Modals/HardeningAction.php

123 lines
3.6 KiB
PHP

<?php
namespace App\Livewire\Modals;
use App\Models\AuditEvent;
use App\Models\Server;
use App\Services\HardeningService;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Str;
use LivewireUI\Modal\ModalComponent;
use Throwable;
/**
* Preview + confirm modal for one server-hardening TOGGLE (R5).
*
* `$enable` is the desired feature state — true turns the feature on, false off.
* mount() loads a direction-aware title + the exact root commands (preview) so the
* operator sees what will run BEFORE applying. apply() runs it, AUDITs, notifies,
* asks the page to reload its hardening state, and shows the result.
*/
class HardeningAction extends ModalComponent
{
public int $serverId;
public string $action;
/** Desired feature state: true = aktivieren, false = deaktivieren. */
public bool $enable;
public string $heading = '';
public string $description = '';
public bool $done = false;
public bool $ok = false;
public string $output = '';
public ?string $error = null;
public function mount(int $serverId, string $action, bool $enable): void
{
abort_unless(auth()->user()?->can('manage-network'), 403);
$this->serverId = $serverId;
$this->action = $action;
$this->enable = $enable;
$server = Server::find($serverId);
if (! $server) {
$this->error = __('common.server_not_found');
return;
}
try {
$hardening = app(HardeningService::class);
$this->heading = $hardening->title($action, $enable);
$this->description = $hardening->description($action, $enable);
} catch (Throwable $e) {
$this->error = $e->getMessage();
}
}
public static function modalMaxWidth(): string
{
return 'lg';
}
public function apply(): void
{
abort_unless(auth()->user()?->can('manage-network'), 403);
if ($this->error !== null || $this->done) {
return;
}
$server = Server::find($this->serverId);
if (! $server) {
$this->error = __('common.server_not_found');
return;
}
try {
$result = app(HardeningService::class)->apply($server, $this->action, $this->enable);
} catch (Throwable $e) {
$this->done = true;
$this->ok = false;
$this->output = $e->getMessage();
return;
}
$this->done = true;
$this->ok = $result['ok'];
// Clean result only — no raw command output on success; a short reason on failure.
$this->output = $this->ok ? '' : Str::limit(trim($result['output']) ?: __('modals.hardening_action.error_unknown'), 200);
AuditEvent::create([
'user_id' => Auth::id(),
'server_id' => $server->id,
'actor' => Auth::user()?->name ?? 'system',
'action' => 'harden.'.$this->action.($this->enable ? '.on' : '.off'),
'target' => $server->name.' · '.$this->heading.($this->ok ? '' : ' '.__('modals.hardening_action.audit_failed_suffix')),
'ip' => request()->ip(),
]);
if ($this->ok) {
$this->dispatch('hardeningApplied');
$this->dispatch('notify', message: __('modals.hardening_action.notify_applied', ['action' => $this->heading]));
} else {
$this->dispatch('notify', message: __('modals.hardening_action.notify_failed', ['action' => $this->heading]));
}
}
public function render()
{
return view('livewire.modals.hardening-action');
}
}