reslib 2.2.0 → 2.3.0

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.
@@ -2,1957 +2,90 @@ import { Observable } from '../observable';
2
2
  import { ClassConstructor } from '../types';
3
3
  import { ResourceActionName, ResourceName } from '../resources/types';
4
4
  import 'reflect-metadata';
5
- import { Dictionary } from '../types/dictionary';
6
5
  import './types';
7
- import { AuthEvent, AuthPerm, AuthPerms, AuthSecureStorage, AuthSessionStorage, AuthUser } from './types';
6
+ import { AuthConfig, AuthEvent, AuthPerm, AuthPerms, AuthSecureStorage, AuthUser } from './types';
7
+ export * from './errors';
8
8
  export * from './types';
9
- /***
10
- * A class that provides methods for managing session data.
11
- *
12
- */
13
- declare class Session {
14
- /**
15
- * Retrieves a specific value from the session data based on the provided session name and key.
16
- *
17
- * This function first checks if the provided key is a non-null string. If it is not, it returns undefined.
18
- * It then retrieves the session data using `getData` and returns the value associated with the specified key.
19
- *
20
- * @param sessionName - An optional string that represents the name of the session.
21
- * @param key - A string representing the key of the value to retrieve from the session data.
22
- *
23
- * @returns The value associated with the specified key in the session data, or undefined if the key is invalid.
24
- *
25
- * @example
26
- * // Example of retrieving a specific value from session data
27
- * const value = get('mySession', 'userPreference'); // Returns: 'darkMode'
28
- *
29
- * @example
30
- * // Example of trying to retrieve a value with an invalid key
31
- * const value = get('mySession', null); // Returns: undefined
32
- */
33
- static get(sessionName?: string, key?: string): any;
34
- /**
35
- * Sets a value or an object in the session data for a specific session name.
36
- *
37
- * This function retrieves the current session data using `getData`. If a valid key is provided, it sets the
38
- * corresponding value in the session data. If an object is provided as the key, it replaces the entire session data.
39
- * Finally, it saves the updated session data back to the session storage.
40
- *
41
- * @param sessionName - An optional string that represents the name of the session.
42
- * @param key - A string representing the key to set a value for, or an object containing multiple key-value pairs.
43
- * @param value - The value to set for the specified key. This parameter is ignored if an object is provided as the key.
44
- *
45
- * @returns The updated session data as an object.
46
- *
47
- * @example
48
- * // Example of setting a single value in session data
49
- * const updatedData = set('mySession', 'userPreference', 'darkMode'); // Returns: { userPreference: 'darkMode' }
50
- *
51
- * @example
52
- * // Example of replacing the entire session data with an object
53
- * const updatedData = set('mySession', { userPreference: 'lightMode', language: ' English' }); // Returns: { userPreference: 'lightMode', language: 'English' }
54
- */
55
- static set(sessionName?: string, key?: string | Dictionary, value?: any): Dictionary;
56
- /**
57
- * Generates a unique session key based on the authenticated user's ID and an optional session name.
58
- *
59
- * The session key is constructed in the format: `auth-{userId}-{sessionName}`. If the user is not signed in,
60
- * the user ID will be an empty string. This key is used to store and retrieve session data.
61
- *
62
- * @param sessionName - An optional string that represents the name of the session. If not provided,
63
- * an empty string will be used in the key.
64
- *
65
- * @returns A string representing the unique session key.
66
- *
67
- * @example
68
- * // Example of generating a session key for a user with ID '12345'
69
- * const sessionKey = getKey('mySession'); // Returns: 'auth-12345-mySession'
70
- *
71
- * @example
72
- * // Example of generating a session key when no user is signed in
73
- * const sessionKey = getKey(); // Returns: 'auth--'
74
- */
75
- static getKey(sessionName?: string): string;
76
- /**
77
- * Retrieves session data associated with a specific session name.
78
- *
79
- * This function checks if the provided session name is a non-null string. If it is not, an empty object is returned.
80
- * Otherwise, it constructs a key using `getKey` and retrieves the corresponding data from the session storage.
81
- *
82
- * @param sessionName - An optional string that represents the name of the session. If not provided or invalid,
83
- * an empty object will be returned.
84
- *
85
- * @returns An object containing the session data associated with the specified session name.
86
- * If the session name is invalid, an empty object is returned.
87
- *
88
- * @example
89
- * // Example of retrieving session data for a specific session name
90
- * const sessionData = getData('mySession'); // Returns: { }
91
- *
92
- * @example
93
- * // Example of retrieving session data with an invalid session name
94
- * const sessionData = getData(null); // Returns: {}
95
- */
96
- static getData(sessionName?: string): Dictionary;
97
- /**
98
- * Retrieves a session storage object that provides methods for managing session data.
99
- *
100
- * This function creates an object that allows you to interact with session storage
101
- * using a specified session name. It provides methods to get, set, and retrieve data
102
- * associated with the session, as well as to retrieve the session key.
103
- *
104
- * @param sessionName - An optional string that represents the name of the session.
105
- * If provided, it will be used as a prefix for the keys stored
106
- * in session storage. If not provided, the session will be
107
- * treated as anonymous.
108
- *
109
- * @returns An object implementing the `AuthSessionStorage` interface, which includes
110
- * methods for session management:
111
- * - `get(key?: string): any`: Retrieves the value associated with the specified key.
112
- * - `set(key?: string | Dictionary, value?: any): void`: Stores a value under the specified key.
113
- * - `getData(): Dictionary`: Returns all data stored in the session as a dictionary.
114
- * - `getKey(): string`: Returns the session key used for storage.
115
- *
116
- * @example
117
- * // Create a session storage object with a specific session name
118
- * const session = getSessionStorage('userSession');
119
- *
120
- * // Get the session key
121
- * const sessionKey = session.getKey(); // 'userSession'
122
- *
123
- * @remarks
124
- * This function is particularly useful for managing user authentication sessions
125
- * in web applications. By using session storage, data persists across page reloads
126
- * but is cleared when the tab or browser is closed.
127
- *
128
- * Ensure that the keys used for storing data are unique to avoid collisions with
129
- * other session data. Consider using a structured naming convention for keys.
130
- */
131
- static getStorage(sessionName?: string): AuthSessionStorage;
132
- }
133
- export declare class Auth {
134
- /**
135
- * Authentication event handler.
136
- * Initializes an observable event handler for authentication Auth.events.
137
- *
138
- * This constant `events` is assigned an instance of `Observable<AuthEvent>`, which is used to manage
139
- * authentication-related events in the application. The initialization checks if the global
140
- * `Global.eventsResourcesObservableHandler` exists and is an object. If it does, it assigns it to
141
- * `events`; otherwise, it defaults to an empty object cast as `Observable<AuthEvent>`.
142
- *
143
- * This pattern allows for flexible handling of events, ensuring that the application can respond
144
- * to authentication actions such as sign-in, sign-out, and sign-up.
145
- *
146
- * @type {Observable<AuthEvent>}
147
- *
148
- * @example
149
- * import {Auth} from 'reslib/auth';
150
- * Auth.events.on('SIGN_IN', (user) => {
151
- * console.log(`User signed in: ${user.username}`);
152
- * });
153
- *
154
- * function userSignIn(user) {
155
- * Auth.events.trigger('SIGN_IN', user);
156
- * }
157
- */
158
- static events: Observable<AuthEvent>;
159
- private static localUserRef;
160
- /**
161
- * Checks if the user is a master admin.
162
- *
163
- * The `isMasterAdmin` function determines whether the provided user
164
- * has master admin privileges. If no user is provided, it will
165
- * attempt to retrieve the signed user from the session.
166
- *
167
- * ### Parameters
168
- *
169
- * - `user` (AuthUser , optional): The user object to check. If not
170
- * provided, the function will attempt to retrieve the signed user
171
- * from the session.
172
- *
173
- * ### Returns
174
- *
175
- * - `boolean`: Returns `true` if the user is a master admin, or `false` otherwise.
176
- *
177
- * ### Example Usage
178
- *
179
- * ```typescript
180
- * const user: AuthUser = { id: "admin123" };
181
- * Auth.isMasterAdmin = (user)=>{
182
- * return checkSomeCondition(user);
183
- * }; // false (assuming the user is not a master admin)
184
- * ```
185
- * @see {@link AuthUser} for the `AuthUser` type.
186
- */
187
- static isMasterAdmin?: (user?: AuthUser) => boolean;
188
- private static _isMasterAdmin;
189
- /**
190
- * Retrieves the currently authenticated user from secure session storage.
191
- *
192
- * This method implements a secure user session retrieval system that handles encrypted
193
- * user data storage. It first checks for a cached user reference in memory for performance
194
- * optimization, then attempts to decrypt and parse the user data from session storage
195
- * if no cached version exists. The method includes comprehensive error handling for
196
- * decryption failures and data corruption scenarios.
197
- *
198
- * ### Security Features:
199
- * - **Encrypted Storage**: User data is encrypted using AES encryption before storage
200
- * - **Memory Caching**: Cached in `localUserRef` for improved performance and reduced decryption overhead
201
- * - **Safe Parsing**: Uses `JsonHelper.parse` for secure JSON deserialization
202
- * - **Error Recovery**: Gracefully handles corrupted or invalid session data
203
- *
204
- * ### Performance Optimization:
205
- * The method implements a two-tier retrieval strategy:
206
- * 1. **Memory Cache**: Returns immediately if user is already loaded in memory
207
- * 2. **Session Storage**: Decrypts and parses data from persistent storage only when needed
208
- *
209
- * @returns The authenticated user object containing user information, permissions, and roles,
210
- * or `null` if no user is currently signed in, session data is corrupted, or
211
- * decryption fails. The returned object conforms to the `AuthUser` interface.
212
- *
213
- * @example
214
- * ```typescript
215
- * // Basic usage - check if user is signed in
216
- * const currentUser = Auth.getSignedUser();
217
- * if (currentUser) {
218
- * console.log(`Welcome back, ${currentUser.username}!`);
219
- * console.log(`User ID: ${currentUser.id}`);
220
- * } else {
221
- * console.log("No user is currently signed in");
222
- * }
223
- * ```
224
- *
225
- * @example
226
- * ```typescript
227
- * // Using with permission checking
228
- * const user = Auth.getSignedUser();
229
- * if (user) {
230
- * const canEditDocuments = Auth.checkUserPermission(user, "documents", "update");
231
- * if (canEditDocuments) {
232
- * showEditButton();
233
- * }
234
- * }
235
- * ```
236
- *
237
- * @example
238
- * ```typescript
239
- * // Handling authentication state in React component
240
- * function UserProfile() {
241
- * const [user, setUser] = useState<AuthUser | null>(null);
242
- *
243
- * useEffect(() => {
244
- * const currentUser = Auth.getSignedUser();
245
- * setUser(currentUser);
246
- *
247
- * if (!currentUser) {
248
- * // Redirect to login page
249
- * router.push('/login');
250
- * }
251
- * }, []);
252
- *
253
- * return user ? <div>Hello, {user.username}</div> : <div>Loading...</div>;
254
- * }
255
- * ```
256
- *
257
- * @example
258
- * ```typescript
259
- * // Using with authentication guards
260
- * class AuthGuard {
261
- * static requireAuth(): boolean {
262
- * const user = Auth.getSignedUser();
263
- * if (!user) {
264
- * throw new Error("Authentication required");
265
- * }
266
- * return true;
267
- * }
268
- *
269
- * static requireRole(roleName: string): boolean {
270
- * const user = Auth.getSignedUser();
271
- * return user?.roles?.some(role => role.name === roleName) ?? false;
272
- * }
273
- * }
274
- * ```
275
- *
276
- * @example
277
- *
278
- * @throws {CryptoError} May throw during decryption if session data is corrupted
279
- * @throws {SyntaxError} May throw during JSON parsing if decrypted data is malformed
280
- *
281
- * @see {@link AuthUser} - Complete user object interface definition
282
- * @see {@link setSignedUser} - Method to store user in session
283
- * @see {@link signIn} - High-level user authentication method
284
- * @see {@link signOut} - Method to clear user session
285
- * @see {@link checkUserPermission} - Check specific user permissions
286
- *
287
- *
288
- * @public
289
- *
290
- * @remarks
291
- * **Security Considerations:**
292
- * - Session data is automatically encrypted using AES encryption
293
- * - The encryption key `SESSION_ENCRYPT_KEY` should be kept secure
294
- * - User data includes sensitive information like tokens and permissions
295
- * - Always validate user data before using in security-critical operations
296
- *
297
- * **Performance Notes:**
298
- * - First call after page load requires decryption (slower)
299
- * - Subsequent calls return cached data (faster)
300
- * - Cache is automatically cleared when user signs out
301
- * - Consider the performance impact in render loops
302
- *
303
- * **Error Handling:**
304
- * - Returns `null` instead of throwing errors for better UX
305
- * - Logs errors to console for debugging purposes
306
- * - Gracefully handles session storage corruption
307
- * - Automatically recovers from temporary decryption failures
308
- */
309
- static getSignedUser(): AuthUser | null;
310
- /**
311
- * Securely stores an authenticated user in encrypted session storage with event broadcasting.
312
- *
313
- * This method is the core user session management function that handles secure storage of user
314
- * authentication data. It encrypts user information using AES encryption before persisting to
315
- * session storage, maintains local memory cache for performance, and optionally broadcasts
316
- * authentication events to notify other parts of the application about user state changes.
317
- *
318
- * ### Security Architecture:
319
- * - **AES Encryption**: User data is encrypted before storage to protect sensitive information
320
- * - **Session Timestamping**: Automatically adds `sessionCreatedAt` timestamp for session tracking
321
- * - **Error Isolation**: Encryption failures don't crash the application, user reference is safely cleared
322
- * - **Memory Management**: Updates local cache reference for immediate access
323
- *
324
- * ### Event System Integration:
325
- * The method integrates with the authentication event system to broadcast state changes:
326
- * - **SIGN_IN Event**: Triggered when a valid user is stored with successful encryption
327
- * - **SIGN_OUT Event**: Triggered when user is cleared (null) or encryption fails
328
- * - **Event Payload**: Includes the user object for event handlers to process
329
- *
330
- * @param u - The user object to store in session, or `null` to clear the current session.
331
- * When providing a user object, it should contain all necessary authentication
332
- * information including permissions, roles, and tokens. The object will be
333
- * automatically timestamped with `sessionCreatedAt`.
334
- *
335
- * @param triggerEvent - Optional flag controlling whether to broadcast authentication events.
336
- * When `true` (default), triggers either 'SIGN_IN' or 'SIGN_OUT' events
337
- * based on the operation result. Set to `false` to perform silent
338
- * session updates without notifying event listeners.
339
- *
340
- * @returns A promise that resolves to the result of the session storage operation.
341
- * The promise completes after the encrypted data has been written to storage.
342
- * Returns the storage operation result, typically indicating success or failure.
343
- *
344
- * @example
345
- * ```typescript
346
- * // Standard user sign-in with event broadcasting
347
- * const user: AuthUser = {
348
- * id: "user123",
349
- * username: "john_doe",
350
- * email: "john@example.com",
351
- * perms: { documents: ["read", "write"] },
352
- * roles: [{ name: "editor", perms: { images: ["upload"] } }]
353
- * };
354
- *
355
- * await Auth.setSignedUser(user, true);
356
- * console.log("User signed in with events triggered");
357
- * ```
358
- *
359
- * @example
360
- * ```typescript
361
- * // Silent session update without triggering events
362
- * const updatedUser = { ...currentUser, lastActivity: new Date() };
363
- * await Auth.setSignedUser(updatedUser, false);
364
- * console.log("User session updated silently");
365
- * ```
366
- *
367
- * @example
368
- * ```typescript
369
- * // Clear user session (sign out)
370
- * await Auth.setSignedUser(null, true);
371
- * console.log("User signed out, SIGN_OUT event triggered");
372
- * ```
373
- *
374
- * @example
375
- * ```typescript
376
- * // Using with event listeners
377
- * Auth.events.on('SIGN_IN', (user) => {
378
- * console.log(`Welcome ${user.username}!`);
379
- * initializeUserDashboard(user);
380
- * trackUserLogin(user.id);
381
- * });
382
- *
383
- * Auth.events.on('SIGN_OUT', () => {
384
- * console.log('User signed out');
385
- * clearUserDashboard();
386
- * redirectToLogin();
387
- * });
388
- *
389
- * // Now when we set a user, events will fire automatically
390
- * await Auth.setSignedUser(authenticatedUser);
391
- * ```
392
- *
393
- * @example
394
- * ```typescript
395
- * // Error handling with session management
396
- * try {
397
- * await Auth.setSignedUser(userFromAPI);
398
- * showSuccessMessage("Login successful");
399
- * } catch (error) {
400
- * console.error("Failed to store user session:", error);
401
- * showErrorMessage("Login failed, please try again");
402
- * }
403
- * ```
404
- *
405
- * @example
406
- * ```typescript
407
- * // Updating user permissions after role change
408
- * const currentUser = Auth.getSignedUser();
409
- * if (currentUser) {
410
- * const updatedUser = {
411
- * ...currentUser,
412
- * roles: [...currentUser.roles, newRole],
413
- * perms: { ...currentUser.perms, ...newPermissions }
414
- * };
415
- *
416
- * await Auth.setSignedUser(updatedUser, false); // Silent update
417
- * console.log("User permissions updated");
418
- * }
419
- * ```
420
- *
421
- * @throws {CryptoError} May throw if encryption fails due to invalid encryption key
422
- * @throws {StorageError} May throw if session storage is unavailable or quota exceeded
423
- *
424
- * @see {@link AuthUser} - Complete user object interface with all required fields
425
- * @see {@link getSignedUser} - Retrieve the currently stored user from session
426
- * @see {@link signIn} - High-level user authentication wrapper
427
- * @see {@link signOut} - High-level user sign-out wrapper
428
- * @see {@link Auth.events} - Authentication event system for state change notifications
429
- * @see {@link AuthEvent} - Available authentication event types and payloads
430
- *
431
- *
432
- * @public
433
- * @async
434
- *
435
- * @remarks
436
- * **Security Best Practices:**
437
- * - User objects should be validated before storage
438
- * - Sensitive data like tokens are automatically encrypted
439
- * - Session timestamps help with security auditing
440
- * - Always handle encryption errors gracefully
441
- *
442
- * **Performance Considerations:**
443
- * - Encryption/decryption adds computational overhead
444
- * - Local cache is updated synchronously for immediate access
445
- * - Event broadcasting may trigger multiple listeners
446
- * - Consider batching multiple user updates to reduce I/O
447
- *
448
- * **Event System:**
449
- * - Events are asynchronous and don't block the storage operation
450
- * - Multiple listeners can subscribe to the same event
451
- * - Event payload includes the full user object for flexibility
452
- * - Use `triggerEvent: false` for internal operations to avoid recursion
453
- */
454
- static setSignedUser(u: AuthUser | null, triggerEvent?: boolean): Promise<AuthUser | null>;
455
- /**
456
- * Authenticates a user and establishes a secure session with comprehensive validation.
457
- *
458
- * This high-level authentication method provides a complete user sign-in workflow with
459
- * input validation, secure session establishment, and event broadcasting. It serves as
460
- * the primary entry point for user authentication in applications, handling all the
461
- * complexity of secure session management while providing a simple, promise-based API.
462
- *
463
- * ### Authentication Workflow:
464
- * 1. **Input Validation**: Validates that the provided user object is properly structured
465
- * 2. **Session Creation**: Calls `setSignedUser` to securely store user data
466
- * 3. **Event Broadcasting**: Optionally triggers authentication events for app-wide notifications
467
- * 4. **Return Confirmation**: Returns the authenticated user object on successful completion
468
- *
469
- * ### Security Features:
470
- * - **Object Validation**: Ensures user object is valid before processing
471
- * - **Encrypted Storage**: Leverages `setSignedUser` for secure data persistence
472
- * - **Error Handling**: Provides meaningful error messages for failed authentication
473
- * - **Session Timestamping**: Automatically tracks when authentication session was created
474
- *
475
- * @param user - The authenticated user object containing all necessary user information.
476
- * Must be a valid object conforming to the `AuthUser` interface, including
477
- * properties like id, username, email, permissions, roles.
478
- * The object should come from a successful authentication process (login API, OAuth, etc.).
479
- *
480
- * @param triggerEvent - Optional flag controlling whether to broadcast authentication events.
481
- * When `true` (default), triggers a 'SIGN_IN' event that other parts of
482
- * the application can listen to for initialization, analytics, or UI updates.
483
- * Set to `false` for silent authentication without event notifications.
484
- *
485
- * @returns A promise that resolves to the authenticated user object when sign-in is successful.
486
- * The returned user object is the same as the input but may include additional
487
- * properties added during the authentication process (like session timestamps).
488
- *
489
- * @throws {Error} Throws an error with internationalized message if the user object is invalid,
490
- * null, undefined, or not a proper object structure. The error message is
491
- * retrieved from the i18n system using key "auth.invalidSignInUser".
492
- *
493
- * @example
494
- * ```typescript
495
- * // Basic user sign-in after successful API authentication
496
- * try {
497
- * const response = await fetch('/api/auth/login', {
498
- * method: 'POST',
499
- * body: JSON.stringify({ username, password }),
500
- * headers: { 'Content-Type': 'application/json' }
501
- * });
502
- *
503
- * const userData = await response.json();
504
- * const authenticatedUser = await Auth.signIn(userData);
505
- *
506
- * console.log(`Welcome ${authenticatedUser.username}!`);
507
- * router.push('/dashboard');
508
- * } catch (error) {
509
- * console.error('Sign-in failed:', error.message);
510
- * showErrorMessage('Invalid credentials');
511
- * }
512
- * ```
513
- *
514
- * @example
515
- * ```typescript
516
- * // OAuth authentication workflow
517
- * async function handleOAuthCallback(authCode: string) {
518
- * try {
519
- * // Exchange auth code for user data
520
- * const tokenResponse = await exchangeCodeForToken(authCode);
521
- * const userProfile = await fetchUserProfile(tokenResponse.access_token);
522
- *
523
- * const user: AuthUser = {
524
- * id: userProfile.id,
525
- * username: userProfile.login,
526
- * email: userProfile.email,
527
- * perms: await fetchUserPermissions(userProfile.id),
528
- * roles: await fetchUserRoles(userProfile.id),
529
- * provider: 'oauth'
530
- * };
531
- *
532
- * await Auth.signIn(user);
533
- * console.log('OAuth sign-in successful');
534
- * } catch (error) {
535
- * console.error('OAuth sign-in failed:', error);
536
- * }
537
- * }
538
- * ```
539
- *
540
- * @example
541
- * ```typescript
542
- * // Silent authentication without triggering events
543
- * async function silentAuth(sessionToken: string) {
544
- * try {
545
- * const userData = await validateSessionToken(sessionToken);
546
- * const user = await Auth.signIn(userData, false); // No events
547
- *
548
- * console.log('Silent authentication successful');
549
- * return user;
550
- * } catch (error) {
551
- * console.log('Silent auth failed, user needs to login');
552
- * return null;
553
- * }
554
- * }
555
- * ```
556
- *
557
- * @example
558
- * ```typescript
559
- * // Complete authentication flow with event handling
560
- * // Set up event listeners first
561
- * Auth.events.on('SIGN_IN', (user) => {
562
- * // Initialize user-specific features
563
- * initializeUserPreferences(user.id);
564
- * loadUserDashboard(user.perms);
565
- * trackAnalyticsEvent('user_signin', { userId: user.id });
566
- *
567
- * // Update UI state
568
- * updateNavigationForUser(user.roles);
569
- * showWelcomeMessage(user.username);
570
- * });
571
- *
572
- * // Perform authentication
573
- * async function loginUser(credentials: LoginCredentials) {
574
- * try {
575
- * const authResult = await authenticateWithAPI(credentials);
576
- * const user = await Auth.signIn(authResult.user); // Events will fire
577
- *
578
- * return { success: true, user };
579
- * } catch (error) {
580
- * return { success: false, error: error.message };
581
- * }
582
- * }
583
- * ```
584
- *
585
- * @example
586
- * ```typescript
587
- * // Multi-step authentication with role-based redirection
588
- * async function signInWithRoleRedirect(userData: any) {
589
- * try {
590
- * const user = await Auth.signIn(userData);
591
- *
592
- * // Redirect based on user role
593
- * if (user.roles?.some(role => role.name === 'admin')) {
594
- * router.push('/admin/dashboard');
595
- * } else if (user.roles?.some(role => role.name === 'moderator')) {
596
- * router.push('/moderator/panel');
597
- * } else {
598
- * router.push('/user/dashboard');
599
- * }
600
- *
601
- * return user;
602
- * } catch (error) {
603
- * console.error('Role-based sign-in failed:', error);
604
- * throw error;
605
- * }
606
- * }
607
- * ```
608
- *
609
- * @see {@link AuthUser} - Complete user object interface specification
610
- * @see {@link setSignedUser} - Lower-level method for secure user storage
611
- * @see {@link getSignedUser} - Retrieve currently authenticated user
612
- * @see {@link signOut} - Sign out and clear user session
613
- * @see {@link Auth.events} - Authentication event system for state notifications
614
- * @see {@link isAllowed} - Check user permissions for access control
615
- *
616
- *
617
- * @public
618
- * @async
619
- *
620
- * @remarks
621
- * **Best Practices:**
622
- * - Always validate user data before calling this method
623
- * - Use try-catch blocks to handle authentication failures gracefully
624
- * - Use event listeners to initialize user-specific application features
625
- *
626
- * **Error Handling:**
627
- * - The method throws immediately on invalid input for fast failure
628
- * - Use internationalized error messages for better user experience
629
- * - Consider logging authentication attempts for security monitoring
630
- * - Implement retry logic for transient authentication failures
631
- *
632
- * **Integration Notes:**
633
- * - Works seamlessly with any authentication provider (JWT, OAuth, custom)
634
- * - Integrates with the permission system for access control
635
- * - Compatible with SSR/SPA applications through secure session storage
636
- * - Supports both traditional and modern authentication workflows
637
- */
638
- static signIn(user: AuthUser, triggerEvent?: boolean): Promise<AuthUser>;
639
- /**
640
- * Signs out the currently authenticated user and securely clears their session.
641
- *
642
- * This method provides a high-level, convenient interface for user sign-out operations.
643
- * It handles the complete user session termination workflow by clearing the encrypted
644
- * user data from session storage, removing the cached user reference from memory, and
645
- * optionally broadcasting sign-out events to notify other parts of the application
646
- * about the authentication state change.
647
- *
648
- * ### Sign-Out Workflow:
649
- * 1. **Session Clearing**: Calls `setSignedUser(null)` to remove user data from encrypted storage
650
- * 2. **Memory Cleanup**: Clears the local user reference cache for immediate effect
651
- * 3. **Event Broadcasting**: Optionally triggers 'SIGN_OUT' events for application-wide notifications
652
- * 4. **Security Cleanup**: Ensures no sensitive user data remains in browser storage
653
- *
654
- * ### Security Features:
655
- * - **Complete Data Removal**: Eliminates all traces of user session from storage
656
- * - **Memory Safety**: Clears in-memory user references to prevent data leakage
657
- * - **Event Coordination**: Allows other components to perform cleanup operations
658
- * - **Immediate Effect**: Session termination is effective immediately after method completion
659
- *
660
- * ### Application Integration:
661
- * The method integrates seamlessly with the authentication event system, allowing
662
- * other parts of the application to react to sign-out events by clearing user-specific
663
- * data, redirecting to login pages, or performing cleanup operations.
664
- *
665
- * @param triggerEvent - Optional flag controlling whether to broadcast authentication events.
666
- * When `true` (default), triggers a 'SIGN_OUT' event that other parts
667
- * of the application can listen to for cleanup operations, analytics,
668
- * or UI state updates. Set to `false` to perform silent sign-out
669
- * without notifying event listeners (useful for internal operations).
670
- *
671
- * @returns A promise that resolves when the sign-out operation is complete and all
672
- * user session data has been successfully removed from storage. The promise
673
- * resolves to `void` as no return value is needed after successful sign-out.
674
- *
675
- * @example
676
- * ```typescript
677
- * // Standard user sign-out with event broadcasting
678
- * async function handleUserSignOut() {
679
- * try {
680
- * await Auth.signOut();
681
- * console.log('User signed out successfully');
682
- *
683
- * // Redirect to login page
684
- * window.location.href = '/login';
685
- * } catch (error) {
686
- * console.error('Sign-out failed:', error);
687
- * showErrorMessage('Failed to sign out');
688
- * }
689
- * }
690
- * ```
691
- *
692
- * @example
693
- * ```typescript
694
- * // Silent sign-out without triggering events
695
- * async function silentSignOut() {
696
- * await Auth.signOut(false); // No events triggered
697
- * console.log('Silent sign-out completed');
698
- *
699
- * // Manually handle post-signout operations
700
- * clearUserSpecificData();
701
- * redirectToPublicArea();
702
- * }
703
- * ```
704
- *
705
- * @example
706
- * ```typescript
707
- * // Sign-out with comprehensive event handling
708
- * // Set up event listener first
709
- * Auth.events.on('SIGN_OUT', () => {
710
- * console.log('User signed out - cleaning up...');
711
- *
712
- * // Clear user-specific application state
713
- * clearUserPreferences();
714
- * clearUserCache();
715
- * resetApplicationState();
716
- *
717
- * // Update UI
718
- * hideUserMenus();
719
- * showGuestContent();
720
- *
721
- * // Analytics and logging
722
- * trackAnalyticsEvent('user_signout');
723
- * logSecurityEvent('session_terminated');
724
- * });
725
- *
726
- * // Perform sign-out - events will fire automatically
727
- * await Auth.signOut();
728
- * ```
729
- *
730
- * @example
731
- * ```typescript
732
- * // Session timeout handling
733
- * class SessionManager {
734
- * private timeoutId: NodeJS.Timeout | null = null;
735
- *
736
- * startSessionTimer(durationMs: number) {
737
- * this.clearSessionTimer();
738
- *
739
- * this.timeoutId = setTimeout(async () => {
740
- * console.log('Session expired - signing out user');
741
- * await Auth.signOut(); // Will trigger events
742
- *
743
- * showNotification('Session expired. Please sign in again.');
744
- * }, durationMs);
745
- * }
746
- *
747
- * clearSessionTimer() {
748
- * if (this.timeoutId) {
749
- * clearTimeout(this.timeoutId);
750
- * this.timeoutId = null;
751
- * }
752
- * }
753
- * }
754
- * ```
755
- *
756
- * @example
757
- * ```typescript
758
- * // Multi-tab sign-out coordination
759
- * // Listen for storage events to handle sign-out in other tabs
760
- * window.addEventListener('storage', (event) => {
761
- * if (event.key === USER_SESSION_KEY && event.newValue === null) {
762
- * console.log('User signed out in another tab');
763
- *
764
- * // Perform silent sign-out in this tab without triggering events
765
- * Auth.signOut(false);
766
- *
767
- * // Update UI to reflect signed-out state
768
- * updateUIForSignedOutUser();
769
- * }
770
- * });
771
- * ```
772
- *
773
- * @example
774
- * ```typescript
775
- * // Complete authentication flow with error handling
776
- * class AuthenticationService {
777
- * async performSignOut(): Promise<boolean> {
778
- * try {
779
- * // Check if user is actually signed in
780
- * const currentUser = Auth.getSignedUser();
781
- * if (!currentUser) {
782
- * console.log('No user to sign out');
783
- * return true;
784
- * }
785
- *
786
- * // Sign out locally
787
- * await Auth.signOut();
788
- *
789
- * console.log('Complete sign-out successful');
790
- * return true;
791
- * } catch (error) {
792
- * console.error('Sign-out process failed:', error);
793
- *
794
- * // Force local sign-out even if server call failed
795
- * await Auth.signOut(false);
796
- * return false;
797
- * }
798
- * }
799
- * }
800
- * ```
801
- *
802
- * @throws {StorageError} May throw if session storage is unavailable during cleanup
803
- * @throws {CryptoError} May throw if there are issues clearing encrypted session data
804
- *
805
- * @see {@link setSignedUser} - Lower-level method used internally for session management
806
- * @see {@link getSignedUser} - Check if a user is currently signed in before sign-out
807
- * @see {@link signIn} - Corresponding method for user authentication
808
- * @see {@link Auth.events} - Event system for handling sign-out notifications
809
- * @see {@link AuthEvent} - Authentication event types including 'SIGN_OUT'
810
- * @see {@link USER_SESSION_KEY} - Storage key used for session data
811
- *
812
- *
813
- * @public
814
- * @async
815
- *
816
- * @remarks
817
- * **Security Considerations:**
818
- * - Always sign out users when suspicious activity is detected
819
- * - Consider notifying the server about client-side sign-outs for security auditing
820
- * - Be aware that local sign-out doesn't invalidate server-side sessions automatically
821
- * - Use HTTPS to prevent session hijacking during the sign-out process
822
- *
823
- * **Best Practices:**
824
- * - Always handle sign-out errors gracefully to avoid leaving users in inconsistent states
825
- * - Use event listeners to coordinate sign-out across multiple application components
826
- * - Consider implementing automatic sign-out for security-sensitive applications
827
- * - Provide clear feedback to users about successful sign-out operations
828
- *
829
- * **Performance Notes:**
830
- * - Sign-out is typically fast as it only involves storage cleanup
831
- * - Event broadcasting may trigger multiple listeners, consider the performance impact
832
- * - Silent sign-out (`triggerEvent: false`) is faster as it skips event processing
833
- * - Consider batching multiple sign-out operations if needed programmatically
834
- *
835
- * **Multi-Tab Considerations:**
836
- * - Sign-out in one tab affects session storage visible to all tabs
837
- * - Other tabs should listen for storage events to stay synchronized
838
- * - Consider implementing cross-tab communication for better user experience
839
- * - Be careful with silent sign-outs in multi-tab scenarios to avoid confusion
840
- */
841
- static signOut(triggerEvent?: boolean): Promise<AuthUser | null>;
842
- private static isResourceActionTupleArray;
843
- private static isResourceActionTupleObject;
844
- /**
845
- * Determines whether a user has permission to access a resource or perform an action.
846
- *
847
- * This comprehensive authorization method evaluates various types of permission configurations
848
- * to determine if the specified user (or currently signed-in user) is allowed to perform
849
- * the requested operation. It supports multiple permission formats including boolean flags,
850
- * function-based permissions, resource-action tuples, and complex permission arrays.
851
- *
852
- * The method follows a priority-based evaluation system:
853
- * 1. Boolean permissions are returned directly
854
- * 2. Master admin users are always granted access
855
- * 3. Null/undefined permissions default to `true` (open access)
856
- * 4. Function permissions are evaluated with the user context
857
- * 5. Resource-action permissions are checked against user's role permissions
858
- * 6. Array permissions are evaluated with OR logic (any match grants access)
859
- *
860
- * @template TResourceName - The resource name type, extending ResourceName
861
- *
862
- * @param perm - The permission configuration to evaluate. Can be:
863
- * - `boolean`: Direct permission flag (true = allowed, false = denied)
864
- * - `function`: Custom permission evaluator receiving user context
865
- * - `ResourceActionTupleObject`: Object with resourceName and action properties
866
- * - `ResourceActionTupleArray`: Array tuple [resourceName, action]
867
- * - `Array<AuthPerm>`: Multiple permission configurations (OR logic)
868
- * - `null|undefined`: Defaults to allowing access
869
- *
870
- * @param user - Optional user object to check permissions against.
871
- * If not provided, uses the currently signed-in user from session.
872
- * The user object should contain permissions and role information.
873
- *
874
- * @returns `true` if the user is authorized to perform the action, `false` otherwise
875
- *
876
- * @example
877
- * ```typescript
878
- * // Boolean permission - direct access control
879
- * const canAccess = Auth.isAllowed(true); // Returns: true
880
- * const cannotAccess = Auth.isAllowed(false); // Returns: false
881
- *
882
- * // Function-based permission - custom logic
883
- * const customPerm = (user: AuthUser) => user.age >= 18;
884
- * const canAccessAdultContent = Auth.isAllowed(customPerm); // Returns: true if user is 18+
885
- * ```
886
- *
887
- * @example
888
- * ```typescript
889
- * // Resource-action tuple object - structured permissions
890
- * const documentEditPerm = { resourceName: "documents", action: "update" };
891
- * const canEditDocs = Auth.isAllowed(documentEditPerm);
892
- * // Returns: true if user has "update" permission on "documents" resource
893
- *
894
- * // Resource-action tuple array - compact format
895
- * const userDeletePerm: [string, string] = ["users", "delete"];
896
- * const canDeleteUsers = Auth.isAllowed(userDeletePerm);
897
- * // Returns: true if user has "delete" permission on "users" resource
898
- * ```
899
- *
900
- * @example
901
- * ```typescript
902
- * // Array of permissions - OR logic (any match grants access)
903
- * const multiplePerms = [
904
- * { resourceName: "documents", action: "read" },
905
- * { resourceName: "documents", action: "update" },
906
- * ["admin", "all"]
907
- * ];
908
- * const canAccessDocs = Auth.isAllowed(multiplePerms);
909
- * // Returns: true if user has any of the specified permissions
910
- * ```
911
- *
912
- * @example
913
- * ```typescript
914
- * // Checking permissions for a specific user
915
- * const specificUser: AuthUser = {
916
- * id: "user123",
917
- * perms: { documents: ["read", "update"] },
918
- * roles: [{ name: "editor", perms: { images: ["upload"] } }]
919
- * };
920
- *
921
- * const canEdit = Auth.isAllowed(
922
- * { resourceName: "documents", action: "update" },
923
- * specificUser
924
- * ); // Returns: true
925
- * ```
926
- *
927
- * @example
928
- * ```typescript
929
- * // Master admin bypass - always returns true
930
- * Auth.isMasterAdmin = (user) => user.id === "admin";
931
- * const adminUser = { id: "admin" };
932
- * const canDoAnything = Auth.isAllowed(
933
- * { resourceName: "secret", action: "delete" },
934
- * adminUser
935
- * ); // Returns: true (master admin bypass)
936
- * ```
937
- *
938
- * @see {@link AuthPerm} - Permission configuration type definitions
939
- * @see {@link AuthUser} - User object structure with permissions and roles
940
- * @see {@link ResourceName} - Valid resource name types
941
- * @see {@link ResourceActionName} - Valid action name types
942
- * @see {@link checkUserPermission} - Low-level permission checking
943
- * @see {@link isMasterAdmin} - Master admin detection function
944
- *
945
- *
946
- * @public
947
- */
948
- static isAllowed<TResourceName extends ResourceName = ResourceName>(perm: AuthPerm<TResourceName>, user?: AuthUser): boolean;
949
- /**
950
- * Validates whether a specific user has permission to perform an action on a resource.
951
- *
952
- * This core authorization method performs comprehensive permission checking by evaluating
953
- * both direct user permissions and role-based permissions. It serves as the foundation
954
- * for access control throughout the application, providing a reliable and secure way to
955
- * determine if a user is authorized to perform specific operations on protected resources.
956
- *
957
- * ### Permission Evaluation Strategy:
958
- * The method implements a hierarchical permission checking system:
959
- * 1. **Input Validation**: Ensures the user object is valid and properly structured
960
- * 2. **Direct Permissions**: Checks permissions directly assigned to the user
961
- * 3. **Role-Based Permissions**: Iterates through user roles to check role-specific permissions
962
- * 4. **First Match Wins**: Returns `true` as soon as any valid permission is found
963
- * 5. **Secure Default**: Returns `false` if no matching permissions are discovered
964
- *
965
- * ### Security Architecture:
966
- * - **Fail-Safe Design**: Defaults to denying access when permissions are unclear
967
- * - **Comprehensive Validation**: Validates user object structure and permission data
968
- * - **Role Inheritance**: Supports complex permission models through role-based access
969
- * - **Performance Optimized**: Uses early return to minimize computation time
970
- *
971
- * ### Permission Hierarchy:
972
- * The method checks permissions in the following order:
973
- * 1. User's direct permissions (`user.perms`)
974
- * 2. Permissions inherited from user roles (`user.roles[].perms`)
975
- *
976
- * @param user - The user object containing permission and role information.
977
- * Must be a valid `AuthUser` object with properly structured
978
- * permissions and roles. The object should include `perms` for
979
- * direct permissions and optionally `roles` array for role-based permissions.
980
- *
981
- * @param resource - The resource name to check permissions against.
982
- * Should be a valid resource identifier from the `ResourceName` type.
983
- * Examples include "documents", "users", "admin", "reports", etc.
984
- * The resource name is case-sensitive and should match exactly.
985
- *
986
- * @param action - The specific action to check permission for on the given resource.
987
- * Defaults to "read" if not specified. Common actions include:
988
- * "read", "create", "update", "delete", "all", or custom actions
989
- * specific to your application's permission model.
990
- *
991
- * @returns `true` if the user has permission to perform the specified action
992
- * on the resource, either through direct permissions or role inheritance.
993
- * Returns `false` if the user lacks permission, has invalid data,
994
- * or if any validation checks fail.
995
- *
996
- * @example
997
- * ```typescript
998
- * // Basic permission checking - user with direct permissions
999
- * const user: AuthUser = {
1000
- * id: "user123",
1001
- * username: "john_doe",
1002
- * perms: {
1003
- * documents: ["read", "create", "update"],
1004
- * reports: ["read"]
1005
- * }
1006
- * };
1007
- *
1008
- * const canReadDocs = Auth.checkUserPermission(user, "documents", "read");
1009
- * console.log(canReadDocs); // true
1010
- *
1011
- * const canDeleteDocs = Auth.checkUserPermission(user, "documents", "delete");
1012
- * console.log(canDeleteDocs); // false
1013
- * ```
1014
- *
1015
- * @example
1016
- * ```typescript
1017
- * // Role-based permission checking
1018
- * const userWithRoles: AuthUser = {
1019
- * id: "user456",
1020
- * username: "jane_smith",
1021
- * perms: {
1022
- * profile: ["read", "update"]
1023
- * },
1024
- * roles: [
1025
- * {
1026
- * name: "editor",
1027
- * perms: {
1028
- * documents: ["read", "create", "update"],
1029
- * images: ["upload", "edit"]
1030
- * }
1031
- * },
1032
- * {
1033
- * name: "moderator",
1034
- * perms: {
1035
- * comments: ["read", "update", "delete"],
1036
- * users: ["read", "suspend"]
1037
- * }
1038
- * }
1039
- * ]
1040
- * };
1041
- *
1042
- * // Check direct permission
1043
- * const canUpdateProfile = Auth.checkUserPermission(userWithRoles, "profile", "update");
1044
- * console.log(canUpdateProfile); // true (from direct perms)
1045
- *
1046
- * // Check role-inherited permission
1047
- * const canEditDocs = Auth.checkUserPermission(userWithRoles, "documents", "update");
1048
- * console.log(canEditDocs); // true (from editor role)
1049
- *
1050
- * // Check another role permission
1051
- * const canDeleteComments = Auth.checkUserPermission(userWithRoles, "comments", "delete");
1052
- * console.log(canDeleteComments); // true (from moderator role)
1053
- * ```
1054
- *
1055
- * @example
1056
- * ```typescript
1057
- * // Default action parameter (read)
1058
- * const user: AuthUser = {
1059
- * id: "reader",
1060
- * perms: {
1061
- * articles: ["read"],
1062
- * news: ["read", "create"]
1063
- * }
1064
- * };
1065
- *
1066
- * // These calls are equivalent
1067
- * const canRead1 = Auth.checkUserPermission(user, "articles", "read");
1068
- * const canRead2 = Auth.checkUserPermission(user, "articles"); // defaults to "read"
1069
- * console.log(canRead1 === canRead2); // true
1070
- * ```
1071
- *
1072
- * @example
1073
- * ```typescript
1074
- * // Error handling and validation
1075
- * const invalidUser = null;
1076
- * const emptyUser = {};
1077
- * const validUser = { id: "test", perms: { docs: ["read"] } };
1078
- *
1079
- * console.log(Auth.checkUserPermission(invalidUser, "documents", "read")); // false
1080
- * console.log(Auth.checkUserPermission(emptyUser, "documents", "read")); // false
1081
- * console.log(Auth.checkUserPermission(validUser, "docs", "read")); // true
1082
- * ```
1083
- *
1084
- * @example
1085
- * ```typescript
1086
- * // Integration with access control middleware
1087
- * class PermissionGuard {
1088
- * static requirePermission(resource: ResourceName, action: ResourceActionName = "read") {
1089
- * return (req: Request, res: Response, next: NextFunction) => {
1090
- * const user = Auth.getSignedUser();
1091
- *
1092
- * if (!user) {
1093
- * return res.status(401).json({ error: "Authentication required" });
1094
- * }
1095
- *
1096
- * if (!Auth.checkUserPermission(user, resource, action)) {
1097
- * return res.status(403).json({
1098
- * error: `Permission denied: ${action} on ${resource}`
1099
- * });
1100
- * }
1101
- *
1102
- * next();
1103
- * };
1104
- * }
1105
- * }
1106
- *
1107
- * // Usage in Express routes
1108
- * app.get('/documents', PermissionGuard.requirePermission('documents', 'read'), getDocuments);
1109
- * app.post('/documents', PermissionGuard.requirePermission('documents', 'create'), createDocument);
1110
- * app.delete('/documents/:id', PermissionGuard.requirePermission('documents', 'delete'), deleteDocument);
1111
- * ```
1112
- *
1113
- * @example
1114
- * ```typescript
1115
- * // Batch permission checking for UI elements
1116
- * function getUserCapabilities(user: AuthUser) {
1117
- * const capabilities = {
1118
- * canReadDocs: Auth.checkUserPermission(user, "documents", "read"),
1119
- * canCreateDocs: Auth.checkUserPermission(user, "documents", "create"),
1120
- * canUpdateDocs: Auth.checkUserPermission(user, "documents", "update"),
1121
- * canDeleteDocs: Auth.checkUserPermission(user, "documents", "delete"),
1122
- * canManageUsers: Auth.checkUserPermission(user, "users", "update"),
1123
- * canViewReports: Auth.checkUserPermission(user, "reports", "read"),
1124
- * canConfigureSystem: Auth.checkUserPermission(user, "system", "configure")
1125
- * };
1126
- *
1127
- * return capabilities;
1128
- * }
1129
- *
1130
- * // Usage in React component
1131
- * function DocumentToolbar() {
1132
- * const user = Auth.getSignedUser();
1133
- * const capabilities = getUserCapabilities(user);
1134
- *
1135
- * return (
1136
- * <div className="toolbar">
1137
- * {capabilities.canCreateDocs && <CreateButton />}
1138
- * {capabilities.canUpdateDocs && <EditButton />}
1139
- * {capabilities.canDeleteDocs && <DeleteButton />}
1140
- * </div>
1141
- * );
1142
- * }
1143
- * ```
1144
- *
1145
- * @example
1146
- * ```typescript
1147
- * // Complex permission scenarios with multiple roles
1148
- * const adminUser: AuthUser = {
1149
- * id: "admin001",
1150
- * perms: {
1151
- * profile: ["read", "update"]
1152
- * },
1153
- * roles: [
1154
- * {
1155
- * name: "super_admin",
1156
- * perms: {
1157
- * users: ["all"],
1158
- * system: ["all"],
1159
- * reports: ["all"]
1160
- * }
1161
- * },
1162
- * {
1163
- * name: "content_manager",
1164
- * perms: {
1165
- * documents: ["read", "create", "update", "delete"],
1166
- * media: ["upload", "edit", "delete"]
1167
- * }
1168
- * }
1169
- * ]
1170
- * };
1171
- *
1172
- * // Check various permissions
1173
- * console.log(Auth.checkUserPermission(adminUser, "users", "delete")); // true (super_admin role)
1174
- * console.log(Auth.checkUserPermission(adminUser, "documents", "create")); // true (content_manager role)
1175
- * console.log(Auth.checkUserPermission(adminUser, "profile", "update")); // true (direct permission)
1176
- * console.log(Auth.checkUserPermission(adminUser, "billing", "read")); // false (no permission)
1177
- * ```
1178
- *
1179
- * @see {@link AuthUser} - Complete user object interface with permissions and roles
1180
- * @see {@link ResourceName} - Valid resource name types for permission checking
1181
- * @see {@link ResourceActionName} - Valid action types for permission operations
1182
- * @see {@link checkPermission} - Lower-level permission checking against permission objects
1183
- * @see {@link isAllowed} - Higher-level permission checking with multiple formats
1184
- * @see {@link AuthPerms} - Permission object structure and format
1185
- * @see {@link AuthRole} - Role object structure with embedded permissions
1186
- *
1187
- *
1188
- * @public
1189
- *
1190
- * @remarks
1191
- * **Security Best Practices:**
1192
- * - Always validate user input before calling this method
1193
- * - Use this method as the primary gate for access control decisions
1194
- * - Consider implementing audit logging for permission checks in security-sensitive applications
1195
- * - Regularly review and update permission models as application requirements evolve
1196
- *
1197
- * **Performance Considerations:**
1198
- * - The method uses early return for optimal performance
1199
- * - Role iteration stops at the first matching permission found
1200
- * - Consider caching results for frequently checked permissions
1201
- * - Large role hierarchies may impact performance; consider flattening permissions when possible
1202
- *
1203
- * **Design Patterns:**
1204
- * - Implements the "Fail-Safe Defaults" security pattern
1205
- * - Supports both direct and inherited permission models
1206
- * - Compatible with Role-Based Access Control (RBAC) systems
1207
- * - Integrates seamlessly with middleware and guard patterns
1208
- *
1209
- * **Error Handling:**
1210
- * - Returns `false` for any invalid or malformed input
1211
- * - Gracefully handles missing permission structures
1212
- * - Does not throw exceptions, making it safe for use in conditional statements
1213
- * - Logs errors internally for debugging purposes without exposing sensitive information
1214
- */
1215
- static checkUserPermission<TResourceName extends ResourceName = ResourceName>(user: AuthUser, resource: TResourceName, action?: ResourceActionName<TResourceName>): boolean;
1216
- /**
1217
- * Evaluates whether a permission object grants access to perform a specific action on a resource.
1218
- *
1219
- * This fundamental permission checking method serves as the core authorization engine for
1220
- * the authentication system. It performs low-level permission validation by examining
1221
- * permission objects and determining if they contain the necessary action permissions
1222
- * for a given resource. The method implements case-insensitive resource matching and
1223
- * supports both specific action permissions and universal "all" permissions.
1224
- *
1225
- * ### Permission Evaluation Algorithm:
1226
- * 1. **Input Sanitization**: Normalizes and validates input parameters for consistent processing
1227
- * 2. **Resource Matching**: Performs case-insensitive resource name matching in permission object
1228
- * 3. **Action Discovery**: Extracts the list of allowed actions for the matched resource
1229
- * 4. **Universal Permission Check**: Returns `true` immediately if "all" permission is found
1230
- * 5. **Specific Action Validation**: Iterates through actions to find exact or compatible matches
1231
- * 6. **Fail-Safe Return**: Returns `false` if no matching permissions are discovered
1232
- *
1233
- * ### Security Features:
1234
- * - **Defensive Programming**: Validates all inputs and handles malformed data gracefully
1235
- * - **Case-Insensitive Matching**: Prevents permission bypass through case manipulation
1236
- * - **Universal Permission Support**: Recognizes "all" as a wildcard permission
1237
- * - **Strict Validation**: Requires exact resource and action matches for security
1238
- *
1239
- * ### Performance Optimization:
1240
- * - **Early Exit Strategy**: Returns immediately when "all" permission is found
1241
- * - **Efficient Iteration**: Stops processing at the first matching permission
1242
- * - **Memory Safety**: Creates defensive copies of input objects to prevent mutation
1243
- * - **Minimal Processing**: Only processes relevant permission entries
1244
- *
1245
- * @template TResourceName - The resource name type constraint extending ResourceName
1246
- *
1247
- * @param perms - The permission object containing resource-to-actions mappings.
1248
- * Must be a valid `AuthPerms` object where keys are resource names
1249
- * and values are arrays of allowed actions. The object is defensively
1250
- * copied to prevent external mutations during processing.
1251
- *
1252
- * @param resource - The resource name to check permissions for.
1253
- * Should be a valid identifier from the `ResourceName` type.
1254
- * The resource name undergoes case-insensitive matching, so
1255
- * "Documents", "documents", and "DOCUMENTS" are treated as equivalent.
1256
- * Empty or invalid resource names result in permission denial.
1257
- *
1258
- * @param action - The specific action to validate against the resource permissions.
1259
- * Defaults to "read" if not specified. The action must match exactly
1260
- * (case-insensitive) with one of the allowed actions in the permission
1261
- * array, or the resource must have "all" permission for universal access.
1262
- *
1263
- * @returns `true` if the permission object grants the specified action on the resource,
1264
- * either through explicit action permission or universal "all" permission.
1265
- * Returns `false` if permissions are insufficient, invalid, or if input
1266
- * validation fails.
1267
- *
1268
- * @example
1269
- * ```typescript
1270
- * // Basic permission checking with explicit actions
1271
- * const permissions: AuthPerms = {
1272
- * documents: ["read", "create", "update"],
1273
- * users: ["read"],
1274
- * reports: ["read", "export"]
1275
- * };
1276
- *
1277
- * // Check various permissions
1278
- * const canReadDocs = Auth.checkPermission(permissions, "documents", "read");
1279
- * console.log(canReadDocs); // true
1280
- *
1281
- * const canDeleteDocs = Auth.checkPermission(permissions, "documents", "delete");
1282
- * console.log(canDeleteDocs); // false
1283
- *
1284
- * const canCreateUsers = Auth.checkPermission(permissions, "users", "create");
1285
- * console.log(canCreateUsers); // false
1286
- * ```
1287
- *
1288
- * @example
1289
- * ```typescript
1290
- * // Universal "all" permission handling
1291
- * const adminPermissions: AuthPerms = {
1292
- * system: ["all"],
1293
- * documents: ["read", "create"],
1294
- * users: ["all"]
1295
- * };
1296
- *
1297
- * // "all" permission grants access to any action
1298
- * console.log(Auth.checkPermission(adminPermissions, "system", "configure")); // true
1299
- * console.log(Auth.checkPermission(adminPermissions, "system", "delete")); // true
1300
- * console.log(Auth.checkPermission(adminPermissions, "system", "custom_action")); // true
1301
- *
1302
- * // Specific permissions still work normally
1303
- * console.log(Auth.checkPermission(adminPermissions, "documents", "read")); // true
1304
- * console.log(Auth.checkPermission(adminPermissions, "documents", "delete")); // false
1305
- * ```
1306
- *
1307
- * @example
1308
- * ```typescript
1309
- * // Case-insensitive resource matching
1310
- * const permissions: AuthPerms = {
1311
- * Documents: ["read", "write"],
1312
- * USERS: ["read"],
1313
- * api_endpoints: ["access"]
1314
- * };
1315
- *
1316
- * // All of these will match the "Documents" resource
1317
- * console.log(Auth.checkPermission(permissions, "documents", "read")); // true
1318
- * console.log(Auth.checkPermission(permissions, "DOCUMENTS", "read")); // true
1319
- * console.log(Auth.checkPermission(permissions, "DoCtMeNtS", "read")); // true
1320
- *
1321
- * // Case-insensitive matching for all resources
1322
- * console.log(Auth.checkPermission(permissions, "users", "read")); // true
1323
- * console.log(Auth.checkPermission(permissions, "API_ENDPOINTS", "access")); // true
1324
- * ```
1325
- *
1326
- * @example
1327
- * ```typescript
1328
- * // Default action parameter behavior
1329
- * const readOnlyPermissions: AuthPerms = {
1330
- * articles: ["read"],
1331
- * news: ["read", "comment"],
1332
- * profiles: ["read", "update"]
1333
- * };
1334
- *
1335
- * // These calls are equivalent (default action is "read")
1336
- * const canRead1 = Auth.checkPermission(readOnlyPermissions, "articles", "read");
1337
- * const canRead2 = Auth.checkPermission(readOnlyPermissions, "articles");
1338
- * console.log(canRead1 === canRead2); // true, both return true
1339
- *
1340
- * // Default "read" action checking
1341
- * console.log(Auth.checkPermission(readOnlyPermissions, "news")); // true (has read)
1342
- * console.log(Auth.checkPermission(readOnlyPermissions, "profiles")); // true (has read)
1343
- * ```
1344
- *
1345
- * @example
1346
- * ```typescript
1347
- * // Error handling and edge cases
1348
- * const validPermissions: AuthPerms = { docs: ["read"] };
1349
- * const emptyPermissions: AuthPerms = {};
1350
- * const nullPermissions = null;
1351
- *
1352
- * // Valid permission object
1353
- * console.log(Auth.checkPermission(validPermissions, "docs", "read")); // true
1354
- *
1355
- * // Empty permission object
1356
- * console.log(Auth.checkPermission(emptyPermissions, "docs", "read")); // false
1357
- *
1358
- * // Invalid permission object
1359
- * console.log(Auth.checkPermission(nullPermissions as any, "docs", "read")); // false
1360
- *
1361
- * // Invalid resource name
1362
- * console.log(Auth.checkPermission(validPermissions, "" as ResourceName, "read")); // false
1363
- * console.log(Auth.checkPermission(validPermissions, null as any, "read")); // false
1364
- * ```
1365
- *
1366
- * @example
1367
- * ```typescript
1368
- * // Permission validation utility function
1369
- * function validateUserAccess(
1370
- * userPerms: AuthPerms,
1371
- * requiredResource: ResourceName,
1372
- * requiredAction: ResourceActionName
1373
- * ): { allowed: boolean; reason: string } {
1374
- * if (!userPerms || typeof userPerms !== 'object') {
1375
- * return { allowed: false, reason: 'Invalid permission object' };
1376
- * }
1377
- *
1378
- * if (!requiredResource) {
1379
- * return { allowed: false, reason: 'Resource name is required' };
1380
- * }
1381
- *
1382
- * const hasPermission = Auth.checkPermission(userPerms, requiredResource, requiredAction);
1383
- *
1384
- * return {
1385
- * allowed: hasPermission,
1386
- * reason: hasPermission
1387
- * ? `Access granted for ${requiredAction} on ${requiredResource}`
1388
- * : `Access denied: insufficient permissions for ${requiredAction} on ${requiredResource}`
1389
- * };
1390
- * }
1391
- *
1392
- * // Usage example
1393
- * const userPermissions: AuthPerms = {
1394
- * documents: ["read", "create"],
1395
- * users: ["read"]
1396
- * };
1397
- *
1398
- * const result = validateUserAccess(userPermissions, "documents", "update");
1399
- * console.log(result); // { allowed: false, reason: "Access denied: insufficient permissions..." }
1400
- * ```
1401
- *
1402
- * @example
1403
- * ```typescript
1404
- * // Integration with role-based permission systems
1405
- * class PermissionManager {
1406
- * static combinePermissions(...permissionSets: AuthPerms[]): AuthPerms {
1407
- * const combined: AuthPerms = {};
1408
- *
1409
- * for (const perms of permissionSets) {
1410
- * if (!perms) continue;
1411
- *
1412
- * for (const [resource, actions] of Object.entries(perms)) {
1413
- * if (!combined[resource as keyof AuthPerms]) {
1414
- * combined[resource as keyof AuthPerms] = [];
1415
- * }
1416
- *
1417
- * const existingActions = combined[resource as keyof AuthPerms] as ResourceActionName[];
1418
- * const newActions = actions as ResourceActionName[];
1419
- *
1420
- * // Merge actions, avoiding duplicates
1421
- * for (const action of newActions) {
1422
- * if (!existingActions.includes(action)) {
1423
- * existingActions.push(action);
1424
- * }
1425
- * }
1426
- * }
1427
- * }
1428
- *
1429
- * return combined;
1430
- * }
1431
- *
1432
- * static hasAnyPermission(perms: AuthPerms, checks: Array<[ResourceName, ResourceActionName]>): boolean {
1433
- * return checks.some(([resource, action]) =>
1434
- * Auth.checkPermission(perms, resource, action)
1435
- * );
1436
- * }
1437
- *
1438
- * static hasAllPermissions(perms: AuthPerms, checks: Array<[ResourceName, ResourceActionName]>): boolean {
1439
- * return checks.every(([resource, action]) =>
1440
- * Auth.checkPermission(perms, resource, action)
1441
- * );
1442
- * }
1443
- * }
1444
- *
1445
- * // Usage
1446
- * const userPerms: AuthPerms = { documents: ["read"], users: ["read", "update"] };
1447
- * const rolePerms: AuthPerms = { documents: ["create"], reports: ["read"] };
1448
- *
1449
- * const combinedPerms = PermissionManager.combinePermissions(userPerms, rolePerms);
1450
- * console.log(Auth.checkPermission(combinedPerms, "documents", "create")); // true
1451
- * ```
1452
- *
1453
- * @see {@link AuthPerms} - Permission object structure and type definitions
1454
- * @see {@link ResourceName} - Valid resource name types for permission checking
1455
- * @see {@link ResourceActionName} - Valid action types for permission operations
1456
- * @see {@link checkUserPermission} - Higher-level user permission checking method
1457
- * @see {@link isAllowed} - Comprehensive permission evaluation with multiple formats
1458
- * @see {@link isAllowedForAction} - Action-specific permission matching utility
1459
- *
1460
- *
1461
- * @public
1462
- *
1463
- * @remarks
1464
- * **Security Considerations:**
1465
- * - This method performs case-insensitive matching to prevent security bypasses
1466
- * - Always validates input parameters to prevent injection or manipulation attacks
1467
- * - Returns `false` by default for any ambiguous or invalid scenarios
1468
- * - The "all" permission should be used carefully as it grants universal access
1469
- *
1470
- * **Performance Best Practices:**
1471
- * - The method creates defensive copies of input objects, consider caching results for frequently checked permissions
1472
- * - Early termination when "all" permission is found improves performance for administrative users
1473
- * - Use this method as the foundation for higher-level permission checking utilities
1474
- * - Consider implementing permission result caching for high-frequency checks
1475
- *
1476
- * **Design Patterns:**
1477
- * - Implements the "Secure by Default" principle with fail-safe returns
1478
- * - Supports the Strategy pattern through flexible action matching
1479
- * - Compatible with Role-Based Access Control (RBAC) and Attribute-Based Access Control (ABAC) systems
1480
- * - Follows the Single Responsibility Principle by focusing solely on permission object evaluation
1481
- *
1482
- * **Error Handling Strategy:**
1483
- * - Never throws exceptions, always returns boolean values for predictable behavior
1484
- * - Handles null, undefined, and malformed inputs gracefully
1485
- * - Provides meaningful return values that can be safely used in conditional statements
1486
- * - Logs internal errors for debugging without exposing sensitive permission details
1487
- */
1488
- static checkPermission<TResourceName extends ResourceName = ResourceName>(perms: AuthPerms, resource: TResourceName, action?: ResourceActionName<TResourceName>): boolean;
9
+ export declare class Auth {
1489
10
  /**
1490
- * Determines whether a specific permission action matches a requested action.
1491
- *
1492
- * This utility method performs precise action-to-action comparison for permission validation.
1493
- * It serves as the atomic-level matching function in the permission checking hierarchy,
1494
- * providing case-insensitive string comparison with proper normalization. The method
1495
- * ensures that permission actions are evaluated consistently and securely across the
1496
- * entire authentication system.
1497
- *
1498
- * ### Matching Algorithm:
1499
- * 1. **Input Validation**: Ensures both parameters are valid non-null strings
1500
- * 2. **String Normalization**: Trims whitespace and converts to lowercase for comparison
1501
- * 3. **Exact Matching**: Performs strict equality comparison after normalization
1502
- * 4. **Binary Result**: Returns boolean result for immediate conditional usage
1503
- *
1504
- * ### Security Features:
1505
- * - **Case-Insensitive Matching**: Prevents permission bypass through case manipulation
1506
- * - **Whitespace Normalization**: Eliminates accidental whitespace-based security issues
1507
- * - **Strict Validation**: Rejects null, undefined, or non-string inputs for security
1508
- * - **Deterministic Behavior**: Always produces consistent results for identical inputs
1509
- *
1510
- * ### Performance Characteristics:
1511
- * - **Minimal Overhead**: Lightweight string operations with O(1) complexity
1512
- * - **Early Termination**: Returns immediately on validation failure
1513
- * - **String Optimization**: Uses native JavaScript string methods for efficiency
1514
- * - **Memory Efficient**: No intermediate object creation or complex processing
1515
- *
1516
- * @template TResourceName - The resource name type constraint extending ResourceName
1517
- *
1518
- * @param permFromResource - The permission action to check against.
1519
- * Must be a valid string conforming to `ResourceActionName<TResourceName>`.
1520
- * This represents the action that is granted by a permission entry.
1521
- * Examples: "read", "write", "delete", "create", "all", "custom_action".
1522
- * Empty strings, null, or undefined values will result in `false`.
1523
- *
1524
- * @param action - The requested action to validate.
1525
- * Must be a valid string conforming to `ResourceActionName<TResourceName>`.
1526
- * This represents the action that a user is attempting to perform.
1527
- * The comparison is performed case-insensitively with whitespace trimming.
1528
- * Examples: "READ", "Write", " delete ", "CREATE", "All".
1529
- *
1530
- * @returns `true` if the permission action exactly matches the requested action
1531
- * after case-insensitive comparison and whitespace normalization.
1532
- * Returns `false` if either parameter is invalid, null, undefined,
1533
- * empty, or if the normalized strings do not match exactly.
1534
- *
1535
- * @example
1536
- * ```typescript
1537
- * // Basic exact matching (case-insensitive)
1538
- * console.log(Auth.isAllowedForAction("read", "read")); // true
1539
- * console.log(Auth.isAllowedForAction("READ", "read")); // true
1540
- * console.log(Auth.isAllowedForAction("Read", "READ")); // true
1541
- * console.log(Auth.isAllowedForAction("write", "read")); // false
1542
- * ```
1543
- *
1544
- * @example
1545
- * ```typescript
1546
- * // Whitespace handling and normalization
1547
- * console.log(Auth.isAllowedForAction(" read ", "read")); // true
1548
- * console.log(Auth.isAllowedForAction("update", " UPDATE ")); // true
1549
- * console.log(Auth.isAllowedForAction("\tdelete\n", "delete")); // true
1550
- * console.log(Auth.isAllowedForAction("create ", " create")); // true
1551
- * ```
1552
- *
1553
- * @example
1554
- * ```typescript
1555
- * // Input validation and edge cases
1556
- * console.log(Auth.isAllowedForAction("", "read")); // false (empty permission)
1557
- * console.log(Auth.isAllowedForAction("read", "")); // false (empty action)
1558
- * console.log(Auth.isAllowedForAction(null as any, "read")); // false (null permission)
1559
- * console.log(Auth.isAllowedForAction("read", undefined as any)); // false (undefined action)
1560
- * console.log(Auth.isAllowedForAction("valid", "valid")); // true (both valid)
1561
- * ```
1562
- *
1563
- * @example
1564
- * ```typescript
1565
- * // Integration with permission checking workflow
1566
- * function checkSpecificPermission(
1567
- * userActions: ResourceActionName[],
1568
- * requiredAction: ResourceActionName
1569
- * ): boolean {
1570
- * // Check if user has "all" permission (universal access)
1571
- * if (userActions.includes("all")) {
1572
- * return true;
1573
- * }
1574
- *
1575
- * // Check each specific action permission
1576
- * for (const userAction of userActions) {
1577
- * if (Auth.isAllowedForAction(userAction, requiredAction)) {
1578
- * return true;
1579
- * }
1580
- * }
1581
- *
1582
- * return false;
1583
- * }
1584
- *
1585
- * // Usage example
1586
- * const userPermissions: ResourceActionName[] = ["read", "UPDATE", " create "];
1587
- *
1588
- * console.log(checkSpecificPermission(userPermissions, "read")); // true
1589
- * console.log(checkSpecificPermission(userPermissions, "update")); // true (case-insensitive)
1590
- * console.log(checkSpecificPermission(userPermissions, "create")); // true (whitespace normalized)
1591
- * console.log(checkSpecificPermission(userPermissions, "delete")); // false
1592
- * ```
1593
- *
1594
- * @example
1595
- * ```typescript
1596
- * // Custom action validation system
1597
- * class ActionValidator {
1598
- * private static readonly VALID_ACTIONS = [
1599
- * "read", "create", "update", "delete",
1600
- * "list", "search", "export", "import", "all"
1601
- * ];
1602
- *
1603
- * static isValidAction(action: string): boolean {
1604
- * return this.VALID_ACTIONS.some(validAction =>
1605
- * Auth.isAllowedForAction(validAction, action)
1606
- * );
1607
- * }
1608
- *
1609
- * static normalizeAction(action: string): string {
1610
- * if (!action || typeof action !== 'string') {
1611
- * return '';
1612
- * }
1613
- * return action.trim().toLowerCase();
1614
- * }
1615
- *
1616
- * static compareActions(action1: string, action2: string): boolean {
1617
- * return Auth.isAllowedForAction(action1, action2);
1618
- * }
1619
- * }
1620
- *
1621
- * // Usage
1622
- * console.log(ActionValidator.isValidAction("READ")); // true
1623
- * console.log(ActionValidator.isValidAction("INVALID")); // false
1624
- * console.log(ActionValidator.compareActions("Create", "create")); // true
1625
- * ```
1626
- *
1627
- * @example
1628
- * ```typescript
1629
- * // Permission matrix validation
1630
- * interface PermissionCheck {
1631
- * granted: ResourceActionName;
1632
- * requested: ResourceActionName;
1633
- * expected: boolean;
1634
- * }
11
+ * Authentication event handler.
12
+ * Initializes an observable event handler for authentication Auth.events.
1635
13
  *
1636
- * function validatePermissionMatrix(checks: PermissionCheck[]): boolean {
1637
- * return checks.every(check => {
1638
- * const result = Auth.isAllowedForAction(check.granted, check.requested);
1639
- * if (result !== check.expected) {
1640
- * console.error(`Permission check failed: ${check.granted} vs ${check.requested}`);
1641
- * return false;
1642
- * }
1643
- * return true;
1644
- * });
1645
- * }
14
+ * This constant `events` is assigned an instance of `Observable<AuthEvent>`, which is used to manage
15
+ * authentication-related events in the application. The initialization checks if the global
16
+ * `Global.eventsResourcesObservableHandler` exists and is an object. If it does, it assigns it to
17
+ * `events`; otherwise, it defaults to an empty object cast as `Observable<AuthEvent>`.
1646
18
  *
1647
- * // Test matrix
1648
- * const permissionTests: PermissionCheck[] = [
1649
- * { granted: "read", requested: "read", expected: true },
1650
- * { granted: "READ", requested: "read", expected: true },
1651
- * { granted: "write", requested: "read", expected: false },
1652
- * { granted: " update ", requested: "UPDATE", expected: true },
1653
- * { granted: "all", requested: "anything", expected: true }
1654
- * ];
19
+ * This pattern allows for flexible handling of events, ensuring that the application can respond
20
+ * to authentication actions such as sign-in, sign-out, and sign-up.
1655
21
  *
1656
- * const allTestsPassed = validatePermissionMatrix(permissionTests);
1657
- * console.log(`All permission tests passed: ${allTestsPassed}`);
1658
- * ```
22
+ * @type {Observable<AuthEvent>}
1659
23
  *
1660
24
  * @example
1661
- * ```typescript
1662
- * // Real-world usage in permission engine
1663
- * class PermissionEngine {
1664
- * static evaluateActionPermission(
1665
- * grantedActions: ResourceActionName[],
1666
- * requestedAction: ResourceActionName
1667
- * ): { allowed: boolean; matchedAction?: ResourceActionName } {
1668
- * // Check for universal permission first
1669
- * if (grantedActions.includes("all")) {
1670
- * return { allowed: true, matchedAction: "all" };
1671
- * }
1672
- *
1673
- * // Find specific matching action
1674
- * for (const grantedAction of grantedActions) {
1675
- * if (Auth.isAllowedForAction(grantedAction, requestedAction)) {
1676
- * return { allowed: true, matchedAction: grantedAction };
1677
- * }
1678
- * }
25
+ * import {Auth} from 'reslib/auth';
26
+ * Auth.events.on('SIGN_IN', (user) => {
27
+ * console.log(`User signed in: ${user.username}`);
28
+ * });
1679
29
  *
1680
- * return { allowed: false };
1681
- * }
30
+ * function userSignIn(user) {
31
+ * Auth.events.trigger('SIGN_IN', user);
1682
32
  * }
1683
- *
1684
- * // Usage
1685
- * const result = PermissionEngine.evaluateActionPermission(
1686
- * ["read", "CREATE", " update "],
1687
- * "create"
1688
- * );
1689
- * console.log(result); // { allowed: true, matchedAction: "CREATE" }
1690
- * ```
1691
- *
1692
- * @see {@link ResourceActionName} - Type definition for valid action names
1693
- * @see {@link checkPermission} - Higher-level permission checking method that uses this function
1694
- * @see {@link checkUserPermission} - User-specific permission validation
1695
- * @see {@link isAllowed} - Comprehensive permission evaluation system
1696
- *
1697
- *
1698
- * @public
1699
- *
1700
- * @remarks
1701
- * **Implementation Notes:**
1702
- * - This method is used internally by `checkPermission` for action matching
1703
- * - The case-insensitive comparison helps prevent common permission configuration errors
1704
- * - Whitespace trimming ensures that formatting inconsistencies don't affect security
1705
- * - The method is designed to be called frequently, so performance is optimized
1706
- *
1707
- * **Security Considerations:**
1708
- * - Input validation prevents type confusion attacks
1709
- * - Normalization prevents case-based permission bypass attempts
1710
- * - Exact matching after normalization ensures no unexpected permission grants
1711
- * - No regular expressions are used to avoid ReDoS vulnerabilities
1712
- *
1713
- * **Performance Optimization:**
1714
- * - Uses native string methods for maximum performance
1715
- * - Early return on invalid inputs minimizes processing time
1716
- * - No object allocation or complex logic for minimal memory footprint
1717
- * - Suitable for high-frequency permission checking scenarios
1718
- *
1719
- * **Testing Strategy:**
1720
- * - Test with various case combinations (lowercase, uppercase, mixed)
1721
- * - Verify whitespace handling (leading, trailing, internal spaces)
1722
- * - Validate edge cases (empty strings, null, undefined)
1723
- * - Ensure consistent behavior across different JavaScript environments
1724
33
  */
1725
- static isAllowedForAction<TResourceName extends ResourceName = ResourceName>(permFromResource: ResourceActionName<TResourceName>, action: ResourceActionName<TResourceName>): boolean;
34
+ static events: Observable<AuthEvent>;
35
+ private static localUserRef;
36
+ private static config;
37
+ static isMasterAdmin?: (user?: AuthUser) => Promise<boolean> | boolean;
1726
38
  /**
1727
- * Provides access to the Session utility class for authentication-related session management.
1728
- *
1729
- * This static getter exposes the Session class, which contains utility methods and properties
1730
- * for managing browser session storage, encrypted data persistence, and session-related
1731
- * operations. It serves as a convenient access point to session functionality without
1732
- * requiring separate imports, maintaining the cohesive design of the Auth class API.
1733
- *
1734
- * ### Session Management Features:
1735
- * The Session class provides comprehensive session management capabilities including:
1736
- * - **Encrypted Storage**: Secure storage and retrieval of sensitive session data
1737
- * - **Cross-Tab Synchronization**: Session state management across multiple browser tabs
1738
- * - **Storage Abstraction**: Unified interface for localStorage and sessionStorage
1739
- * - **Data Serialization**: Automatic JSON serialization/deserialization with error handling
1740
- * - **Storage Events**: Event-driven session updates and notifications
1741
- *
1742
- * ### Integration Benefits:
1743
- * - **Unified API**: Access session functionality through the Auth class namespace
1744
- * - **Consistent Interface**: Maintains the same design patterns as other Auth methods
1745
- * - **Type Safety**: Full TypeScript support with proper type definitions
1746
- * - **Documentation**: Comprehensive JSDoc documentation for all session methods
1747
- *
1748
- * @returns The Session class containing static methods for session management.
1749
- * This includes methods for storing, retrieving, and managing encrypted
1750
- * session data, as well as utilities for session lifecycle management.
1751
- *
1752
- * @example
1753
- * ```typescript
1754
- * // Basic session storage operations
1755
- * const session = Auth.Session;
1756
- *
1757
- * // Store data in session
1758
- * await session.set('user_preferences', { theme: 'dark', language: 'en' });
1759
- *
1760
- * // Retrieve data from session
1761
- * const preferences = session.get('user_preferences');
1762
- * console.log(preferences); // { theme: 'dark', language: 'en' }
1763
- *
1764
- * // Remove data from session
1765
- * await session.remove('user_preferences');
1766
- * ```
1767
- *
1768
- * @example
1769
- * ```typescript
1770
- * // Encrypted session data management
1771
- * const session = Auth.Session;
1772
- *
1773
- * // Store sensitive data with encryption
1774
- * const sensitiveData = {
1775
- * apiKey: 'secret_api_key_12345',
1776
- * userToken: 'bearer_token_xyz789',
1777
- * personalInfo: { ssn: '123-45-6789', creditCard: '4111-1111-1111-1111' }
1778
- * };
1779
- *
1780
- * await session.setEncrypted('sensitive_data', sensitiveData, 'encryption_key');
1781
- *
1782
- * // Retrieve and decrypt sensitive data
1783
- * const decryptedData = session.getEncrypted('sensitive_data', 'encryption_key');
1784
- * console.log(decryptedData.apiKey); // 'secret_api_key_12345'
1785
- * ```
1786
- *
1787
- * @example
1788
- * ```typescript
1789
- * // Session lifecycle management
1790
- * const session = Auth.Session;
1791
- *
1792
- * // Initialize session with configuration
1793
- * session.configure({
1794
- * storageType: 'sessionStorage', // or 'localStorage'
1795
- * encryptionEnabled: true,
1796
- * keyPrefix: 'myapp_',
1797
- * maxAge: 3600000 // 1 hour in milliseconds
1798
- * });
1799
- *
1800
- * // Check session validity
1801
- * const isValid = session.isValid('user_session');
1802
- * if (isValid) {
1803
- * console.log('Session is still valid');
1804
- * } else {
1805
- * console.log('Session has expired or is invalid');
1806
- * }
1807
- *
1808
- * // Clear expired sessions
1809
- * session.clearExpired();
1810
- * ```
39
+ * Configures the Auth module with custom settings.
1811
40
  *
41
+ * @param options - Configuration options
1812
42
  * @example
1813
- * ```typescript
1814
- * // Cross-tab session synchronization
1815
- * const session = Auth.Session;
1816
- *
1817
- * // Listen for session changes across tabs
1818
- * session.onStorageChange((event) => {
1819
- * console.log('Session changed in another tab:', event);
1820
- * if (event.key === 'user_session' && event.newValue === null) {
1821
- * console.log('User logged out in another tab');
1822
- * handleCrossTabLogout();
1823
- * }
43
+ * Auth.configure({
44
+ * encryptionKey: process.env.AUTH_KEY,
45
+ * sessionTTL: 7 * 24 * 60 * 60 * 1000, // 7 days
46
+ * masterAdminCheck: (user) => user?.roles?.includes('admin')
1824
47
  * });
48
+ */
49
+ static configure(options: AuthConfig): void;
50
+ private static _isMasterAdmin;
51
+ /**
52
+ * Validates if a session is expired based on configured TTL.
53
+ * @param sessionCreatedAt - Session creation timestamp
54
+ * @returns true if session is valid, false if expired
55
+ */
56
+ private static isSessionValid;
57
+ /**
58
+ * Retrieves the currently authenticated user from secure storage.
1825
59
  *
1826
- * // Broadcast session updates to other tabs
1827
- * await session.broadcast('user_status_change', { status: 'online' });
1828
- * ```
1829
- *
1830
- * @example
1831
- * ```typescript
1832
- * // Session-based caching system
1833
- * class SessionCache {
1834
- * private static session = Auth.Session;
1835
- *
1836
- * static async cacheApiResponse<T>(key: string, data: T, ttl: number = 300000): Promise<void> {
1837
- * const cacheEntry = {
1838
- * data,
1839
- * timestamp: Date.now(),
1840
- * ttl
1841
- * };
1842
- *
1843
- * await this.session.set(`cache_${key}`, cacheEntry);
1844
- * }
1845
- *
1846
- * static getCachedData<T>(key: string): T | null {
1847
- * const cacheEntry = this.session.get(`cache_${key}`);
1848
- *
1849
- * if (!cacheEntry) return null;
1850
- *
1851
- * const { data, timestamp, ttl } = cacheEntry;
1852
- * const isExpired = Date.now() - timestamp > ttl;
1853
- *
1854
- * if (isExpired) {
1855
- * this.session.remove(`cache_${key}`);
1856
- * return null;
1857
- * }
1858
- *
1859
- * return data;
1860
- * }
1861
- *
1862
- * static clearCache(): void {
1863
- * this.session.clearByPrefix('cache_');
1864
- * }
1865
- * }
1866
- *
1867
- * // Usage
1868
- * await SessionCache.cacheApiResponse('user_profile', userData, 600000); // 10 minutes
1869
- * const cachedProfile = SessionCache.getCachedData('user_profile');
1870
- * ```
1871
- *
1872
- * @example
1873
- * ```typescript
1874
- * // Integration with authentication workflow
1875
- * class AuthSessionManager {
1876
- * private static session = Auth.Session;
1877
- *
1878
- * static async storeAuthSession(user: AuthUser, rememberMe: boolean = false): Promise<void> {
1879
- * const sessionData = {
1880
- * user,
1881
- * timestamp: Date.now(),
1882
- * rememberMe,
1883
- * sessionId: crypto.randomUUID()
1884
- * };
1885
- *
1886
- * const storageType = rememberMe ? 'localStorage' : 'sessionStorage';
1887
- *
1888
- * await this.session.setWithOptions('auth_session', sessionData, {
1889
- * storage: storageType,
1890
- * encrypted: true,
1891
- * maxAge: rememberMe ? 2592000000 : 86400000 // 30 days or 1 day
1892
- * });
1893
- * }
1894
- *
1895
- * static getAuthSession(): { user: AuthUser; sessionId: string } | null {
1896
- * const sessionData = this.session.getDecrypted('auth_session');
1897
- *
1898
- * if (!sessionData || this.isSessionExpired(sessionData)) {
1899
- * this.clearAuthSession();
1900
- * return null;
1901
- * }
1902
- *
1903
- * return {
1904
- * user: sessionData.user,
1905
- * sessionId: sessionData.sessionId
1906
- * };
1907
- * }
1908
- *
1909
- * static clearAuthSession(): void {
1910
- * this.session.remove('auth_session');
1911
- * this.session.clearByPrefix('user_');
1912
- * }
1913
- *
1914
- * private static isSessionExpired(sessionData: any): boolean {
1915
- * const maxAge = sessionData.rememberMe ? 2592000000 : 86400000;
1916
- * return Date.now() - sessionData.timestamp > maxAge;
1917
- * }
1918
- * }
1919
- * ```
1920
- *
1921
- * @see {@link Session} - The Session class with complete session management functionality
1922
- * @see {@link setSignedUser} - Method that uses Session for storing encrypted user data
1923
- * @see {@link getSignedUser} - Method that uses Session for retrieving encrypted user data
1924
- * @see {@link AuthUser} - User interface that may be stored in session
1925
- *
1926
- *
1927
- * @public
1928
- * @readonly
1929
- *
1930
- * @remarks
1931
- * **Usage Patterns:**
1932
- * - Use `Auth.Session` for all session-related operations within authentication workflows
1933
- * - The Session class provides both synchronous and asynchronous methods for flexibility
1934
- * - Encrypted storage methods should be used for sensitive authentication data
1935
- * - Consider session storage vs local storage based on data persistence requirements
1936
- *
1937
- * **Security Considerations:**
1938
- * - Always use encrypted storage methods for sensitive authentication data
1939
- * - Be aware that session storage is cleared when the browser tab closes
1940
- * - Local storage persists across browser sessions and should be used carefully
1941
- * - Implement proper session timeout and cleanup mechanisms
60
+ * @returns The authenticated user or null if not signed in
61
+ */
62
+ static getSignedUser(): Promise<AuthUser | null>;
63
+ /**
64
+ * Forces a refresh of the user session from storage.
65
+ * Clears the cache and retrieves fresh data.
1942
66
  *
1943
- * **Performance Notes:**
1944
- * - Session operations are generally fast but may involve encryption/decryption overhead
1945
- * - Consider caching frequently accessed session data to reduce storage operations
1946
- * - Be mindful of storage quotas when storing large amounts of session data
1947
- * - Use appropriate storage types (sessionStorage vs localStorage) based on use case
67
+ * @returns The refreshed user object or null
68
+ */
69
+ static refreshSignedUser(): Promise<AuthUser | null>;
70
+ /**
71
+ * Securely stores an authenticated user in secure storage.
72
+ * Only triggers events if storage operation succeeds.
1948
73
  *
1949
- * **Browser Compatibility:**
1950
- * - Session functionality is supported in all modern browsers
1951
- * - Fallback mechanisms are available for environments without storage support
1952
- * - Storage events work consistently across different browser implementations
1953
- * - Encryption features require a compatible JavaScript environment
74
+ * @param u - The user object to store, or null to sign out
75
+ * @param triggerEvent - Whether to trigger SIGN_IN/SIGN_OUT events
76
+ * @returns The stored user object
77
+ * @throws {AuthError} If storage operation fails
1954
78
  */
1955
- static get Session(): typeof Session;
79
+ static setSignedUser(u: AuthUser | null, triggerEvent?: boolean): Promise<AuthUser | null>;
80
+ static signIn(user: AuthUser, triggerEvent?: boolean): Promise<AuthUser>;
81
+ static signOut(triggerEvent?: boolean): Promise<void>;
82
+ private static isResourceActionTupleArray;
83
+ private static isResourceActionTupleObject;
84
+ static isValidUser(user: unknown): user is AuthUser;
85
+ static isAllowed<TResourceName extends ResourceName = ResourceName>(perm: AuthPerm<TResourceName>, user?: AuthUser | null): Promise<boolean>;
86
+ static checkUserPermission<TResourceName extends ResourceName = ResourceName>(user: AuthUser, resource: TResourceName, action?: ResourceActionName<TResourceName>): boolean;
87
+ static checkPermission<TResourceName extends ResourceName = ResourceName>(perms: AuthPerms, resource: TResourceName, action?: ResourceActionName<TResourceName>): boolean;
88
+ static isAllowedForAction<TResourceName extends ResourceName = ResourceName>(permFromResource: ResourceActionName<TResourceName>, action: ResourceActionName<TResourceName>): boolean;
1956
89
  private static _secureStorage;
1957
90
  /**
1958
91
  * Gets the currently configured secure storage implementation for authentication data.
@@ -2202,37 +335,6 @@ export declare class Auth {
2202
335
  * - Validate behavior across different platforms
2203
336
  */
2204
337
  static set secureStorage(secureStorage: AuthSecureStorage);
2205
- /**
2206
- * Retrieves the authentication token from secure storage.
2207
- *
2208
- * This method provides secure, cross-platform access to the stored authentication token.
2209
- * The token is stored separately from user data for enhanced security and to prevent
2210
- * accidental exposure through session data serialization.
2211
- *
2212
- * @returns Promise resolving to the token string, or null if no token is stored
2213
- * @example
2214
- * ```typescript
2215
- * const token = await Auth.getToken();
2216
- * if (token) {
2217
- * // Use token for API calls
2218
- * }
2219
- * ```
2220
- */
2221
- static getToken(): Promise<string | null>;
2222
- /**
2223
- * Stores the authentication token in secure storage.
2224
- *
2225
- * This method securely stores the authentication token using the configured secure storage
2226
- * implementation. The token is isolated from user session data for better security practices.
2227
- *
2228
- * @param token - The authentication token to store
2229
- * @returns Promise that resolves when the token is stored
2230
- * @example
2231
- * ```typescript
2232
- * await Auth.setToken('jwt-token-here');
2233
- * ```
2234
- */
2235
- static setToken(token: string): Promise<void>;
2236
338
  private static readonly authStorageMetaData;
2237
339
  }
2238
340
  /**