WIP - multitenant initial work

This commit is contained in:
Francisco Gaona
2025-11-29 05:09:00 +01:00
parent 859dca6c84
commit 57f27d28cd
36 changed files with 2784 additions and 36 deletions

View File

@@ -1,16 +1,64 @@
import { Injectable, NestMiddleware } from '@nestjs/common';
import { Injectable, NestMiddleware, Logger } from '@nestjs/common';
import { FastifyRequest, FastifyReply } from 'fastify';
import { TenantDatabaseService } from './tenant-database.service';
@Injectable()
export class TenantMiddleware implements NestMiddleware {
use(req: FastifyRequest['raw'], res: FastifyReply['raw'], next: () => void) {
const tenantId = req.headers['x-tenant-id'] as string;
if (tenantId) {
// Attach tenantId to request object
(req as any).tenantId = tenantId;
private readonly logger = new Logger(TenantMiddleware.name);
constructor(private readonly tenantDbService: TenantDatabaseService) {}
async use(
req: FastifyRequest['raw'],
res: FastifyReply['raw'],
next: () => void,
) {
try {
// Extract subdomain from hostname
const host = req.headers.host || '';
const hostname = host.split(':')[0]; // Remove port if present
const parts = hostname.split('.');
// For local development, accept x-tenant-id header as fallback
let tenantId = req.headers['x-tenant-id'] as string;
let subdomain: string | null = null;
// Extract subdomain (e.g., "acme" from "acme.routebox.co")
if (parts.length > 2) {
subdomain = parts[0];
// Ignore www subdomain
if (subdomain === 'www') {
subdomain = null;
}
}
// Get tenant by subdomain if available
if (subdomain) {
const tenant = await this.tenantDbService.getTenantByDomain(subdomain);
if (tenant) {
tenantId = tenant.id;
this.logger.log(
`Tenant identified: ${tenant.name} (${tenant.id}) from subdomain: ${subdomain}`,
);
} else {
this.logger.warn(`No tenant found for subdomain: ${subdomain}`);
}
}
if (tenantId) {
// Attach tenant info to request object
(req as any).tenantId = tenantId;
if (subdomain) {
(req as any).subdomain = subdomain;
}
} else {
this.logger.warn(`No tenant identified from host: ${hostname}`);
}
next();
} catch (error) {
this.logger.error('Error in tenant middleware', error);
next();
}
next();
}
}