@noony-serverless/core 0.1.0 → 0.1.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/build/middlewares/authenticationMiddleware.d.ts +379 -0
- package/build/middlewares/authenticationMiddleware.js +216 -0
- package/build/middlewares/bodyParserMiddleware.d.ts +99 -0
- package/build/middlewares/bodyParserMiddleware.js +99 -0
- package/build/middlewares/bodyValidationMiddleware.d.ts +68 -4
- package/build/middlewares/bodyValidationMiddleware.js +64 -0
- package/build/middlewares/dependencyInjectionMiddleware.d.ts +238 -0
- package/build/middlewares/dependencyInjectionMiddleware.js +238 -0
- package/build/middlewares/errorHandlerMiddleware.d.ts +94 -0
- package/build/middlewares/errorHandlerMiddleware.js +105 -0
- package/build/middlewares/guards/RouteGuards.d.ts +475 -0
- package/build/middlewares/guards/RouteGuards.js +604 -0
- package/build/middlewares/guards/cache/CacheAdapter.d.ts +473 -0
- package/build/middlewares/guards/cache/CacheAdapter.js +205 -0
- package/build/middlewares/guards/cache/ConservativeCacheInvalidation.d.ts +191 -0
- package/build/middlewares/guards/cache/ConservativeCacheInvalidation.js +510 -0
- package/build/middlewares/guards/cache/MemoryCacheAdapter.d.ts +228 -0
- package/build/middlewares/guards/cache/MemoryCacheAdapter.js +403 -0
- package/build/middlewares/guards/cache/NoopCacheAdapter.d.ts +95 -0
- package/build/middlewares/guards/cache/NoopCacheAdapter.js +131 -0
- package/build/middlewares/guards/config/GuardConfiguration.d.ts +612 -0
- package/build/middlewares/guards/config/GuardConfiguration.js +334 -0
- package/build/middlewares/guards/guards/FastAuthGuard.d.ts +201 -0
- package/build/middlewares/guards/guards/FastAuthGuard.js +460 -0
- package/build/middlewares/guards/guards/PermissionGuardFactory.d.ts +202 -0
- package/build/middlewares/guards/guards/PermissionGuardFactory.js +563 -0
- package/build/middlewares/guards/index.d.ts +67 -0
- package/build/middlewares/guards/index.js +192 -0
- package/build/middlewares/guards/registry/PermissionRegistry.d.ts +188 -0
- package/build/middlewares/guards/registry/PermissionRegistry.js +425 -0
- package/build/middlewares/guards/resolvers/ExpressionPermissionResolver.d.ts +129 -0
- package/build/middlewares/guards/resolvers/ExpressionPermissionResolver.js +451 -0
- package/build/middlewares/guards/resolvers/PermissionResolver.d.ts +155 -0
- package/build/middlewares/guards/resolvers/PermissionResolver.js +176 -0
- package/build/middlewares/guards/resolvers/PlainPermissionResolver.d.ts +101 -0
- package/build/middlewares/guards/resolvers/PlainPermissionResolver.js +248 -0
- package/build/middlewares/guards/resolvers/WildcardPermissionResolver.d.ts +146 -0
- package/build/middlewares/guards/resolvers/WildcardPermissionResolver.js +377 -0
- package/build/middlewares/guards/services/FastUserContextService.d.ts +216 -0
- package/build/middlewares/guards/services/FastUserContextService.js +435 -0
- package/build/middlewares/headerVariablesMiddleware.d.ts +118 -0
- package/build/middlewares/headerVariablesMiddleware.js +118 -0
- package/build/middlewares/httpAttributesMiddleware.d.ts +235 -0
- package/build/middlewares/httpAttributesMiddleware.js +235 -0
- package/build/middlewares/index.d.ts +1 -0
- package/build/middlewares/index.js +1 -0
- package/build/middlewares/queryParametersMiddleware.d.ts +105 -0
- package/build/middlewares/queryParametersMiddleware.js +105 -0
- package/build/middlewares/rateLimitingMiddleware.d.ts +109 -5
- package/build/middlewares/rateLimitingMiddleware.js +109 -5
- package/build/middlewares/responseWrapperMiddleware.d.ts +170 -1
- package/build/middlewares/responseWrapperMiddleware.js +170 -1
- package/build/middlewares/securityAuditMiddleware.js +5 -5
- package/build/middlewares/validationMiddleware.d.ts +145 -0
- package/build/middlewares/validationMiddleware.js +145 -0
- package/package.json +2 -2
|
@@ -0,0 +1,604 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Route Guards Facade
|
|
4
|
+
*
|
|
5
|
+
* Main entry point for the guard system providing a clean, NestJS-inspired API
|
|
6
|
+
* for protecting routes with authentication and authorization. This facade
|
|
7
|
+
* orchestrates all guard components to provide three distinct protection methods
|
|
8
|
+
* optimized for different use cases.
|
|
9
|
+
*
|
|
10
|
+
* Three Protection Methods:
|
|
11
|
+
* 1. `requirePermissions()` - Simple permission list checks (fastest)
|
|
12
|
+
* 2. `requireWildcardPermissions()` - Hierarchical wildcard patterns
|
|
13
|
+
* 3. `requireComplexPermissions()` - Boolean expression evaluation
|
|
14
|
+
*
|
|
15
|
+
* Key Features:
|
|
16
|
+
* - Automatic resolver selection for optimal performance
|
|
17
|
+
* - Intelligent caching strategies per protection method
|
|
18
|
+
* - Conservative security approach with automatic cache invalidation
|
|
19
|
+
* - Built-in authentication with cached user context loading
|
|
20
|
+
* - Comprehensive monitoring and audit trails
|
|
21
|
+
* - Framework-agnostic middleware integration
|
|
22
|
+
*
|
|
23
|
+
* @example
|
|
24
|
+
* Complete guard system setup:
|
|
25
|
+
* ```typescript
|
|
26
|
+
* import { RouteGuards, GuardSetup } from '@noony-serverless/core';
|
|
27
|
+
*
|
|
28
|
+
* // Define user permission source
|
|
29
|
+
* const userPermissionSource = {
|
|
30
|
+
* async getUserPermissions(userId: string): Promise<string[]> {
|
|
31
|
+
* const user = await getUserFromDatabase(userId);
|
|
32
|
+
* return user.permissions;
|
|
33
|
+
* }
|
|
34
|
+
* };
|
|
35
|
+
*
|
|
36
|
+
* // Define token validator
|
|
37
|
+
* const tokenValidator = {
|
|
38
|
+
* async validateToken(token: string) {
|
|
39
|
+
* try {
|
|
40
|
+
* const decoded = jwt.verify(token, process.env.JWT_SECRET);
|
|
41
|
+
* return { valid: true, decoded };
|
|
42
|
+
* } catch (error) {
|
|
43
|
+
* return { valid: false, error: error.message };
|
|
44
|
+
* }
|
|
45
|
+
* },
|
|
46
|
+
* extractUserId: (decoded: any) => decoded.sub,
|
|
47
|
+
* isTokenExpired: (decoded: any) => decoded.exp < Date.now() / 1000
|
|
48
|
+
* };
|
|
49
|
+
*
|
|
50
|
+
* // Configure guard system
|
|
51
|
+
* await RouteGuards.configure(
|
|
52
|
+
* GuardSetup.production(),
|
|
53
|
+
* userPermissionSource,
|
|
54
|
+
* tokenValidator,
|
|
55
|
+
* {
|
|
56
|
+
* tokenHeader: 'authorization',
|
|
57
|
+
* tokenPrefix: 'Bearer ',
|
|
58
|
+
* requireEmailVerification: true,
|
|
59
|
+
* allowInactiveUsers: false
|
|
60
|
+
* }
|
|
61
|
+
* );
|
|
62
|
+
* ```
|
|
63
|
+
*
|
|
64
|
+
* @example
|
|
65
|
+
* Simple permission checks (fastest - ~0.1ms cached):
|
|
66
|
+
* ```typescript
|
|
67
|
+
* import { Handler, RouteGuards } from '@noony-serverless/core';
|
|
68
|
+
*
|
|
69
|
+
* const userManagementHandler = new Handler()
|
|
70
|
+
* .use(RouteGuards.requirePermissions(['user:read', 'user:update']))
|
|
71
|
+
* .handle(async (context) => {
|
|
72
|
+
* // User has either 'user:read' OR 'user:update' permission
|
|
73
|
+
* const users = await getUsers();
|
|
74
|
+
* return { success: true, users };
|
|
75
|
+
* });
|
|
76
|
+
* ```
|
|
77
|
+
*
|
|
78
|
+
* @example
|
|
79
|
+
* Wildcard permission patterns (hierarchical - ~0.2ms cached):
|
|
80
|
+
* ```typescript
|
|
81
|
+
* const adminHandler = new Handler()
|
|
82
|
+
* .use(RouteGuards.requireWildcardPermissions(['admin.*', 'org.reports.*']))
|
|
83
|
+
* .handle(async (context) => {
|
|
84
|
+
* // User has any permission starting with 'admin.' OR 'org.reports.'
|
|
85
|
+
* const adminData = await getAdminDashboard();
|
|
86
|
+
* return { success: true, data: adminData };
|
|
87
|
+
* });
|
|
88
|
+
* ```
|
|
89
|
+
*
|
|
90
|
+
* @example
|
|
91
|
+
* Complex boolean expressions (~0.5ms cached):
|
|
92
|
+
* ```typescript
|
|
93
|
+
* const complexAccessHandler = new Handler()
|
|
94
|
+
* .use(RouteGuards.requireComplexPermissions({
|
|
95
|
+
* or: [
|
|
96
|
+
* { permission: 'admin.users' },
|
|
97
|
+
* { and: [
|
|
98
|
+
* { permission: 'moderator.content' },
|
|
99
|
+
* { permission: 'org.reports.view' }
|
|
100
|
+
* ]}
|
|
101
|
+
* ]
|
|
102
|
+
* }))
|
|
103
|
+
* .handle(async (context) => {
|
|
104
|
+
* // User has 'admin.users' OR ('moderator.content' AND 'org.reports.view')
|
|
105
|
+
* return { success: true, accessGranted: true };
|
|
106
|
+
* });
|
|
107
|
+
* ```
|
|
108
|
+
*
|
|
109
|
+
* @example
|
|
110
|
+
* Authentication-only (no permissions):
|
|
111
|
+
* ```typescript
|
|
112
|
+
* const profileHandler = new Handler()
|
|
113
|
+
* .use(RouteGuards.requireAuth())
|
|
114
|
+
* .handle(async (context) => {
|
|
115
|
+
* // Only checks if user is authenticated
|
|
116
|
+
* const profile = await getUserProfile(context.user.id);
|
|
117
|
+
* return { success: true, profile };
|
|
118
|
+
* });
|
|
119
|
+
* ```
|
|
120
|
+
*
|
|
121
|
+
* @example
|
|
122
|
+
* Cache invalidation for security:
|
|
123
|
+
* ```typescript
|
|
124
|
+
* // Invalidate specific user when permissions change
|
|
125
|
+
* await RouteGuards.invalidateUserPermissions('user-123', 'Permission update');
|
|
126
|
+
*
|
|
127
|
+
* // System-wide invalidation for major updates
|
|
128
|
+
* await RouteGuards.invalidateAllPermissions('System update deployed');
|
|
129
|
+
*
|
|
130
|
+
* // Emergency invalidation for security incidents
|
|
131
|
+
* await RouteGuards.emergencyInvalidation('Security breach detected');
|
|
132
|
+
* ```
|
|
133
|
+
*
|
|
134
|
+
* @example
|
|
135
|
+
* Monitoring and health checks:
|
|
136
|
+
* ```typescript
|
|
137
|
+
* // Get comprehensive system statistics
|
|
138
|
+
* const stats = RouteGuards.getSystemStats();
|
|
139
|
+
* console.log('Guard system performance:', stats.systemHealth);
|
|
140
|
+
*
|
|
141
|
+
* // Perform health check
|
|
142
|
+
* const health = await RouteGuards.healthCheck();
|
|
143
|
+
* console.log('System status:', health.status);
|
|
144
|
+
* console.log('Recommendations:', health.details.recommendations);
|
|
145
|
+
* ```
|
|
146
|
+
*
|
|
147
|
+
* @author Noony Framework Team
|
|
148
|
+
* @version 1.0.0
|
|
149
|
+
*/
|
|
150
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
151
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
152
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
153
|
+
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;
|
|
154
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
155
|
+
};
|
|
156
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
157
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
158
|
+
};
|
|
159
|
+
var RouteGuards_1;
|
|
160
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
161
|
+
exports.RouteGuards = void 0;
|
|
162
|
+
const typedi_1 = require("typedi");
|
|
163
|
+
const GuardConfiguration_1 = require("./config/GuardConfiguration");
|
|
164
|
+
const MemoryCacheAdapter_1 = require("./cache/MemoryCacheAdapter");
|
|
165
|
+
const NoopCacheAdapter_1 = require("./cache/NoopCacheAdapter");
|
|
166
|
+
const FastUserContextService_1 = require("./services/FastUserContextService");
|
|
167
|
+
const ConservativeCacheInvalidation_1 = require("./cache/ConservativeCacheInvalidation");
|
|
168
|
+
const FastAuthGuard_1 = require("./guards/FastAuthGuard");
|
|
169
|
+
const PermissionGuardFactory_1 = require("./guards/PermissionGuardFactory");
|
|
170
|
+
const PermissionRegistry_1 = require("./registry/PermissionRegistry");
|
|
171
|
+
/**
|
|
172
|
+
* Route Guards Facade Implementation
|
|
173
|
+
*
|
|
174
|
+
* This class provides the main API for the guard system and handles
|
|
175
|
+
* the orchestration of all guard components. It follows the facade pattern
|
|
176
|
+
* to simplify the complex underlying guard architecture.
|
|
177
|
+
*/
|
|
178
|
+
let RouteGuards = class RouteGuards {
|
|
179
|
+
static { RouteGuards_1 = this; }
|
|
180
|
+
static instance = null;
|
|
181
|
+
static isConfigured = false;
|
|
182
|
+
// @ts-expect-error - Reserved for future functionality
|
|
183
|
+
_config;
|
|
184
|
+
cache;
|
|
185
|
+
userContextService;
|
|
186
|
+
cacheInvalidation;
|
|
187
|
+
authGuard;
|
|
188
|
+
guardFactory;
|
|
189
|
+
// @ts-expect-error - Reserved for future functionality
|
|
190
|
+
_permissionRegistry;
|
|
191
|
+
// System-wide statistics
|
|
192
|
+
systemStartTime = Date.now();
|
|
193
|
+
totalGuardChecks = 0;
|
|
194
|
+
totalErrors = 0;
|
|
195
|
+
totalResponseTime = 0;
|
|
196
|
+
constructor(config, cache, userContextService, cacheInvalidation, authGuard, guardFactory, permissionRegistry) {
|
|
197
|
+
this._config = config;
|
|
198
|
+
this.cache = cache;
|
|
199
|
+
this.userContextService = userContextService;
|
|
200
|
+
this.cacheInvalidation = cacheInvalidation;
|
|
201
|
+
this.authGuard = authGuard;
|
|
202
|
+
this.guardFactory = guardFactory;
|
|
203
|
+
this._permissionRegistry = permissionRegistry;
|
|
204
|
+
}
|
|
205
|
+
/**
|
|
206
|
+
* Configure the guard system with environment-specific settings
|
|
207
|
+
*
|
|
208
|
+
* This method must be called once before using any guard methods.
|
|
209
|
+
* It sets up all guard components with optimal configurations for
|
|
210
|
+
* the target environment (development, production, serverless).
|
|
211
|
+
*
|
|
212
|
+
* @param profile - Environment profile with guard configurations
|
|
213
|
+
* @param permissionSource - User permission data source
|
|
214
|
+
* @param tokenValidator - JWT token validation service
|
|
215
|
+
* @param authConfig - Authentication guard configuration
|
|
216
|
+
* @returns Promise resolving when configuration is complete
|
|
217
|
+
*/
|
|
218
|
+
static async configure(profile, permissionSource, tokenValidator, authConfig) {
|
|
219
|
+
if (RouteGuards_1.isConfigured) {
|
|
220
|
+
console.warn('⚠️ RouteGuards already configured, skipping reconfiguration');
|
|
221
|
+
return;
|
|
222
|
+
}
|
|
223
|
+
try {
|
|
224
|
+
// Create guard configuration
|
|
225
|
+
const config = GuardConfiguration_1.GuardConfiguration.fromEnvironmentProfile(profile);
|
|
226
|
+
// Select cache adapter based on environment
|
|
227
|
+
let cache;
|
|
228
|
+
if (profile.cacheType === 'memory') {
|
|
229
|
+
cache = new MemoryCacheAdapter_1.MemoryCacheAdapter({
|
|
230
|
+
maxSize: config.cache.maxEntries || 1000,
|
|
231
|
+
defaultTTL: config.cache.defaultTtlMs || 15 * 60 * 1000,
|
|
232
|
+
name: 'guard-memory-cache',
|
|
233
|
+
});
|
|
234
|
+
}
|
|
235
|
+
else if (profile.cacheType === 'none') {
|
|
236
|
+
cache = new NoopCacheAdapter_1.NoopCacheAdapter();
|
|
237
|
+
}
|
|
238
|
+
else {
|
|
239
|
+
// Default to memory cache
|
|
240
|
+
cache = new MemoryCacheAdapter_1.MemoryCacheAdapter({
|
|
241
|
+
maxSize: 1000,
|
|
242
|
+
defaultTTL: 15 * 60 * 1000,
|
|
243
|
+
name: 'guard-default-cache',
|
|
244
|
+
});
|
|
245
|
+
}
|
|
246
|
+
// Initialize permission registry
|
|
247
|
+
const permissionRegistry = new PermissionRegistry_1.DefaultPermissionRegistry();
|
|
248
|
+
// Create user context service
|
|
249
|
+
const userContextService = new FastUserContextService_1.FastUserContextService(cache, config, permissionSource, permissionRegistry);
|
|
250
|
+
// Create cache invalidation service
|
|
251
|
+
const cacheInvalidation = new ConservativeCacheInvalidation_1.ConservativeCacheInvalidation(cache);
|
|
252
|
+
// Create authentication guard
|
|
253
|
+
const authGuard = new FastAuthGuard_1.FastAuthGuard(cache, config, authConfig, userContextService, cacheInvalidation, tokenValidator);
|
|
254
|
+
// Create permission guard factory
|
|
255
|
+
const guardFactory = new PermissionGuardFactory_1.PermissionGuardFactory(userContextService, config, cache);
|
|
256
|
+
// Register services with TypeDI container
|
|
257
|
+
typedi_1.Container.set('GuardConfiguration', config);
|
|
258
|
+
typedi_1.Container.set('CacheAdapter', cache);
|
|
259
|
+
typedi_1.Container.set('FastUserContextService', userContextService);
|
|
260
|
+
typedi_1.Container.set('ConservativeCacheInvalidation', cacheInvalidation);
|
|
261
|
+
typedi_1.Container.set('FastAuthGuard', authGuard);
|
|
262
|
+
typedi_1.Container.set('PermissionGuardFactory', guardFactory);
|
|
263
|
+
typedi_1.Container.set('PermissionRegistry', permissionRegistry);
|
|
264
|
+
// Create and register the main RouteGuards instance
|
|
265
|
+
const routeGuards = new RouteGuards_1(config, cache, userContextService, cacheInvalidation, authGuard, guardFactory, permissionRegistry);
|
|
266
|
+
typedi_1.Container.set('RouteGuards', routeGuards);
|
|
267
|
+
RouteGuards_1.instance = routeGuards;
|
|
268
|
+
RouteGuards_1.isConfigured = true;
|
|
269
|
+
console.log('✅ RouteGuards configured successfully', {
|
|
270
|
+
environment: profile.environment,
|
|
271
|
+
cacheType: profile.cacheType,
|
|
272
|
+
permissionStrategy: config.security.permissionResolutionStrategy,
|
|
273
|
+
timestamp: new Date().toISOString(),
|
|
274
|
+
});
|
|
275
|
+
}
|
|
276
|
+
catch (error) {
|
|
277
|
+
console.error('❌ RouteGuards configuration failed', {
|
|
278
|
+
error: error instanceof Error ? error.message : 'Unknown error',
|
|
279
|
+
profile: profile.environment,
|
|
280
|
+
});
|
|
281
|
+
throw error;
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
/**
|
|
285
|
+
* Get the configured RouteGuards instance
|
|
286
|
+
*
|
|
287
|
+
* @returns Configured RouteGuards instance
|
|
288
|
+
* @throws Error if not configured
|
|
289
|
+
*/
|
|
290
|
+
static getInstance() {
|
|
291
|
+
if (!RouteGuards_1.instance || !RouteGuards_1.isConfigured) {
|
|
292
|
+
throw new Error('RouteGuards not configured. Call RouteGuards.configure() first.');
|
|
293
|
+
}
|
|
294
|
+
return RouteGuards_1.instance;
|
|
295
|
+
}
|
|
296
|
+
/**
|
|
297
|
+
* Create middleware for simple permission list checks
|
|
298
|
+
*
|
|
299
|
+
* This is the fastest protection method using direct O(1) set membership
|
|
300
|
+
* checks. Ideal for high-traffic endpoints with straightforward permission
|
|
301
|
+
* requirements.
|
|
302
|
+
*
|
|
303
|
+
* Performance: ~0.1ms cached, ~1-2ms uncached
|
|
304
|
+
*
|
|
305
|
+
* @param permissions - Array of required permissions (OR logic)
|
|
306
|
+
* @param options - Optional guard configuration
|
|
307
|
+
* @returns Middleware instance for permission checking
|
|
308
|
+
*/
|
|
309
|
+
static requirePermissions(permissions, options = {}) {
|
|
310
|
+
const instance = RouteGuards_1.getInstance();
|
|
311
|
+
return instance.createPlainPermissionGuard(permissions, options);
|
|
312
|
+
}
|
|
313
|
+
/**
|
|
314
|
+
* Create middleware for wildcard permission pattern checks
|
|
315
|
+
*
|
|
316
|
+
* Supports hierarchical permission patterns with wildcards for flexible
|
|
317
|
+
* permission management. Uses configurable pre-expansion or on-demand
|
|
318
|
+
* matching strategies.
|
|
319
|
+
*
|
|
320
|
+
* Performance: ~0.2ms cached (pre-expansion), ~2-5ms cached (on-demand)
|
|
321
|
+
*
|
|
322
|
+
* @param wildcardPatterns - Array of wildcard patterns
|
|
323
|
+
* @param options - Optional guard configuration
|
|
324
|
+
* @returns Middleware instance for wildcard permission checking
|
|
325
|
+
*/
|
|
326
|
+
static requireWildcardPermissions(wildcardPatterns, options = {}) {
|
|
327
|
+
const instance = RouteGuards_1.getInstance();
|
|
328
|
+
return instance.createWildcardPermissionGuard(wildcardPatterns, options);
|
|
329
|
+
}
|
|
330
|
+
/**
|
|
331
|
+
* Create middleware for complex boolean expression checks
|
|
332
|
+
*
|
|
333
|
+
* Supports advanced permission logic with AND, OR, and NOT operations.
|
|
334
|
+
* Includes expression caching and complexity tracking for performance
|
|
335
|
+
* optimization.
|
|
336
|
+
*
|
|
337
|
+
* Performance: ~0.5ms cached, ~5-15ms uncached (depends on complexity)
|
|
338
|
+
*
|
|
339
|
+
* @param expression - Permission expression with boolean logic
|
|
340
|
+
* @param options - Optional guard configuration
|
|
341
|
+
* @returns Middleware instance for expression permission checking
|
|
342
|
+
*/
|
|
343
|
+
static requireComplexPermissions(expression, options = {}) {
|
|
344
|
+
const instance = RouteGuards_1.getInstance();
|
|
345
|
+
return instance.createExpressionPermissionGuard(expression, options);
|
|
346
|
+
}
|
|
347
|
+
/**
|
|
348
|
+
* Create middleware with automatic resolver selection
|
|
349
|
+
*
|
|
350
|
+
* Analyzes permission requirements and automatically selects the optimal
|
|
351
|
+
* resolution strategy for best performance. Useful when you want the
|
|
352
|
+
* system to choose the best approach.
|
|
353
|
+
*
|
|
354
|
+
* @param permissions - Any type of permission requirement
|
|
355
|
+
* @param options - Optional guard configuration
|
|
356
|
+
* @returns Optimally configured middleware instance
|
|
357
|
+
*/
|
|
358
|
+
static requireAny(permissions, options = {}) {
|
|
359
|
+
const instance = RouteGuards_1.getInstance();
|
|
360
|
+
return instance.createAutoPermissionGuard(permissions, options);
|
|
361
|
+
}
|
|
362
|
+
/**
|
|
363
|
+
* Get authentication-only middleware
|
|
364
|
+
*
|
|
365
|
+
* Provides user authentication without permission checking.
|
|
366
|
+
* Useful for endpoints that only need to verify user identity.
|
|
367
|
+
*
|
|
368
|
+
* @param options - Optional guard configuration
|
|
369
|
+
* @returns Authentication-only middleware
|
|
370
|
+
*/
|
|
371
|
+
static requireAuth(_options = {}) {
|
|
372
|
+
const instance = RouteGuards_1.getInstance();
|
|
373
|
+
return instance.authGuard;
|
|
374
|
+
}
|
|
375
|
+
/**
|
|
376
|
+
* Invalidate user permissions cache
|
|
377
|
+
*
|
|
378
|
+
* Use when user permissions change to ensure fresh permission checks.
|
|
379
|
+
* Implements conservative invalidation strategy for security.
|
|
380
|
+
*
|
|
381
|
+
* @param userId - User ID to invalidate
|
|
382
|
+
* @param reason - Reason for invalidation (for audit)
|
|
383
|
+
* @returns Promise resolving when invalidation is complete
|
|
384
|
+
*/
|
|
385
|
+
static async invalidateUserPermissions(userId, reason) {
|
|
386
|
+
const instance = RouteGuards_1.getInstance();
|
|
387
|
+
await instance.cacheInvalidation.invalidateUserPermissions(userId, reason);
|
|
388
|
+
}
|
|
389
|
+
/**
|
|
390
|
+
* System-wide cache invalidation
|
|
391
|
+
*
|
|
392
|
+
* Nuclear option for clearing all permission-related caches.
|
|
393
|
+
* Use for major system updates or security incidents.
|
|
394
|
+
*
|
|
395
|
+
* @param reason - Reason for system-wide invalidation
|
|
396
|
+
* @returns Promise resolving when invalidation is complete
|
|
397
|
+
*/
|
|
398
|
+
static async invalidateAllPermissions(reason) {
|
|
399
|
+
const instance = RouteGuards_1.getInstance();
|
|
400
|
+
await instance.cacheInvalidation.invalidateSystemWide(reason);
|
|
401
|
+
}
|
|
402
|
+
/**
|
|
403
|
+
* Emergency security invalidation
|
|
404
|
+
*
|
|
405
|
+
* Immediate cache clearing for security incidents.
|
|
406
|
+
* Bypasses backup creation for maximum speed.
|
|
407
|
+
*
|
|
408
|
+
* @param reason - Security incident description
|
|
409
|
+
* @returns Promise resolving when emergency invalidation is complete
|
|
410
|
+
*/
|
|
411
|
+
static async emergencyInvalidation(reason) {
|
|
412
|
+
const instance = RouteGuards_1.getInstance();
|
|
413
|
+
await instance.cacheInvalidation.emergencySecurityInvalidation(reason);
|
|
414
|
+
}
|
|
415
|
+
/**
|
|
416
|
+
* Get comprehensive system statistics
|
|
417
|
+
*
|
|
418
|
+
* @returns Complete guard system performance and health metrics
|
|
419
|
+
*/
|
|
420
|
+
static getSystemStats() {
|
|
421
|
+
const instance = RouteGuards_1.getInstance();
|
|
422
|
+
return instance.getSystemStats();
|
|
423
|
+
}
|
|
424
|
+
/**
|
|
425
|
+
* Reset all system statistics
|
|
426
|
+
*/
|
|
427
|
+
static resetSystemStats() {
|
|
428
|
+
const instance = RouteGuards_1.getInstance();
|
|
429
|
+
instance.resetSystemStats();
|
|
430
|
+
}
|
|
431
|
+
/**
|
|
432
|
+
* Health check for the guard system
|
|
433
|
+
*
|
|
434
|
+
* @returns Health status with key metrics
|
|
435
|
+
*/
|
|
436
|
+
static async healthCheck() {
|
|
437
|
+
const instance = RouteGuards_1.getInstance();
|
|
438
|
+
return instance.performHealthCheck();
|
|
439
|
+
}
|
|
440
|
+
// Private implementation methods
|
|
441
|
+
createPlainPermissionGuard(permissions, options) {
|
|
442
|
+
this.trackGuardCreation();
|
|
443
|
+
const guardConfig = {
|
|
444
|
+
requireAuth: options.requireAuth !== false,
|
|
445
|
+
cacheResults: options.cacheResults !== false,
|
|
446
|
+
auditTrail: options.auditTrail === true,
|
|
447
|
+
errorMessage: options.errorMessage,
|
|
448
|
+
};
|
|
449
|
+
const guard = this.guardFactory.createPlainGuard(permissions, guardConfig);
|
|
450
|
+
return this.wrapGuardWithStats(guard, 'plain');
|
|
451
|
+
}
|
|
452
|
+
createWildcardPermissionGuard(wildcardPatterns, options) {
|
|
453
|
+
this.trackGuardCreation();
|
|
454
|
+
const guardConfig = {
|
|
455
|
+
requireAuth: options.requireAuth !== false,
|
|
456
|
+
cacheResults: options.cacheResults !== false,
|
|
457
|
+
auditTrail: options.auditTrail === true,
|
|
458
|
+
errorMessage: options.errorMessage,
|
|
459
|
+
};
|
|
460
|
+
const guard = this.guardFactory.createWildcardGuard(wildcardPatterns, guardConfig);
|
|
461
|
+
return this.wrapGuardWithStats(guard, 'wildcard');
|
|
462
|
+
}
|
|
463
|
+
createExpressionPermissionGuard(expression, options) {
|
|
464
|
+
this.trackGuardCreation();
|
|
465
|
+
const guardConfig = {
|
|
466
|
+
requireAuth: options.requireAuth !== false,
|
|
467
|
+
cacheResults: options.cacheResults !== false,
|
|
468
|
+
auditTrail: options.auditTrail === true,
|
|
469
|
+
errorMessage: options.errorMessage,
|
|
470
|
+
};
|
|
471
|
+
const guard = this.guardFactory.createExpressionGuard(expression, guardConfig);
|
|
472
|
+
return this.wrapGuardWithStats(guard, 'expression');
|
|
473
|
+
}
|
|
474
|
+
createAutoPermissionGuard(permissions, options) {
|
|
475
|
+
this.trackGuardCreation();
|
|
476
|
+
const guardConfig = {
|
|
477
|
+
requireAuth: options.requireAuth !== false,
|
|
478
|
+
cacheResults: options.cacheResults !== false,
|
|
479
|
+
auditTrail: options.auditTrail === true,
|
|
480
|
+
errorMessage: options.errorMessage,
|
|
481
|
+
};
|
|
482
|
+
const guard = this.guardFactory.createAutoGuard(permissions, guardConfig);
|
|
483
|
+
return this.wrapGuardWithStats(guard, 'auto');
|
|
484
|
+
}
|
|
485
|
+
wrapGuardWithStats(guard, _type) {
|
|
486
|
+
const originalBefore = guard.before?.bind(guard);
|
|
487
|
+
if (!originalBefore) {
|
|
488
|
+
return guard;
|
|
489
|
+
}
|
|
490
|
+
guard.before = async (context) => {
|
|
491
|
+
const startTime = Date.now();
|
|
492
|
+
this.totalGuardChecks++;
|
|
493
|
+
try {
|
|
494
|
+
await originalBefore(context);
|
|
495
|
+
this.totalResponseTime += Date.now() - startTime;
|
|
496
|
+
}
|
|
497
|
+
catch (error) {
|
|
498
|
+
this.totalErrors++;
|
|
499
|
+
this.totalResponseTime += Date.now() - startTime;
|
|
500
|
+
throw error;
|
|
501
|
+
}
|
|
502
|
+
};
|
|
503
|
+
return guard;
|
|
504
|
+
}
|
|
505
|
+
trackGuardCreation() {
|
|
506
|
+
// Track guard creation for monitoring
|
|
507
|
+
console.log('🛡️ Guard created', {
|
|
508
|
+
timestamp: new Date().toISOString(),
|
|
509
|
+
});
|
|
510
|
+
}
|
|
511
|
+
getSystemStats() {
|
|
512
|
+
const uptime = Date.now() - this.systemStartTime;
|
|
513
|
+
const errorRate = this.totalGuardChecks > 0
|
|
514
|
+
? (this.totalErrors / this.totalGuardChecks) * 100
|
|
515
|
+
: 0;
|
|
516
|
+
const averageResponseTime = this.totalGuardChecks > 0
|
|
517
|
+
? this.totalResponseTime / this.totalGuardChecks
|
|
518
|
+
: 0;
|
|
519
|
+
const cacheStats = this.cache.getName() === 'noop-cache' ? { hitRate: 0 } : { hitRate: 85 }; // Estimate for memory cache
|
|
520
|
+
return {
|
|
521
|
+
authentication: this.authGuard.getStats(),
|
|
522
|
+
userContextService: this.userContextService.getStats(),
|
|
523
|
+
permissionGuardFactory: this.guardFactory.getStats(),
|
|
524
|
+
cacheInvalidation: this.cacheInvalidation.getStats(),
|
|
525
|
+
cacheAdapter: {
|
|
526
|
+
name: this.cache.getName(),
|
|
527
|
+
stats: cacheStats,
|
|
528
|
+
},
|
|
529
|
+
systemHealth: {
|
|
530
|
+
totalGuardChecks: this.totalGuardChecks,
|
|
531
|
+
averageResponseTime,
|
|
532
|
+
errorRate,
|
|
533
|
+
cacheEfficiency: cacheStats.hitRate,
|
|
534
|
+
uptime,
|
|
535
|
+
},
|
|
536
|
+
};
|
|
537
|
+
}
|
|
538
|
+
resetSystemStats() {
|
|
539
|
+
this.totalGuardChecks = 0;
|
|
540
|
+
this.totalErrors = 0;
|
|
541
|
+
this.totalResponseTime = 0;
|
|
542
|
+
this.systemStartTime = Date.now();
|
|
543
|
+
this.authGuard.resetStats();
|
|
544
|
+
this.userContextService.resetStats();
|
|
545
|
+
this.guardFactory.clearCache();
|
|
546
|
+
}
|
|
547
|
+
async performHealthCheck() {
|
|
548
|
+
const stats = this.getSystemStats();
|
|
549
|
+
const errorRate = stats.systemHealth.errorRate;
|
|
550
|
+
const averageResponseTime = stats.systemHealth.averageResponseTime;
|
|
551
|
+
let status;
|
|
552
|
+
if (errorRate < 1 && averageResponseTime < 10) {
|
|
553
|
+
status = 'healthy';
|
|
554
|
+
}
|
|
555
|
+
else if (errorRate < 5 && averageResponseTime < 50) {
|
|
556
|
+
status = 'degraded';
|
|
557
|
+
}
|
|
558
|
+
else {
|
|
559
|
+
status = 'unhealthy';
|
|
560
|
+
}
|
|
561
|
+
return {
|
|
562
|
+
status,
|
|
563
|
+
details: {
|
|
564
|
+
errorRate: `${errorRate.toFixed(2)}%`,
|
|
565
|
+
averageResponseTime: `${averageResponseTime.toFixed(2)}ms`,
|
|
566
|
+
totalChecks: stats.systemHealth.totalGuardChecks,
|
|
567
|
+
uptime: `${Math.round(stats.systemHealth.uptime / 1000)}s`,
|
|
568
|
+
cacheEfficiency: `${stats.systemHealth.cacheEfficiency.toFixed(1)}%`,
|
|
569
|
+
recommendations: this.getHealthRecommendations(status, stats),
|
|
570
|
+
},
|
|
571
|
+
timestamp: new Date().toISOString(),
|
|
572
|
+
};
|
|
573
|
+
}
|
|
574
|
+
getHealthRecommendations(status, stats) {
|
|
575
|
+
const recommendations = [];
|
|
576
|
+
if (status === 'unhealthy') {
|
|
577
|
+
recommendations.push('Consider emergency cache invalidation');
|
|
578
|
+
recommendations.push('Review error logs for system issues');
|
|
579
|
+
recommendations.push('Check user permission source performance');
|
|
580
|
+
}
|
|
581
|
+
if (stats.systemHealth.errorRate > 2) {
|
|
582
|
+
recommendations.push('High error rate detected - investigate failed permission checks');
|
|
583
|
+
}
|
|
584
|
+
if (stats.systemHealth.averageResponseTime > 20) {
|
|
585
|
+
recommendations.push('Slow response times - consider cache optimization');
|
|
586
|
+
}
|
|
587
|
+
if (stats.systemHealth.cacheEfficiency < 50) {
|
|
588
|
+
recommendations.push('Low cache efficiency - review caching strategy');
|
|
589
|
+
}
|
|
590
|
+
if (recommendations.length === 0) {
|
|
591
|
+
recommendations.push('System is operating optimally');
|
|
592
|
+
}
|
|
593
|
+
return recommendations;
|
|
594
|
+
}
|
|
595
|
+
};
|
|
596
|
+
exports.RouteGuards = RouteGuards;
|
|
597
|
+
exports.RouteGuards = RouteGuards = RouteGuards_1 = __decorate([
|
|
598
|
+
(0, typedi_1.Service)(),
|
|
599
|
+
__metadata("design:paramtypes", [GuardConfiguration_1.GuardConfiguration, Object, FastUserContextService_1.FastUserContextService,
|
|
600
|
+
ConservativeCacheInvalidation_1.ConservativeCacheInvalidation,
|
|
601
|
+
FastAuthGuard_1.FastAuthGuard,
|
|
602
|
+
PermissionGuardFactory_1.PermissionGuardFactory, Object])
|
|
603
|
+
], RouteGuards);
|
|
604
|
+
//# sourceMappingURL=RouteGuards.js.map
|