it0/packages/shared/database/src/tenant-context.middleware.ts

47 lines
1.3 KiB
TypeScript

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());
}
}