47 lines
1.3 KiB
TypeScript
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());
|
|
}
|
|
}
|