import { Injectable, NestMiddleware } from '@nestjs/common'; import { TenantContextService, TenantInfo } from '@it0/common'; @Injectable() export class TenantContextMiddleware implements NestMiddleware { use(req: any, res: any, next: () => void) { let tenantId = req.headers?.['x-tenant-id'] as string; // Decode JWT to populate req.user for RolesGuard const authHeader = req.headers?.['authorization'] as string; if (authHeader?.startsWith('Bearer ')) { try { const token = authHeader.slice(7); const payload = JSON.parse( Buffer.from(token.split('.')[1], 'base64').toString(), ); req.user = { id: payload.sub, email: payload.email, tenantId: payload.tenantId, roles: payload.roles || [], }; // Fall back to JWT tenantId if header is missing if (!tenantId && payload.tenantId) { tenantId = payload.tenantId; } } catch { // Ignore decode errors - JWT validation is handled by Kong } } if (!tenantId) { return next(); } const tenantInfo: TenantInfo = { tenantId, tenantName: tenantId, plan: 'free', schemaName: `it0_t_${tenantId}`, }; TenantContextService.run(tenantInfo, () => next()); } }