UNPKG

@kenniy/godeye-data-contracts

Version:

Enterprise-grade base repository architecture for GOD-EYE microservices with zero overhead and maximum code reuse

138 lines (137 loc) 5.67 kB
"use strict"; /** * Kong Gateway Authentication System * Unified authentication across all GOD-EYE microservices */ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; return c > 3 && r && Object.defineProperty(target, key, r), r; }; var __metadata = (this && this.__metadata) || function (k, v) { if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); }; Object.defineProperty(exports, "__esModule", { value: true }); exports.KongAuthGuard = exports.KongUser = void 0; exports.normalizeHeaders = normalizeHeaders; exports.extractKongUserContext = extractKongUserContext; exports.createKongAuthGuard = createKongAuthGuard; exports.RequireRoles = RequireRoles; const common_1 = require("@nestjs/common"); const auth_constants_1 = require("../constants/auth.constants"); /** * Normalize request headers to string dictionary (DRY utility) * @param requestHeaders - Raw request headers * @returns Normalized headers as string dictionary */ function normalizeHeaders(requestHeaders) { const headers = {}; for (const [key, value] of Object.entries(requestHeaders)) { if (typeof value === 'string') { headers[key] = value; } else if (Array.isArray(value)) { headers[key] = value.join(','); } } return headers; } /** * Extract Kong user context from Gateway headers * @param headers - HTTP headers from Kong Gateway * @returns Kong user context with all available user information */ function extractKongUserContext(headers) { const userId = headers[auth_constants_1.KONG_HEADERS.USER_ID]; const userEmail = headers[auth_constants_1.KONG_HEADERS.USER_EMAIL]; const userType = headers[auth_constants_1.KONG_HEADERS.USER_TYPE]; if (!userId || !userEmail) { throw new common_1.HttpException(auth_constants_1.AUTH_MESSAGES.USER_CONTEXT_MISSING, common_1.HttpStatus.UNAUTHORIZED); } // Parse user types (Kong sends comma-separated string) const userTypes = userType ? userType.split(',').map((t) => t.trim()) : []; return { id: userId, email: userEmail, type: userTypes, profile_id: headers[auth_constants_1.KONG_HEADERS.PROFILE_ID], profile_kind: headers[auth_constants_1.KONG_HEADERS.PROFILE_KIND], phone: headers[auth_constants_1.KONG_HEADERS.PHONE], first_name: headers[auth_constants_1.KONG_HEADERS.FIRST_NAME], last_name: headers[auth_constants_1.KONG_HEADERS.LAST_NAME], }; } /** * Kong User Parameter Decorator * Usage: async method(@KongUser() user: IKongUserContext) */ exports.KongUser = (0, common_1.createParamDecorator)((data, ctx) => { const request = ctx.switchToHttp().getRequest(); const headers = normalizeHeaders(request.headers); return extractKongUserContext(headers); }); /** * Kong Authentication Guard * Automatically validates Kong user context on protected routes */ let KongAuthGuard = class KongAuthGuard { constructor(required_roles, skip_routes) { this.required_roles = required_roles; this.skip_routes = skip_routes; } canActivate(context) { const request = context.switchToHttp().getRequest(); const route = request.route?.path || request.url; // Skip authentication for certain routes if (this.skip_routes?.includes(route)) { return true; } try { // Extract user context using shared utility const headers = normalizeHeaders(request.headers); const userContext = extractKongUserContext(headers); // Check role requirements if (this.required_roles && this.required_roles.length > 0) { const hasRequiredRole = this.required_roles.some(role => userContext.type.includes(role)); if (!hasRequiredRole) { throw new common_1.HttpException(auth_constants_1.AUTH_MESSAGES.ROLE_NOT_ALLOWED, common_1.HttpStatus.FORBIDDEN); } } // Attach user context to request for later use request.user = userContext; return true; } catch (error) { if (error instanceof common_1.HttpException) { throw error; } throw new common_1.HttpException(auth_constants_1.AUTH_MESSAGES.UNAUTHORIZED, common_1.HttpStatus.UNAUTHORIZED); } } }; exports.KongAuthGuard = KongAuthGuard; exports.KongAuthGuard = KongAuthGuard = __decorate([ (0, common_1.Injectable)(), __metadata("design:paramtypes", [Array, Array]) ], KongAuthGuard); /** * Create Kong Auth Guard with specific configuration */ function createKongAuthGuard(options) { return class extends KongAuthGuard { constructor() { super(options?.required_roles, options?.skip_routes); } }; } /** * Role-based access control decorator * Usage: @RequireRoles(['admin', 'manager']) */ function RequireRoles(...roles) { return (target, propertyName, descriptor) => { // Implementation would integrate with NestJS guards system Reflect.defineMetadata('required_roles', roles, descriptor.value); }; }