import axios from 'axios'; import { appConfig } from './config-loader'; // Simple in-memory cache for tenant validation const tenantValidityCache = new Map(); const TENANT_CACHE_TTL_MS = 60_000; // 1 minute /** * Tenant-aware configuration for multi-tenant architecture */ export interface TenantConfig { tenantId: string; databaseUrl: string; redisUrl: string; platformServicesUrl: string; isAdminTenant: boolean; } export const getTenantConfig = (): TenantConfig => { const tenantId = appConfig.config.server.tenant_id; const databaseUrl = tenantId === 'admin' ? appConfig.getDatabaseUrl() : `postgresql://${appConfig.config.database.user}:${appConfig.secrets.postgres_password}@${tenantId}-postgres:5432/${appConfig.config.database.name}`; const redisUrl = tenantId === 'admin' ? appConfig.getRedisUrl() : `redis://${tenantId}-redis:6379`; const platformServicesUrl = appConfig.getPlatformServiceConfig('tenants').url; return { tenantId, databaseUrl, redisUrl, platformServicesUrl, isAdminTenant: tenantId === 'admin' }; }; export const isValidTenant = async (tenantId: string): Promise => { // Check cache const now = Date.now(); const cached = tenantValidityCache.get(tenantId); if (cached && (now - cached.ts) < TENANT_CACHE_TTL_MS) { return cached.ok; } let ok = false; try { const baseUrl = appConfig.getPlatformServiceConfig('tenants').url; const url = `${baseUrl}/api/v1/tenants/${encodeURIComponent(tenantId)}`; const resp = await axios.get(url, { timeout: 2000 }); ok = resp.status === 200; } catch { ok = false; } tenantValidityCache.set(tenantId, { ok, ts: now }); return ok; }; export const extractTenantId = (options: { envTenantId?: string; jwtTenantId?: string; subdomain?: string; }): string => { const { envTenantId, jwtTenantId, subdomain } = options; return envTenantId || jwtTenantId || subdomain || 'admin'; };