TenantAtlas/apps/platform/app/Filament/Resources/ProviderConnectionResource/Pages/ViewProviderConnection.php
Ahmed Darrazi ff0b588901
Some checks failed
PR Fast Feedback / fast-feedback (pull_request) Failing after 1m0s
feat: provider connections resolution guidance v1 (spec 353)
Implemented the first version of provider readiness resolution guidance. Added the ProviderReadinessResolutionAdapter, provider readiness guidance card, and updated EnvironmentRequiredPermissions, ProviderConnectionResource, and ListProviderConnections/ViewProviderConnection. Added tests and updated the design coverage matrix.
2026-06-05 00:38:03 +02:00

140 lines
6.4 KiB
PHP

<?php
namespace App\Filament\Resources\ProviderConnectionResource\Pages;
use App\Models\OperationRun;
use App\Filament\Resources\ProviderConnectionResource;
use App\Models\ManagedEnvironment;
use App\Models\ProviderConnection;
use App\Support\Auth\Capabilities;
use App\Support\Links\RequiredPermissionsLinks;
use App\Support\ManagedEnvironmentLinks;
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))
: 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);
}
}