@noony-serverless/core 0.1.5 → 0.2.1
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/README.md +7 -7
- package/build/core/core.d.ts +18 -50
- package/build/core/core.js +5 -67
- package/build/core/handler.d.ts +37 -16
- package/build/core/handler.js +131 -42
- package/build/core/index.d.ts +0 -1
- package/build/core/index.js +0 -1
- package/build/middlewares/ConsolidatedValidationMiddleware.d.ts +126 -0
- package/build/middlewares/ConsolidatedValidationMiddleware.js +330 -0
- package/build/middlewares/ProcessingMiddleware.d.ts +138 -0
- package/build/middlewares/ProcessingMiddleware.js +425 -0
- package/build/middlewares/SecurityMiddleware.d.ts +157 -0
- package/build/middlewares/SecurityMiddleware.js +307 -0
- package/build/middlewares/bodyValidationMiddleware.d.ts +12 -10
- package/build/middlewares/bodyValidationMiddleware.js +10 -8
- package/build/middlewares/dependencyInjectionMiddleware.js +1 -1
- package/build/middlewares/guards/RouteGuards.d.ts +239 -4
- package/build/middlewares/guards/RouteGuards.js +301 -8
- package/build/middlewares/guards/adapters/CustomTokenVerificationPortAdapter.d.ts +271 -0
- package/build/middlewares/guards/adapters/CustomTokenVerificationPortAdapter.js +301 -0
- package/build/middlewares/guards/config/GuardConfiguration.d.ts +50 -0
- package/build/middlewares/guards/config/GuardConfiguration.js +59 -0
- package/build/middlewares/guards/guards/FastAuthGuard.d.ts +5 -5
- package/build/middlewares/guards/guards/PermissionGuardFactory.d.ts +5 -13
- package/build/middlewares/guards/guards/PermissionGuardFactory.js +4 -4
- package/build/middlewares/guards/index.d.ts +43 -1
- package/build/middlewares/guards/index.js +46 -1
- package/build/middlewares/guards/resolvers/ExpressionPermissionResolver.d.ts +1 -1
- package/build/middlewares/guards/resolvers/ExpressionPermissionResolver.js +1 -1
- package/build/middlewares/guards/resolvers/PermissionResolver.d.ts +1 -1
- package/build/middlewares/guards/resolvers/PlainPermissionResolver.d.ts +1 -1
- package/build/middlewares/guards/resolvers/WildcardPermissionResolver.d.ts +1 -1
- package/build/middlewares/guards/services/FastUserContextService.d.ts +20 -33
- package/build/middlewares/guards/services/FastUserContextService.js +17 -4
- package/build/middlewares/httpAttributesMiddleware.js +1 -1
- package/build/middlewares/index.d.ts +3 -1
- package/build/middlewares/index.js +6 -1
- package/build/middlewares/rateLimitingMiddleware.d.ts +492 -4
- package/build/middlewares/rateLimitingMiddleware.js +514 -6
- package/package.json +11 -9
- package/build/core/containerPool.d.ts +0 -44
- package/build/core/containerPool.js +0 -103
- package/build/middlewares/validationMiddleware.d.ts +0 -154
- package/build/middlewares/validationMiddleware.js +0 -185
|
@@ -0,0 +1,301 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* CustomTokenVerificationPort Adapter
|
|
4
|
+
*
|
|
5
|
+
* Bridges the CustomTokenVerificationPort interface from AuthenticationMiddleware
|
|
6
|
+
* to the RouteGuards TokenValidator interface, enabling code reuse and unified
|
|
7
|
+
* token validation across the entire Noony Framework.
|
|
8
|
+
*
|
|
9
|
+
* Key Features:
|
|
10
|
+
* - Seamless integration between authentication systems
|
|
11
|
+
* - Maintains type safety through generics
|
|
12
|
+
* - Supports any token validation implementation (JWT, OAuth, API keys, etc.)
|
|
13
|
+
* - Preserves all existing RouteGuards functionality
|
|
14
|
+
* - Zero-overhead abstraction with full performance
|
|
15
|
+
*
|
|
16
|
+
* Benefits:
|
|
17
|
+
* - One authentication interface to implement and maintain
|
|
18
|
+
* - Consistent patterns across AuthenticationMiddleware and RouteGuards
|
|
19
|
+
* - Backward compatibility with existing RouteGuards implementations
|
|
20
|
+
* - Simplified setup for authentication workflows
|
|
21
|
+
*
|
|
22
|
+
* @example
|
|
23
|
+
* Bridge a JWT verification port to RouteGuards:
|
|
24
|
+
* ```typescript
|
|
25
|
+
* import { CustomTokenVerificationPort } from '@/middlewares/authenticationMiddleware';
|
|
26
|
+
* import { CustomTokenVerificationPortAdapter } from '@/middlewares/guards/adapters';
|
|
27
|
+
*
|
|
28
|
+
* // Define your user type
|
|
29
|
+
* interface User {
|
|
30
|
+
* id: string;
|
|
31
|
+
* email: string;
|
|
32
|
+
* roles: string[];
|
|
33
|
+
* sub: string; // JWT subject
|
|
34
|
+
* exp: number; // JWT expiration
|
|
35
|
+
* iat: number; // Issued at
|
|
36
|
+
* }
|
|
37
|
+
*
|
|
38
|
+
* // Implement token verification once
|
|
39
|
+
* const jwtVerifier: CustomTokenVerificationPort<User> = {
|
|
40
|
+
* async verifyToken(token: string): Promise<User> {
|
|
41
|
+
* const payload = jwt.verify(token, process.env.JWT_SECRET!) as any;
|
|
42
|
+
* return {
|
|
43
|
+
* id: payload.sub,
|
|
44
|
+
* email: payload.email,
|
|
45
|
+
* roles: payload.roles || [],
|
|
46
|
+
* sub: payload.sub,
|
|
47
|
+
* exp: payload.exp,
|
|
48
|
+
* iat: payload.iat
|
|
49
|
+
* };
|
|
50
|
+
* }
|
|
51
|
+
* };
|
|
52
|
+
*
|
|
53
|
+
* // Create adapter for RouteGuards
|
|
54
|
+
* const tokenValidator = new CustomTokenVerificationPortAdapter(
|
|
55
|
+
* jwtVerifier,
|
|
56
|
+
* {
|
|
57
|
+
* userIdExtractor: (user: User) => user.id,
|
|
58
|
+
* expirationExtractor: (user: User) => user.exp
|
|
59
|
+
* }
|
|
60
|
+
* );
|
|
61
|
+
*
|
|
62
|
+
* // Use with RouteGuards
|
|
63
|
+
* await RouteGuards.configure(
|
|
64
|
+
* GuardSetup.production(),
|
|
65
|
+
* userPermissionSource,
|
|
66
|
+
* tokenValidator, // Works seamlessly!
|
|
67
|
+
* authConfig
|
|
68
|
+
* );
|
|
69
|
+
* ```
|
|
70
|
+
*
|
|
71
|
+
* @example
|
|
72
|
+
* API key verification with custom user structure:
|
|
73
|
+
* ```typescript
|
|
74
|
+
* interface APIKeyUser {
|
|
75
|
+
* keyId: string;
|
|
76
|
+
* permissions: string[];
|
|
77
|
+
* organization: string;
|
|
78
|
+
* expiresAt: number;
|
|
79
|
+
* isActive: boolean;
|
|
80
|
+
* }
|
|
81
|
+
*
|
|
82
|
+
* const apiKeyVerifier: CustomTokenVerificationPort<APIKeyUser> = {
|
|
83
|
+
* async verifyToken(token: string): Promise<APIKeyUser> {
|
|
84
|
+
* const keyData = await validateAPIKey(token);
|
|
85
|
+
* if (!keyData || !keyData.isActive) {
|
|
86
|
+
* throw new Error('Invalid or inactive API key');
|
|
87
|
+
* }
|
|
88
|
+
* return keyData;
|
|
89
|
+
* }
|
|
90
|
+
* };
|
|
91
|
+
*
|
|
92
|
+
* // Adapter with custom extractors
|
|
93
|
+
* const apiTokenValidator = new CustomTokenVerificationPortAdapter(
|
|
94
|
+
* apiKeyVerifier,
|
|
95
|
+
* {
|
|
96
|
+
* userIdExtractor: (user: APIKeyUser) => user.keyId,
|
|
97
|
+
* expirationExtractor: (user: APIKeyUser) => user.expiresAt,
|
|
98
|
+
* additionalValidation: (user: APIKeyUser) => user.isActive
|
|
99
|
+
* }
|
|
100
|
+
* );
|
|
101
|
+
*
|
|
102
|
+
* // Seamlessly works with RouteGuards
|
|
103
|
+
* await RouteGuards.configure(
|
|
104
|
+
* GuardSetup.production(),
|
|
105
|
+
* userPermissionSource,
|
|
106
|
+
* apiTokenValidator,
|
|
107
|
+
* authConfig
|
|
108
|
+
* );
|
|
109
|
+
* ```
|
|
110
|
+
*
|
|
111
|
+
* @example
|
|
112
|
+
* OAuth token verification:
|
|
113
|
+
* ```typescript
|
|
114
|
+
* interface OAuthUser {
|
|
115
|
+
* sub: string; // OAuth subject
|
|
116
|
+
* email: string;
|
|
117
|
+
* scope: string[]; // OAuth scopes
|
|
118
|
+
* exp: number;
|
|
119
|
+
* client_id: string;
|
|
120
|
+
* }
|
|
121
|
+
*
|
|
122
|
+
* const oauthVerifier: CustomTokenVerificationPort<OAuthUser> = {
|
|
123
|
+
* async verifyToken(token: string): Promise<OAuthUser> {
|
|
124
|
+
* // Validate with OAuth provider
|
|
125
|
+
* const response = await fetch(`${OAUTH_INTROSPECT_URL}`, {
|
|
126
|
+
* method: 'POST',
|
|
127
|
+
* headers: { 'Authorization': `Bearer ${token}` }
|
|
128
|
+
* });
|
|
129
|
+
*
|
|
130
|
+
* const tokenInfo = await response.json();
|
|
131
|
+
* if (!tokenInfo.active) {
|
|
132
|
+
* throw new Error('Token is not active');
|
|
133
|
+
* }
|
|
134
|
+
*
|
|
135
|
+
* return tokenInfo as OAuthUser;
|
|
136
|
+
* }
|
|
137
|
+
* };
|
|
138
|
+
*
|
|
139
|
+
* const oauthTokenValidator = new CustomTokenVerificationPortAdapter(
|
|
140
|
+
* oauthVerifier,
|
|
141
|
+
* {
|
|
142
|
+
* userIdExtractor: (user: OAuthUser) => user.sub,
|
|
143
|
+
* expirationExtractor: (user: OAuthUser) => user.exp
|
|
144
|
+
* }
|
|
145
|
+
* );
|
|
146
|
+
* ```
|
|
147
|
+
*
|
|
148
|
+
* @author Noony Framework Team
|
|
149
|
+
* @version 1.0.0
|
|
150
|
+
*/
|
|
151
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
152
|
+
exports.TokenVerificationAdapterFactory = exports.CustomTokenVerificationPortAdapter = void 0;
|
|
153
|
+
/**
|
|
154
|
+
* Adapter class that bridges CustomTokenVerificationPort to TokenValidator.
|
|
155
|
+
* Enables seamless integration between AuthenticationMiddleware and RouteGuards
|
|
156
|
+
* while maintaining full type safety and performance.
|
|
157
|
+
*
|
|
158
|
+
* @template T - The user type returned by the CustomTokenVerificationPort
|
|
159
|
+
*/
|
|
160
|
+
class CustomTokenVerificationPortAdapter {
|
|
161
|
+
verificationPort;
|
|
162
|
+
config;
|
|
163
|
+
constructor(verificationPort, config) {
|
|
164
|
+
this.verificationPort = verificationPort;
|
|
165
|
+
this.config = config;
|
|
166
|
+
}
|
|
167
|
+
/**
|
|
168
|
+
* Validate and decode token using the wrapped CustomTokenVerificationPort.
|
|
169
|
+
*
|
|
170
|
+
* @param token - JWT token string to validate
|
|
171
|
+
* @returns Validation result with decoded user data
|
|
172
|
+
*/
|
|
173
|
+
async validateToken(token) {
|
|
174
|
+
try {
|
|
175
|
+
// Use the wrapped verification port to verify the token
|
|
176
|
+
const user = await this.verificationPort.verifyToken(token);
|
|
177
|
+
// Run additional validation if configured
|
|
178
|
+
if (this.config.additionalValidation) {
|
|
179
|
+
const additionalValid = await this.config.additionalValidation(user);
|
|
180
|
+
if (!additionalValid) {
|
|
181
|
+
return {
|
|
182
|
+
valid: false,
|
|
183
|
+
error: this.config.errorMessage || 'Additional validation failed',
|
|
184
|
+
};
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
return {
|
|
188
|
+
valid: true,
|
|
189
|
+
decoded: user,
|
|
190
|
+
};
|
|
191
|
+
}
|
|
192
|
+
catch (error) {
|
|
193
|
+
return {
|
|
194
|
+
valid: false,
|
|
195
|
+
error: this.config.errorMessage ||
|
|
196
|
+
(error instanceof Error ? error.message : 'Token validation failed'),
|
|
197
|
+
};
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
/**
|
|
201
|
+
* Extract user ID from the decoded token/user data.
|
|
202
|
+
* Uses the configured userIdExtractor function.
|
|
203
|
+
*
|
|
204
|
+
* @param decoded - Decoded user data from validateToken
|
|
205
|
+
* @returns User ID string
|
|
206
|
+
*/
|
|
207
|
+
extractUserId(decoded) {
|
|
208
|
+
return this.config.userIdExtractor(decoded);
|
|
209
|
+
}
|
|
210
|
+
/**
|
|
211
|
+
* Check if the token is expired based on the decoded data.
|
|
212
|
+
* Uses the configured expirationExtractor if available.
|
|
213
|
+
*
|
|
214
|
+
* @param decoded - Decoded user data from validateToken
|
|
215
|
+
* @returns true if token is expired, false otherwise
|
|
216
|
+
*/
|
|
217
|
+
isTokenExpired(decoded) {
|
|
218
|
+
if (!this.config.expirationExtractor) {
|
|
219
|
+
// If no expiration extractor is configured, assume token is valid
|
|
220
|
+
return false;
|
|
221
|
+
}
|
|
222
|
+
const expirationTime = this.config.expirationExtractor(decoded);
|
|
223
|
+
if (!expirationTime) {
|
|
224
|
+
// If no expiration time is available, assume token is valid
|
|
225
|
+
return false;
|
|
226
|
+
}
|
|
227
|
+
// Compare with current time (convert to seconds)
|
|
228
|
+
const currentTime = Math.floor(Date.now() / 1000);
|
|
229
|
+
return expirationTime <= currentTime;
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
exports.CustomTokenVerificationPortAdapter = CustomTokenVerificationPortAdapter;
|
|
233
|
+
/**
|
|
234
|
+
* Helper factory functions for common token verification scenarios.
|
|
235
|
+
* Provides pre-configured adapters for standard authentication patterns.
|
|
236
|
+
*/
|
|
237
|
+
class TokenVerificationAdapterFactory {
|
|
238
|
+
/**
|
|
239
|
+
* Create adapter for standard JWT tokens with common claims.
|
|
240
|
+
* Assumes the user object has 'sub' for user ID and 'exp' for expiration.
|
|
241
|
+
*
|
|
242
|
+
* @param verificationPort - JWT token verification port
|
|
243
|
+
* @returns Configured adapter for JWT tokens
|
|
244
|
+
*/
|
|
245
|
+
static forJWT(verificationPort) {
|
|
246
|
+
return new CustomTokenVerificationPortAdapter(verificationPort, {
|
|
247
|
+
userIdExtractor: (user) => user.sub,
|
|
248
|
+
expirationExtractor: (user) => user.exp,
|
|
249
|
+
});
|
|
250
|
+
}
|
|
251
|
+
/**
|
|
252
|
+
* Create adapter for API key tokens with custom ID and expiration fields.
|
|
253
|
+
*
|
|
254
|
+
* @param verificationPort - API key verification port
|
|
255
|
+
* @param userIdField - Field name for user/key ID (e.g., 'keyId', 'apiKeyId')
|
|
256
|
+
* @param expirationField - Optional field name for expiration (e.g., 'expiresAt', 'exp')
|
|
257
|
+
* @returns Configured adapter for API key tokens
|
|
258
|
+
*/
|
|
259
|
+
static forAPIKey(verificationPort, userIdField, expirationField) {
|
|
260
|
+
return new CustomTokenVerificationPortAdapter(verificationPort, {
|
|
261
|
+
userIdExtractor: (user) => String(user[userIdField]),
|
|
262
|
+
expirationExtractor: expirationField
|
|
263
|
+
? (user) => user[expirationField]
|
|
264
|
+
: undefined,
|
|
265
|
+
});
|
|
266
|
+
}
|
|
267
|
+
/**
|
|
268
|
+
* Create adapter for OAuth tokens with standard OAuth claims.
|
|
269
|
+
*
|
|
270
|
+
* @param verificationPort - OAuth token verification port
|
|
271
|
+
* @param additionalScopes - Optional required OAuth scopes
|
|
272
|
+
* @returns Configured adapter for OAuth tokens
|
|
273
|
+
*/
|
|
274
|
+
static forOAuth(verificationPort, additionalScopes) {
|
|
275
|
+
return new CustomTokenVerificationPortAdapter(verificationPort, {
|
|
276
|
+
userIdExtractor: (user) => user.sub,
|
|
277
|
+
expirationExtractor: (user) => user.exp,
|
|
278
|
+
additionalValidation: additionalScopes
|
|
279
|
+
? (user) => {
|
|
280
|
+
if (!user.scope || !Array.isArray(user.scope)) {
|
|
281
|
+
return false;
|
|
282
|
+
}
|
|
283
|
+
return additionalScopes.every((requiredScope) => user.scope.includes(requiredScope));
|
|
284
|
+
}
|
|
285
|
+
: undefined,
|
|
286
|
+
});
|
|
287
|
+
}
|
|
288
|
+
/**
|
|
289
|
+
* Create adapter with custom configuration.
|
|
290
|
+
* Use this for non-standard token structures or complex validation logic.
|
|
291
|
+
*
|
|
292
|
+
* @param verificationPort - Token verification port
|
|
293
|
+
* @param config - Custom adapter configuration
|
|
294
|
+
* @returns Configured adapter with custom settings
|
|
295
|
+
*/
|
|
296
|
+
static custom(verificationPort, config) {
|
|
297
|
+
return new CustomTokenVerificationPortAdapter(verificationPort, config);
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
exports.TokenVerificationAdapterFactory = TokenVerificationAdapterFactory;
|
|
301
|
+
//# sourceMappingURL=CustomTokenVerificationPortAdapter.js.map
|
|
@@ -607,6 +607,56 @@ export declare class GuardConfiguration {
|
|
|
607
607
|
* // defaultTtlMs must be at least 1000ms (1 second)
|
|
608
608
|
* ```
|
|
609
609
|
*/
|
|
610
|
+
/**
|
|
611
|
+
* Check if caching is enabled via environment variable.
|
|
612
|
+
*
|
|
613
|
+
* Caching is disabled by default for security-first approach.
|
|
614
|
+
* Only enabled when NOONY_GUARD_CACHE_ENABLE is explicitly set to 'true'.
|
|
615
|
+
*
|
|
616
|
+
* @returns true if caching should be enabled, false otherwise
|
|
617
|
+
*
|
|
618
|
+
* @example
|
|
619
|
+
* ```typescript
|
|
620
|
+
* // Caching disabled (default)
|
|
621
|
+
* process.env.NOONY_GUARD_CACHE_ENABLE = undefined;
|
|
622
|
+
* console.log(GuardConfiguration.isCachingEnabled()); // false
|
|
623
|
+
*
|
|
624
|
+
* // Caching enabled
|
|
625
|
+
* process.env.NOONY_GUARD_CACHE_ENABLE = 'true';
|
|
626
|
+
* console.log(GuardConfiguration.isCachingEnabled()); // true
|
|
627
|
+
*
|
|
628
|
+
* // Caching disabled (any other value)
|
|
629
|
+
* process.env.NOONY_GUARD_CACHE_ENABLE = 'false';
|
|
630
|
+
* console.log(GuardConfiguration.isCachingEnabled()); // false
|
|
631
|
+
* ```
|
|
632
|
+
*/
|
|
633
|
+
static isCachingEnabled(): boolean;
|
|
634
|
+
/**
|
|
635
|
+
* Get effective cache type considering environment variable override.
|
|
636
|
+
*
|
|
637
|
+
* Environment variable takes precedence for security:
|
|
638
|
+
* - If NOONY_GUARD_CACHE_ENABLE is not 'true', returns 'none'
|
|
639
|
+
* - Otherwise returns the specified cacheType
|
|
640
|
+
*
|
|
641
|
+
* @param cacheType - Configured cache type
|
|
642
|
+
* @returns Effective cache type after environment variable consideration
|
|
643
|
+
*
|
|
644
|
+
* @example
|
|
645
|
+
* ```typescript
|
|
646
|
+
* // Environment variable not set - caching disabled
|
|
647
|
+
* process.env.NOONY_GUARD_CACHE_ENABLE = undefined;
|
|
648
|
+
* console.log(GuardConfiguration.getEffectiveCacheType('memory')); // 'none'
|
|
649
|
+
* console.log(GuardConfiguration.getEffectiveCacheType('redis')); // 'none'
|
|
650
|
+
* console.log(GuardConfiguration.getEffectiveCacheType('none')); // 'none'
|
|
651
|
+
*
|
|
652
|
+
* // Environment variable enabled - respect cacheType
|
|
653
|
+
* process.env.NOONY_GUARD_CACHE_ENABLE = 'true';
|
|
654
|
+
* console.log(GuardConfiguration.getEffectiveCacheType('memory')); // 'memory'
|
|
655
|
+
* console.log(GuardConfiguration.getEffectiveCacheType('redis')); // 'redis'
|
|
656
|
+
* console.log(GuardConfiguration.getEffectiveCacheType('none')); // 'none'
|
|
657
|
+
* ```
|
|
658
|
+
*/
|
|
659
|
+
static getEffectiveCacheType(cacheType: 'memory' | 'redis' | 'none'): 'memory' | 'redis' | 'none';
|
|
610
660
|
validate(): void;
|
|
611
661
|
}
|
|
612
662
|
//# sourceMappingURL=GuardConfiguration.d.ts.map
|
|
@@ -312,6 +312,65 @@ class GuardConfiguration {
|
|
|
312
312
|
* // defaultTtlMs must be at least 1000ms (1 second)
|
|
313
313
|
* ```
|
|
314
314
|
*/
|
|
315
|
+
/**
|
|
316
|
+
* Check if caching is enabled via environment variable.
|
|
317
|
+
*
|
|
318
|
+
* Caching is disabled by default for security-first approach.
|
|
319
|
+
* Only enabled when NOONY_GUARD_CACHE_ENABLE is explicitly set to 'true'.
|
|
320
|
+
*
|
|
321
|
+
* @returns true if caching should be enabled, false otherwise
|
|
322
|
+
*
|
|
323
|
+
* @example
|
|
324
|
+
* ```typescript
|
|
325
|
+
* // Caching disabled (default)
|
|
326
|
+
* process.env.NOONY_GUARD_CACHE_ENABLE = undefined;
|
|
327
|
+
* console.log(GuardConfiguration.isCachingEnabled()); // false
|
|
328
|
+
*
|
|
329
|
+
* // Caching enabled
|
|
330
|
+
* process.env.NOONY_GUARD_CACHE_ENABLE = 'true';
|
|
331
|
+
* console.log(GuardConfiguration.isCachingEnabled()); // true
|
|
332
|
+
*
|
|
333
|
+
* // Caching disabled (any other value)
|
|
334
|
+
* process.env.NOONY_GUARD_CACHE_ENABLE = 'false';
|
|
335
|
+
* console.log(GuardConfiguration.isCachingEnabled()); // false
|
|
336
|
+
* ```
|
|
337
|
+
*/
|
|
338
|
+
static isCachingEnabled() {
|
|
339
|
+
return process.env.NOONY_GUARD_CACHE_ENABLE === 'true';
|
|
340
|
+
}
|
|
341
|
+
/**
|
|
342
|
+
* Get effective cache type considering environment variable override.
|
|
343
|
+
*
|
|
344
|
+
* Environment variable takes precedence for security:
|
|
345
|
+
* - If NOONY_GUARD_CACHE_ENABLE is not 'true', returns 'none'
|
|
346
|
+
* - Otherwise returns the specified cacheType
|
|
347
|
+
*
|
|
348
|
+
* @param cacheType - Configured cache type
|
|
349
|
+
* @returns Effective cache type after environment variable consideration
|
|
350
|
+
*
|
|
351
|
+
* @example
|
|
352
|
+
* ```typescript
|
|
353
|
+
* // Environment variable not set - caching disabled
|
|
354
|
+
* process.env.NOONY_GUARD_CACHE_ENABLE = undefined;
|
|
355
|
+
* console.log(GuardConfiguration.getEffectiveCacheType('memory')); // 'none'
|
|
356
|
+
* console.log(GuardConfiguration.getEffectiveCacheType('redis')); // 'none'
|
|
357
|
+
* console.log(GuardConfiguration.getEffectiveCacheType('none')); // 'none'
|
|
358
|
+
*
|
|
359
|
+
* // Environment variable enabled - respect cacheType
|
|
360
|
+
* process.env.NOONY_GUARD_CACHE_ENABLE = 'true';
|
|
361
|
+
* console.log(GuardConfiguration.getEffectiveCacheType('memory')); // 'memory'
|
|
362
|
+
* console.log(GuardConfiguration.getEffectiveCacheType('redis')); // 'redis'
|
|
363
|
+
* console.log(GuardConfiguration.getEffectiveCacheType('none')); // 'none'
|
|
364
|
+
* ```
|
|
365
|
+
*/
|
|
366
|
+
static getEffectiveCacheType(cacheType) {
|
|
367
|
+
// If caching is disabled by environment variable, always return 'none'
|
|
368
|
+
if (!GuardConfiguration.isCachingEnabled()) {
|
|
369
|
+
return 'none';
|
|
370
|
+
}
|
|
371
|
+
// Otherwise return the specified cache type
|
|
372
|
+
return cacheType;
|
|
373
|
+
}
|
|
315
374
|
validate() {
|
|
316
375
|
if (this.security.maxPatternDepth !== undefined &&
|
|
317
376
|
(this.security.maxPatternDepth < 2 || this.security.maxPatternDepth > 3)) {
|
|
@@ -43,7 +43,7 @@ export interface AuthenticationResult {
|
|
|
43
43
|
success: boolean;
|
|
44
44
|
user?: UserContext;
|
|
45
45
|
token?: {
|
|
46
|
-
decoded:
|
|
46
|
+
decoded: unknown;
|
|
47
47
|
raw: string;
|
|
48
48
|
expiresAt: string;
|
|
49
49
|
issuer?: string;
|
|
@@ -63,7 +63,7 @@ export interface AuthGuardConfig {
|
|
|
63
63
|
allowedIssuers?: string[];
|
|
64
64
|
requireEmailVerification: boolean;
|
|
65
65
|
allowInactiveUsers: boolean;
|
|
66
|
-
customValidation?: (token:
|
|
66
|
+
customValidation?: (token: unknown, user: UserContext) => Promise<boolean>;
|
|
67
67
|
}
|
|
68
68
|
/**
|
|
69
69
|
* Token validation service interface
|
|
@@ -74,17 +74,17 @@ export interface TokenValidator {
|
|
|
74
74
|
*/
|
|
75
75
|
validateToken(token: string): Promise<{
|
|
76
76
|
valid: boolean;
|
|
77
|
-
decoded?:
|
|
77
|
+
decoded?: unknown;
|
|
78
78
|
error?: string;
|
|
79
79
|
}>;
|
|
80
80
|
/**
|
|
81
81
|
* Extract user ID from decoded token
|
|
82
82
|
*/
|
|
83
|
-
extractUserId(decoded:
|
|
83
|
+
extractUserId(decoded: unknown): string;
|
|
84
84
|
/**
|
|
85
85
|
* Check if token is expired
|
|
86
86
|
*/
|
|
87
|
-
isTokenExpired(decoded:
|
|
87
|
+
isTokenExpired(decoded: unknown): boolean;
|
|
88
88
|
}
|
|
89
89
|
/**
|
|
90
90
|
* Fast Authentication Guard Implementation
|
|
@@ -39,7 +39,7 @@ import { PermissionResolverType, PermissionCheckResult, PermissionExpression } f
|
|
|
39
39
|
*/
|
|
40
40
|
export interface GuardConfig {
|
|
41
41
|
requireAuth: boolean;
|
|
42
|
-
permissions:
|
|
42
|
+
permissions: string | string[] | PermissionExpression | Record<string, unknown>;
|
|
43
43
|
resolverType?: PermissionResolverType;
|
|
44
44
|
cacheResults: boolean;
|
|
45
45
|
auditTrail: boolean;
|
|
@@ -141,7 +141,7 @@ export declare class PermissionGuardFactory {
|
|
|
141
141
|
* @returns Composite permission guard instance
|
|
142
142
|
*/
|
|
143
143
|
createCompositeGuard(requirements: Array<{
|
|
144
|
-
permissions:
|
|
144
|
+
permissions: string | string[] | PermissionExpression | Record<string, unknown>;
|
|
145
145
|
resolverType: PermissionResolverType;
|
|
146
146
|
required: boolean;
|
|
147
147
|
}>, config?: Partial<GuardConfig>): BasePermissionGuard;
|
|
@@ -155,23 +155,15 @@ export declare class PermissionGuardFactory {
|
|
|
155
155
|
* @param config - Optional guard configuration
|
|
156
156
|
* @returns Optimally configured permission guard
|
|
157
157
|
*/
|
|
158
|
-
createAutoGuard(permissions:
|
|
158
|
+
createAutoGuard(permissions: string | string[] | PermissionExpression | Record<string, unknown>, config?: Partial<GuardConfig>): BasePermissionGuard;
|
|
159
159
|
/**
|
|
160
160
|
* Get factory statistics
|
|
161
161
|
*/
|
|
162
162
|
getStats(): {
|
|
163
163
|
totalGuards: number;
|
|
164
164
|
guardsByType: Record<string, number>;
|
|
165
|
-
individualGuardStats:
|
|
166
|
-
|
|
167
|
-
checkCount: number;
|
|
168
|
-
successCount: number;
|
|
169
|
-
failureCount: number;
|
|
170
|
-
successRate: number;
|
|
171
|
-
averageProcessingTimeUs: number;
|
|
172
|
-
totalProcessingTimeUs: number;
|
|
173
|
-
}[];
|
|
174
|
-
aggregatedStats: any;
|
|
165
|
+
individualGuardStats: Record<string, unknown>[];
|
|
166
|
+
aggregatedStats: Record<string, unknown>;
|
|
175
167
|
};
|
|
176
168
|
/**
|
|
177
169
|
* Clear guard cache
|
|
@@ -531,10 +531,10 @@ let PermissionGuardFactory = class PermissionGuardFactory {
|
|
|
531
531
|
};
|
|
532
532
|
}
|
|
533
533
|
const totals = guardStats.reduce((acc, stats) => ({
|
|
534
|
-
checkCount: acc.checkCount + stats.checkCount,
|
|
535
|
-
successCount: acc.successCount + stats.successCount,
|
|
536
|
-
failureCount: acc.failureCount + stats.failureCount,
|
|
537
|
-
totalProcessingTimeUs: acc.totalProcessingTimeUs + stats.totalProcessingTimeUs,
|
|
534
|
+
checkCount: acc.checkCount + (stats.checkCount || 0),
|
|
535
|
+
successCount: acc.successCount + (stats.successCount || 0),
|
|
536
|
+
failureCount: acc.failureCount + (stats.failureCount || 0),
|
|
537
|
+
totalProcessingTimeUs: acc.totalProcessingTimeUs + (stats.totalProcessingTimeUs || 0),
|
|
538
538
|
}), {
|
|
539
539
|
checkCount: 0,
|
|
540
540
|
successCount: 0,
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
* @author Noony Framework Team
|
|
16
16
|
* @version 1.0.0
|
|
17
17
|
*/
|
|
18
|
-
export { RouteGuards, RouteGuardOptions, GuardSystemStats, } from './RouteGuards';
|
|
18
|
+
export { RouteGuards, RouteGuardOptions, GuardSystemStats, AnyTokenValidator, } from './RouteGuards';
|
|
19
19
|
export { GuardConfiguration, GuardEnvironmentProfile, PermissionResolutionStrategy, GuardSecurityConfig, GuardCacheConfig, GuardMonitoringConfig, } from './config/GuardConfiguration';
|
|
20
20
|
export { CacheAdapter, CacheStats, CacheKeyBuilder, } from './cache/CacheAdapter';
|
|
21
21
|
export { MemoryCacheAdapter } from './cache/MemoryCacheAdapter';
|
|
@@ -29,6 +29,7 @@ export { PermissionRegistry } from './registry/PermissionRegistry';
|
|
|
29
29
|
export { FastUserContextService, UserContext, UserPermissionSource, PermissionCheckOptions, } from './services/FastUserContextService';
|
|
30
30
|
export { FastAuthGuard, AuthenticationResult, AuthGuardConfig, TokenValidator, } from './guards/FastAuthGuard';
|
|
31
31
|
export { PermissionGuardFactory, GuardConfig, } from './guards/PermissionGuardFactory';
|
|
32
|
+
export { CustomTokenVerificationPortAdapter, TokenVerificationAdapterFactory, AdapterConfig, } from './adapters/CustomTokenVerificationPortAdapter';
|
|
32
33
|
export declare const GUARD_DEFAULTS: {
|
|
33
34
|
readonly CACHE_TTL_MS: number;
|
|
34
35
|
readonly AUTH_TOKEN_TTL_MS: number;
|
|
@@ -49,18 +50,59 @@ import { GuardEnvironmentProfile } from './config/GuardConfiguration';
|
|
|
49
50
|
export declare class GuardSetup {
|
|
50
51
|
/**
|
|
51
52
|
* Development environment setup
|
|
53
|
+
*
|
|
54
|
+
* Note: Caching is disabled by default unless NOONY_GUARD_CACHE_ENABLE=true is set.
|
|
55
|
+
* Even with cacheType: 'memory', the environment variable takes precedence.
|
|
56
|
+
*
|
|
57
|
+
* @example
|
|
58
|
+
* ```bash
|
|
59
|
+
* # Caching disabled (default)
|
|
60
|
+
* npm run dev
|
|
61
|
+
*
|
|
62
|
+
* # Caching enabled
|
|
63
|
+
* NOONY_GUARD_CACHE_ENABLE=true npm run dev
|
|
64
|
+
* ```
|
|
52
65
|
*/
|
|
53
66
|
static development(): GuardEnvironmentProfile;
|
|
54
67
|
/**
|
|
55
68
|
* Production environment setup
|
|
69
|
+
*
|
|
70
|
+
* Note: Caching is disabled by default unless NOONY_GUARD_CACHE_ENABLE=true is set.
|
|
71
|
+
* This provides a security-first approach where caching must be explicitly enabled.
|
|
72
|
+
*
|
|
73
|
+
* @example
|
|
74
|
+
* ```bash
|
|
75
|
+
* # Production with caching enabled (recommended)
|
|
76
|
+
* NOONY_GUARD_CACHE_ENABLE=true node dist/index.js
|
|
77
|
+
*
|
|
78
|
+
* # Production with caching disabled (debugging/troubleshooting)
|
|
79
|
+
* node dist/index.js
|
|
80
|
+
* ```
|
|
56
81
|
*/
|
|
57
82
|
static production(): GuardEnvironmentProfile;
|
|
58
83
|
/**
|
|
59
84
|
* Serverless environment setup (optimized for cold starts)
|
|
85
|
+
*
|
|
86
|
+
* Note: Caching is disabled by default unless NOONY_GUARD_CACHE_ENABLE=true is set.
|
|
87
|
+
* For serverless environments, consider enabling caching to improve performance
|
|
88
|
+
* across warm invocations.
|
|
89
|
+
*
|
|
90
|
+
* @example
|
|
91
|
+
* ```bash
|
|
92
|
+
* # Serverless with caching enabled (recommended for warm starts)
|
|
93
|
+
* NOONY_GUARD_CACHE_ENABLE=true serverless deploy
|
|
94
|
+
*
|
|
95
|
+
* # Serverless with caching disabled (cold start optimization)
|
|
96
|
+
* serverless deploy
|
|
97
|
+
* ```
|
|
60
98
|
*/
|
|
61
99
|
static serverless(): GuardEnvironmentProfile;
|
|
62
100
|
/**
|
|
63
101
|
* Testing environment setup
|
|
102
|
+
*
|
|
103
|
+
* Note: Uses cacheType: 'none' explicitly, so caching is always disabled
|
|
104
|
+
* regardless of NOONY_GUARD_CACHE_ENABLE environment variable.
|
|
105
|
+
* This ensures predictable test behavior.
|
|
64
106
|
*/
|
|
65
107
|
static testing(): GuardEnvironmentProfile;
|
|
66
108
|
}
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
* @version 1.0.0
|
|
18
18
|
*/
|
|
19
19
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
20
|
-
exports.GuardSetup = exports.PERMISSION_PATTERNS = exports.GUARD_DEFAULTS = exports.PermissionGuardFactory = exports.FastAuthGuard = exports.FastUserContextService = exports.ExpressionPermissionResolver = exports.WildcardPermissionResolver = exports.PlainPermissionResolver = exports.PermissionUtils = exports.PermissionResolverType = exports.PermissionResolver = exports.InvalidationScope = exports.InvalidationType = exports.ConservativeCacheInvalidation = exports.NoopCacheAdapter = exports.MemoryCacheAdapter = exports.CacheKeyBuilder = exports.PermissionResolutionStrategy = exports.GuardConfiguration = exports.RouteGuards = void 0;
|
|
20
|
+
exports.GuardSetup = exports.PERMISSION_PATTERNS = exports.GUARD_DEFAULTS = exports.TokenVerificationAdapterFactory = exports.CustomTokenVerificationPortAdapter = exports.PermissionGuardFactory = exports.FastAuthGuard = exports.FastUserContextService = exports.ExpressionPermissionResolver = exports.WildcardPermissionResolver = exports.PlainPermissionResolver = exports.PermissionUtils = exports.PermissionResolverType = exports.PermissionResolver = exports.InvalidationScope = exports.InvalidationType = exports.ConservativeCacheInvalidation = exports.NoopCacheAdapter = exports.MemoryCacheAdapter = exports.CacheKeyBuilder = exports.PermissionResolutionStrategy = exports.GuardConfiguration = exports.RouteGuards = void 0;
|
|
21
21
|
// Main facade - primary entry point
|
|
22
22
|
var RouteGuards_1 = require("./RouteGuards");
|
|
23
23
|
Object.defineProperty(exports, "RouteGuards", { enumerable: true, get: function () { return RouteGuards_1.RouteGuards; } });
|
|
@@ -55,6 +55,10 @@ var FastAuthGuard_1 = require("./guards/FastAuthGuard");
|
|
|
55
55
|
Object.defineProperty(exports, "FastAuthGuard", { enumerable: true, get: function () { return FastAuthGuard_1.FastAuthGuard; } });
|
|
56
56
|
var PermissionGuardFactory_1 = require("./guards/PermissionGuardFactory");
|
|
57
57
|
Object.defineProperty(exports, "PermissionGuardFactory", { enumerable: true, get: function () { return PermissionGuardFactory_1.PermissionGuardFactory; } });
|
|
58
|
+
// Token verification adapters for integration with AuthenticationMiddleware
|
|
59
|
+
var CustomTokenVerificationPortAdapter_1 = require("./adapters/CustomTokenVerificationPortAdapter");
|
|
60
|
+
Object.defineProperty(exports, "CustomTokenVerificationPortAdapter", { enumerable: true, get: function () { return CustomTokenVerificationPortAdapter_1.CustomTokenVerificationPortAdapter; } });
|
|
61
|
+
Object.defineProperty(exports, "TokenVerificationAdapterFactory", { enumerable: true, get: function () { return CustomTokenVerificationPortAdapter_1.TokenVerificationAdapterFactory; } });
|
|
58
62
|
// Utility types and constants
|
|
59
63
|
exports.GUARD_DEFAULTS = {
|
|
60
64
|
CACHE_TTL_MS: 15 * 60 * 1000, // 15 minutes
|
|
@@ -77,6 +81,18 @@ const GuardConfiguration_2 = require("./config/GuardConfiguration");
|
|
|
77
81
|
class GuardSetup {
|
|
78
82
|
/**
|
|
79
83
|
* Development environment setup
|
|
84
|
+
*
|
|
85
|
+
* Note: Caching is disabled by default unless NOONY_GUARD_CACHE_ENABLE=true is set.
|
|
86
|
+
* Even with cacheType: 'memory', the environment variable takes precedence.
|
|
87
|
+
*
|
|
88
|
+
* @example
|
|
89
|
+
* ```bash
|
|
90
|
+
* # Caching disabled (default)
|
|
91
|
+
* npm run dev
|
|
92
|
+
*
|
|
93
|
+
* # Caching enabled
|
|
94
|
+
* NOONY_GUARD_CACHE_ENABLE=true npm run dev
|
|
95
|
+
* ```
|
|
80
96
|
*/
|
|
81
97
|
static development() {
|
|
82
98
|
return {
|
|
@@ -105,6 +121,18 @@ class GuardSetup {
|
|
|
105
121
|
}
|
|
106
122
|
/**
|
|
107
123
|
* Production environment setup
|
|
124
|
+
*
|
|
125
|
+
* Note: Caching is disabled by default unless NOONY_GUARD_CACHE_ENABLE=true is set.
|
|
126
|
+
* This provides a security-first approach where caching must be explicitly enabled.
|
|
127
|
+
*
|
|
128
|
+
* @example
|
|
129
|
+
* ```bash
|
|
130
|
+
* # Production with caching enabled (recommended)
|
|
131
|
+
* NOONY_GUARD_CACHE_ENABLE=true node dist/index.js
|
|
132
|
+
*
|
|
133
|
+
* # Production with caching disabled (debugging/troubleshooting)
|
|
134
|
+
* node dist/index.js
|
|
135
|
+
* ```
|
|
108
136
|
*/
|
|
109
137
|
static production() {
|
|
110
138
|
return {
|
|
@@ -133,6 +161,19 @@ class GuardSetup {
|
|
|
133
161
|
}
|
|
134
162
|
/**
|
|
135
163
|
* Serverless environment setup (optimized for cold starts)
|
|
164
|
+
*
|
|
165
|
+
* Note: Caching is disabled by default unless NOONY_GUARD_CACHE_ENABLE=true is set.
|
|
166
|
+
* For serverless environments, consider enabling caching to improve performance
|
|
167
|
+
* across warm invocations.
|
|
168
|
+
*
|
|
169
|
+
* @example
|
|
170
|
+
* ```bash
|
|
171
|
+
* # Serverless with caching enabled (recommended for warm starts)
|
|
172
|
+
* NOONY_GUARD_CACHE_ENABLE=true serverless deploy
|
|
173
|
+
*
|
|
174
|
+
* # Serverless with caching disabled (cold start optimization)
|
|
175
|
+
* serverless deploy
|
|
176
|
+
* ```
|
|
136
177
|
*/
|
|
137
178
|
static serverless() {
|
|
138
179
|
return {
|
|
@@ -161,6 +202,10 @@ class GuardSetup {
|
|
|
161
202
|
}
|
|
162
203
|
/**
|
|
163
204
|
* Testing environment setup
|
|
205
|
+
*
|
|
206
|
+
* Note: Uses cacheType: 'none' explicitly, so caching is always disabled
|
|
207
|
+
* regardless of NOONY_GUARD_CACHE_ENABLE environment variable.
|
|
208
|
+
* This ensures predictable test behavior.
|
|
164
209
|
*/
|
|
165
210
|
static testing() {
|
|
166
211
|
return {
|