@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
JavaScript
;
/**
* 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);
};
}