Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 | 1x 1x 1x 1x 1x 6x 6x 6x 1x 5x 5x 1x 4x 4x 4x 1x 3x 3x 2x 1x | import { CanActivate, ExecutionContext, Injectable, ForbiddenException } from '@nestjs/common';
import { Reflector } from '@nestjs/core';
import type { Request } from 'express';
import { IS_PUBLIC_KEY } from './public.decorator';
import { IS_AUTH_ONLY_KEY } from './auth-only.decorator';
import type { ExecutionContext as CeoExecutionContext } from './execution-context';
/**
* Sesiunea request-ului ESTE acum ExecutionContext-ul complet (spec sectiunea 3).
* Numele vechi ramane exportat de aici pentru ca toate modulele de domeniu il
* importa deja; nu are rost sa schimb ~15 fisiere ca sa redenumesc un tip.
*/
export type AuthenticatedSession = CeoExecutionContext;
interface RequestWithSession extends Request {
session?: AuthenticatedSession;
}
/**
* Blueprint 11.3: tenant_id vine intotdeauna din sesiune, niciodata din
* body/query/params. Orice request fara sesiune valida, sau care incearca
* sa suprascrie tenant_id din client, este respins (deny-by-default).
* Inregistrata global (APP_GUARD) -- rutele publice trebuie sa foloseasca
* explicit @Public(), altfel raman blocate implicit.
*/
@Injectable()
export class TenantGuard implements CanActivate {
constructor(private readonly reflector: Reflector) {}
canActivate(context: ExecutionContext): boolean {
const isPublic = this.reflector.getAllAndOverride<boolean>(IS_PUBLIC_KEY, [
context.getHandler(),
context.getClass(),
]);
if (isPublic) {
return true;
}
const isAuthOnly = this.reflector.getAllAndOverride<boolean>(IS_AUTH_ONLY_KEY, [
context.getHandler(),
context.getClass(),
]);
if (isAuthOnly) {
// Rutele de bootstrap (ex. POST /v1/tenants) au user dar inca nu au tenant;
// SessionGuard a validat deja tokenul.
return true;
}
const request = context.switchToHttp().getRequest<RequestWithSession>();
const session = request.session;
if (!session?.tenantId) {
throw new ForbiddenException('No active tenant session');
}
const clientSuppliedTenantId =
(request.body as Record<string, unknown> | undefined)?.tenantId ??
(request.query as Record<string, unknown> | undefined)?.tenantId;
if (clientSuppliedTenantId && clientSuppliedTenantId !== session.tenantId) {
throw new ForbiddenException('tenant_id must not be supplied by the client');
}
return true;
}
}
|