@nocios/crudify-ui 2.0.0 → 3.0.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.
@@ -1,512 +0,0 @@
1
- // src/core/TokenManager.ts
2
- import crudify from "@nocios/crudify-browser";
3
-
4
- // src/components/CrudifyLogin/utils/secureStorage.ts
5
- import CryptoJS from "crypto-js";
6
- var SecureStorage = class {
7
- constructor(storageType = "sessionStorage") {
8
- this.encryptionKey = this.generateEncryptionKey();
9
- this.storage = storageType === "localStorage" ? window.localStorage : window.sessionStorage;
10
- }
11
- generateEncryptionKey() {
12
- const browserFingerprint = [
13
- navigator.userAgent,
14
- navigator.language,
15
- (/* @__PURE__ */ new Date()).getTimezoneOffset(),
16
- screen.colorDepth,
17
- screen.width,
18
- screen.height,
19
- "crudify-login"
20
- ].join("|");
21
- return CryptoJS.SHA256(browserFingerprint).toString();
22
- }
23
- setItem(key, value, expiryMinutes) {
24
- try {
25
- const encrypted = CryptoJS.AES.encrypt(value, this.encryptionKey).toString();
26
- this.storage.setItem(key, encrypted);
27
- if (expiryMinutes) {
28
- const expiryTime = (/* @__PURE__ */ new Date()).getTime() + expiryMinutes * 60 * 1e3;
29
- this.storage.setItem(`${key}_expiry`, expiryTime.toString());
30
- }
31
- } catch (error) {
32
- console.error("Failed to encrypt and store data:", error);
33
- }
34
- }
35
- getItem(key) {
36
- try {
37
- const expiryKey = `${key}_expiry`;
38
- const expiry = this.storage.getItem(expiryKey);
39
- if (expiry) {
40
- const expiryTime = parseInt(expiry, 10);
41
- if ((/* @__PURE__ */ new Date()).getTime() > expiryTime) {
42
- this.removeItem(key);
43
- return null;
44
- }
45
- }
46
- const encrypted = this.storage.getItem(key);
47
- if (!encrypted) return null;
48
- const decrypted = CryptoJS.AES.decrypt(encrypted, this.encryptionKey);
49
- const result = decrypted.toString(CryptoJS.enc.Utf8);
50
- if (!result) {
51
- console.warn("Failed to decrypt stored data - may be corrupted");
52
- this.removeItem(key);
53
- return null;
54
- }
55
- return result;
56
- } catch (error) {
57
- console.error("Failed to decrypt data:", error);
58
- this.removeItem(key);
59
- return null;
60
- }
61
- }
62
- removeItem(key) {
63
- this.storage.removeItem(key);
64
- this.storage.removeItem(`${key}_expiry`);
65
- }
66
- setToken(token) {
67
- try {
68
- const parts = token.split(".");
69
- if (parts.length === 3) {
70
- const payload = JSON.parse(atob(parts[1]));
71
- if (payload.exp) {
72
- const expiryTime = payload.exp * 1e3;
73
- const now = (/* @__PURE__ */ new Date()).getTime();
74
- const minutesUntilExpiry = Math.floor((expiryTime - now) / (60 * 1e3));
75
- if (minutesUntilExpiry > 0) {
76
- this.setItem("authToken", token, minutesUntilExpiry);
77
- return;
78
- }
79
- }
80
- }
81
- } catch (error) {
82
- console.warn("Failed to parse token expiry, using default expiry");
83
- }
84
- this.setItem("authToken", token, 24 * 60);
85
- }
86
- getToken() {
87
- const token = this.getItem("authToken");
88
- if (token) {
89
- try {
90
- const parts = token.split(".");
91
- if (parts.length === 3) {
92
- const payload = JSON.parse(atob(parts[1]));
93
- if (payload.exp) {
94
- const now = Math.floor(Date.now() / 1e3);
95
- if (payload.exp < now) {
96
- this.removeItem("authToken");
97
- return null;
98
- }
99
- }
100
- }
101
- } catch (error) {
102
- console.warn("Failed to validate token expiry");
103
- this.removeItem("authToken");
104
- return null;
105
- }
106
- }
107
- return token;
108
- }
109
- };
110
- var secureSessionStorage = new SecureStorage("sessionStorage");
111
- var secureLocalStorage = new SecureStorage("localStorage");
112
-
113
- // src/utils/jwtUtils.ts
114
- var decodeJwtSafely = (token) => {
115
- try {
116
- const parts = token.split(".");
117
- if (parts.length !== 3) {
118
- console.warn("Invalid JWT format: token must have 3 parts");
119
- return null;
120
- }
121
- const payload = parts[1];
122
- const paddedPayload = payload + "=".repeat((4 - payload.length % 4) % 4);
123
- const decodedPayload = JSON.parse(atob(paddedPayload));
124
- return decodedPayload;
125
- } catch (error) {
126
- console.warn("Failed to decode JWT token:", error);
127
- return null;
128
- }
129
- };
130
- var getCurrentUserEmail = () => {
131
- try {
132
- let token = null;
133
- token = sessionStorage.getItem("authToken");
134
- console.log("\u{1F50D} getCurrentUserEmail - authToken:", token ? `${token.substring(0, 20)}...` : null);
135
- if (!token) {
136
- token = sessionStorage.getItem("token");
137
- console.log("\u{1F50D} getCurrentUserEmail - token:", token ? `${token.substring(0, 20)}...` : null);
138
- }
139
- if (!token) {
140
- token = localStorage.getItem("authToken") || localStorage.getItem("token");
141
- console.log("\u{1F50D} getCurrentUserEmail - localStorage:", token ? `${token.substring(0, 20)}...` : null);
142
- }
143
- if (!token) {
144
- console.warn("\u{1F50D} getCurrentUserEmail - No token found in any storage");
145
- return null;
146
- }
147
- const payload = decodeJwtSafely(token);
148
- if (!payload) {
149
- console.warn("\u{1F50D} getCurrentUserEmail - Failed to decode token");
150
- return null;
151
- }
152
- const email = payload.email || payload["cognito:username"] || null;
153
- console.log("\u{1F50D} getCurrentUserEmail - Extracted email:", email);
154
- return email;
155
- } catch (error) {
156
- console.warn("Failed to get current user email:", error);
157
- return null;
158
- }
159
- };
160
- var isTokenExpired = (token) => {
161
- try {
162
- const payload = decodeJwtSafely(token);
163
- if (!payload || !payload.exp) return true;
164
- const currentTime = Math.floor(Date.now() / 1e3);
165
- return payload.exp < currentTime;
166
- } catch {
167
- return true;
168
- }
169
- };
170
-
171
- // src/core/TokenManager.ts
172
- var _TokenManager = class _TokenManager {
173
- constructor() {
174
- this.TOKEN_KEY = "authToken";
175
- // Compatible with crudia-ui
176
- this.tokenCache = null;
177
- this.parsedTokenCache = null;
178
- this.expirationCheckInterval = null;
179
- this.storageEventListener = null;
180
- this.initializeTokenManager();
181
- }
182
- /**
183
- * Singleton pattern to ensure consistent token management
184
- */
185
- static getInstance() {
186
- if (!_TokenManager.instance) {
187
- _TokenManager.instance = new _TokenManager();
188
- }
189
- return _TokenManager.instance;
190
- }
191
- /**
192
- * Reset the singleton instance (useful for testing)
193
- */
194
- static resetInstance() {
195
- if (_TokenManager.instance) {
196
- _TokenManager.instance.cleanup();
197
- }
198
- _TokenManager.instance = null;
199
- }
200
- /**
201
- * Initialize the token manager with storage synchronization
202
- */
203
- initializeTokenManager() {
204
- console.log("\u{1F510} TokenManager - Initializing token management");
205
- this.migrateFromLocalStorage();
206
- this.loadTokenFromStorage();
207
- this.setupExpirationCheck();
208
- this.setupStorageListener();
209
- console.log("\u{1F510} TokenManager - Initialization complete");
210
- }
211
- /**
212
- * Migrate tokens from plain localStorage to encrypted localStorage
213
- * This ensures compatibility with older implementations
214
- */
215
- migrateFromLocalStorage() {
216
- try {
217
- const legacyKeys = ["authToken", "token", "jwt", "jwtToken"];
218
- for (const key of legacyKeys) {
219
- const token = localStorage.getItem(key);
220
- if (token && !secureLocalStorage.getToken()) {
221
- console.log(`\u{1F510} TokenManager - Migrating token from localStorage key: ${key}`);
222
- secureLocalStorage.setToken(token);
223
- localStorage.removeItem(key);
224
- break;
225
- }
226
- }
227
- } catch (error) {
228
- console.warn("\u{1F510} TokenManager - Token migration failed:", error);
229
- }
230
- }
231
- /**
232
- * Load token from storage and synchronize with crudify
233
- */
234
- loadTokenFromStorage() {
235
- console.log("\u{1F510} TokenManager - LOAD_FROM_STORAGE: Entry point - loading token from storage");
236
- try {
237
- console.log("\u{1F510} TokenManager - LOAD_FROM_STORAGE: Getting token from secure local storage");
238
- const storedToken = secureLocalStorage.getToken();
239
- console.log("\u{1F510} TokenManager - LOAD_FROM_STORAGE: Stored token exists:", !!storedToken);
240
- if (storedToken && this.isTokenValid(storedToken)) {
241
- console.log("\u{1F510} TokenManager - LOAD_FROM_STORAGE: Stored token is valid, updating cache");
242
- this.tokenCache = storedToken;
243
- this.parsedTokenCache = this.parseToken(storedToken);
244
- this.syncTokenWithCrudify(storedToken);
245
- console.log("\u{1F510} TokenManager - LOAD_FROM_STORAGE: Token loaded from storage and synchronized");
246
- } else if (storedToken) {
247
- console.log("\u{1F510} TokenManager - LOAD_FROM_STORAGE: Stored token exists but is invalid/expired, clearing");
248
- this.clearToken();
249
- } else {
250
- console.log("\u{1F510} TokenManager - LOAD_FROM_STORAGE: No stored token found");
251
- }
252
- } catch (error) {
253
- console.warn("\u{1F510} TokenManager - LOAD_FROM_STORAGE: Error loading token from storage:", error);
254
- this.clearToken();
255
- }
256
- }
257
- /**
258
- * Set up automatic token expiration checking
259
- */
260
- setupExpirationCheck() {
261
- this.expirationCheckInterval = window.setInterval(() => {
262
- if (this.tokenCache && !this.isTokenValid(this.tokenCache)) {
263
- console.log("\u{1F510} TokenManager - Token expired, clearing automatically");
264
- this.clearToken();
265
- }
266
- }, 3e4);
267
- }
268
- /**
269
- * Set up storage event listener for cross-tab synchronization
270
- */
271
- setupStorageListener() {
272
- this.storageEventListener = (event) => {
273
- if (event.key === this.TOKEN_KEY) {
274
- console.log("\u{1F510} TokenManager - Token change detected from another tab");
275
- this.loadTokenFromStorage();
276
- }
277
- };
278
- window.addEventListener("storage", this.storageEventListener);
279
- }
280
- /**
281
- * Set a new JWT token with automatic synchronization
282
- */
283
- setToken(token) {
284
- console.log("\u{1F510} TokenManager - SET_TOKEN: Entry point - setting token:", token ? "provided" : "null");
285
- try {
286
- if (!token) {
287
- console.log("\u{1F510} TokenManager - SET_TOKEN: No token provided, clearing token");
288
- this.clearToken();
289
- return;
290
- }
291
- console.log("\u{1F510} TokenManager - SET_TOKEN: Validating token before setting");
292
- if (!this.isTokenValid(token)) {
293
- console.warn("\u{1F510} TokenManager - SET_TOKEN: Attempted to set invalid or expired token");
294
- this.clearToken();
295
- return;
296
- }
297
- console.log("\u{1F510} TokenManager - SET_TOKEN: Token is valid, updating cache");
298
- this.tokenCache = token;
299
- this.parsedTokenCache = this.parseToken(token);
300
- console.log("\u{1F510} TokenManager - SET_TOKEN: Storing token in secure storage");
301
- secureLocalStorage.setToken(token);
302
- console.log("\u{1F510} TokenManager - SET_TOKEN: Synchronizing with crudify");
303
- this.syncTokenWithCrudify(token);
304
- console.log("\u{1F510} TokenManager - SET_TOKEN: Token set and synchronized successfully");
305
- } catch (error) {
306
- console.error("\u{1F510} TokenManager - SET_TOKEN: Error setting token:", error);
307
- this.clearToken();
308
- }
309
- }
310
- /**
311
- * Get the current JWT token
312
- */
313
- getToken() {
314
- console.log("\u{1F510} TokenManager - GET_TOKEN: Entry point - checking cache");
315
- if (this.tokenCache) {
316
- console.log("\u{1F510} TokenManager - GET_TOKEN: Cache exists, validating token");
317
- if (this.isTokenValid(this.tokenCache)) {
318
- console.log("\u{1F510} TokenManager - GET_TOKEN: Cache valid, returning cached token");
319
- return this.tokenCache;
320
- } else {
321
- console.log("\u{1F510} TokenManager - GET_TOKEN: Cache invalid, clearing cache");
322
- this.tokenCache = null;
323
- }
324
- } else {
325
- console.log("\u{1F510} TokenManager - GET_TOKEN: No cache, loading from storage");
326
- }
327
- console.log("\u{1F510} TokenManager - GET_TOKEN: Loading from storage");
328
- this.loadTokenFromStorage();
329
- console.log("\u{1F510} TokenManager - GET_TOKEN: Returning final token:", !!this.tokenCache);
330
- return this.tokenCache;
331
- }
332
- /**
333
- * Parse the current JWT token
334
- */
335
- parseToken(token) {
336
- console.log("\u{1F510} TokenManager - PARSE_TOKEN: Entry point - parsing token");
337
- const targetToken = token !== void 0 ? token : this.tokenCache;
338
- console.log("\u{1F510} TokenManager - PARSE_TOKEN: Target token exists:", !!targetToken);
339
- if (!targetToken) {
340
- console.log("\u{1F510} TokenManager - PARSE_TOKEN: No target token, returning null");
341
- return null;
342
- }
343
- if (this.tokenCache === targetToken && this.parsedTokenCache) {
344
- console.log("\u{1F510} TokenManager - PARSE_TOKEN: Returning cached parsed token");
345
- return this.parsedTokenCache;
346
- }
347
- console.log("\u{1F510} TokenManager - PARSE_TOKEN: Cache miss, parsing token with decodeJwtSafely");
348
- const parsed = decodeJwtSafely(targetToken);
349
- console.log("\u{1F510} TokenManager - PARSE_TOKEN: Token parsed successfully:", !!parsed);
350
- if (targetToken === this.tokenCache) {
351
- console.log("\u{1F510} TokenManager - PARSE_TOKEN: Updating parsed token cache");
352
- this.parsedTokenCache = parsed;
353
- }
354
- return parsed;
355
- }
356
- /**
357
- * Check if a token is valid (properly formatted and not expired)
358
- */
359
- isTokenValid(token) {
360
- console.log("\u{1F510} TokenManager - IS_TOKEN_VALID: Entry point - checking token validity");
361
- const targetToken = token !== void 0 ? token : this.tokenCache;
362
- console.log("\u{1F510} TokenManager - IS_TOKEN_VALID: Target token exists:", !!targetToken);
363
- if (!targetToken) {
364
- console.log("\u{1F510} TokenManager - IS_TOKEN_VALID: No token, returning false");
365
- return false;
366
- }
367
- try {
368
- console.log("\u{1F510} TokenManager - IS_TOKEN_VALID: Checking if token is expired");
369
- if (isTokenExpired(targetToken)) {
370
- console.log("\u{1F510} TokenManager - IS_TOKEN_VALID: Token is expired, returning false");
371
- return false;
372
- }
373
- console.log("\u{1F510} TokenManager - IS_TOKEN_VALID: Token not expired, checking if can be parsed");
374
- const parsed = decodeJwtSafely(targetToken);
375
- const isValid = parsed !== null;
376
- console.log("\u{1F510} TokenManager - IS_TOKEN_VALID: Token parsing result:", isValid);
377
- return isValid;
378
- } catch (error) {
379
- console.log("\u{1F510} TokenManager - IS_TOKEN_VALID: Error validating token:", error);
380
- return false;
381
- }
382
- }
383
- /**
384
- * Get token expiration time as Date object
385
- */
386
- getTokenExpiration() {
387
- const token = this.getToken();
388
- if (!token) return null;
389
- const parsed = this.parseToken(token);
390
- if (!parsed?.exp) return null;
391
- return new Date(parsed.exp * 1e3);
392
- }
393
- /**
394
- * Clear the current token from all storages and crudify
395
- */
396
- clearToken() {
397
- console.log("\u{1F510} TokenManager - CLEAR_TOKEN: Entry point - clearing all tokens");
398
- try {
399
- console.log("\u{1F510} TokenManager - CLEAR_TOKEN: Clearing cache");
400
- this.tokenCache = null;
401
- this.parsedTokenCache = null;
402
- console.log("\u{1F510} TokenManager - CLEAR_TOKEN: Clearing from secure storage");
403
- secureLocalStorage.removeItem(this.TOKEN_KEY);
404
- console.log("\u{1F510} TokenManager - CLEAR_TOKEN: Clearing from crudify");
405
- crudify.setToken("");
406
- console.log("\u{1F510} TokenManager - CLEAR_TOKEN: Token cleared from all storages successfully");
407
- } catch (error) {
408
- console.warn("\u{1F510} TokenManager - CLEAR_TOKEN: Error clearing token:", error);
409
- }
410
- }
411
- /**
412
- * Synchronize token with crudify library
413
- */
414
- syncTokenWithCrudify(token) {
415
- try {
416
- console.log("\u{1F510} TokenManager - SYNC_TOKEN: Starting token sync with crudify");
417
- console.log(" - Token to sync:", token ? `${token.substring(0, 20)}...` : "null");
418
- crudify.setToken(token);
419
- console.log(" - crudify.getToken() after sync:", crudify.getToken?.() ? `${crudify.getToken?.()?.substring(0, 20)}...` : "null");
420
- console.log("\u{1F510} TokenManager - Token synchronized with crudify successfully");
421
- } catch (error) {
422
- console.warn("\u{1F510} TokenManager - Failed to sync token with crudify:", error);
423
- }
424
- }
425
- /**
426
- * Refresh token (placeholder for future implementation)
427
- */
428
- async refreshToken() {
429
- throw new Error("Token refresh not yet implemented");
430
- }
431
- /**
432
- * Get user information from the current token
433
- */
434
- getUserInfo() {
435
- const parsed = this.parseToken();
436
- if (!parsed) {
437
- return {
438
- email: null,
439
- userId: null,
440
- userIdentifier: null,
441
- username: null
442
- };
443
- }
444
- return {
445
- email: parsed.email || null,
446
- userId: parsed.sub || null,
447
- userIdentifier: parsed["cognito:username"] || parsed.email || parsed.sub || null,
448
- username: parsed["cognito:username"] || null
449
- };
450
- }
451
- /**
452
- * Check if user is currently authenticated
453
- */
454
- isAuthenticated() {
455
- return this.isTokenValid();
456
- }
457
- /**
458
- * Get time until token expires in minutes
459
- */
460
- getTimeUntilExpiration() {
461
- const expiration = this.getTokenExpiration();
462
- if (!expiration) return null;
463
- const now = /* @__PURE__ */ new Date();
464
- const minutesUntilExpiry = Math.floor((expiration.getTime() - now.getTime()) / (60 * 1e3));
465
- return Math.max(0, minutesUntilExpiry);
466
- }
467
- /**
468
- * Cleanup resources (call when the component unmounts)
469
- */
470
- cleanup() {
471
- if (this.expirationCheckInterval) {
472
- window.clearInterval(this.expirationCheckInterval);
473
- this.expirationCheckInterval = null;
474
- }
475
- if (this.storageEventListener) {
476
- window.removeEventListener("storage", this.storageEventListener);
477
- this.storageEventListener = null;
478
- }
479
- console.log("\u{1F510} TokenManager - Cleanup completed");
480
- }
481
- /**
482
- * Get debug information about the current token state
483
- */
484
- getDebugInfo() {
485
- const token = this.getToken();
486
- const parsed = this.parseToken();
487
- const expiration = this.getTokenExpiration();
488
- return {
489
- hasToken: !!token,
490
- tokenLength: token?.length || 0,
491
- isValid: this.isTokenValid(),
492
- isAuthenticated: this.isAuthenticated(),
493
- expiration: expiration?.toISOString() || null,
494
- minutesUntilExpiry: this.getTimeUntilExpiration(),
495
- userInfo: this.getUserInfo(),
496
- parsedTokenKeys: parsed ? Object.keys(parsed) : []
497
- };
498
- }
499
- };
500
- _TokenManager.instance = null;
501
- var TokenManager = _TokenManager;
502
- var tokenManager = TokenManager.getInstance();
503
-
504
- export {
505
- secureSessionStorage,
506
- secureLocalStorage,
507
- decodeJwtSafely,
508
- getCurrentUserEmail,
509
- isTokenExpired,
510
- TokenManager,
511
- tokenManager
512
- };