userReadRepository->find($userId); if (!$user) { return null; } $activeTenantIds = $this->scopeGateway->getUserTenantIds($userId); if (!$activeTenantIds) { return null; } // Priority: last-used tenant → primary tenant → first available. $currentTenantId = (int) ($user['current_tenant_id'] ?? 0); if ($currentTenantId > 0 && in_array($currentTenantId, $activeTenantIds, true)) { return $currentTenantId; } $primaryTenantId = (int) ($user['primary_tenant_id'] ?? 0); if ($primaryTenantId > 0 && in_array($primaryTenantId, $activeTenantIds, true)) { return $primaryTenantId; } return $activeTenantIds[0] ?? null; } /** * Get the current tenant data for a user */ public function getCurrentTenant(int $userId): ?array { $currentTenantId = $this->getCurrentTenantId($userId); if (!$currentTenantId) { return null; } return $this->directoryGateway->findTenant($currentTenantId); } /** * Get all tenants the user has access to */ public function getAvailableTenants(int $userId): array { $tenantIds = $this->scopeGateway->getUserTenantIds($userId); if (!$tenantIds) { return []; } $tenants = []; foreach ($tenantIds as $tenantId) { $tenant = $this->directoryGateway->findTenant((int) $tenantId); if ($tenant && (($tenant['status'] ?? 'active') === 'active')) { $tenants[] = $tenant; } } usort($tenants, static function ($a, $b) { return strcmp((string) ($a['description'] ?? ''), (string) ($b['description'] ?? '')); }); return $tenants; } /** * Get only explicitly assigned active tenants for a user. * This intentionally ignores global tenant-scope bypass permissions. */ public function getAssignedActiveTenants(int $userId): array { if ($userId <= 0) { return []; } $tenantIds = array_values(array_unique(array_map( 'intval', $this->userTenantRepository->listTenantIdsByUserId($userId) ))); $tenantIds = array_values(array_filter($tenantIds, static fn ($id) => $id > 0)); if (!$tenantIds) { return []; } $activeTenantIds = $this->directoryGateway->listActiveTenantIdsByIds($tenantIds); if (!$activeTenantIds) { return []; } $tenantsById = []; foreach ($this->directoryGateway->listTenantsByIds($activeTenantIds) as $tenant) { $tenantId = (int) ($tenant['id'] ?? 0); if ($tenantId <= 0) { continue; } $tenantsById[$tenantId] = $tenant; } $tenants = []; foreach ($tenantIds as $tenantId) { if (isset($tenantsById[$tenantId])) { $tenants[] = $tenantsById[$tenantId]; } } usort($tenants, static function ($a, $b) { return strcmp((string) ($a['description'] ?? ''), (string) ($b['description'] ?? '')); }); return $tenants; } /** * Get available departments grouped by tenant for a user. * Returns an array of groups: ['tenant' => [...], 'departments' => [...]] */ public function getAvailableDepartmentsByTenant(int $userId): array { $tenants = $this->getAvailableTenants($userId); if (!$tenants) { return []; } $groups = []; foreach ($tenants as $tenant) { $tenantId = (int) ($tenant['id'] ?? 0); if ($tenantId <= 0) { continue; } $departments = $this->directoryGateway->listDepartmentsByTenantIds([$tenantId]); usort($departments, static function ($a, $b) { return strcmp((string) ($a['description'] ?? ''), (string) ($b['description'] ?? '')); }); $departments = array_map(static function (array $department): array { return [ 'id' => (int) ($department['id'] ?? 0), 'uuid' => $department['uuid'] ?? '', 'description' => $department['description'] ?? '', ]; }, $departments); $groups[] = [ 'tenant' => [ 'id' => (int) ($tenant['id'] ?? 0), 'uuid' => $tenant['uuid'] ?? '', 'description' => $tenant['description'] ?? '', ], 'departments' => $departments, ]; } return $groups; } /** * Set the current tenant for a user (with validation) */ public function setCurrentTenant(int $userId, int $tenantId): array { if ($tenantId <= 0) { return ['ok' => false, 'error' => 'invalid_tenant']; } $userTenantIds = $this->userTenantRepository->listTenantIdsByUserId($userId); if (!in_array($tenantId, $userTenantIds, true)) { return ['ok' => false, 'error' => 'tenant_not_assigned']; } $tenant = $this->directoryGateway->findTenant($tenantId); if (!$tenant) { return ['ok' => false, 'error' => 'tenant_not_found']; } if (($tenant['status'] ?? 'active') !== 'active') { return ['ok' => false, 'error' => 'tenant_inactive']; } $updated = $this->userWriteRepository->setCurrentTenant($userId, $tenantId); if (!$updated) { return ['ok' => false, 'error' => 'update_failed']; } return ['ok' => true, 'tenant' => $tenant]; } }