Implements Spec 114 System Console Control Tower pages, widgets, triage actions, directory views, and enterprise polish (badges, repair workspace owners table, health indicator).
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();
|
|
}),
|
|
];
|
|
}
|
|
}
|