feat(portal): complete masterplan with deterministic budget simulator, RAG assistant, agency cross-tenant view and multi-tenant middleware
This commit is contained in:
43
src/middleware.ts
Normal file
43
src/middleware.ts
Normal file
@@ -0,0 +1,43 @@
|
||||
import { NextRequest, NextResponse } from 'next/server';
|
||||
|
||||
export function middleware(req: NextRequest) {
|
||||
const url = req.nextUrl.clone();
|
||||
const hostname = req.headers.get('host') || '';
|
||||
|
||||
// 1. Extraer slug desde subdominio (ej: acme.4ventures.es)
|
||||
let tenantSlug = '4ventures-hub';
|
||||
const parts = hostname.split('.');
|
||||
|
||||
if (parts.length > 2) {
|
||||
const sub = parts[0].toLowerCase();
|
||||
if (sub !== 'app' && sub !== 'git' && sub !== 'supabase' && sub !== 'n8n' && sub !== 'www') {
|
||||
tenantSlug = sub;
|
||||
}
|
||||
}
|
||||
|
||||
// 2. Override opcional vía query param ?tenant=slug
|
||||
const queryTenant = url.searchParams.get('tenant');
|
||||
if (queryTenant) {
|
||||
tenantSlug = queryTenant.toLowerCase();
|
||||
} else {
|
||||
const cookieTenant = req.cookies.get('4v_tenant')?.value;
|
||||
if (cookieTenant) {
|
||||
tenantSlug = cookieTenant;
|
||||
}
|
||||
}
|
||||
|
||||
const response = NextResponse.next({
|
||||
request: {
|
||||
headers: new Headers(req.headers)
|
||||
}
|
||||
});
|
||||
|
||||
response.headers.set('x-tenant-slug', tenantSlug);
|
||||
response.cookies.set('4v_tenant', tenantSlug, { path: '/', maxAge: 60 * 60 * 24 * 30 });
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
export const config = {
|
||||
matcher: ['/((?!_next/static|_next/image|favicon.ico|_4v_attr.js).*)']
|
||||
};
|
||||
Reference in New Issue
Block a user