Feature branch PR for Spec 114. This branch contains the merged agent session work (see merge commit on branch). Tests - `vendor/bin/sail artisan test --compact tests/Feature/System/Spec114/` Co-authored-by: Ahmed Darrazi <ahmed.darrazi@live.de> Reviewed-on: #139
172 lines
5.8 KiB
PHP
172 lines
5.8 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace App\Filament\System\Pages;
|
|
|
|
use App\Filament\System\Widgets\ControlTowerHealthIndicator;
|
|
use App\Filament\System\Widgets\ControlTowerKpis;
|
|
use App\Filament\System\Widgets\ControlTowerRecentFailures;
|
|
use App\Filament\System\Widgets\ControlTowerTopOffenders;
|
|
use App\Models\PlatformUser;
|
|
use App\Services\Auth\BreakGlassSession;
|
|
use App\Support\Auth\PlatformCapabilities;
|
|
use App\Support\SystemConsole\SystemConsoleWindow;
|
|
use Filament\Actions\Action;
|
|
use Filament\Forms\Components\Select;
|
|
use Filament\Forms\Components\Textarea;
|
|
use Filament\Notifications\Notification;
|
|
use Filament\Pages\Dashboard as BaseDashboard;
|
|
use Filament\Widgets\Widget;
|
|
use Filament\Widgets\WidgetConfiguration;
|
|
use Illuminate\Database\Eloquent\Model;
|
|
|
|
class Dashboard extends BaseDashboard
|
|
{
|
|
public string $window = SystemConsoleWindow::LastDay;
|
|
|
|
/**
|
|
* @param array<mixed> $parameters
|
|
*/
|
|
public static function getUrl(array $parameters = [], bool $isAbsolute = true, ?string $panel = null, ?Model $tenant = null, bool $shouldGuessMissingParameters = false): string
|
|
{
|
|
return parent::getUrl($parameters, $isAbsolute, $panel ?? 'system', $tenant, $shouldGuessMissingParameters);
|
|
}
|
|
|
|
public static function canAccess(): bool
|
|
{
|
|
$user = auth('platform')->user();
|
|
|
|
if (! $user instanceof PlatformUser) {
|
|
return false;
|
|
}
|
|
|
|
if (! $user->hasCapability(PlatformCapabilities::ACCESS_SYSTEM_PANEL)) {
|
|
return false;
|
|
}
|
|
|
|
return $user->hasCapability(PlatformCapabilities::CONSOLE_VIEW)
|
|
|| ($user->hasCapability(PlatformCapabilities::OPS_VIEW) && $user->hasCapability(PlatformCapabilities::RUNBOOKS_VIEW));
|
|
}
|
|
|
|
public function mount(): void
|
|
{
|
|
$this->window = SystemConsoleWindow::fromNullable((string) request()->query('window', $this->window))->value;
|
|
}
|
|
|
|
/**
|
|
* @return array<class-string<Widget> | WidgetConfiguration>
|
|
*/
|
|
public function getWidgets(): array
|
|
{
|
|
return [
|
|
ControlTowerHealthIndicator::class,
|
|
ControlTowerKpis::class,
|
|
ControlTowerTopOffenders::class,
|
|
ControlTowerRecentFailures::class,
|
|
];
|
|
}
|
|
|
|
public function getColumns(): int|array
|
|
{
|
|
return 1;
|
|
}
|
|
|
|
public function selectedWindow(): SystemConsoleWindow
|
|
{
|
|
return SystemConsoleWindow::fromNullable($this->window);
|
|
}
|
|
|
|
/**
|
|
* @return array<Action>
|
|
*/
|
|
protected function getHeaderActions(): array
|
|
{
|
|
$breakGlass = app(BreakGlassSession::class);
|
|
$user = auth('platform')->user();
|
|
|
|
$canUseBreakGlass = $breakGlass->isEnabled()
|
|
&& $user instanceof PlatformUser
|
|
&& $user->hasCapability(PlatformCapabilities::USE_BREAK_GLASS);
|
|
|
|
return [
|
|
Action::make('set_window')
|
|
->label('Time window')
|
|
->icon('heroicon-o-clock')
|
|
->color('gray')
|
|
->form([
|
|
Select::make('window')
|
|
->label('Window')
|
|
->options(SystemConsoleWindow::options())
|
|
->default($this->window)
|
|
->required(),
|
|
])
|
|
->action(function (array $data): void {
|
|
$window = SystemConsoleWindow::fromNullable((string) ($data['window'] ?? null));
|
|
|
|
$this->window = $window->value;
|
|
|
|
$this->redirect(static::getUrl([
|
|
'window' => $window->value,
|
|
]));
|
|
}),
|
|
|
|
Action::make('enter_break_glass')
|
|
->label('Enter break-glass mode')
|
|
->color('danger')
|
|
->visible(fn (): bool => $canUseBreakGlass && ! $breakGlass->isActive())
|
|
->requiresConfirmation()
|
|
->modalHeading('Enter break-glass mode')
|
|
->modalDescription('Recovery mode is time-limited and fully audited. Use for recovery only.')
|
|
->form([
|
|
Textarea::make('reason')
|
|
->label('Reason')
|
|
->required()
|
|
->minLength(5)
|
|
->maxLength(500)
|
|
->rows(4),
|
|
])
|
|
->action(function (array $data, BreakGlassSession $breakGlass): void {
|
|
$user = auth('platform')->user();
|
|
|
|
if (! $user instanceof PlatformUser) {
|
|
abort(403);
|
|
}
|
|
|
|
if (! $user->hasCapability(PlatformCapabilities::USE_BREAK_GLASS)) {
|
|
abort(403);
|
|
}
|
|
|
|
$breakGlass->start($user, (string) ($data['reason'] ?? ''));
|
|
|
|
Notification::make()
|
|
->title('Recovery mode enabled')
|
|
->success()
|
|
->send();
|
|
}),
|
|
|
|
Action::make('exit_break_glass')
|
|
->label('Exit break-glass')
|
|
->color('gray')
|
|
->visible(fn (): bool => $canUseBreakGlass && $breakGlass->isActive())
|
|
->requiresConfirmation()
|
|
->modalHeading('Exit break-glass mode')
|
|
->modalDescription('This will immediately end recovery mode.')
|
|
->action(function (BreakGlassSession $breakGlass): void {
|
|
$user = auth('platform')->user();
|
|
|
|
if (! $user instanceof PlatformUser) {
|
|
abort(403);
|
|
}
|
|
|
|
$breakGlass->exit($user);
|
|
|
|
Notification::make()
|
|
->title('Recovery mode ended')
|
|
->success()
|
|
->send();
|
|
}),
|
|
];
|
|
}
|
|
}
|