@nocios/crudify-ui 3.0.62 → 3.0.64
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.mts +15 -2
- package/dist/index.d.ts +15 -2
- package/dist/index.js +78 -53
- package/dist/index.mjs +78 -53
- package/package.json +2 -2
package/dist/index.d.mts
CHANGED
|
@@ -163,15 +163,24 @@ type TokenData = {
|
|
|
163
163
|
expiresAt: number;
|
|
164
164
|
refreshExpiresAt: number;
|
|
165
165
|
};
|
|
166
|
-
type StorageType =
|
|
166
|
+
type StorageType = "localStorage" | "sessionStorage" | "none";
|
|
167
167
|
declare class TokenStorage {
|
|
168
168
|
private static readonly TOKEN_KEY;
|
|
169
|
-
private static readonly
|
|
169
|
+
private static readonly ENCRYPTION_KEY_STORAGE;
|
|
170
|
+
private static encryptionKey;
|
|
170
171
|
private static storageType;
|
|
171
172
|
/**
|
|
172
173
|
* Configurar tipo de almacenamiento
|
|
173
174
|
*/
|
|
174
175
|
static setStorageType(type: StorageType): void;
|
|
176
|
+
/**
|
|
177
|
+
* Generar clave de encriptación única y persistente
|
|
178
|
+
*/
|
|
179
|
+
private static generateEncryptionKey;
|
|
180
|
+
/**
|
|
181
|
+
* Obtener o generar clave de encriptación
|
|
182
|
+
*/
|
|
183
|
+
private static getEncryptionKey;
|
|
175
184
|
/**
|
|
176
185
|
* Verificar si el storage está disponible
|
|
177
186
|
*/
|
|
@@ -200,6 +209,10 @@ declare class TokenStorage {
|
|
|
200
209
|
* Limpiar tokens almacenados
|
|
201
210
|
*/
|
|
202
211
|
static clearTokens(): void;
|
|
212
|
+
/**
|
|
213
|
+
* Rotar clave de encriptación (limpia tokens existentes por seguridad)
|
|
214
|
+
*/
|
|
215
|
+
static rotateEncryptionKey(): void;
|
|
203
216
|
/**
|
|
204
217
|
* Verificar si hay tokens válidos guardados
|
|
205
218
|
*/
|
package/dist/index.d.ts
CHANGED
|
@@ -163,15 +163,24 @@ type TokenData = {
|
|
|
163
163
|
expiresAt: number;
|
|
164
164
|
refreshExpiresAt: number;
|
|
165
165
|
};
|
|
166
|
-
type StorageType =
|
|
166
|
+
type StorageType = "localStorage" | "sessionStorage" | "none";
|
|
167
167
|
declare class TokenStorage {
|
|
168
168
|
private static readonly TOKEN_KEY;
|
|
169
|
-
private static readonly
|
|
169
|
+
private static readonly ENCRYPTION_KEY_STORAGE;
|
|
170
|
+
private static encryptionKey;
|
|
170
171
|
private static storageType;
|
|
171
172
|
/**
|
|
172
173
|
* Configurar tipo de almacenamiento
|
|
173
174
|
*/
|
|
174
175
|
static setStorageType(type: StorageType): void;
|
|
176
|
+
/**
|
|
177
|
+
* Generar clave de encriptación única y persistente
|
|
178
|
+
*/
|
|
179
|
+
private static generateEncryptionKey;
|
|
180
|
+
/**
|
|
181
|
+
* Obtener o generar clave de encriptación
|
|
182
|
+
*/
|
|
183
|
+
private static getEncryptionKey;
|
|
175
184
|
/**
|
|
176
185
|
* Verificar si el storage está disponible
|
|
177
186
|
*/
|
|
@@ -200,6 +209,10 @@ declare class TokenStorage {
|
|
|
200
209
|
* Limpiar tokens almacenados
|
|
201
210
|
*/
|
|
202
211
|
static clearTokens(): void;
|
|
212
|
+
/**
|
|
213
|
+
* Rotar clave de encriptación (limpia tokens existentes por seguridad)
|
|
214
|
+
*/
|
|
215
|
+
static rotateEncryptionKey(): void;
|
|
203
216
|
/**
|
|
204
217
|
* Verificar si hay tokens válidos guardados
|
|
205
218
|
*/
|
package/dist/index.js
CHANGED
|
@@ -504,6 +504,47 @@ var _TokenStorage = class _TokenStorage {
|
|
|
504
504
|
static setStorageType(type) {
|
|
505
505
|
_TokenStorage.storageType = type;
|
|
506
506
|
}
|
|
507
|
+
/**
|
|
508
|
+
* Generar clave de encriptación única y persistente
|
|
509
|
+
*/
|
|
510
|
+
static generateEncryptionKey() {
|
|
511
|
+
const browserInfo = [
|
|
512
|
+
navigator.userAgent,
|
|
513
|
+
navigator.language,
|
|
514
|
+
navigator.platform,
|
|
515
|
+
screen.width,
|
|
516
|
+
screen.height,
|
|
517
|
+
Date.now().toString(),
|
|
518
|
+
Math.random().toString(36)
|
|
519
|
+
].join("|");
|
|
520
|
+
return import_crypto_js.default.SHA256(browserInfo).toString();
|
|
521
|
+
}
|
|
522
|
+
/**
|
|
523
|
+
* Obtener o generar clave de encriptación
|
|
524
|
+
*/
|
|
525
|
+
static getEncryptionKey() {
|
|
526
|
+
if (_TokenStorage.encryptionKey) {
|
|
527
|
+
return _TokenStorage.encryptionKey;
|
|
528
|
+
}
|
|
529
|
+
const storage = window.localStorage;
|
|
530
|
+
if (!storage) {
|
|
531
|
+
_TokenStorage.encryptionKey = _TokenStorage.generateEncryptionKey();
|
|
532
|
+
return _TokenStorage.encryptionKey;
|
|
533
|
+
}
|
|
534
|
+
try {
|
|
535
|
+
let existingKey = storage.getItem(_TokenStorage.ENCRYPTION_KEY_STORAGE);
|
|
536
|
+
if (!existingKey || existingKey.length < 32) {
|
|
537
|
+
existingKey = _TokenStorage.generateEncryptionKey();
|
|
538
|
+
storage.setItem(_TokenStorage.ENCRYPTION_KEY_STORAGE, existingKey);
|
|
539
|
+
}
|
|
540
|
+
_TokenStorage.encryptionKey = existingKey;
|
|
541
|
+
return existingKey;
|
|
542
|
+
} catch (error) {
|
|
543
|
+
console.warn("Crudify: Cannot persist encryption key, using temporary key");
|
|
544
|
+
_TokenStorage.encryptionKey = _TokenStorage.generateEncryptionKey();
|
|
545
|
+
return _TokenStorage.encryptionKey;
|
|
546
|
+
}
|
|
547
|
+
}
|
|
507
548
|
/**
|
|
508
549
|
* Verificar si el storage está disponible
|
|
509
550
|
*/
|
|
@@ -534,7 +575,8 @@ var _TokenStorage = class _TokenStorage {
|
|
|
534
575
|
*/
|
|
535
576
|
static encrypt(data) {
|
|
536
577
|
try {
|
|
537
|
-
|
|
578
|
+
const encryptionKey = _TokenStorage.getEncryptionKey();
|
|
579
|
+
return import_crypto_js.default.AES.encrypt(data, encryptionKey).toString();
|
|
538
580
|
} catch (error) {
|
|
539
581
|
console.error("Crudify: Encryption failed", error);
|
|
540
582
|
return data;
|
|
@@ -545,7 +587,8 @@ var _TokenStorage = class _TokenStorage {
|
|
|
545
587
|
*/
|
|
546
588
|
static decrypt(encryptedData) {
|
|
547
589
|
try {
|
|
548
|
-
const
|
|
590
|
+
const encryptionKey = _TokenStorage.getEncryptionKey();
|
|
591
|
+
const bytes = import_crypto_js.default.AES.decrypt(encryptedData, encryptionKey);
|
|
549
592
|
const decrypted = bytes.toString(import_crypto_js.default.enc.Utf8);
|
|
550
593
|
return decrypted || encryptedData;
|
|
551
594
|
} catch (error) {
|
|
@@ -620,6 +663,22 @@ var _TokenStorage = class _TokenStorage {
|
|
|
620
663
|
console.error("Crudify: Failed to clear tokens", error);
|
|
621
664
|
}
|
|
622
665
|
}
|
|
666
|
+
/**
|
|
667
|
+
* Rotar clave de encriptación (limpia tokens existentes por seguridad)
|
|
668
|
+
*/
|
|
669
|
+
static rotateEncryptionKey() {
|
|
670
|
+
try {
|
|
671
|
+
_TokenStorage.clearTokens();
|
|
672
|
+
_TokenStorage.encryptionKey = null;
|
|
673
|
+
const storage = window.localStorage;
|
|
674
|
+
if (storage) {
|
|
675
|
+
storage.removeItem(_TokenStorage.ENCRYPTION_KEY_STORAGE);
|
|
676
|
+
}
|
|
677
|
+
console.info("Crudify: Encryption key rotated successfully");
|
|
678
|
+
} catch (error) {
|
|
679
|
+
console.error("Crudify: Failed to rotate encryption key", error);
|
|
680
|
+
}
|
|
681
|
+
}
|
|
623
682
|
/**
|
|
624
683
|
* Verificar si hay tokens válidos guardados
|
|
625
684
|
*/
|
|
@@ -658,7 +717,8 @@ var _TokenStorage = class _TokenStorage {
|
|
|
658
717
|
}
|
|
659
718
|
};
|
|
660
719
|
_TokenStorage.TOKEN_KEY = "crudify_tokens";
|
|
661
|
-
_TokenStorage.
|
|
720
|
+
_TokenStorage.ENCRYPTION_KEY_STORAGE = "crudify_enc_key";
|
|
721
|
+
_TokenStorage.encryptionKey = null;
|
|
662
722
|
_TokenStorage.storageType = "localStorage";
|
|
663
723
|
var TokenStorage = _TokenStorage;
|
|
664
724
|
|
|
@@ -1571,15 +1631,17 @@ function InnerSessionProvider({
|
|
|
1571
1631
|
showNotificationFn = showNotification;
|
|
1572
1632
|
} catch {
|
|
1573
1633
|
}
|
|
1574
|
-
const enhancedOptions = import_react7.default.useMemo(
|
|
1575
|
-
|
|
1576
|
-
|
|
1577
|
-
|
|
1578
|
-
|
|
1579
|
-
|
|
1580
|
-
|
|
1581
|
-
|
|
1582
|
-
|
|
1634
|
+
const enhancedOptions = import_react7.default.useMemo(
|
|
1635
|
+
() => ({
|
|
1636
|
+
...options,
|
|
1637
|
+
showNotification: showNotificationFn,
|
|
1638
|
+
// TODO: Agregar translateFn cuando esté disponible
|
|
1639
|
+
onSessionExpired: () => {
|
|
1640
|
+
options.onSessionExpired?.();
|
|
1641
|
+
}
|
|
1642
|
+
}),
|
|
1643
|
+
[options, showNotificationFn]
|
|
1644
|
+
);
|
|
1583
1645
|
const sessionHook = useSession(enhancedOptions);
|
|
1584
1646
|
const resolvedConfig = (0, import_react7.useMemo)(() => {
|
|
1585
1647
|
let publicApiKey;
|
|
@@ -1628,12 +1690,6 @@ function InnerSessionProvider({
|
|
|
1628
1690
|
loginActions = decodedActions.split(",").map((s) => s.trim()).filter(Boolean);
|
|
1629
1691
|
}
|
|
1630
1692
|
}
|
|
1631
|
-
console.log("\u{1F50D} SessionProvider - Configuration Detection:");
|
|
1632
|
-
console.log(" - Config source:", configSource);
|
|
1633
|
-
console.log(" - PublicApiKey:", publicApiKey ? publicApiKey.substring(0, 15) + "..." : "undefined");
|
|
1634
|
-
console.log(" - Environment:", env);
|
|
1635
|
-
console.log(" - App name:", appName);
|
|
1636
|
-
console.log(" - Login actions:", loginActions);
|
|
1637
1693
|
return {
|
|
1638
1694
|
publicApiKey,
|
|
1639
1695
|
env,
|
|
@@ -2061,11 +2117,13 @@ var LoginForm = ({ onScreenChange, onExternalNavigate, onLoginSuccess, onError,
|
|
|
2061
2117
|
const { crudify: crudify7 } = useCrudify();
|
|
2062
2118
|
const { state, updateFormData, setFieldError, clearErrors, setLoading } = useLoginState();
|
|
2063
2119
|
const { login: sessionLogin } = useSessionContext();
|
|
2064
|
-
const
|
|
2120
|
+
const translationContext = useTranslation();
|
|
2121
|
+
const { t } = translationContext;
|
|
2122
|
+
const i18n = translationContext.i18n;
|
|
2065
2123
|
const usernameInputRef = (0, import_react8.useRef)(null);
|
|
2066
2124
|
const errorTranslator = createErrorTranslator(t, {
|
|
2067
2125
|
currentLanguage: i18n?.language,
|
|
2068
|
-
enableDebug:
|
|
2126
|
+
enableDebug: false
|
|
2069
2127
|
});
|
|
2070
2128
|
const getRedirectUrl = () => {
|
|
2071
2129
|
if (state.searchParams.redirect) {
|
|
@@ -4039,7 +4097,6 @@ var useUserData = (options = {}) => {
|
|
|
4039
4097
|
}, []);
|
|
4040
4098
|
const refreshProfile = (0, import_react18.useCallback)(async () => {
|
|
4041
4099
|
const userEmail = getUserEmail();
|
|
4042
|
-
console.log("\u{1F464} useUserData - Refreshing profile for:", userEmail);
|
|
4043
4100
|
if (!userEmail) {
|
|
4044
4101
|
if (mountedRef.current) {
|
|
4045
4102
|
setError("No user email available from session data");
|
|
@@ -4065,91 +4122,59 @@ var useUserData = (options = {}) => {
|
|
|
4065
4122
|
setLoading(true);
|
|
4066
4123
|
setError(null);
|
|
4067
4124
|
}
|
|
4068
|
-
console.log("\u{1F464} useUserData - Fetching profile data from database");
|
|
4069
4125
|
const response = await import_crudify_browser4.default.readItems("users", {
|
|
4070
4126
|
filter: { email: userEmail },
|
|
4071
4127
|
pagination: { limit: 1 }
|
|
4072
4128
|
});
|
|
4073
|
-
console.log("\u{1F464} useUserData - Database response:", response);
|
|
4074
|
-
console.log("\u{1F464} useUserData - response.data:", response.data);
|
|
4075
|
-
console.log("\u{1F464} useUserData - response.data type:", typeof response.data);
|
|
4076
4129
|
if (currentRequestId === requestIdRef.current && mountedRef.current && !abortController.signal.aborted) {
|
|
4077
4130
|
let userData2 = null;
|
|
4078
4131
|
if (response.success) {
|
|
4079
|
-
console.log("\u{1F464} useUserData - Processing successful response:", {
|
|
4080
|
-
dataType: typeof response.data,
|
|
4081
|
-
isArray: Array.isArray(response.data),
|
|
4082
|
-
hasResponse: !!response.data?.response,
|
|
4083
|
-
hasResponseData: !!response.data?.response?.data,
|
|
4084
|
-
responseDataType: typeof response.data?.response?.data
|
|
4085
|
-
});
|
|
4086
4132
|
if (Array.isArray(response.data) && response.data.length > 0) {
|
|
4087
|
-
console.log("\u{1F464} useUserData - Found direct array format");
|
|
4088
4133
|
userData2 = response.data[0];
|
|
4089
4134
|
} else if (response.data?.response?.data) {
|
|
4090
|
-
console.log("\u{1F464} useUserData - Found nested response.data format");
|
|
4091
4135
|
try {
|
|
4092
4136
|
const rawData = response.data.response.data;
|
|
4093
|
-
console.log("\u{1F464} useUserData - Raw nested data:", rawData);
|
|
4094
|
-
console.log("\u{1F464} useUserData - Raw data type:", typeof rawData);
|
|
4095
4137
|
const parsedData = typeof rawData === "string" ? JSON.parse(rawData) : rawData;
|
|
4096
|
-
console.log("\u{1F464} useUserData - Parsed nested data:", parsedData);
|
|
4097
4138
|
if (parsedData && parsedData.items && Array.isArray(parsedData.items) && parsedData.items.length > 0) {
|
|
4098
4139
|
userData2 = parsedData.items[0];
|
|
4099
|
-
console.log("\u{1F464} useUserData - Extracted user from nested items:", userData2);
|
|
4100
4140
|
} else {
|
|
4101
|
-
console.log("\u{1F464} useUserData - No items found in parsed data or items array is empty");
|
|
4102
4141
|
}
|
|
4103
4142
|
} catch (parseError) {
|
|
4104
|
-
console.error("\u{1F464} useUserData - Error parsing nested response data:", parseError);
|
|
4105
4143
|
}
|
|
4106
4144
|
} else if (response.data && typeof response.data === "object") {
|
|
4107
|
-
console.log("\u{1F464} useUserData - Found object format, checking for items");
|
|
4108
4145
|
if (response.data.items && Array.isArray(response.data.items) && response.data.items.length > 0) {
|
|
4109
|
-
console.log("\u{1F464} useUserData - Found items in object format");
|
|
4110
4146
|
userData2 = response.data.items[0];
|
|
4111
4147
|
} else {
|
|
4112
|
-
console.log("\u{1F464} useUserData - No items found in object format");
|
|
4113
4148
|
}
|
|
4114
4149
|
} else if (response.data?.data?.response?.data) {
|
|
4115
|
-
console.log("\u{1F464} useUserData - Found double-nested data.data.response.data format");
|
|
4116
4150
|
try {
|
|
4117
4151
|
const rawData = response.data.data.response.data;
|
|
4118
|
-
console.log("\u{1F464} useUserData - Raw double-nested data:", rawData);
|
|
4119
4152
|
const parsedData = typeof rawData === "string" ? JSON.parse(rawData) : rawData;
|
|
4120
|
-
console.log("\u{1F464} useUserData - Parsed double-nested data:", parsedData);
|
|
4121
4153
|
if (parsedData && parsedData.items && Array.isArray(parsedData.items) && parsedData.items.length > 0) {
|
|
4122
4154
|
userData2 = parsedData.items[0];
|
|
4123
|
-
console.log("\u{1F464} useUserData - Extracted user from double-nested items:", userData2);
|
|
4124
4155
|
}
|
|
4125
4156
|
} catch (parseError) {
|
|
4126
|
-
console.error("\u{1F464} useUserData - Error parsing double-nested response data:", parseError);
|
|
4127
4157
|
}
|
|
4128
4158
|
}
|
|
4129
4159
|
}
|
|
4130
4160
|
if (userData2) {
|
|
4131
|
-
console.log("\u{1F464} useUserData - User data found:", userData2);
|
|
4132
4161
|
setUserData(userData2);
|
|
4133
4162
|
setError(null);
|
|
4134
4163
|
retryCountRef.current = 0;
|
|
4135
|
-
console.log("\u{1F464} useUserData - Profile loaded successfully:", userData2);
|
|
4136
4164
|
} else {
|
|
4137
4165
|
setError("User profile not found in database");
|
|
4138
4166
|
setUserData(null);
|
|
4139
|
-
console.warn("\u{1F464} useUserData - User not found for email:", userEmail);
|
|
4140
4167
|
}
|
|
4141
4168
|
}
|
|
4142
4169
|
} catch (err) {
|
|
4143
4170
|
if (currentRequestId === requestIdRef.current && mountedRef.current) {
|
|
4144
4171
|
const error2 = err;
|
|
4145
|
-
console.error("\u{1F464} useUserData - Error fetching profile:", error2);
|
|
4146
4172
|
if (error2.name === "AbortError") {
|
|
4147
4173
|
return;
|
|
4148
4174
|
}
|
|
4149
4175
|
const shouldRetry = retryOnError && retryCountRef.current < maxRetries && (error2.message?.includes("Network Error") || error2.message?.includes("Failed to fetch"));
|
|
4150
4176
|
if (shouldRetry) {
|
|
4151
4177
|
retryCountRef.current++;
|
|
4152
|
-
console.log(`\u{1F464} useUserData - Retrying profile fetch (${retryCountRef.current}/${maxRetries})`);
|
|
4153
4178
|
setTimeout(() => {
|
|
4154
4179
|
if (mountedRef.current) {
|
|
4155
4180
|
refreshProfile();
|
package/dist/index.mjs
CHANGED
|
@@ -431,6 +431,47 @@ var _TokenStorage = class _TokenStorage {
|
|
|
431
431
|
static setStorageType(type) {
|
|
432
432
|
_TokenStorage.storageType = type;
|
|
433
433
|
}
|
|
434
|
+
/**
|
|
435
|
+
* Generar clave de encriptación única y persistente
|
|
436
|
+
*/
|
|
437
|
+
static generateEncryptionKey() {
|
|
438
|
+
const browserInfo = [
|
|
439
|
+
navigator.userAgent,
|
|
440
|
+
navigator.language,
|
|
441
|
+
navigator.platform,
|
|
442
|
+
screen.width,
|
|
443
|
+
screen.height,
|
|
444
|
+
Date.now().toString(),
|
|
445
|
+
Math.random().toString(36)
|
|
446
|
+
].join("|");
|
|
447
|
+
return CryptoJS.SHA256(browserInfo).toString();
|
|
448
|
+
}
|
|
449
|
+
/**
|
|
450
|
+
* Obtener o generar clave de encriptación
|
|
451
|
+
*/
|
|
452
|
+
static getEncryptionKey() {
|
|
453
|
+
if (_TokenStorage.encryptionKey) {
|
|
454
|
+
return _TokenStorage.encryptionKey;
|
|
455
|
+
}
|
|
456
|
+
const storage = window.localStorage;
|
|
457
|
+
if (!storage) {
|
|
458
|
+
_TokenStorage.encryptionKey = _TokenStorage.generateEncryptionKey();
|
|
459
|
+
return _TokenStorage.encryptionKey;
|
|
460
|
+
}
|
|
461
|
+
try {
|
|
462
|
+
let existingKey = storage.getItem(_TokenStorage.ENCRYPTION_KEY_STORAGE);
|
|
463
|
+
if (!existingKey || existingKey.length < 32) {
|
|
464
|
+
existingKey = _TokenStorage.generateEncryptionKey();
|
|
465
|
+
storage.setItem(_TokenStorage.ENCRYPTION_KEY_STORAGE, existingKey);
|
|
466
|
+
}
|
|
467
|
+
_TokenStorage.encryptionKey = existingKey;
|
|
468
|
+
return existingKey;
|
|
469
|
+
} catch (error) {
|
|
470
|
+
console.warn("Crudify: Cannot persist encryption key, using temporary key");
|
|
471
|
+
_TokenStorage.encryptionKey = _TokenStorage.generateEncryptionKey();
|
|
472
|
+
return _TokenStorage.encryptionKey;
|
|
473
|
+
}
|
|
474
|
+
}
|
|
434
475
|
/**
|
|
435
476
|
* Verificar si el storage está disponible
|
|
436
477
|
*/
|
|
@@ -461,7 +502,8 @@ var _TokenStorage = class _TokenStorage {
|
|
|
461
502
|
*/
|
|
462
503
|
static encrypt(data) {
|
|
463
504
|
try {
|
|
464
|
-
|
|
505
|
+
const encryptionKey = _TokenStorage.getEncryptionKey();
|
|
506
|
+
return CryptoJS.AES.encrypt(data, encryptionKey).toString();
|
|
465
507
|
} catch (error) {
|
|
466
508
|
console.error("Crudify: Encryption failed", error);
|
|
467
509
|
return data;
|
|
@@ -472,7 +514,8 @@ var _TokenStorage = class _TokenStorage {
|
|
|
472
514
|
*/
|
|
473
515
|
static decrypt(encryptedData) {
|
|
474
516
|
try {
|
|
475
|
-
const
|
|
517
|
+
const encryptionKey = _TokenStorage.getEncryptionKey();
|
|
518
|
+
const bytes = CryptoJS.AES.decrypt(encryptedData, encryptionKey);
|
|
476
519
|
const decrypted = bytes.toString(CryptoJS.enc.Utf8);
|
|
477
520
|
return decrypted || encryptedData;
|
|
478
521
|
} catch (error) {
|
|
@@ -547,6 +590,22 @@ var _TokenStorage = class _TokenStorage {
|
|
|
547
590
|
console.error("Crudify: Failed to clear tokens", error);
|
|
548
591
|
}
|
|
549
592
|
}
|
|
593
|
+
/**
|
|
594
|
+
* Rotar clave de encriptación (limpia tokens existentes por seguridad)
|
|
595
|
+
*/
|
|
596
|
+
static rotateEncryptionKey() {
|
|
597
|
+
try {
|
|
598
|
+
_TokenStorage.clearTokens();
|
|
599
|
+
_TokenStorage.encryptionKey = null;
|
|
600
|
+
const storage = window.localStorage;
|
|
601
|
+
if (storage) {
|
|
602
|
+
storage.removeItem(_TokenStorage.ENCRYPTION_KEY_STORAGE);
|
|
603
|
+
}
|
|
604
|
+
console.info("Crudify: Encryption key rotated successfully");
|
|
605
|
+
} catch (error) {
|
|
606
|
+
console.error("Crudify: Failed to rotate encryption key", error);
|
|
607
|
+
}
|
|
608
|
+
}
|
|
550
609
|
/**
|
|
551
610
|
* Verificar si hay tokens válidos guardados
|
|
552
611
|
*/
|
|
@@ -585,7 +644,8 @@ var _TokenStorage = class _TokenStorage {
|
|
|
585
644
|
}
|
|
586
645
|
};
|
|
587
646
|
_TokenStorage.TOKEN_KEY = "crudify_tokens";
|
|
588
|
-
_TokenStorage.
|
|
647
|
+
_TokenStorage.ENCRYPTION_KEY_STORAGE = "crudify_enc_key";
|
|
648
|
+
_TokenStorage.encryptionKey = null;
|
|
589
649
|
_TokenStorage.storageType = "localStorage";
|
|
590
650
|
var TokenStorage = _TokenStorage;
|
|
591
651
|
|
|
@@ -1498,15 +1558,17 @@ function InnerSessionProvider({
|
|
|
1498
1558
|
showNotificationFn = showNotification;
|
|
1499
1559
|
} catch {
|
|
1500
1560
|
}
|
|
1501
|
-
const enhancedOptions = React5.useMemo(
|
|
1502
|
-
|
|
1503
|
-
|
|
1504
|
-
|
|
1505
|
-
|
|
1506
|
-
|
|
1507
|
-
|
|
1508
|
-
|
|
1509
|
-
|
|
1561
|
+
const enhancedOptions = React5.useMemo(
|
|
1562
|
+
() => ({
|
|
1563
|
+
...options,
|
|
1564
|
+
showNotification: showNotificationFn,
|
|
1565
|
+
// TODO: Agregar translateFn cuando esté disponible
|
|
1566
|
+
onSessionExpired: () => {
|
|
1567
|
+
options.onSessionExpired?.();
|
|
1568
|
+
}
|
|
1569
|
+
}),
|
|
1570
|
+
[options, showNotificationFn]
|
|
1571
|
+
);
|
|
1510
1572
|
const sessionHook = useSession(enhancedOptions);
|
|
1511
1573
|
const resolvedConfig = useMemo2(() => {
|
|
1512
1574
|
let publicApiKey;
|
|
@@ -1555,12 +1617,6 @@ function InnerSessionProvider({
|
|
|
1555
1617
|
loginActions = decodedActions.split(",").map((s) => s.trim()).filter(Boolean);
|
|
1556
1618
|
}
|
|
1557
1619
|
}
|
|
1558
|
-
console.log("\u{1F50D} SessionProvider - Configuration Detection:");
|
|
1559
|
-
console.log(" - Config source:", configSource);
|
|
1560
|
-
console.log(" - PublicApiKey:", publicApiKey ? publicApiKey.substring(0, 15) + "..." : "undefined");
|
|
1561
|
-
console.log(" - Environment:", env);
|
|
1562
|
-
console.log(" - App name:", appName);
|
|
1563
|
-
console.log(" - Login actions:", loginActions);
|
|
1564
1620
|
return {
|
|
1565
1621
|
publicApiKey,
|
|
1566
1622
|
env,
|
|
@@ -1988,11 +2044,13 @@ var LoginForm = ({ onScreenChange, onExternalNavigate, onLoginSuccess, onError,
|
|
|
1988
2044
|
const { crudify: crudify7 } = useCrudify();
|
|
1989
2045
|
const { state, updateFormData, setFieldError, clearErrors, setLoading } = useLoginState();
|
|
1990
2046
|
const { login: sessionLogin } = useSessionContext();
|
|
1991
|
-
const
|
|
2047
|
+
const translationContext = useTranslation();
|
|
2048
|
+
const { t } = translationContext;
|
|
2049
|
+
const i18n = translationContext.i18n;
|
|
1992
2050
|
const usernameInputRef = useRef(null);
|
|
1993
2051
|
const errorTranslator = createErrorTranslator(t, {
|
|
1994
2052
|
currentLanguage: i18n?.language,
|
|
1995
|
-
enableDebug:
|
|
2053
|
+
enableDebug: false
|
|
1996
2054
|
});
|
|
1997
2055
|
const getRedirectUrl = () => {
|
|
1998
2056
|
if (state.searchParams.redirect) {
|
|
@@ -4025,7 +4083,6 @@ var useUserData = (options = {}) => {
|
|
|
4025
4083
|
}, []);
|
|
4026
4084
|
const refreshProfile = useCallback4(async () => {
|
|
4027
4085
|
const userEmail = getUserEmail();
|
|
4028
|
-
console.log("\u{1F464} useUserData - Refreshing profile for:", userEmail);
|
|
4029
4086
|
if (!userEmail) {
|
|
4030
4087
|
if (mountedRef.current) {
|
|
4031
4088
|
setError("No user email available from session data");
|
|
@@ -4051,91 +4108,59 @@ var useUserData = (options = {}) => {
|
|
|
4051
4108
|
setLoading(true);
|
|
4052
4109
|
setError(null);
|
|
4053
4110
|
}
|
|
4054
|
-
console.log("\u{1F464} useUserData - Fetching profile data from database");
|
|
4055
4111
|
const response = await crudify4.readItems("users", {
|
|
4056
4112
|
filter: { email: userEmail },
|
|
4057
4113
|
pagination: { limit: 1 }
|
|
4058
4114
|
});
|
|
4059
|
-
console.log("\u{1F464} useUserData - Database response:", response);
|
|
4060
|
-
console.log("\u{1F464} useUserData - response.data:", response.data);
|
|
4061
|
-
console.log("\u{1F464} useUserData - response.data type:", typeof response.data);
|
|
4062
4115
|
if (currentRequestId === requestIdRef.current && mountedRef.current && !abortController.signal.aborted) {
|
|
4063
4116
|
let userData2 = null;
|
|
4064
4117
|
if (response.success) {
|
|
4065
|
-
console.log("\u{1F464} useUserData - Processing successful response:", {
|
|
4066
|
-
dataType: typeof response.data,
|
|
4067
|
-
isArray: Array.isArray(response.data),
|
|
4068
|
-
hasResponse: !!response.data?.response,
|
|
4069
|
-
hasResponseData: !!response.data?.response?.data,
|
|
4070
|
-
responseDataType: typeof response.data?.response?.data
|
|
4071
|
-
});
|
|
4072
4118
|
if (Array.isArray(response.data) && response.data.length > 0) {
|
|
4073
|
-
console.log("\u{1F464} useUserData - Found direct array format");
|
|
4074
4119
|
userData2 = response.data[0];
|
|
4075
4120
|
} else if (response.data?.response?.data) {
|
|
4076
|
-
console.log("\u{1F464} useUserData - Found nested response.data format");
|
|
4077
4121
|
try {
|
|
4078
4122
|
const rawData = response.data.response.data;
|
|
4079
|
-
console.log("\u{1F464} useUserData - Raw nested data:", rawData);
|
|
4080
|
-
console.log("\u{1F464} useUserData - Raw data type:", typeof rawData);
|
|
4081
4123
|
const parsedData = typeof rawData === "string" ? JSON.parse(rawData) : rawData;
|
|
4082
|
-
console.log("\u{1F464} useUserData - Parsed nested data:", parsedData);
|
|
4083
4124
|
if (parsedData && parsedData.items && Array.isArray(parsedData.items) && parsedData.items.length > 0) {
|
|
4084
4125
|
userData2 = parsedData.items[0];
|
|
4085
|
-
console.log("\u{1F464} useUserData - Extracted user from nested items:", userData2);
|
|
4086
4126
|
} else {
|
|
4087
|
-
console.log("\u{1F464} useUserData - No items found in parsed data or items array is empty");
|
|
4088
4127
|
}
|
|
4089
4128
|
} catch (parseError) {
|
|
4090
|
-
console.error("\u{1F464} useUserData - Error parsing nested response data:", parseError);
|
|
4091
4129
|
}
|
|
4092
4130
|
} else if (response.data && typeof response.data === "object") {
|
|
4093
|
-
console.log("\u{1F464} useUserData - Found object format, checking for items");
|
|
4094
4131
|
if (response.data.items && Array.isArray(response.data.items) && response.data.items.length > 0) {
|
|
4095
|
-
console.log("\u{1F464} useUserData - Found items in object format");
|
|
4096
4132
|
userData2 = response.data.items[0];
|
|
4097
4133
|
} else {
|
|
4098
|
-
console.log("\u{1F464} useUserData - No items found in object format");
|
|
4099
4134
|
}
|
|
4100
4135
|
} else if (response.data?.data?.response?.data) {
|
|
4101
|
-
console.log("\u{1F464} useUserData - Found double-nested data.data.response.data format");
|
|
4102
4136
|
try {
|
|
4103
4137
|
const rawData = response.data.data.response.data;
|
|
4104
|
-
console.log("\u{1F464} useUserData - Raw double-nested data:", rawData);
|
|
4105
4138
|
const parsedData = typeof rawData === "string" ? JSON.parse(rawData) : rawData;
|
|
4106
|
-
console.log("\u{1F464} useUserData - Parsed double-nested data:", parsedData);
|
|
4107
4139
|
if (parsedData && parsedData.items && Array.isArray(parsedData.items) && parsedData.items.length > 0) {
|
|
4108
4140
|
userData2 = parsedData.items[0];
|
|
4109
|
-
console.log("\u{1F464} useUserData - Extracted user from double-nested items:", userData2);
|
|
4110
4141
|
}
|
|
4111
4142
|
} catch (parseError) {
|
|
4112
|
-
console.error("\u{1F464} useUserData - Error parsing double-nested response data:", parseError);
|
|
4113
4143
|
}
|
|
4114
4144
|
}
|
|
4115
4145
|
}
|
|
4116
4146
|
if (userData2) {
|
|
4117
|
-
console.log("\u{1F464} useUserData - User data found:", userData2);
|
|
4118
4147
|
setUserData(userData2);
|
|
4119
4148
|
setError(null);
|
|
4120
4149
|
retryCountRef.current = 0;
|
|
4121
|
-
console.log("\u{1F464} useUserData - Profile loaded successfully:", userData2);
|
|
4122
4150
|
} else {
|
|
4123
4151
|
setError("User profile not found in database");
|
|
4124
4152
|
setUserData(null);
|
|
4125
|
-
console.warn("\u{1F464} useUserData - User not found for email:", userEmail);
|
|
4126
4153
|
}
|
|
4127
4154
|
}
|
|
4128
4155
|
} catch (err) {
|
|
4129
4156
|
if (currentRequestId === requestIdRef.current && mountedRef.current) {
|
|
4130
4157
|
const error2 = err;
|
|
4131
|
-
console.error("\u{1F464} useUserData - Error fetching profile:", error2);
|
|
4132
4158
|
if (error2.name === "AbortError") {
|
|
4133
4159
|
return;
|
|
4134
4160
|
}
|
|
4135
4161
|
const shouldRetry = retryOnError && retryCountRef.current < maxRetries && (error2.message?.includes("Network Error") || error2.message?.includes("Failed to fetch"));
|
|
4136
4162
|
if (shouldRetry) {
|
|
4137
4163
|
retryCountRef.current++;
|
|
4138
|
-
console.log(`\u{1F464} useUserData - Retrying profile fetch (${retryCountRef.current}/${maxRetries})`);
|
|
4139
4164
|
setTimeout(() => {
|
|
4140
4165
|
if (mountedRef.current) {
|
|
4141
4166
|
refreshProfile();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nocios/crudify-ui",
|
|
3
|
-
"version": "3.0.
|
|
3
|
+
"version": "3.0.64",
|
|
4
4
|
"description": "Biblioteca de componentes UI para Crudify",
|
|
5
5
|
"author": "Nocios",
|
|
6
6
|
"license": "MIT",
|
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
"@mui/icons-material": "^7.1.0",
|
|
26
26
|
"@mui/material": "^7.1.0",
|
|
27
27
|
"@mui/x-data-grid": "^8.5.1",
|
|
28
|
-
"@nocios/crudify-browser": "^2.0.
|
|
28
|
+
"@nocios/crudify-browser": "^2.0.62",
|
|
29
29
|
"@types/dompurify": "^3.0.5",
|
|
30
30
|
"@types/uuid": "^10.0.0",
|
|
31
31
|
"crypto-js": "^4.2.0",
|