This PR introduces the Operation Run Actionability System. Co-authored-by: Ahmed Darrazi <ahmed.darrazi@live.de> Reviewed-on: #439
145 lines
6.6 KiB
PHP
145 lines
6.6 KiB
PHP
<?php
|
|
|
|
namespace App\Filament\Resources\ProviderConnectionResource\Pages;
|
|
|
|
use App\Filament\Resources\ProviderConnectionResource;
|
|
use App\Models\ManagedEnvironment;
|
|
use App\Models\OperationRun;
|
|
use App\Models\ProviderConnection;
|
|
use App\Support\Auth\Capabilities;
|
|
use App\Support\Links\RequiredPermissionsLinks;
|
|
use App\Support\ManagedEnvironmentLinks;
|
|
use App\Support\Navigation\CanonicalNavigationContext;
|
|
use App\Support\OperationRunLinks;
|
|
use App\Support\Rbac\UiEnforcement;
|
|
use App\Support\ResolutionGuidance\Adapters\ProviderReadinessResolutionAdapter;
|
|
use Filament\Actions;
|
|
use Filament\Resources\Pages\ViewRecord;
|
|
|
|
class ViewProviderConnection extends ViewRecord
|
|
{
|
|
protected static string $resource = ProviderConnectionResource::class;
|
|
|
|
protected function getHeaderActions(): array
|
|
{
|
|
$tenant = $this->currentTenant();
|
|
$primaryAction = $this->primaryReadinessHeaderAction($tenant);
|
|
$primaryActionName = $primaryAction?->getName();
|
|
|
|
return array_values(array_filter([
|
|
$primaryAction,
|
|
Actions\ActionGroup::make($this->sharedConnectionActions($primaryActionName))
|
|
->label('More')
|
|
->icon('heroicon-o-ellipsis-vertical')
|
|
->color('gray'),
|
|
]));
|
|
}
|
|
|
|
/**
|
|
* @return array<int, Actions\Action>
|
|
*/
|
|
private function sharedConnectionActions(?string $primaryActionName = null): array
|
|
{
|
|
$actions = [
|
|
ProviderConnectionResource::makeEditNavigationAction(),
|
|
ProviderConnectionResource::makeCheckConnectionAction(),
|
|
ProviderConnectionResource::makeInventorySyncAction(),
|
|
ProviderConnectionResource::makeComplianceSnapshotAction(),
|
|
ProviderConnectionResource::makeSetDefaultAction(),
|
|
ProviderConnectionResource::makeEnableDedicatedOverrideAction(
|
|
source: 'provider_connection.view_page',
|
|
modalDescription: 'Dedicated credentials are stored encrypted and reset consent to the dedicated app registration.',
|
|
),
|
|
ProviderConnectionResource::makeRotateDedicatedCredentialAction(),
|
|
ProviderConnectionResource::makeDeleteDedicatedCredentialAction(),
|
|
ProviderConnectionResource::makeRevertToPlatformAction(source: 'provider_connection.view_page'),
|
|
ProviderConnectionResource::makeEnableConnectionAction(),
|
|
ProviderConnectionResource::makeDisableConnectionAction(),
|
|
];
|
|
|
|
if (! is_string($primaryActionName) || $primaryActionName === '') {
|
|
return $actions;
|
|
}
|
|
|
|
return array_values(array_filter(
|
|
$actions,
|
|
static fn (Actions\Action $action): bool => $action->getName() !== $primaryActionName,
|
|
));
|
|
}
|
|
|
|
private function primaryReadinessHeaderAction(?ManagedEnvironment $tenant): ?Actions\Action
|
|
{
|
|
if (! $tenant instanceof ManagedEnvironment || ! $this->record instanceof ProviderConnection) {
|
|
return null;
|
|
}
|
|
|
|
$guidance = app(ProviderReadinessResolutionAdapter::class)
|
|
->forConnection($tenant, $this->record, ProviderReadinessResolutionAdapter::SURFACE_PROVIDER_CONNECTIONS_VIEW);
|
|
$primaryAction = is_array($guidance['primary_action'] ?? null) ? $guidance['primary_action'] : [];
|
|
$guidanceKey = (string) ($guidance['key'] ?? '');
|
|
|
|
return match ($guidanceKey) {
|
|
'provider_readiness.admin_consent_required' => UiEnforcement::forAction(
|
|
Actions\Action::make('grant_admin_consent')
|
|
->label((string) ($primaryAction['label'] ?? 'Grant admin consent'))
|
|
->icon('heroicon-o-clipboard-document')
|
|
->url(function () use ($tenant): ?string {
|
|
return RequiredPermissionsLinks::adminConsentPrimaryUrl($tenant);
|
|
})
|
|
->visible(fn (): bool => true)
|
|
->openUrlInNewTab()
|
|
)
|
|
->requireCapability(Capabilities::PROVIDER_MANAGE)
|
|
->apply(),
|
|
'provider_readiness.required_permissions_missing',
|
|
'provider_readiness.delegated_permissions_missing' => Actions\Action::make('open_required_permissions')
|
|
->label((string) ($primaryAction['label'] ?? 'Open required permissions'))
|
|
->icon('heroicon-o-key')
|
|
->url($primaryAction['url'] ?? RequiredPermissionsLinks::requiredPermissions($tenant)),
|
|
'provider_readiness.verification_required' => ProviderConnectionResource::makeCheckConnectionAction()
|
|
->label((string) ($primaryAction['label'] ?? 'Run provider verification')),
|
|
'provider_readiness.verification_failed' => $this->latestVerificationRun($tenant) instanceof OperationRun
|
|
? Actions\Action::make('open_verification_operation')
|
|
->label((string) ($primaryAction['label'] ?? 'Open verification operation'))
|
|
->icon('heroicon-o-eye')
|
|
->url(OperationRunLinks::view(
|
|
$this->latestVerificationRun($tenant),
|
|
$tenant,
|
|
CanonicalNavigationContext::fromRequest(request()),
|
|
))
|
|
: ProviderConnectionResource::makeCheckConnectionAction()
|
|
->label('Run provider verification'),
|
|
'provider_readiness.connection_review_required' => ProviderConnectionResource::makeEditNavigationAction()
|
|
->label((string) ($primaryAction['label'] ?? 'Edit provider connection')),
|
|
default => Actions\Action::make('open_environment_dashboard')
|
|
->label((string) ($primaryAction['label'] ?? 'Open environment dashboard'))
|
|
->icon('heroicon-o-home')
|
|
->url(ManagedEnvironmentLinks::viewUrl($tenant)),
|
|
};
|
|
}
|
|
|
|
private function latestVerificationRun(ManagedEnvironment $tenant): ?OperationRun
|
|
{
|
|
if (! $this->record instanceof ProviderConnection) {
|
|
return null;
|
|
}
|
|
|
|
return OperationRun::query()
|
|
->where('workspace_id', (int) $tenant->workspace_id)
|
|
->where('managed_environment_id', (int) $tenant->getKey())
|
|
->where('type', 'provider.connection.check')
|
|
->where('context->provider_connection_id', (int) $this->record->getKey())
|
|
->orderByDesc('id')
|
|
->first();
|
|
}
|
|
|
|
private function currentTenant(): ?ManagedEnvironment
|
|
{
|
|
if (! $this->record instanceof ProviderConnection) {
|
|
return null;
|
|
}
|
|
|
|
return ProviderConnectionResource::resolveTenantForRecord($this->record);
|
|
}
|
|
}
|