NestJS (6 services): implement @RequirePermission decorator with SetMetadata+Reflector, register APP_GUARD globally, fix as assertions to type guards, add explicit return types, fix import type for express, fix /metrics implicit any, replace native Error with ApplicationError, remove typeorm remnants, register LifecycleService. teacher-bff: add logger, ApplicationError, GlobalErrorFilter, forward real userId to downstream, log downstream failures, migrate health controller to shared/health. Go (2 services): interface to any, doc comments, CORS dev whitelist, JWT secret fail-fast, push-gateway internal API auth, metrics and readyz endpoints, remove dead code. Python (2 services): lifespan return type, dev_mode to bool, data-ana APIRouter, ai POST body model, ClickHouse async wrapping.
31 lines
887 B
TypeScript
31 lines
887 B
TypeScript
import {
|
|
Injectable,
|
|
NestMiddleware,
|
|
UnauthorizedException,
|
|
} from "@nestjs/common";
|
|
import type { Request, Response, NextFunction } from "express";
|
|
|
|
export interface AuthenticatedRequest extends Request {
|
|
userId?: string;
|
|
userRoles?: string[];
|
|
}
|
|
|
|
@Injectable()
|
|
export class AuthMiddleware implements NestMiddleware {
|
|
use(req: AuthenticatedRequest, _res: Response, next: NextFunction): void {
|
|
const userIdHeader = req.headers["x-user-id"];
|
|
const userId = typeof userIdHeader === "string" ? userIdHeader : undefined;
|
|
const rolesHeaderRaw = req.headers["x-user-roles"];
|
|
const rolesHeader =
|
|
typeof rolesHeaderRaw === "string" ? rolesHeaderRaw : undefined;
|
|
|
|
if (!userId) {
|
|
throw new UnauthorizedException("Missing x-user-id header");
|
|
}
|
|
|
|
req.userId = userId;
|
|
req.userRoles = rolesHeader ? rolesHeader.split(",") : [];
|
|
next();
|
|
}
|
|
}
|