UNPKG

@noony-serverless/core

Version:

A Middy base framework compatible with Firebase and GCP Cloud Functions with TypeScript

897 lines 36.1 kB
"use strict"; /** * Route Guards Facade * * Main entry point for the guard system providing a clean, NestJS-inspired API * for protecting routes with authentication and authorization. This facade * orchestrates all guard components to provide three distinct protection methods * optimized for different use cases. * * Three Protection Methods: * 1. `requirePermissions()` - Simple permission list checks (fastest) * 2. `requireWildcardPermissions()` - Hierarchical wildcard patterns * 3. `requireComplexPermissions()` - Boolean expression evaluation * * Key Features: * - Automatic resolver selection for optimal performance * - Intelligent caching strategies per protection method * - Conservative security approach with automatic cache invalidation * - Built-in authentication with cached user context loading * - Comprehensive monitoring and audit trails * - Framework-agnostic middleware integration * * @example * Complete guard system setup: * ```typescript * import { RouteGuards, GuardSetup } from '@noony-serverless/core'; * * // Define user permission source * const userPermissionSource = { * async getUserPermissions(userId: string): Promise<string[]> { * const user = await getUserFromDatabase(userId); * return user.permissions; * } * }; * * // Define token validator * const tokenValidator = { * async validateToken(token: string) { * try { * const decoded = jwt.verify(token, process.env.JWT_SECRET); * return { valid: true, decoded }; * } catch (error) { * return { valid: false, error: error.message }; * } * }, * extractUserId: (decoded: any) => decoded.sub, * isTokenExpired: (decoded: any) => decoded.exp < Date.now() / 1000 * }; * * // Configure guard system * await RouteGuards.configure( * GuardSetup.production(), * userPermissionSource, * tokenValidator, * { * tokenHeader: 'authorization', * tokenPrefix: 'Bearer ', * requireEmailVerification: true, * allowInactiveUsers: false * } * ); * ``` * * @example * Simple permission checks (fastest - ~0.1ms cached): * ```typescript * import { Handler, RouteGuards } from '@noony-serverless/core'; * * const userManagementHandler = new Handler() * .use(RouteGuards.requirePermissions(['user:read', 'user:update'])) * .handle(async (context) => { * // User has either 'user:read' OR 'user:update' permission * const users = await getUsers(); * return { success: true, users }; * }); * ``` * * @example * Wildcard permission patterns (hierarchical - ~0.2ms cached): * ```typescript * const adminHandler = new Handler() * .use(RouteGuards.requireWildcardPermissions(['admin.*', 'org.reports.*'])) * .handle(async (context) => { * // User has any permission starting with 'admin.' OR 'org.reports.' * const adminData = await getAdminDashboard(); * return { success: true, data: adminData }; * }); * ``` * * @example * Complex boolean expressions (~0.5ms cached): * ```typescript * const complexAccessHandler = new Handler() * .use(RouteGuards.requireComplexPermissions({ * or: [ * { permission: 'admin.users' }, * { and: [ * { permission: 'moderator.content' }, * { permission: 'org.reports.view' } * ]} * ] * })) * .handle(async (context) => { * // User has 'admin.users' OR ('moderator.content' AND 'org.reports.view') * return { success: true, accessGranted: true }; * }); * ``` * * @example * Authentication-only (no permissions): * ```typescript * const profileHandler = new Handler() * .use(RouteGuards.requireAuth()) * .handle(async (context) => { * // Only checks if user is authenticated * const profile = await getUserProfile(context.user.id); * return { success: true, profile }; * }); * ``` * * @example * Cache invalidation for security: * ```typescript * // Invalidate specific user when permissions change * await RouteGuards.invalidateUserPermissions('user-123', 'Permission update'); * * // System-wide invalidation for major updates * await RouteGuards.invalidateAllPermissions('System update deployed'); * * // Emergency invalidation for security incidents * await RouteGuards.emergencyInvalidation('Security breach detected'); * ``` * * @example * Monitoring and health checks: * ```typescript * // Get comprehensive system statistics * const stats = RouteGuards.getSystemStats(); * console.log('Guard system performance:', stats.systemHealth); * * // Perform health check * const health = await RouteGuards.healthCheck(); * console.log('System status:', health.status); * console.log('Recommendations:', health.details.recommendations); * ``` * * @author Noony Framework Team * @version 1.0.0 */ 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); }; var RouteGuards_1; Object.defineProperty(exports, "__esModule", { value: true }); exports.RouteGuards = void 0; const typedi_1 = require("typedi"); const GuardConfiguration_1 = require("./config/GuardConfiguration"); const MemoryCacheAdapter_1 = require("./cache/MemoryCacheAdapter"); const NoopCacheAdapter_1 = require("./cache/NoopCacheAdapter"); const FastUserContextService_1 = require("./services/FastUserContextService"); const ConservativeCacheInvalidation_1 = require("./cache/ConservativeCacheInvalidation"); const FastAuthGuard_1 = require("./guards/FastAuthGuard"); const PermissionGuardFactory_1 = require("./guards/PermissionGuardFactory"); const PermissionRegistry_1 = require("./registry/PermissionRegistry"); const CustomTokenVerificationPortAdapter_1 = require("./adapters/CustomTokenVerificationPortAdapter"); /** * Helper function to check if a token validator is a CustomTokenVerificationPort */ function isCustomTokenVerificationPort(validator) { return (typeof validator === 'object' && 'verifyToken' in validator && !('validateToken' in validator)); } /** * Convert any token validator to the TokenValidator interface expected by RouteGuards. * Automatically wraps CustomTokenVerificationPort implementations with an adapter. */ function normalizeTokenValidator(validator) { if (isCustomTokenVerificationPort(validator)) { // For CustomTokenVerificationPort, we create a generic adapter // We use a basic configuration that tries to extract common fields return new CustomTokenVerificationPortAdapter_1.CustomTokenVerificationPortAdapter(validator, { userIdExtractor: (user) => { // Try to extract user ID from common field names if (user && typeof user === 'object') { const userObj = user; return String(userObj.sub || userObj.id || userObj.userId || userObj.user_id || 'unknown'); } return 'unknown'; }, expirationExtractor: (user) => { // Try to extract expiration from common field names if (user && typeof user === 'object') { const userObj = user; const exp = userObj.exp || userObj.expiresAt || userObj.expires_at; return typeof exp === 'number' ? exp : undefined; } return undefined; }, }); } // Already a TokenValidator, return as-is return validator; } /** * Route Guards Facade Implementation * * This class provides the main API for the guard system and handles * the orchestration of all guard components. It follows the facade pattern * to simplify the complex underlying guard architecture. */ let RouteGuards = class RouteGuards { static { RouteGuards_1 = this; } static instance = null; static isConfigured = false; // @ts-expect-error - Reserved for future functionality _config; cache; userContextService; cacheInvalidation; authGuard; guardFactory; // @ts-expect-error - Reserved for future functionality _permissionRegistry; // System-wide statistics systemStartTime = Date.now(); totalGuardChecks = 0; totalErrors = 0; totalResponseTime = 0; constructor(config, cache, userContextService, cacheInvalidation, authGuard, guardFactory, permissionRegistry) { this._config = config; this.cache = cache; this.userContextService = userContextService; this.cacheInvalidation = cacheInvalidation; this.authGuard = authGuard; this.guardFactory = guardFactory; this._permissionRegistry = permissionRegistry; } /** * Configure the guard system with environment-specific settings * * This method must be called once before using any guard methods. * It sets up all guard components with optimal configurations for * the target environment (development, production, serverless). * * @param profile - Environment profile with guard configurations * @param permissionSource - User permission data source * @param tokenValidator - Token validation service (supports both TokenValidator and CustomTokenVerificationPort) * @param authConfig - Authentication guard configuration * @returns Promise resolving when configuration is complete * * @example * Using with CustomTokenVerificationPort from AuthenticationMiddleware: * ```typescript * import { CustomTokenVerificationPort } from '@/middlewares/authenticationMiddleware'; * import { RouteGuards, GuardSetup } from '@/middlewares/guards'; * * // Same token verifier used across the framework * const tokenVerifier: CustomTokenVerificationPort<User> = { * async verifyToken(token: string): Promise<User> { * const payload = jwt.verify(token, process.env.JWT_SECRET!) as JWTPayload; * return { * id: payload.sub, * email: payload.email, * roles: payload.roles || [], * sub: payload.sub, * exp: payload.exp * }; * } * }; * * // Configure RouteGuards with the same verifier * await RouteGuards.configure( * GuardSetup.production(), * userPermissionSource, * tokenVerifier, // Automatically wrapped with adapter * authConfig * ); * ``` * * @example * Traditional usage with TokenValidator (backward compatible): * ```typescript * const tokenValidator: TokenValidator = { * async validateToken(token: string) { * // Your existing validation logic * return { valid: true, decoded: userPayload }; * }, * extractUserId: (decoded) => decoded.sub, * isTokenExpired: (decoded) => decoded.exp < Date.now() / 1000 * }; * * await RouteGuards.configure( * GuardSetup.production(), * userPermissionSource, * tokenValidator, // Works as before * authConfig * ); * ``` */ static async configure(profile, permissionSource, tokenValidator, authConfig) { if (RouteGuards_1.isConfigured) { console.warn('⚠️ RouteGuards already configured, skipping reconfiguration'); return; } try { // Create guard configuration const config = GuardConfiguration_1.GuardConfiguration.fromEnvironmentProfile(profile); // Get effective cache type considering environment variable override // Environment variable NOONY_GUARD_CACHE_ENABLE takes precedence for security const effectiveCacheType = GuardConfiguration_1.GuardConfiguration.getEffectiveCacheType(profile.cacheType); // Select cache adapter based on effective cache type let cache; if (effectiveCacheType === 'memory') { cache = new MemoryCacheAdapter_1.MemoryCacheAdapter({ maxSize: config.cache.maxEntries || 1000, defaultTTL: config.cache.defaultTtlMs || 15 * 60 * 1000, name: 'guard-memory-cache', }); } else if (effectiveCacheType === 'none') { cache = new NoopCacheAdapter_1.NoopCacheAdapter(); // Log cache status for debugging if (!GuardConfiguration_1.GuardConfiguration.isCachingEnabled()) { console.log(`🚫 Guard caching disabled by environment variable NOONY_GUARD_CACHE_ENABLE`); } else { console.log(`🚫 Guard caching disabled by configuration (cacheType: 'none')`); } } else { // Default to memory cache (redis support would go here) cache = new MemoryCacheAdapter_1.MemoryCacheAdapter({ maxSize: 1000, defaultTTL: 15 * 60 * 1000, name: 'guard-default-cache', }); } // Initialize permission registry const permissionRegistry = new PermissionRegistry_1.DefaultPermissionRegistry(); // Create user context service const userContextService = new FastUserContextService_1.FastUserContextService(cache, config, permissionSource, permissionRegistry); // Create cache invalidation service const cacheInvalidation = new ConservativeCacheInvalidation_1.ConservativeCacheInvalidation(cache); // Normalize token validator to ensure compatibility const normalizedTokenValidator = normalizeTokenValidator(tokenValidator); // Create authentication guard const authGuard = new FastAuthGuard_1.FastAuthGuard(cache, config, authConfig, userContextService, cacheInvalidation, normalizedTokenValidator); // Create permission guard factory const guardFactory = new PermissionGuardFactory_1.PermissionGuardFactory(userContextService, config, cache); // Register services with TypeDI container typedi_1.Container.set('GuardConfiguration', config); typedi_1.Container.set('CacheAdapter', cache); typedi_1.Container.set('FastUserContextService', userContextService); typedi_1.Container.set('ConservativeCacheInvalidation', cacheInvalidation); typedi_1.Container.set('FastAuthGuard', authGuard); typedi_1.Container.set('PermissionGuardFactory', guardFactory); typedi_1.Container.set('PermissionRegistry', permissionRegistry); // Create and register the main RouteGuards instance const routeGuards = new RouteGuards_1(config, cache, userContextService, cacheInvalidation, authGuard, guardFactory, permissionRegistry); typedi_1.Container.set('RouteGuards', routeGuards); RouteGuards_1.instance = routeGuards; RouteGuards_1.isConfigured = true; console.log('✅ RouteGuards configured successfully', { environment: profile.environment, cacheType: profile.cacheType, effectiveCacheType: effectiveCacheType, cachingEnabled: GuardConfiguration_1.GuardConfiguration.isCachingEnabled(), permissionStrategy: config.security.permissionResolutionStrategy, timestamp: new Date().toISOString(), }); } catch (error) { console.error('❌ RouteGuards configuration failed', { error: error instanceof Error ? error.message : 'Unknown error', profile: profile.environment, }); throw error; } } /** * Get the configured RouteGuards instance * * @returns Configured RouteGuards instance * @throws Error if not configured */ static getInstance() { if (!RouteGuards_1.instance || !RouteGuards_1.isConfigured) { throw new Error('RouteGuards not configured. Call RouteGuards.configure() first.'); } return RouteGuards_1.instance; } /** * Create middleware for simple permission list checks * * This is the fastest protection method using direct O(1) set membership * checks. Ideal for high-traffic endpoints with straightforward permission * requirements. * * Performance: ~0.1ms cached, ~1-2ms uncached * * @param permissions - Array of required permissions (OR logic) * @param options - Optional guard configuration * @returns Middleware instance for permission checking */ static requirePermissions(permissions, options = {}) { const instance = RouteGuards_1.getInstance(); return instance.createPlainPermissionGuard(permissions, options); } /** * Create middleware for wildcard permission pattern checks * * Supports hierarchical permission patterns with wildcards for flexible * permission management. Uses configurable pre-expansion or on-demand * matching strategies. * * Performance: ~0.2ms cached (pre-expansion), ~2-5ms cached (on-demand) * * @param wildcardPatterns - Array of wildcard patterns * @param options - Optional guard configuration * @returns Middleware instance for wildcard permission checking */ static requireWildcardPermissions(wildcardPatterns, options = {}) { const instance = RouteGuards_1.getInstance(); return instance.createWildcardPermissionGuard(wildcardPatterns, options); } /** * Create middleware for complex boolean expression checks * * Supports advanced permission logic with AND, OR, and NOT operations. * Includes expression caching and complexity tracking for performance * optimization. * * Performance: ~0.5ms cached, ~5-15ms uncached (depends on complexity) * * @param expression - Permission expression with boolean logic * @param options - Optional guard configuration * @returns Middleware instance for expression permission checking */ static requireComplexPermissions(expression, options = {}) { const instance = RouteGuards_1.getInstance(); return instance.createExpressionPermissionGuard(expression, options); } /** * Create middleware with automatic resolver selection * * Analyzes permission requirements and automatically selects the optimal * resolution strategy for best performance. Useful when you want the * system to choose the best approach. * * @param permissions - Any type of permission requirement * @param options - Optional guard configuration * @returns Optimally configured middleware instance */ static requireAny(permissions, options = {}) { const instance = RouteGuards_1.getInstance(); return instance.createAutoPermissionGuard(permissions, options); } /** * Get authentication-only middleware * * Provides user authentication without permission checking. * Useful for endpoints that only need to verify user identity. * * @param options - Optional guard configuration * @returns Authentication-only middleware */ static requireAuth(_options = {}) { const instance = RouteGuards_1.getInstance(); return instance.authGuard; } /** * Invalidate user permissions cache * * Use when user permissions change to ensure fresh permission checks. * Implements conservative invalidation strategy for security. * * @param userId - User ID to invalidate * @param reason - Reason for invalidation (for audit) * @returns Promise resolving when invalidation is complete */ static async invalidateUserPermissions(userId, reason) { const instance = RouteGuards_1.getInstance(); await instance.cacheInvalidation.invalidateUserPermissions(userId, reason); } /** * System-wide cache invalidation * * Nuclear option for clearing all permission-related caches. * Use for major system updates or security incidents. * * @param reason - Reason for system-wide invalidation * @returns Promise resolving when invalidation is complete */ static async invalidateAllPermissions(reason) { const instance = RouteGuards_1.getInstance(); await instance.cacheInvalidation.invalidateSystemWide(reason); } /** * Emergency security invalidation * * Immediate cache clearing for security incidents. * Bypasses backup creation for maximum speed. * * @param reason - Security incident description * @returns Promise resolving when emergency invalidation is complete */ static async emergencyInvalidation(reason) { const instance = RouteGuards_1.getInstance(); await instance.cacheInvalidation.emergencySecurityInvalidation(reason); } /** * Get comprehensive system statistics * * @returns Complete guard system performance and health metrics */ static getSystemStats() { const instance = RouteGuards_1.getInstance(); return instance.getSystemStats(); } /** * Reset all system statistics */ static resetSystemStats() { const instance = RouteGuards_1.getInstance(); instance.resetSystemStats(); } /** * Health check for the guard system * * @returns Health status with key metrics */ static async healthCheck() { const instance = RouteGuards_1.getInstance(); return instance.performHealthCheck(); } /** * Factory method: Configure RouteGuards with CustomTokenVerificationPort for JWT tokens. * Provides a streamlined setup for JWT-based authentication with common field extraction. * * @example * Quick JWT setup with CustomTokenVerificationPort: * ```typescript * import { CustomTokenVerificationPort } from '@/middlewares/authenticationMiddleware'; * * interface JWTUser { * sub: string; * email: string; * roles: string[]; * exp: number; * } * * const jwtVerifier: CustomTokenVerificationPort<JWTUser> = { * async verifyToken(token: string): Promise<JWTUser> { * const payload = jwt.verify(token, process.env.JWT_SECRET!) as any; * return { * sub: payload.sub, * email: payload.email, * roles: payload.roles || [], * exp: payload.exp * }; * } * }; * * // One-line setup for JWT authentication * await RouteGuards.configureWithJWT( * GuardSetup.production(), * userPermissionSource, * jwtVerifier, * { * tokenHeader: 'authorization', * tokenPrefix: 'Bearer ', * requireEmailVerification: true * } * ); * ``` */ static async configureWithJWT(profile, permissionSource, jwtVerifier, authConfig) { // Create a properly typed adapter for JWT tokens const tokenValidator = CustomTokenVerificationPortAdapter_1.TokenVerificationAdapterFactory.forJWT(jwtVerifier); await RouteGuards_1.configure(profile, permissionSource, tokenValidator, authConfig); } /** * Factory method: Configure RouteGuards with CustomTokenVerificationPort for API keys. * Provides setup for API key-based authentication with flexible field mapping. * * @example * API key authentication setup: * ```typescript * interface APIKeyUser { * keyId: string; * permissions: string[]; * organization: string; * expiresAt?: number; * isActive: boolean; * } * * const apiKeyVerifier: CustomTokenVerificationPort<APIKeyUser> = { * async verifyToken(token: string): Promise<APIKeyUser> { * const keyData = await validateAPIKeyInDatabase(token); * if (!keyData || !keyData.isActive) { * throw new Error('Invalid or inactive API key'); * } * return keyData; * } * }; * * await RouteGuards.configureWithAPIKey( * GuardSetup.production(), * userPermissionSource, * apiKeyVerifier, * { * tokenHeader: 'x-api-key', * tokenPrefix: '', * allowInactiveUsers: false * }, * 'keyId', * 'expiresAt' * ); * ``` */ static async configureWithAPIKey(profile, permissionSource, apiKeyVerifier, authConfig, userIdField, expirationField) { // Create a properly configured adapter for API keys const tokenValidator = CustomTokenVerificationPortAdapter_1.TokenVerificationAdapterFactory.forAPIKey(apiKeyVerifier, userIdField, expirationField); await RouteGuards_1.configure(profile, permissionSource, tokenValidator, authConfig); } /** * Factory method: Configure RouteGuards with CustomTokenVerificationPort for OAuth tokens. * Provides setup for OAuth-based authentication with scope validation. * * @example * OAuth token authentication with scope requirements: * ```typescript * interface OAuthUser { * sub: string; * email: string; * scope: string[]; * exp: number; * client_id: string; * } * * const oauthVerifier: CustomTokenVerificationPort<OAuthUser> = { * async verifyToken(token: string): Promise<OAuthUser> { * const response = await fetch(`${OAUTH_INTROSPECT_URL}`, { * method: 'POST', * headers: { 'Authorization': `Bearer ${token}` }, * body: new URLSearchParams({ token }) * }); * * const tokenInfo = await response.json(); * if (!tokenInfo.active) { * throw new Error('Token is not active'); * } * * return tokenInfo as OAuthUser; * } * }; * * await RouteGuards.configureWithOAuth( * GuardSetup.production(), * userPermissionSource, * oauthVerifier, * { * tokenHeader: 'authorization', * tokenPrefix: 'Bearer ', * requireEmailVerification: false * }, * ['read:profile', 'write:data'] // Required OAuth scopes * ); * ``` */ static async configureWithOAuth(profile, permissionSource, oauthVerifier, authConfig, requiredScopes) { // Create a properly configured adapter for OAuth tokens const tokenValidator = CustomTokenVerificationPortAdapter_1.TokenVerificationAdapterFactory.forOAuth(oauthVerifier, requiredScopes); await RouteGuards_1.configure(profile, permissionSource, tokenValidator, authConfig); } /** * Factory method: Configure RouteGuards with a custom CustomTokenVerificationPort adapter. * Provides maximum flexibility for custom token validation scenarios. * * @example * Custom token validation with business-specific logic: * ```typescript * interface CustomUser { * userId: string; * tenantId: string; * roles: string[]; * sessionExpiry: number; * isVerified: boolean; * } * * const customVerifier: CustomTokenVerificationPort<CustomUser> = { * async verifyToken(token: string): Promise<CustomUser> { * // Your custom verification logic * return await verifyCustomToken(token); * } * }; * * await RouteGuards.configureWithCustom( * GuardSetup.production(), * userPermissionSource, * customVerifier, * { * tokenHeader: 'x-auth-token', * tokenPrefix: 'Custom ', * customValidation: async (token, user) => { * return user.isVerified && user.tenantId === 'valid-tenant'; * } * }, * { * userIdExtractor: (user) => user.userId, * expirationExtractor: (user) => user.sessionExpiry, * additionalValidation: (user) => user.isVerified * } * ); * ``` */ static async configureWithCustom(profile, permissionSource, customVerifier, authConfig, adapterConfig) { // Create a custom configured adapter const tokenValidator = CustomTokenVerificationPortAdapter_1.TokenVerificationAdapterFactory.custom(customVerifier, adapterConfig); await RouteGuards_1.configure(profile, permissionSource, tokenValidator, authConfig); } // Private implementation methods createPlainPermissionGuard(permissions, options) { this.trackGuardCreation(); const guardConfig = { requireAuth: options.requireAuth !== false, cacheResults: options.cacheResults !== false, auditTrail: options.auditTrail === true, errorMessage: options.errorMessage, }; const guard = this.guardFactory.createPlainGuard(permissions, guardConfig); return this.wrapGuardWithStats(guard, 'plain'); } createWildcardPermissionGuard(wildcardPatterns, options) { this.trackGuardCreation(); const guardConfig = { requireAuth: options.requireAuth !== false, cacheResults: options.cacheResults !== false, auditTrail: options.auditTrail === true, errorMessage: options.errorMessage, }; const guard = this.guardFactory.createWildcardGuard(wildcardPatterns, guardConfig); return this.wrapGuardWithStats(guard, 'wildcard'); } createExpressionPermissionGuard(expression, options) { this.trackGuardCreation(); const guardConfig = { requireAuth: options.requireAuth !== false, cacheResults: options.cacheResults !== false, auditTrail: options.auditTrail === true, errorMessage: options.errorMessage, }; const guard = this.guardFactory.createExpressionGuard(expression, guardConfig); return this.wrapGuardWithStats(guard, 'expression'); } createAutoPermissionGuard(permissions, options) { this.trackGuardCreation(); const guardConfig = { requireAuth: options.requireAuth !== false, cacheResults: options.cacheResults !== false, auditTrail: options.auditTrail === true, errorMessage: options.errorMessage, }; const guard = this.guardFactory.createAutoGuard(permissions, guardConfig); return this.wrapGuardWithStats(guard, 'auto'); } wrapGuardWithStats(guard, _type) { const originalBefore = guard.before?.bind(guard); if (!originalBefore) { return guard; } guard.before = async (context) => { const startTime = Date.now(); this.totalGuardChecks++; try { await originalBefore(context); this.totalResponseTime += Date.now() - startTime; } catch (error) { this.totalErrors++; this.totalResponseTime += Date.now() - startTime; throw error; } }; return guard; } trackGuardCreation() { // Track guard creation for monitoring console.log('🛡️ Guard created', { timestamp: new Date().toISOString(), }); } getSystemStats() { const uptime = Date.now() - this.systemStartTime; const errorRate = this.totalGuardChecks > 0 ? (this.totalErrors / this.totalGuardChecks) * 100 : 0; const averageResponseTime = this.totalGuardChecks > 0 ? this.totalResponseTime / this.totalGuardChecks : 0; const cacheStats = this.cache.getName() === 'noop-cache' ? { hitRate: 0 } : { hitRate: 85 }; // Estimate for memory cache return { authentication: this.authGuard.getStats(), userContextService: this.userContextService.getStats(), permissionGuardFactory: this.guardFactory.getStats(), cacheInvalidation: this.cacheInvalidation.getStats(), cacheAdapter: { name: this.cache.getName(), stats: cacheStats, }, systemHealth: { totalGuardChecks: this.totalGuardChecks, averageResponseTime, errorRate, cacheEfficiency: cacheStats.hitRate, uptime, }, }; } resetSystemStats() { this.totalGuardChecks = 0; this.totalErrors = 0; this.totalResponseTime = 0; this.systemStartTime = Date.now(); this.authGuard.resetStats(); this.userContextService.resetStats(); this.guardFactory.clearCache(); } async performHealthCheck() { const stats = this.getSystemStats(); const errorRate = stats.systemHealth.errorRate; const averageResponseTime = stats.systemHealth.averageResponseTime; let status; if (errorRate < 1 && averageResponseTime < 10) { status = 'healthy'; } else if (errorRate < 5 && averageResponseTime < 50) { status = 'degraded'; } else { status = 'unhealthy'; } return { status, details: { errorRate: `${errorRate.toFixed(2)}%`, averageResponseTime: `${averageResponseTime.toFixed(2)}ms`, totalChecks: stats.systemHealth.totalGuardChecks, uptime: `${Math.round(stats.systemHealth.uptime / 1000)}s`, cacheEfficiency: `${stats.systemHealth.cacheEfficiency.toFixed(1)}%`, recommendations: this.getHealthRecommendations(status, stats), }, timestamp: new Date().toISOString(), }; } getHealthRecommendations(status, stats) { const recommendations = []; if (status === 'unhealthy') { recommendations.push('Consider emergency cache invalidation'); recommendations.push('Review error logs for system issues'); recommendations.push('Check user permission source performance'); } if (stats.systemHealth.errorRate > 2) { recommendations.push('High error rate detected - investigate failed permission checks'); } if (stats.systemHealth.averageResponseTime > 20) { recommendations.push('Slow response times - consider cache optimization'); } if (stats.systemHealth.cacheEfficiency < 50) { recommendations.push('Low cache efficiency - review caching strategy'); } if (recommendations.length === 0) { recommendations.push('System is operating optimally'); } return recommendations; } }; exports.RouteGuards = RouteGuards; exports.RouteGuards = RouteGuards = RouteGuards_1 = __decorate([ (0, typedi_1.Service)(), __metadata("design:paramtypes", [GuardConfiguration_1.GuardConfiguration, Object, FastUserContextService_1.FastUserContextService, ConservativeCacheInvalidation_1.ConservativeCacheInvalidation, FastAuthGuard_1.FastAuthGuard, PermissionGuardFactory_1.PermissionGuardFactory, Object]) ], RouteGuards); //# sourceMappingURL=RouteGuards.js.map