@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,377 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Wildcard Permission Resolver
|
|
4
|
+
*
|
|
5
|
+
* Configurable permission resolver supporting hierarchical wildcard patterns
|
|
6
|
+
* with two distinct strategies for optimal performance in different scenarios:
|
|
7
|
+
*
|
|
8
|
+
* 1. PRE_EXPANSION Strategy:
|
|
9
|
+
* - Expand wildcards at user context load time
|
|
10
|
+
* - Store expanded permissions in user context
|
|
11
|
+
* - Runtime: O(1) set membership checks (fastest)
|
|
12
|
+
* - Memory: Higher usage due to expanded permission sets
|
|
13
|
+
* - Best for: Production environments with predictable permission sets
|
|
14
|
+
*
|
|
15
|
+
* 2. ON_DEMAND Strategy:
|
|
16
|
+
* - Pattern matching at permission check time
|
|
17
|
+
* - Cache pattern matching results
|
|
18
|
+
* - Runtime: Pattern matching cost with caching benefits
|
|
19
|
+
* - Memory: Lower usage, only caches results
|
|
20
|
+
* - Best for: Development, dynamic permissions, memory-constrained environments
|
|
21
|
+
*
|
|
22
|
+
* Supported Patterns:
|
|
23
|
+
* - 2 levels: "admin.users", "org.reports"
|
|
24
|
+
* - 3 levels: "admin.users.create", "org.reports.view"
|
|
25
|
+
* - Wildcards: "admin.*", "org.reports.*"
|
|
26
|
+
*
|
|
27
|
+
* @author Noony Framework Team
|
|
28
|
+
* @version 1.0.0
|
|
29
|
+
*/
|
|
30
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
31
|
+
exports.WildcardPermissionResolver = void 0;
|
|
32
|
+
const PermissionResolver_1 = require("./PermissionResolver");
|
|
33
|
+
const CacheAdapter_1 = require("../cache/CacheAdapter");
|
|
34
|
+
const GuardConfiguration_1 = require("../config/GuardConfiguration");
|
|
35
|
+
/**
|
|
36
|
+
* Wildcard permission resolver with configurable resolution strategies
|
|
37
|
+
*/
|
|
38
|
+
class WildcardPermissionResolver extends PermissionResolver_1.PermissionResolver {
|
|
39
|
+
strategy;
|
|
40
|
+
permissionRegistry;
|
|
41
|
+
cache;
|
|
42
|
+
maxPatternDepth;
|
|
43
|
+
// Performance tracking
|
|
44
|
+
checkCount = 0;
|
|
45
|
+
totalResolutionTimeUs = 0;
|
|
46
|
+
cacheHits = 0;
|
|
47
|
+
cacheMisses = 0;
|
|
48
|
+
constructor(strategy, permissionRegistry, cache, maxPatternDepth = 3) {
|
|
49
|
+
super();
|
|
50
|
+
this.strategy = strategy;
|
|
51
|
+
this.permissionRegistry = permissionRegistry;
|
|
52
|
+
this.cache = cache;
|
|
53
|
+
this.maxPatternDepth = maxPatternDepth;
|
|
54
|
+
if (maxPatternDepth < 2 || maxPatternDepth > 3) {
|
|
55
|
+
throw new Error('Max pattern depth must be 2 or 3');
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Check if user permissions satisfy wildcard patterns
|
|
60
|
+
*
|
|
61
|
+
* @param userPermissions - Set of user's permissions (may be pre-expanded)
|
|
62
|
+
* @param wildcardPatterns - Array of wildcard patterns to check
|
|
63
|
+
* @returns Promise resolving to true if user matches any pattern
|
|
64
|
+
*/
|
|
65
|
+
async check(userPermissions, wildcardPatterns) {
|
|
66
|
+
const startTime = process.hrtime.bigint();
|
|
67
|
+
try {
|
|
68
|
+
// Validate inputs
|
|
69
|
+
if (!userPermissions || userPermissions.size === 0) {
|
|
70
|
+
return false;
|
|
71
|
+
}
|
|
72
|
+
if (!wildcardPatterns || wildcardPatterns.length === 0) {
|
|
73
|
+
return false;
|
|
74
|
+
}
|
|
75
|
+
// Validate patterns
|
|
76
|
+
for (const pattern of wildcardPatterns) {
|
|
77
|
+
if (!this.isValidWildcardPattern(pattern)) {
|
|
78
|
+
throw new Error(`Invalid wildcard pattern: ${pattern}`);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
// Route to appropriate strategy
|
|
82
|
+
if (this.strategy === GuardConfiguration_1.PermissionResolutionStrategy.PRE_EXPANSION) {
|
|
83
|
+
return await this.checkPreExpanded(userPermissions, wildcardPatterns);
|
|
84
|
+
}
|
|
85
|
+
else {
|
|
86
|
+
return await this.checkOnDemand(userPermissions, wildcardPatterns);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
finally {
|
|
90
|
+
// Track performance metrics
|
|
91
|
+
const endTime = process.hrtime.bigint();
|
|
92
|
+
const resolutionTimeUs = Number(endTime - startTime) / 1000;
|
|
93
|
+
this.checkCount++;
|
|
94
|
+
this.totalResolutionTimeUs += resolutionTimeUs;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Pre-expansion strategy: O(1) set membership checks
|
|
99
|
+
*
|
|
100
|
+
* Assumes user permissions have been pre-expanded to include all
|
|
101
|
+
* concrete permissions that match wildcard patterns in their roles.
|
|
102
|
+
* This provides the fastest runtime performance.
|
|
103
|
+
*/
|
|
104
|
+
async checkPreExpanded(userPermissions, wildcardPatterns) {
|
|
105
|
+
// For pre-expanded permissions, we check both:
|
|
106
|
+
// 1. Exact pattern matches (if user was granted the wildcard directly)
|
|
107
|
+
// 2. Concrete permission matches (if user has specific permissions)
|
|
108
|
+
for (const pattern of wildcardPatterns) {
|
|
109
|
+
// Check if user has the wildcard permission directly
|
|
110
|
+
if (userPermissions.has(pattern)) {
|
|
111
|
+
return true;
|
|
112
|
+
}
|
|
113
|
+
// If it's a wildcard pattern, check for any matching concrete permissions
|
|
114
|
+
if (pattern.includes('*')) {
|
|
115
|
+
const concretePermissions = this.permissionRegistry.getMatchingPermissions(pattern);
|
|
116
|
+
for (const concretePermission of concretePermissions) {
|
|
117
|
+
if (userPermissions.has(concretePermission)) {
|
|
118
|
+
return true;
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
return false;
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* On-demand strategy: Pattern matching with caching
|
|
127
|
+
*
|
|
128
|
+
* Performs pattern matching at runtime but caches results to avoid
|
|
129
|
+
* repeated pattern matching for the same user/pattern combinations.
|
|
130
|
+
*/
|
|
131
|
+
async checkOnDemand(userPermissions, wildcardPatterns) {
|
|
132
|
+
// Create cache key for this specific check
|
|
133
|
+
const userPermissionArray = Array.from(userPermissions).sort();
|
|
134
|
+
const cacheKey = CacheAdapter_1.CacheKeyBuilder.wildcardPattern(wildcardPatterns, userPermissionArray);
|
|
135
|
+
// Check cache first
|
|
136
|
+
const cachedResult = await this.cache.get(cacheKey);
|
|
137
|
+
if (cachedResult !== null) {
|
|
138
|
+
this.cacheHits++;
|
|
139
|
+
return cachedResult;
|
|
140
|
+
}
|
|
141
|
+
this.cacheMisses++;
|
|
142
|
+
// Perform pattern matching
|
|
143
|
+
let result = false;
|
|
144
|
+
for (const pattern of wildcardPatterns) {
|
|
145
|
+
if (this.matchesAnyUserPermission(userPermissions, pattern)) {
|
|
146
|
+
result = true;
|
|
147
|
+
break; // Short-circuit on first match
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
// Cache the result for 1 minute (configurable)
|
|
151
|
+
await this.cache.set(cacheKey, result, 60 * 1000);
|
|
152
|
+
return result;
|
|
153
|
+
}
|
|
154
|
+
/**
|
|
155
|
+
* Check if any user permission matches the given pattern
|
|
156
|
+
*/
|
|
157
|
+
matchesAnyUserPermission(userPermissions, pattern) {
|
|
158
|
+
// Direct exact match
|
|
159
|
+
if (userPermissions.has(pattern)) {
|
|
160
|
+
return true;
|
|
161
|
+
}
|
|
162
|
+
// If not a wildcard pattern, no further matching needed
|
|
163
|
+
if (!pattern.includes('*')) {
|
|
164
|
+
return false;
|
|
165
|
+
}
|
|
166
|
+
// Pattern matching for wildcard
|
|
167
|
+
for (const userPermission of userPermissions) {
|
|
168
|
+
if (PermissionResolver_1.PermissionUtils.matchesWildcard(userPermission, pattern)) {
|
|
169
|
+
return true;
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
return false;
|
|
173
|
+
}
|
|
174
|
+
/**
|
|
175
|
+
* Expand wildcard patterns to concrete permissions
|
|
176
|
+
*
|
|
177
|
+
* Used by the user context service when pre-expansion strategy is enabled.
|
|
178
|
+
* Converts wildcard patterns to all matching concrete permissions.
|
|
179
|
+
*
|
|
180
|
+
* @param patterns - Array of wildcard patterns
|
|
181
|
+
* @returns Set of concrete permissions
|
|
182
|
+
*/
|
|
183
|
+
async expandWildcardPatterns(patterns) {
|
|
184
|
+
const expandedPermissions = new Set();
|
|
185
|
+
for (const pattern of patterns) {
|
|
186
|
+
if (!this.isValidWildcardPattern(pattern)) {
|
|
187
|
+
throw new Error(`Invalid wildcard pattern: ${pattern}`);
|
|
188
|
+
}
|
|
189
|
+
if (pattern.includes('*')) {
|
|
190
|
+
// Expand wildcard to concrete permissions
|
|
191
|
+
const concretePermissions = this.permissionRegistry.getMatchingPermissions(pattern);
|
|
192
|
+
concretePermissions.forEach((permission) => expandedPermissions.add(permission));
|
|
193
|
+
}
|
|
194
|
+
else {
|
|
195
|
+
// Add concrete permission as-is
|
|
196
|
+
expandedPermissions.add(pattern);
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
return expandedPermissions;
|
|
200
|
+
}
|
|
201
|
+
/**
|
|
202
|
+
* Check permissions with detailed result information
|
|
203
|
+
*/
|
|
204
|
+
async checkWithResult(userPermissions, wildcardPatterns) {
|
|
205
|
+
const startTime = process.hrtime.bigint();
|
|
206
|
+
const cached = false;
|
|
207
|
+
const matchedPermissions = [];
|
|
208
|
+
try {
|
|
209
|
+
// Validate inputs
|
|
210
|
+
if (!userPermissions || userPermissions.size === 0) {
|
|
211
|
+
return {
|
|
212
|
+
allowed: false,
|
|
213
|
+
resolverType: this.getType(),
|
|
214
|
+
resolutionTimeUs: 0,
|
|
215
|
+
cached: false,
|
|
216
|
+
reason: 'User has no permissions',
|
|
217
|
+
};
|
|
218
|
+
}
|
|
219
|
+
if (!wildcardPatterns || wildcardPatterns.length === 0) {
|
|
220
|
+
return {
|
|
221
|
+
allowed: false,
|
|
222
|
+
resolverType: this.getType(),
|
|
223
|
+
resolutionTimeUs: 0,
|
|
224
|
+
cached: false,
|
|
225
|
+
reason: 'No patterns specified',
|
|
226
|
+
};
|
|
227
|
+
}
|
|
228
|
+
// Find all matching patterns/permissions
|
|
229
|
+
for (const pattern of wildcardPatterns) {
|
|
230
|
+
if (!this.isValidWildcardPattern(pattern)) {
|
|
231
|
+
throw new Error(`Invalid wildcard pattern: ${pattern}`);
|
|
232
|
+
}
|
|
233
|
+
if (this.strategy === GuardConfiguration_1.PermissionResolutionStrategy.PRE_EXPANSION) {
|
|
234
|
+
// Check pre-expanded permissions
|
|
235
|
+
if (userPermissions.has(pattern)) {
|
|
236
|
+
matchedPermissions.push(pattern);
|
|
237
|
+
}
|
|
238
|
+
else if (pattern.includes('*')) {
|
|
239
|
+
const concretePermissions = this.permissionRegistry.getMatchingPermissions(pattern);
|
|
240
|
+
for (const concretePermission of concretePermissions) {
|
|
241
|
+
if (userPermissions.has(concretePermission)) {
|
|
242
|
+
matchedPermissions.push(concretePermission);
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
else {
|
|
248
|
+
// On-demand pattern matching
|
|
249
|
+
if (this.matchesAnyUserPermission(userPermissions, pattern)) {
|
|
250
|
+
matchedPermissions.push(pattern);
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
const allowed = matchedPermissions.length > 0;
|
|
255
|
+
const endTime = process.hrtime.bigint();
|
|
256
|
+
const resolutionTimeUs = Number(endTime - startTime) / 1000;
|
|
257
|
+
return {
|
|
258
|
+
allowed,
|
|
259
|
+
resolverType: this.getType(),
|
|
260
|
+
resolutionTimeUs,
|
|
261
|
+
cached,
|
|
262
|
+
reason: allowed
|
|
263
|
+
? undefined
|
|
264
|
+
: `No matching patterns: ${wildcardPatterns.join(', ')}`,
|
|
265
|
+
matchedPermissions: allowed ? matchedPermissions : undefined,
|
|
266
|
+
};
|
|
267
|
+
}
|
|
268
|
+
catch (error) {
|
|
269
|
+
const endTime = process.hrtime.bigint();
|
|
270
|
+
const resolutionTimeUs = Number(endTime - startTime) / 1000;
|
|
271
|
+
return {
|
|
272
|
+
allowed: false,
|
|
273
|
+
resolverType: this.getType(),
|
|
274
|
+
resolutionTimeUs,
|
|
275
|
+
cached,
|
|
276
|
+
reason: error instanceof Error ? error.message : 'Unknown error',
|
|
277
|
+
};
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
/**
|
|
281
|
+
* Validate wildcard pattern format
|
|
282
|
+
*/
|
|
283
|
+
isValidWildcardPattern(pattern) {
|
|
284
|
+
if (!pattern || typeof pattern !== 'string') {
|
|
285
|
+
return false;
|
|
286
|
+
}
|
|
287
|
+
// Check basic permission format first
|
|
288
|
+
if (!PermissionResolver_1.PermissionUtils.isValidPermission(pattern)) {
|
|
289
|
+
return false;
|
|
290
|
+
}
|
|
291
|
+
// Count depth levels
|
|
292
|
+
const parts = pattern.split('.');
|
|
293
|
+
if (parts.length < 2 || parts.length > this.maxPatternDepth) {
|
|
294
|
+
return false;
|
|
295
|
+
}
|
|
296
|
+
// If contains wildcard, it should be at the end
|
|
297
|
+
if (pattern.includes('*')) {
|
|
298
|
+
if (!pattern.endsWith('*') ||
|
|
299
|
+
pattern.indexOf('*') !== pattern.length - 1) {
|
|
300
|
+
return false;
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
return true;
|
|
304
|
+
}
|
|
305
|
+
/**
|
|
306
|
+
* Get resolver type for identification
|
|
307
|
+
*/
|
|
308
|
+
getType() {
|
|
309
|
+
return PermissionResolver_1.PermissionResolverType.WILDCARD;
|
|
310
|
+
}
|
|
311
|
+
/**
|
|
312
|
+
* Get performance characteristics for monitoring
|
|
313
|
+
*/
|
|
314
|
+
getPerformanceCharacteristics() {
|
|
315
|
+
const isPreExpansion = this.strategy === GuardConfiguration_1.PermissionResolutionStrategy.PRE_EXPANSION;
|
|
316
|
+
return {
|
|
317
|
+
timeComplexity: isPreExpansion
|
|
318
|
+
? 'O(1) per pattern'
|
|
319
|
+
: 'O(n*m) with caching',
|
|
320
|
+
memoryUsage: isPreExpansion ? 'high' : 'medium',
|
|
321
|
+
cacheUtilization: isPreExpansion ? 'none' : 'high',
|
|
322
|
+
recommendedFor: isPreExpansion
|
|
323
|
+
? [
|
|
324
|
+
'Production environments',
|
|
325
|
+
'Predictable permission sets',
|
|
326
|
+
'Maximum performance',
|
|
327
|
+
]
|
|
328
|
+
: [
|
|
329
|
+
'Development environments',
|
|
330
|
+
'Dynamic permissions',
|
|
331
|
+
'Memory-constrained scenarios',
|
|
332
|
+
],
|
|
333
|
+
};
|
|
334
|
+
}
|
|
335
|
+
/**
|
|
336
|
+
* Get performance statistics
|
|
337
|
+
*/
|
|
338
|
+
getStats() {
|
|
339
|
+
const totalCacheRequests = this.cacheHits + this.cacheMisses;
|
|
340
|
+
return {
|
|
341
|
+
strategy: this.strategy,
|
|
342
|
+
checkCount: this.checkCount,
|
|
343
|
+
averageResolutionTimeUs: this.checkCount > 0 ? this.totalResolutionTimeUs / this.checkCount : 0,
|
|
344
|
+
totalResolutionTimeUs: this.totalResolutionTimeUs,
|
|
345
|
+
cacheHitRate: totalCacheRequests > 0
|
|
346
|
+
? (this.cacheHits / totalCacheRequests) * 100
|
|
347
|
+
: 0,
|
|
348
|
+
cacheHits: this.cacheHits,
|
|
349
|
+
cacheMisses: this.cacheMisses,
|
|
350
|
+
};
|
|
351
|
+
}
|
|
352
|
+
/**
|
|
353
|
+
* Reset performance statistics
|
|
354
|
+
*/
|
|
355
|
+
resetStats() {
|
|
356
|
+
this.checkCount = 0;
|
|
357
|
+
this.totalResolutionTimeUs = 0;
|
|
358
|
+
this.cacheHits = 0;
|
|
359
|
+
this.cacheMisses = 0;
|
|
360
|
+
}
|
|
361
|
+
/**
|
|
362
|
+
* Get resolver name for debugging
|
|
363
|
+
*/
|
|
364
|
+
getName() {
|
|
365
|
+
return `WildcardPermissionResolver(${this.strategy})`;
|
|
366
|
+
}
|
|
367
|
+
/**
|
|
368
|
+
* Check if this resolver can handle the given requirement type
|
|
369
|
+
*/
|
|
370
|
+
canHandle(requirement) {
|
|
371
|
+
return (Array.isArray(requirement) &&
|
|
372
|
+
requirement.length > 0 &&
|
|
373
|
+
requirement.every((item) => typeof item === 'string' && this.isValidWildcardPattern(item)));
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
exports.WildcardPermissionResolver = WildcardPermissionResolver;
|
|
377
|
+
//# sourceMappingURL=WildcardPermissionResolver.js.map
|
|
@@ -0,0 +1,216 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Fast User Context Service
|
|
3
|
+
*
|
|
4
|
+
* High-performance user context management with configurable permission resolution.
|
|
5
|
+
* This service orchestrates the permission resolution strategies, manages caching,
|
|
6
|
+
* and provides sub-millisecond user permission checks for serverless environments.
|
|
7
|
+
*
|
|
8
|
+
* Key Features:
|
|
9
|
+
* - Configurable permission resolution (pre-expansion vs on-demand)
|
|
10
|
+
* - Multi-layer caching (L1 memory + L2 distributed)
|
|
11
|
+
* - Conservative cache invalidation for security
|
|
12
|
+
* - Permission expansion and validation
|
|
13
|
+
* - Performance monitoring and metrics
|
|
14
|
+
* - TypeDI integration for dependency injection
|
|
15
|
+
*
|
|
16
|
+
* Architecture:
|
|
17
|
+
* - Uses strategy pattern for different resolution approaches
|
|
18
|
+
* - Implements repository pattern for user context storage
|
|
19
|
+
* - Follows single responsibility principle with focused methods
|
|
20
|
+
* - Provides comprehensive error handling and logging
|
|
21
|
+
*
|
|
22
|
+
* @author Noony Framework Team
|
|
23
|
+
* @version 1.0.0
|
|
24
|
+
*/
|
|
25
|
+
import { CacheAdapter } from '../cache/CacheAdapter';
|
|
26
|
+
import { GuardConfiguration, PermissionResolutionStrategy } from '../config/GuardConfiguration';
|
|
27
|
+
import { PermissionRegistry } from '../registry/PermissionRegistry';
|
|
28
|
+
import { PermissionResolverType, PermissionCheckResult } from '../resolvers/PermissionResolver';
|
|
29
|
+
/**
|
|
30
|
+
* User context with cached permissions and metadata
|
|
31
|
+
*/
|
|
32
|
+
export interface UserContext {
|
|
33
|
+
userId: string;
|
|
34
|
+
permissions: Set<string>;
|
|
35
|
+
roles: string[];
|
|
36
|
+
metadata: Record<string, any>;
|
|
37
|
+
expandedPermissions?: Set<string>;
|
|
38
|
+
lastUpdated: string;
|
|
39
|
+
expiresAt?: string;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* User permission source for loading raw user data
|
|
43
|
+
*/
|
|
44
|
+
export interface UserPermissionSource {
|
|
45
|
+
/**
|
|
46
|
+
* Load user's basic information and permissions
|
|
47
|
+
*/
|
|
48
|
+
getUserPermissions(userId: string): Promise<{
|
|
49
|
+
permissions: string[];
|
|
50
|
+
roles: string[];
|
|
51
|
+
metadata?: Record<string, any>;
|
|
52
|
+
} | null>;
|
|
53
|
+
/**
|
|
54
|
+
* Get role-based permissions for expansion
|
|
55
|
+
*/
|
|
56
|
+
getRolePermissions(roles: string[]): Promise<string[]>;
|
|
57
|
+
/**
|
|
58
|
+
* Check if user context needs refresh
|
|
59
|
+
*/
|
|
60
|
+
isUserContextStale(userId: string, lastUpdated: string): Promise<boolean>;
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Permission check options
|
|
64
|
+
*/
|
|
65
|
+
export interface PermissionCheckOptions {
|
|
66
|
+
resolverType?: PermissionResolverType;
|
|
67
|
+
useCache?: boolean;
|
|
68
|
+
trackMetrics?: boolean;
|
|
69
|
+
auditTrail?: boolean;
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Fast User Context Service Implementation
|
|
73
|
+
*/
|
|
74
|
+
export declare class FastUserContextService {
|
|
75
|
+
private readonly cache;
|
|
76
|
+
private readonly config;
|
|
77
|
+
private readonly permissionSource;
|
|
78
|
+
private readonly _permissionRegistry;
|
|
79
|
+
private readonly plainResolver;
|
|
80
|
+
private readonly wildcardResolver;
|
|
81
|
+
private readonly expressionResolver;
|
|
82
|
+
private contextLoads;
|
|
83
|
+
private cacheHits;
|
|
84
|
+
private cacheMisses;
|
|
85
|
+
private permissionChecks;
|
|
86
|
+
private totalResolutionTimeUs;
|
|
87
|
+
constructor(cache: CacheAdapter, config: GuardConfiguration, permissionSource: UserPermissionSource, permissionRegistry: PermissionRegistry);
|
|
88
|
+
/**
|
|
89
|
+
* Get or load user context with permissions
|
|
90
|
+
*
|
|
91
|
+
* This is the primary method for retrieving user contexts with caching.
|
|
92
|
+
* It handles both pre-expansion and on-demand permission strategies.
|
|
93
|
+
*
|
|
94
|
+
* @param userId - Unique user identifier
|
|
95
|
+
* @param forceRefresh - Skip cache and force reload
|
|
96
|
+
* @returns User context with permissions or null if user not found
|
|
97
|
+
*/
|
|
98
|
+
getUserContext(userId: string, forceRefresh?: boolean): Promise<UserContext | null>;
|
|
99
|
+
/**
|
|
100
|
+
* Check user permission using appropriate resolver
|
|
101
|
+
*
|
|
102
|
+
* Routes permission checks to the optimal resolver based on requirement type.
|
|
103
|
+
* Provides detailed results including performance metrics and cache status.
|
|
104
|
+
*
|
|
105
|
+
* @param userId - User identifier
|
|
106
|
+
* @param requirement - Permission requirement (string[], wildcard pattern, or expression)
|
|
107
|
+
* @param options - Check options
|
|
108
|
+
* @returns Detailed permission check result
|
|
109
|
+
*/
|
|
110
|
+
checkPermission(userId: string, requirement: any, options?: PermissionCheckOptions): Promise<PermissionCheckResult>;
|
|
111
|
+
/**
|
|
112
|
+
* Batch check multiple permissions for a user
|
|
113
|
+
*
|
|
114
|
+
* Optimized for checking multiple permissions at once.
|
|
115
|
+
* Uses the same user context for all checks to minimize overhead.
|
|
116
|
+
*
|
|
117
|
+
* @param userId - User identifier
|
|
118
|
+
* @param requirements - Array of permission requirements
|
|
119
|
+
* @param options - Check options
|
|
120
|
+
* @returns Array of permission check results
|
|
121
|
+
*/
|
|
122
|
+
checkPermissions(userId: string, requirements: Array<{
|
|
123
|
+
requirement: any;
|
|
124
|
+
resolverType?: PermissionResolverType;
|
|
125
|
+
}>, options?: PermissionCheckOptions): Promise<PermissionCheckResult[]>;
|
|
126
|
+
/**
|
|
127
|
+
* Invalidate user context cache
|
|
128
|
+
*
|
|
129
|
+
* Removes user context from cache when permissions change.
|
|
130
|
+
* Uses conservative approach by also clearing related cached data.
|
|
131
|
+
*
|
|
132
|
+
* @param userId - User identifier
|
|
133
|
+
* @param clearRelated - Also clear permission-related caches
|
|
134
|
+
*/
|
|
135
|
+
invalidateUserContext(userId: string, clearRelated?: boolean): Promise<void>;
|
|
136
|
+
/**
|
|
137
|
+
* Pre-expand wildcard permissions for user context
|
|
138
|
+
*
|
|
139
|
+
* Used when pre-expansion strategy is enabled to convert
|
|
140
|
+
* wildcard permissions to concrete permission sets.
|
|
141
|
+
*
|
|
142
|
+
* @param permissions - Raw permissions from user/roles
|
|
143
|
+
* @returns Expanded permission set
|
|
144
|
+
*/
|
|
145
|
+
expandPermissions(permissions: string[]): Promise<Set<string>>;
|
|
146
|
+
/**
|
|
147
|
+
* Get service performance statistics
|
|
148
|
+
*/
|
|
149
|
+
getStats(): {
|
|
150
|
+
contextLoads: number;
|
|
151
|
+
permissionChecks: number;
|
|
152
|
+
cacheHitRate: number;
|
|
153
|
+
cacheHits: number;
|
|
154
|
+
cacheMisses: number;
|
|
155
|
+
averageResolutionTimeUs: number;
|
|
156
|
+
totalResolutionTimeUs: number;
|
|
157
|
+
resolverStats: {
|
|
158
|
+
plain: {
|
|
159
|
+
checkCount: number;
|
|
160
|
+
averageResolutionTimeUs: number;
|
|
161
|
+
totalResolutionTimeUs: number;
|
|
162
|
+
};
|
|
163
|
+
wildcard: {
|
|
164
|
+
strategy: PermissionResolutionStrategy;
|
|
165
|
+
checkCount: number;
|
|
166
|
+
averageResolutionTimeUs: number;
|
|
167
|
+
totalResolutionTimeUs: number;
|
|
168
|
+
cacheHitRate: number;
|
|
169
|
+
cacheHits: number;
|
|
170
|
+
cacheMisses: number;
|
|
171
|
+
};
|
|
172
|
+
expression: {
|
|
173
|
+
checkCount: number;
|
|
174
|
+
averageResolutionTimeUs: number;
|
|
175
|
+
totalResolutionTimeUs: number;
|
|
176
|
+
cacheHitRate: number;
|
|
177
|
+
cacheHits: number;
|
|
178
|
+
cacheMisses: number;
|
|
179
|
+
complexityDistribution: {
|
|
180
|
+
simple: number;
|
|
181
|
+
moderate: number;
|
|
182
|
+
complex: number;
|
|
183
|
+
};
|
|
184
|
+
};
|
|
185
|
+
};
|
|
186
|
+
};
|
|
187
|
+
/**
|
|
188
|
+
* Reset performance statistics
|
|
189
|
+
*/
|
|
190
|
+
resetStats(): void;
|
|
191
|
+
/**
|
|
192
|
+
* Load user context from cache
|
|
193
|
+
*/
|
|
194
|
+
private loadFromCache;
|
|
195
|
+
/**
|
|
196
|
+
* Save user context to cache
|
|
197
|
+
*/
|
|
198
|
+
private saveToCache;
|
|
199
|
+
/**
|
|
200
|
+
* Build user context from raw user data
|
|
201
|
+
*/
|
|
202
|
+
private buildUserContext;
|
|
203
|
+
/**
|
|
204
|
+
* Select appropriate permission resolver
|
|
205
|
+
*/
|
|
206
|
+
private selectResolver;
|
|
207
|
+
/**
|
|
208
|
+
* Get resolver by type
|
|
209
|
+
*/
|
|
210
|
+
private getResolverByType;
|
|
211
|
+
/**
|
|
212
|
+
* Record audit trail for permission checks
|
|
213
|
+
*/
|
|
214
|
+
private recordAuditTrail;
|
|
215
|
+
}
|
|
216
|
+
//# sourceMappingURL=FastUserContextService.d.ts.map
|