@noony-serverless/core 0.1.0 → 0.1.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.
Files changed (33) hide show
  1. package/build/middlewares/guards/RouteGuards.d.ts +255 -0
  2. package/build/middlewares/guards/RouteGuards.js +500 -0
  3. package/build/middlewares/guards/cache/CacheAdapter.d.ts +132 -0
  4. package/build/middlewares/guards/cache/CacheAdapter.js +86 -0
  5. package/build/middlewares/guards/cache/ConservativeCacheInvalidation.d.ts +191 -0
  6. package/build/middlewares/guards/cache/ConservativeCacheInvalidation.js +510 -0
  7. package/build/middlewares/guards/cache/MemoryCacheAdapter.d.ts +119 -0
  8. package/build/middlewares/guards/cache/MemoryCacheAdapter.js +294 -0
  9. package/build/middlewares/guards/cache/NoopCacheAdapter.d.ts +95 -0
  10. package/build/middlewares/guards/cache/NoopCacheAdapter.js +131 -0
  11. package/build/middlewares/guards/config/GuardConfiguration.d.ts +112 -0
  12. package/build/middlewares/guards/config/GuardConfiguration.js +137 -0
  13. package/build/middlewares/guards/guards/FastAuthGuard.d.ts +201 -0
  14. package/build/middlewares/guards/guards/FastAuthGuard.js +460 -0
  15. package/build/middlewares/guards/guards/PermissionGuardFactory.d.ts +202 -0
  16. package/build/middlewares/guards/guards/PermissionGuardFactory.js +563 -0
  17. package/build/middlewares/guards/index.d.ts +67 -0
  18. package/build/middlewares/guards/index.js +192 -0
  19. package/build/middlewares/guards/registry/PermissionRegistry.d.ts +188 -0
  20. package/build/middlewares/guards/registry/PermissionRegistry.js +425 -0
  21. package/build/middlewares/guards/resolvers/ExpressionPermissionResolver.d.ts +129 -0
  22. package/build/middlewares/guards/resolvers/ExpressionPermissionResolver.js +451 -0
  23. package/build/middlewares/guards/resolvers/PermissionResolver.d.ts +155 -0
  24. package/build/middlewares/guards/resolvers/PermissionResolver.js +176 -0
  25. package/build/middlewares/guards/resolvers/PlainPermissionResolver.d.ts +101 -0
  26. package/build/middlewares/guards/resolvers/PlainPermissionResolver.js +248 -0
  27. package/build/middlewares/guards/resolvers/WildcardPermissionResolver.d.ts +146 -0
  28. package/build/middlewares/guards/resolvers/WildcardPermissionResolver.js +377 -0
  29. package/build/middlewares/guards/services/FastUserContextService.d.ts +216 -0
  30. package/build/middlewares/guards/services/FastUserContextService.js +434 -0
  31. package/build/middlewares/index.d.ts +1 -0
  32. package/build/middlewares/index.js +1 -0
  33. package/package.json +2 -2
@@ -0,0 +1,425 @@
1
+ "use strict";
2
+ /**
3
+ * Permission Registry
4
+ *
5
+ * Central registry for managing available permissions in the system.
6
+ * Supports wildcard pattern expansion, permission discovery, and
7
+ * category-based organization for efficient permission management.
8
+ *
9
+ * Key Features:
10
+ * - Permission registration and discovery
11
+ * - Wildcard pattern expansion ("admin.*" -> ["admin.users", "admin.roles"])
12
+ * - Category-based organization
13
+ * - Thread-safe operations with caching
14
+ * - Auto-discovery from codebase annotations
15
+ * - Permission hierarchy validation
16
+ *
17
+ * @author Noony Framework Team
18
+ * @version 1.0.0
19
+ */
20
+ Object.defineProperty(exports, "__esModule", { value: true });
21
+ exports.PermissionRegistryFactory = exports.DefaultPermissionRegistry = void 0;
22
+ /**
23
+ * Default permission registry implementation
24
+ *
25
+ * Thread-safe in-memory registry with caching for pattern matching.
26
+ * In production, this could be backed by a database or external service.
27
+ */
28
+ class DefaultPermissionRegistry {
29
+ permissions = new Map();
30
+ categoryIndex = new Map();
31
+ patternCache = new Map();
32
+ // Performance tracking
33
+ stats = {
34
+ totalLookups: 0,
35
+ patternMatchingTime: 0,
36
+ cacheHits: 0,
37
+ cacheMisses: 0,
38
+ };
39
+ constructor() {
40
+ // Initialize with common system permissions
41
+ this.initializeSystemPermissions();
42
+ }
43
+ /**
44
+ * Register a permission with metadata
45
+ */
46
+ registerPermission(metadata) {
47
+ // Validate permission format
48
+ if (!this.isValidPermissionFormat(metadata.permission)) {
49
+ throw new Error(`Invalid permission format: ${metadata.permission}`);
50
+ }
51
+ // Check for duplicates
52
+ if (this.permissions.has(metadata.permission)) {
53
+ console.warn(`Permission ${metadata.permission} is already registered`);
54
+ return;
55
+ }
56
+ // Extract category from permission if not provided
57
+ if (!metadata.category) {
58
+ metadata.category = this.extractCategory(metadata.permission);
59
+ }
60
+ // Store permission
61
+ this.permissions.set(metadata.permission, {
62
+ ...metadata,
63
+ registeredAt: new Date(),
64
+ });
65
+ // Update category index
66
+ if (!this.categoryIndex.has(metadata.category)) {
67
+ this.categoryIndex.set(metadata.category, new Set());
68
+ }
69
+ this.categoryIndex.get(metadata.category).add(metadata.permission);
70
+ // Invalidate pattern cache since new permission might affect wildcard matches
71
+ this.patternCache.clear();
72
+ console.debug(`Registered permission: ${metadata.permission} (${metadata.category})`);
73
+ }
74
+ /**
75
+ * Register multiple permissions at once
76
+ */
77
+ registerPermissions(permissions) {
78
+ for (const permission of permissions) {
79
+ this.registerPermission(permission);
80
+ }
81
+ }
82
+ /**
83
+ * Get all permissions matching a wildcard pattern
84
+ */
85
+ getMatchingPermissions(wildcardPattern) {
86
+ const startTime = process.hrtime.bigint();
87
+ this.stats.totalLookups++;
88
+ try {
89
+ // Check cache first
90
+ if (this.patternCache.has(wildcardPattern)) {
91
+ this.stats.cacheHits++;
92
+ return this.patternCache.get(wildcardPattern);
93
+ }
94
+ this.stats.cacheMisses++;
95
+ // Convert wildcard pattern to regex
96
+ const regex = this.wildcardToRegex(wildcardPattern);
97
+ const matchingPermissions = [];
98
+ // Find all matching permissions
99
+ for (const permission of this.permissions.keys()) {
100
+ if (regex.test(permission)) {
101
+ matchingPermissions.push(permission);
102
+ }
103
+ }
104
+ // Cache the result
105
+ this.patternCache.set(wildcardPattern, matchingPermissions);
106
+ return matchingPermissions;
107
+ }
108
+ finally {
109
+ const endTime = process.hrtime.bigint();
110
+ this.stats.patternMatchingTime += Number(endTime - startTime) / 1000; // microseconds
111
+ }
112
+ }
113
+ /**
114
+ * Get all permissions in a category
115
+ */
116
+ getCategoryPermissions(category) {
117
+ const permissions = this.categoryIndex.get(category);
118
+ return permissions ? Array.from(permissions) : [];
119
+ }
120
+ /**
121
+ * Check if a permission exists in the registry
122
+ */
123
+ hasPermission(permission) {
124
+ return this.permissions.has(permission);
125
+ }
126
+ /**
127
+ * Get permission metadata
128
+ */
129
+ getPermissionMetadata(permission) {
130
+ return this.permissions.get(permission) || null;
131
+ }
132
+ /**
133
+ * Get all registered permissions
134
+ */
135
+ getAllPermissions() {
136
+ return Array.from(this.permissions.keys());
137
+ }
138
+ /**
139
+ * Get all categories
140
+ */
141
+ getAllCategories() {
142
+ return Array.from(this.categoryIndex.keys());
143
+ }
144
+ /**
145
+ * Get registry statistics
146
+ */
147
+ getStats() {
148
+ const permissionsByCategory = {};
149
+ const riskLevelDistribution = {};
150
+ const registrationTimeline = [];
151
+ for (const [category, permissions] of this.categoryIndex) {
152
+ permissionsByCategory[category] = permissions.size;
153
+ }
154
+ for (const metadata of this.permissions.values()) {
155
+ riskLevelDistribution[metadata.riskLevel] =
156
+ (riskLevelDistribution[metadata.riskLevel] || 0) + 1;
157
+ registrationTimeline.push(metadata.registeredAt);
158
+ }
159
+ return {
160
+ totalPermissions: this.permissions.size,
161
+ totalCategories: this.categoryIndex.size,
162
+ permissionsByCategory,
163
+ riskLevelDistribution,
164
+ registrationTimeline: registrationTimeline.sort((a, b) => a.getTime() - b.getTime()),
165
+ };
166
+ }
167
+ /**
168
+ * Get performance statistics
169
+ */
170
+ getPerformanceStats() {
171
+ const totalCacheRequests = this.stats.cacheHits + this.stats.cacheMisses;
172
+ return {
173
+ totalLookups: this.stats.totalLookups,
174
+ averagePatternMatchingTimeUs: this.stats.totalLookups > 0
175
+ ? this.stats.patternMatchingTime / this.stats.totalLookups
176
+ : 0,
177
+ cacheHitRate: totalCacheRequests > 0
178
+ ? (this.stats.cacheHits / totalCacheRequests) * 100
179
+ : 0,
180
+ cacheSize: this.patternCache.size,
181
+ };
182
+ }
183
+ /**
184
+ * Clear the pattern cache
185
+ */
186
+ clearCache() {
187
+ this.patternCache.clear();
188
+ }
189
+ /**
190
+ * Initialize common system permissions
191
+ */
192
+ initializeSystemPermissions() {
193
+ const now = new Date();
194
+ const systemPermissions = [
195
+ // User management permissions
196
+ {
197
+ permission: 'user.create',
198
+ description: 'Create new user accounts',
199
+ category: 'user',
200
+ action: 'create',
201
+ riskLevel: 'medium',
202
+ requiresValidation: true,
203
+ registeredAt: now,
204
+ },
205
+ {
206
+ permission: 'user.read',
207
+ description: 'View user information',
208
+ category: 'user',
209
+ action: 'read',
210
+ riskLevel: 'low',
211
+ requiresValidation: false,
212
+ registeredAt: now,
213
+ },
214
+ {
215
+ permission: 'user.update',
216
+ description: 'Update user information',
217
+ category: 'user',
218
+ action: 'update',
219
+ riskLevel: 'medium',
220
+ requiresValidation: true,
221
+ registeredAt: now,
222
+ },
223
+ {
224
+ permission: 'user.delete',
225
+ description: 'Delete user accounts',
226
+ category: 'user',
227
+ action: 'delete',
228
+ riskLevel: 'high',
229
+ requiresValidation: true,
230
+ registeredAt: now,
231
+ },
232
+ {
233
+ permission: 'user.list',
234
+ description: 'List users with filtering',
235
+ category: 'user',
236
+ action: 'list',
237
+ riskLevel: 'low',
238
+ requiresValidation: false,
239
+ registeredAt: now,
240
+ },
241
+ // Admin permissions
242
+ {
243
+ permission: 'admin.users',
244
+ description: 'Full administrative access to user management',
245
+ category: 'admin',
246
+ subCategory: 'users',
247
+ riskLevel: 'critical',
248
+ requiresValidation: true,
249
+ registeredAt: now,
250
+ },
251
+ {
252
+ permission: 'admin.system',
253
+ description: 'System-level administrative access',
254
+ category: 'admin',
255
+ subCategory: 'system',
256
+ riskLevel: 'critical',
257
+ requiresValidation: true,
258
+ registeredAt: now,
259
+ },
260
+ {
261
+ permission: 'admin.monitoring',
262
+ description: 'Access to monitoring and metrics',
263
+ category: 'admin',
264
+ subCategory: 'monitoring',
265
+ riskLevel: 'medium',
266
+ requiresValidation: false,
267
+ registeredAt: now,
268
+ },
269
+ // Organization permissions
270
+ {
271
+ permission: 'organization.view',
272
+ description: 'View organization information',
273
+ category: 'organization',
274
+ action: 'view',
275
+ riskLevel: 'low',
276
+ requiresValidation: false,
277
+ registeredAt: now,
278
+ },
279
+ {
280
+ permission: 'organization.manage',
281
+ description: 'Manage organization settings',
282
+ category: 'organization',
283
+ action: 'manage',
284
+ riskLevel: 'high',
285
+ requiresValidation: true,
286
+ registeredAt: now,
287
+ },
288
+ // Situation report permissions
289
+ {
290
+ permission: 'situation.reports.create',
291
+ description: 'Create situation reports',
292
+ category: 'situation',
293
+ subCategory: 'reports',
294
+ action: 'create',
295
+ riskLevel: 'medium',
296
+ requiresValidation: false,
297
+ registeredAt: now,
298
+ },
299
+ {
300
+ permission: 'situation.reports.view',
301
+ description: 'View situation reports',
302
+ category: 'situation',
303
+ subCategory: 'reports',
304
+ action: 'view',
305
+ riskLevel: 'low',
306
+ requiresValidation: false,
307
+ registeredAt: now,
308
+ },
309
+ {
310
+ permission: 'situation.reports.update',
311
+ description: 'Update situation reports',
312
+ category: 'situation',
313
+ subCategory: 'reports',
314
+ action: 'update',
315
+ riskLevel: 'medium',
316
+ requiresValidation: true,
317
+ registeredAt: now,
318
+ },
319
+ {
320
+ permission: 'situation.reports.delete',
321
+ description: 'Delete situation reports',
322
+ category: 'situation',
323
+ subCategory: 'reports',
324
+ action: 'delete',
325
+ riskLevel: 'high',
326
+ requiresValidation: true,
327
+ registeredAt: now,
328
+ },
329
+ // System permissions
330
+ {
331
+ permission: 'system.health',
332
+ description: 'Access system health information',
333
+ category: 'system',
334
+ action: 'health',
335
+ riskLevel: 'low',
336
+ requiresValidation: false,
337
+ registeredAt: now,
338
+ },
339
+ {
340
+ permission: 'system.metrics',
341
+ description: 'Access system metrics',
342
+ category: 'system',
343
+ action: 'metrics',
344
+ riskLevel: 'low',
345
+ requiresValidation: false,
346
+ registeredAt: now,
347
+ },
348
+ {
349
+ permission: 'system.logs',
350
+ description: 'Access system logs',
351
+ category: 'system',
352
+ action: 'logs',
353
+ riskLevel: 'medium',
354
+ requiresValidation: true,
355
+ registeredAt: now,
356
+ },
357
+ ];
358
+ this.registerPermissions(systemPermissions);
359
+ }
360
+ /**
361
+ * Validate permission format (2-3 levels with alphanumeric + dots)
362
+ */
363
+ isValidPermissionFormat(permission) {
364
+ if (!permission || typeof permission !== 'string') {
365
+ return false;
366
+ }
367
+ // Allow both concrete permissions and wildcard patterns
368
+ const validPattern = /^[a-zA-Z0-9-]+(\.[a-zA-Z0-9-]+){1,2}$/;
369
+ const wildcardPattern = /^[a-zA-Z0-9-]+(\.[a-zA-Z0-9-]+)*\.\*$/;
370
+ return validPattern.test(permission) || wildcardPattern.test(permission);
371
+ }
372
+ /**
373
+ * Extract category from permission string
374
+ */
375
+ extractCategory(permission) {
376
+ const parts = permission.split('.');
377
+ return parts[0] || 'unknown';
378
+ }
379
+ /**
380
+ * Convert wildcard pattern to regex
381
+ */
382
+ wildcardToRegex(wildcardPattern) {
383
+ if (!wildcardPattern.includes('*')) {
384
+ // Exact match for non-wildcard patterns
385
+ return new RegExp(`^${wildcardPattern.replace(/\./g, '\\.')}$`);
386
+ }
387
+ // Convert wildcard pattern to regex
388
+ // "admin.*" becomes /^admin\..*$/
389
+ // "admin.users.*" becomes /^admin\.users\..*$/
390
+ const regexPattern = wildcardPattern
391
+ .replace(/\./g, '\\.') // Escape dots
392
+ .replace(/\*/g, '.*'); // Replace * with any characters
393
+ return new RegExp(`^${regexPattern}$`);
394
+ }
395
+ }
396
+ exports.DefaultPermissionRegistry = DefaultPermissionRegistry;
397
+ /**
398
+ * Factory for creating permission registries
399
+ */
400
+ class PermissionRegistryFactory {
401
+ /**
402
+ * Create a default permission registry with system permissions
403
+ */
404
+ static createDefault() {
405
+ return new DefaultPermissionRegistry();
406
+ }
407
+ /**
408
+ * Create an empty permission registry
409
+ */
410
+ static createEmpty() {
411
+ const registry = new DefaultPermissionRegistry();
412
+ // Clear system permissions if needed for testing
413
+ return registry;
414
+ }
415
+ /**
416
+ * Create a registry from a permission definition file
417
+ */
418
+ static createFromDefinitions(definitions) {
419
+ const registry = new DefaultPermissionRegistry();
420
+ registry.registerPermissions(definitions);
421
+ return registry;
422
+ }
423
+ }
424
+ exports.PermissionRegistryFactory = PermissionRegistryFactory;
425
+ //# sourceMappingURL=PermissionRegistry.js.map
@@ -0,0 +1,129 @@
1
+ /**
2
+ * Expression Permission Resolver
3
+ *
4
+ * Advanced permission resolver supporting complex boolean expressions with
5
+ * AND, OR, and NOT operations. Limited to 2-level nesting to prevent
6
+ * performance degradation while maintaining flexibility for complex
7
+ * authorization scenarios.
8
+ *
9
+ * Supported Expression Structure:
10
+ * - Leaf permissions: { permission: "admin.users" }
11
+ * - AND operations: { and: [expr1, expr2, ...] }
12
+ * - OR operations: { or: [expr1, expr2, ...] }
13
+ * - NOT operations: { not: expr }
14
+ * - Maximum 2-level nesting depth
15
+ *
16
+ * Performance Features:
17
+ * - Result caching for expensive expression evaluations
18
+ * - Short-circuit evaluation (AND stops at first false, OR stops at first true)
19
+ * - Expression normalization for consistent cache keys
20
+ * - Performance metrics and monitoring
21
+ *
22
+ * Example Expressions:
23
+ * ```
24
+ * // Simple OR: user needs admin OR manager role
25
+ * { or: [{ permission: "admin.platform" }, { permission: "role.manager" }] }
26
+ *
27
+ * // Complex AND/OR: (admin OR (manager AND finance))
28
+ * {
29
+ * or: [
30
+ * { permission: "admin.platform" },
31
+ * { and: [{ permission: "role.manager" }, { permission: "department.finance" }] }
32
+ * ]
33
+ * }
34
+ * ```
35
+ *
36
+ * @author Noony Framework Team
37
+ * @version 1.0.0
38
+ */
39
+ import { PermissionResolver, PermissionResolverType, PerformanceCharacteristics, PermissionCheckResult, PermissionExpression } from './PermissionResolver';
40
+ import { CacheAdapter } from '../cache/CacheAdapter';
41
+ /**
42
+ * Expression permission resolver for complex boolean logic
43
+ */
44
+ export declare class ExpressionPermissionResolver extends PermissionResolver<PermissionExpression> {
45
+ private readonly cache;
46
+ private readonly maxNestingDepth;
47
+ private checkCount;
48
+ private totalResolutionTimeUs;
49
+ private cacheHits;
50
+ private cacheMisses;
51
+ private expressionComplexityStats;
52
+ constructor(cache: CacheAdapter);
53
+ /**
54
+ * Check if user permissions satisfy the permission expression
55
+ *
56
+ * @param userPermissions - Set of user's permissions for O(1) lookup
57
+ * @param expression - Permission expression to evaluate
58
+ * @returns Promise resolving to true if expression evaluates to true
59
+ */
60
+ check(userPermissions: Set<string>, expression: PermissionExpression): Promise<boolean>;
61
+ /**
62
+ * Check permissions with detailed result information
63
+ */
64
+ checkWithResult(userPermissions: Set<string>, expression: PermissionExpression): Promise<PermissionCheckResult>;
65
+ /**
66
+ * Evaluate permission expression recursively
67
+ *
68
+ * @param userPermissions - User's permissions as Set for O(1) lookup
69
+ * @param expression - Expression to evaluate
70
+ * @param depth - Current nesting depth
71
+ * @returns Boolean result of expression evaluation
72
+ */
73
+ private evaluateExpression;
74
+ /**
75
+ * Evaluate expression with detailed result information
76
+ */
77
+ private evaluateExpressionWithDetails;
78
+ /**
79
+ * Track expression complexity for analytics
80
+ */
81
+ private trackComplexity;
82
+ /**
83
+ * Get the depth of an expression
84
+ */
85
+ private getExpressionDepth;
86
+ /**
87
+ * Get resolver type for identification
88
+ */
89
+ getType(): PermissionResolverType;
90
+ /**
91
+ * Get performance characteristics for monitoring
92
+ */
93
+ getPerformanceCharacteristics(): PerformanceCharacteristics;
94
+ /**
95
+ * Get performance statistics
96
+ */
97
+ getStats(): {
98
+ checkCount: number;
99
+ averageResolutionTimeUs: number;
100
+ totalResolutionTimeUs: number;
101
+ cacheHitRate: number;
102
+ cacheHits: number;
103
+ cacheMisses: number;
104
+ complexityDistribution: {
105
+ simple: number;
106
+ moderate: number;
107
+ complex: number;
108
+ };
109
+ };
110
+ /**
111
+ * Reset performance statistics
112
+ */
113
+ resetStats(): void;
114
+ /**
115
+ * Get resolver name for debugging
116
+ */
117
+ getName(): string;
118
+ /**
119
+ * Check if this resolver can handle the given requirement type
120
+ */
121
+ canHandle(requirement: any): requirement is PermissionExpression;
122
+ /**
123
+ * Normalize expression for consistent cache keys
124
+ *
125
+ * Sorts arrays and standardizes structure for reliable caching
126
+ */
127
+ static normalizeExpression(expression: PermissionExpression): PermissionExpression;
128
+ }
129
+ //# sourceMappingURL=ExpressionPermissionResolver.d.ts.map