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->isEntitled($rememberedTenant, $request, TenantPageCategory::WorkspaceScoped)) { $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->isEntitled($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->isEntitled($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->isEntitled($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 isEntitled(Tenant $tenant, ?Request $request = null, ?TenantPageCategory $pageCategory = null): 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; } $decision = $this->tenantOperabilityService->decisionFor($tenant); $pageCategory ??= TenantPageCategory::fromRequest($request); return match ($pageCategory) { TenantPageCategory::TenantBound => $decision->canViewTenantSurface, default => $decision->canSelectAsContext, }; } private function pageCategory(?Request $request = null): TenantPageCategory { return TenantPageCategory::fromRequest($request); } }