record instanceof ProviderConnection ? ProviderConnectionResource::resolveTenantForRecord($this->record) : null; if ($recordTenant instanceof Tenant) { $this->scopedTenantExternalId = (string) $recordTenant->external_id; return; } $tenantIdFromQuery = request()->query('tenant_id'); if (is_string($tenantIdFromQuery) && $tenantIdFromQuery !== '') { $this->scopedTenantExternalId = $tenantIdFromQuery; return; } $tenant = request()->route('tenant'); if ($tenant instanceof Tenant) { $this->scopedTenantExternalId = (string) $tenant->external_id; return; } if (is_string($tenant) && $tenant !== '') { $this->scopedTenantExternalId = $tenant; } } protected function mutateFormDataBeforeSave(array $data): array { $this->shouldMakeDefault = (bool) ($data['is_default'] ?? false); unset($data['is_default']); return $data; } protected function afterSave(): void { $record = $this->getRecord(); $tenant = $record instanceof ProviderConnection ? ($record->tenant ?? $this->currentTenant()) : $this->currentTenant(); if (! $tenant instanceof Tenant) { return; } $changedFields = array_values(array_diff(array_keys($record->getChanges()), ['updated_at'])); if ($this->shouldMakeDefault && ! $record->is_default) { $record->makeDefault(); $this->defaultWasChanged = true; } $hasDefault = $tenant->providerConnections() ->where('provider', $record->provider) ->where('is_default', true) ->exists(); if (! $hasDefault) { $record->makeDefault(); $this->defaultWasChanged = true; } $user = auth()->user(); $actorId = $user instanceof User ? (int) $user->getKey() : null; $actorEmail = $user instanceof User ? $user->email : null; $actorName = $user instanceof User ? $user->name : null; if ($changedFields !== []) { app(AuditLogger::class)->log( tenant: $tenant, action: 'provider_connection.updated', context: [ 'metadata' => [ 'provider' => $record->provider, 'entra_tenant_id' => $record->entra_tenant_id, 'fields' => $changedFields, ], ], actorId: $actorId, actorEmail: $actorEmail, actorName: $actorName, resourceType: 'provider_connection', resourceId: (string) $record->getKey(), status: 'success', ); } if ($this->defaultWasChanged) { app(AuditLogger::class)->log( tenant: $tenant, action: 'provider_connection.default_set', context: [ 'metadata' => [ 'provider' => $record->provider, 'entra_tenant_id' => $record->entra_tenant_id, ], ], actorId: $actorId, actorEmail: $actorEmail, actorName: $actorName, resourceType: 'provider_connection', resourceId: (string) $record->getKey(), status: 'success', ); } } protected function getHeaderActions(): array { $tenant = $this->currentTenant(); return [ Actions\DeleteAction::make() ->visible(false), Actions\ActionGroup::make([ UiEnforcement::forAction( Action::make('view_last_check_run') ->label('View last check run') ->icon('heroicon-o-eye') ->color('gray') ->visible(fn (ProviderConnection $record): bool => $tenant instanceof Tenant && OperationRun::query() ->where('tenant_id', $tenant->getKey()) ->where('type', 'provider.connection.check') ->where('context->provider_connection_id', (int) $record->getKey()) ->exists()) ->url(function (ProviderConnection $record): ?string { $tenant = $this->currentTenant(); if (! $tenant instanceof Tenant) { return null; } $run = OperationRun::query() ->where('tenant_id', $tenant->getKey()) ->where('type', 'provider.connection.check') ->where('context->provider_connection_id', (int) $record->getKey()) ->orderByDesc('id') ->first(); if (! $run instanceof OperationRun) { return null; } return OperationRunLinks::view($run, $tenant); }) ) ->requireCapability(Capabilities::PROVIDER_VIEW) ->tooltip('You do not have permission to view provider connections.') ->preserveVisibility() ->apply(), ProviderConnectionResource::makeCheckConnectionAction(), ProviderConnectionResource::makeInventorySyncAction(), ProviderConnectionResource::makeComplianceSnapshotAction(), ProviderConnectionResource::makeSetDefaultAction(), ProviderConnectionResource::makeEnableDedicatedOverrideAction( source: 'provider_connection.edit_page', modalDescription: 'Dedicated credentials are stored encrypted and reset consent to the dedicated app registration.', ), ProviderConnectionResource::makeRotateDedicatedCredentialAction( modalDescription: 'Stores a replacement dedicated client secret and refreshes dedicated identity state.', ), ProviderConnectionResource::makeDeleteDedicatedCredentialAction( modalDescription: 'Deletes the dedicated credential and leaves the connection blocked until a replacement is added or the type is reverted.', ), ProviderConnectionResource::makeRevertToPlatformAction( source: 'provider_connection.edit_page', modalDescription: 'Reverts the connection to the platform-managed identity and removes any dedicated credential.', ), ProviderConnectionResource::makeEnableConnectionAction(), ProviderConnectionResource::makeDisableConnectionAction(), ]) ->label('Actions') ->icon('heroicon-o-ellipsis-vertical') ->color('gray'), ]; } protected function getFormActions(): array { $tenant = $this->currentTenant(); $user = auth()->user(); if (! $tenant instanceof Tenant || ! $user instanceof User) { return [ $this->getCancelFormAction(), ]; } $capabilityResolver = app(CapabilityResolver::class); if ($capabilityResolver->can($user, $tenant, Capabilities::PROVIDER_MANAGE)) { return parent::getFormActions(); } return [ $this->getCancelFormAction(), ]; } protected function handleRecordUpdate(Model $record, array $data): Model { $tenant = $record instanceof ProviderConnection ? ($record->tenant ?? $this->currentTenant()) : $this->currentTenant(); $user = auth()->user(); if (! $tenant instanceof Tenant || ! $user instanceof User) { abort(404); } $capabilityResolver = app(CapabilityResolver::class); if (! $capabilityResolver->isMember($user, $tenant)) { abort(404); } if (! $capabilityResolver->can($user, $tenant, Capabilities::PROVIDER_MANAGE)) { abort(403); } return parent::handleRecordUpdate($record, $data); } private function currentTenant(): ?Tenant { if (isset($this->record) && $this->record instanceof ProviderConnection) { $recordTenant = ProviderConnectionResource::resolveTenantForRecord($this->record); if ($recordTenant instanceof Tenant) { return $recordTenant; } } if (is_string($this->scopedTenantExternalId) && $this->scopedTenantExternalId !== '') { return Tenant::query() ->where('external_id', $this->scopedTenantExternalId) ->first(); } $tenant = request()->route('tenant'); if ($tenant instanceof Tenant) { return $tenant; } if (is_string($tenant) && $tenant !== '') { return Tenant::query() ->where('external_id', $tenant) ->first(); } $tenantFromCreateResolution = ProviderConnectionResource::resolveTenantForCreate(); if ($tenantFromCreateResolution instanceof Tenant) { return $tenantFromCreateResolution; } return Tenant::current(); } }