activeEntitledTenant($request); if ($activeTenant instanceof Tenant) { return 'Tenant scope: '.$activeTenant->name; } return 'All tenants'; } /** * @return array{label: string, url: string}|null */ public function returnAffordance(?Request $request = null): ?array { $activeTenant = $this->activeEntitledTenant($request); if ($activeTenant instanceof Tenant) { return [ 'label' => 'Back to '.$activeTenant->name, 'url' => TenantDashboard::getUrl(panel: 'tenant', tenant: $activeTenant), ]; } return null; } /** * @return array */ public function headerActions( string $scopeActionName = 'operate_hub_scope', string $returnActionName = 'operate_hub_return', ?Request $request = null, ): array { $actions = [ Action::make($scopeActionName) ->label($this->scopeLabel($request)) ->color('gray') ->disabled(), ]; $returnAffordance = $this->returnAffordance($request); if (is_array($returnAffordance)) { $actions[] = Action::make($returnActionName) ->label($returnAffordance['label']) ->icon('heroicon-o-arrow-left') ->color('gray') ->url($returnAffordance['url']); } return $actions; } public function activeEntitledTenant(?Request $request = null): ?Tenant { return $this->resolveActiveTenant($request); } private function resolveActiveTenant(?Request $request = null): ?Tenant { $pageCategory = $this->pageCategory($request); $routeTenant = $this->resolveRouteTenant($request, $pageCategory); if ($routeTenant instanceof Tenant) { return $routeTenant; } $tenant = $this->resolveValidatedFilamentTenant($request, $pageCategory); if ($tenant instanceof Tenant) { return $tenant; } if ($pageCategory === TenantPageCategory::TenantBound) { return null; } $rememberedTenant = $this->workspaceContext->rememberedTenant($request); if (! $rememberedTenant instanceof Tenant) { return null; } if (! $this->isRememberedTenantValid($rememberedTenant, $request)) { $this->workspaceContext->clearRememberedTenantContext($request); return null; } return $rememberedTenant; } private function resolveValidatedFilamentTenant(?Request $request = null, ?TenantPageCategory $pageCategory = null): ?Tenant { $tenant = Filament::getTenant(); if (! $tenant instanceof Tenant) { return null; } $pageCategory ??= $this->pageCategory($request); if ($this->isContextTenantEntitled($tenant, $request, $pageCategory)) { return $tenant; } Filament::setTenant(null, true); return null; } private function resolveRouteTenant(?Request $request = null, ?TenantPageCategory $pageCategory = null): ?Tenant { $route = $request?->route(); $pageCategory ??= $this->pageCategory($request); if ($route?->hasParameter('tenant')) { $tenant = $this->resolveTenantRouteParameter($route->parameter('tenant')); if (! $tenant instanceof Tenant || ! $this->isRouteTenantEntitled($tenant, $request, $pageCategory)) { return null; } return $tenant; } if ( $pageCategory !== TenantPageCategory::TenantBound || ! $route?->hasParameter('record') || ! str_starts_with((string) ($route->getName() ?? ''), 'filament.admin.resources.tenants.') ) { return null; } $tenant = $this->resolveTenantRouteParameter($route->parameter('record')); if (! $tenant instanceof Tenant || ! $this->isRouteTenantEntitled($tenant, $request, $pageCategory)) { return null; } return $tenant; } private function resolveTenantRouteParameter(mixed $routeTenant): ?Tenant { if ($routeTenant instanceof Tenant) { return $routeTenant; } $routeTenant = trim((string) $routeTenant); if ($routeTenant === '') { return null; } return Tenant::query() ->withTrashed() ->where(static function ($query) use ($routeTenant): void { $query->where('external_id', $routeTenant); if (ctype_digit($routeTenant)) { $query->orWhereKey((int) $routeTenant); } }) ->first(); } private function isRouteTenantEntitled(Tenant $tenant, ?Request $request = null, ?TenantPageCategory $pageCategory = null): bool { $pageCategory ??= TenantPageCategory::fromRequest($request); if ($pageCategory !== TenantPageCategory::TenantBound) { return $this->isContextTenantEntitled($tenant, $request, $pageCategory); } return $this->evaluateOutcome( tenant: $tenant, request: $request, question: TenantOperabilityQuestion::TenantBoundViewability, lane: TenantInteractionLane::AdministrativeManagement, ); } private function isContextTenantEntitled(Tenant $tenant, ?Request $request = null, ?TenantPageCategory $pageCategory = null): bool { $pageCategory ??= TenantPageCategory::fromRequest($request); return match ($pageCategory) { TenantPageCategory::TenantBound => $this->evaluateOutcome( tenant: $tenant, request: $request, question: TenantOperabilityQuestion::TenantBoundViewability, lane: TenantInteractionLane::AdministrativeManagement, ), TenantPageCategory::CanonicalWorkspaceRecordViewer, TenantPageCategory::OnboardingWorkflow, TenantPageCategory::WorkspaceScoped => $this->evaluateOutcome( tenant: $tenant, request: $request, question: TenantOperabilityQuestion::AdministrativeDiscoverability, lane: TenantInteractionLane::AdministrativeManagement, ), }; } private function isRememberedTenantValid(Tenant $tenant, ?Request $request = null): bool { return $this->evaluateOutcome( tenant: $tenant, request: $request, question: TenantOperabilityQuestion::RememberedContextValidity, lane: TenantInteractionLane::StandardActiveOperating, ); } private function evaluateOutcome( Tenant $tenant, ?Request $request, TenantOperabilityQuestion $question, TenantInteractionLane $lane, ): bool { $user = auth()->user(); if (! $user instanceof User) { return false; } $workspaceId = $this->workspaceContext->currentWorkspaceId($request); if ($workspaceId !== null && (int) $tenant->workspace_id !== (int) $workspaceId) { return false; } if (! $this->capabilityResolver->isMember($user, $tenant)) { return false; } return $this->tenantOperabilityService->outcomeFor( tenant: $tenant, question: $question, actor: $user, workspaceId: $workspaceId, lane: $lane, selectedTenant: Filament::getTenant() instanceof Tenant ? Filament::getTenant() : null, )->allowed; } private function pageCategory(?Request $request = null): TenantPageCategory { return TenantPageCategory::fromRequest($request); } }