isPlatformSuperadmin()) { return TenantRole::Owner; } $membership = $this->getMembership($user, $tenant); if ($membership === null) { return null; } return TenantRole::tryFrom($membership['role']); } /** * Check if user can perform a capability on a tenant */ public function can(User $user, Tenant $tenant, string $capability): bool { if ($user->isPlatformSuperadmin()) { return true; } $role = $this->getRole($user, $tenant); if ($role === null) { return false; } return RoleCapabilityMap::hasCapability($role, $capability); } /** * Check if user has any membership for a tenant */ public function isMember(User $user, Tenant $tenant): bool { if ($user->isPlatformSuperadmin()) { return true; } return $this->getMembership($user, $tenant) !== null; } /** * Get membership details (cached per request) */ private function getMembership(User $user, Tenant $tenant): ?array { $cacheKey = "membership_{$user->id}_{$tenant->id}"; if (! isset($this->resolvedMemberships[$cacheKey])) { $membership = TenantMembership::query() ->where('user_id', $user->id) ->where('tenant_id', $tenant->id) ->first(['role', 'source', 'source_ref']); $this->resolvedMemberships[$cacheKey] = $membership?->toArray(); } return $this->resolvedMemberships[$cacheKey]; } /** * Clear cached memberships (useful for testing or after membership changes) */ public function clearCache(): void { $this->resolvedMemberships = []; } }