@nocios/crudify-ui 3.0.4 → 3.0.10
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/README.md +114 -17
- package/dist/index.d.mts +15 -2
- package/dist/index.d.ts +15 -2
- package/dist/index.js +1793 -1767
- package/dist/index.mjs +1829 -1803
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -45,7 +45,7 @@ __export(index_exports, {
|
|
|
45
45
|
SessionStatus: () => SessionStatus,
|
|
46
46
|
TokenStorage: () => TokenStorage,
|
|
47
47
|
UserProfileDisplay: () => UserProfileDisplay_default,
|
|
48
|
-
crudify: () =>
|
|
48
|
+
crudify: () => import_crudify_browser6.default,
|
|
49
49
|
decodeJwtSafely: () => decodeJwtSafely,
|
|
50
50
|
getCookie: () => getCookie,
|
|
51
51
|
getCurrentUserEmail: () => getCurrentUserEmail,
|
|
@@ -65,7 +65,7 @@ __export(index_exports, {
|
|
|
65
65
|
useUserProfile: () => useUserProfile
|
|
66
66
|
});
|
|
67
67
|
module.exports = __toCommonJS(index_exports);
|
|
68
|
-
var
|
|
68
|
+
var import_crudify_browser6 = __toESM(require("@nocios/crudify-browser"));
|
|
69
69
|
__reExport(index_exports, require("@nocios/crudify-browser"), module.exports);
|
|
70
70
|
|
|
71
71
|
// src/components/CrudifyLogin/index.tsx
|
|
@@ -733,7 +733,7 @@ function handleCrudifyError(error) {
|
|
|
733
733
|
// src/components/CrudifyLogin/Forms/LoginForm.tsx
|
|
734
734
|
var import_jsx_runtime4 = require("react/jsx-runtime");
|
|
735
735
|
var LoginForm = ({ onScreenChange, onExternalNavigate, onLoginSuccess, onError, redirectUrl = "/" }) => {
|
|
736
|
-
const { crudify:
|
|
736
|
+
const { crudify: crudify6 } = useCrudify();
|
|
737
737
|
const { state, updateFormData, setFieldError, clearErrors, setLoading } = useLoginState();
|
|
738
738
|
const { t } = useTranslation();
|
|
739
739
|
const usernameInputRef = (0, import_react5.useRef)(null);
|
|
@@ -784,10 +784,10 @@ var LoginForm = ({ onScreenChange, onExternalNavigate, onLoginSuccess, onError,
|
|
|
784
784
|
clearErrors();
|
|
785
785
|
setLoading(true);
|
|
786
786
|
try {
|
|
787
|
-
if (!
|
|
787
|
+
if (!crudify6) {
|
|
788
788
|
throw new Error("Crudify not initialized");
|
|
789
789
|
}
|
|
790
|
-
const response = await
|
|
790
|
+
const response = await crudify6.login(state.formData.username, state.formData.password);
|
|
791
791
|
setLoading(false);
|
|
792
792
|
if (response.success) {
|
|
793
793
|
console.log("\u{1F510} LoginForm - Login successful, calling onLoginSuccess");
|
|
@@ -942,7 +942,7 @@ var import_react6 = require("react");
|
|
|
942
942
|
var import_material2 = require("@mui/material");
|
|
943
943
|
var import_jsx_runtime5 = require("react/jsx-runtime");
|
|
944
944
|
var ForgotPasswordForm = ({ onScreenChange, onError }) => {
|
|
945
|
-
const { crudify:
|
|
945
|
+
const { crudify: crudify6 } = useCrudify();
|
|
946
946
|
const [email, setEmail] = (0, import_react6.useState)("");
|
|
947
947
|
const [loading, setLoading] = (0, import_react6.useState)(false);
|
|
948
948
|
const [errors, setErrors] = (0, import_react6.useState)([]);
|
|
@@ -971,7 +971,7 @@ var ForgotPasswordForm = ({ onScreenChange, onError }) => {
|
|
|
971
971
|
return emailRegex.test(email2);
|
|
972
972
|
};
|
|
973
973
|
const handleSubmit = async () => {
|
|
974
|
-
if (loading || !
|
|
974
|
+
if (loading || !crudify6) return;
|
|
975
975
|
setErrors([]);
|
|
976
976
|
setHelperTextEmail(null);
|
|
977
977
|
if (!email) {
|
|
@@ -985,7 +985,7 @@ var ForgotPasswordForm = ({ onScreenChange, onError }) => {
|
|
|
985
985
|
setLoading(true);
|
|
986
986
|
try {
|
|
987
987
|
const data = [{ operation: "requestPasswordReset", data: { email } }];
|
|
988
|
-
const response = await
|
|
988
|
+
const response = await crudify6.transaction(data);
|
|
989
989
|
if (response.success) {
|
|
990
990
|
if (response.data && response.data.existingCodeValid) {
|
|
991
991
|
setCodeAlreadyExists(true);
|
|
@@ -1088,7 +1088,7 @@ var import_react7 = require("react");
|
|
|
1088
1088
|
var import_material3 = require("@mui/material");
|
|
1089
1089
|
var import_jsx_runtime6 = require("react/jsx-runtime");
|
|
1090
1090
|
var ResetPasswordForm = ({ onScreenChange, onError, searchParams, onResetSuccess }) => {
|
|
1091
|
-
const { crudify:
|
|
1091
|
+
const { crudify: crudify6 } = useCrudify();
|
|
1092
1092
|
const [newPassword, setNewPassword] = (0, import_react7.useState)("");
|
|
1093
1093
|
const [confirmPassword, setConfirmPassword] = (0, import_react7.useState)("");
|
|
1094
1094
|
const [loading, setLoading] = (0, import_react7.useState)(false);
|
|
@@ -1168,9 +1168,9 @@ var ResetPasswordForm = ({ onScreenChange, onError, searchParams, onResetSuccess
|
|
|
1168
1168
|
setErrors([t("resetPassword.invalidCode")]);
|
|
1169
1169
|
setValidatingCode(false);
|
|
1170
1170
|
setTimeout(() => onScreenChange?.("forgotPassword"), 3e3);
|
|
1171
|
-
}, [searchParams,
|
|
1171
|
+
}, [searchParams, crudify6, t, onScreenChange]);
|
|
1172
1172
|
(0, import_react7.useEffect)(() => {
|
|
1173
|
-
if (
|
|
1173
|
+
if (crudify6 && pendingValidation && !isValidating) {
|
|
1174
1174
|
setIsValidating(true);
|
|
1175
1175
|
const validateCode = async (emailToValidate, codeToValidate) => {
|
|
1176
1176
|
try {
|
|
@@ -1180,7 +1180,7 @@ var ResetPasswordForm = ({ onScreenChange, onError, searchParams, onResetSuccess
|
|
|
1180
1180
|
data: { email: emailToValidate, codePassword: codeToValidate }
|
|
1181
1181
|
}
|
|
1182
1182
|
];
|
|
1183
|
-
const response = await
|
|
1183
|
+
const response = await crudify6.transaction(data);
|
|
1184
1184
|
if (response.data && Array.isArray(response.data)) {
|
|
1185
1185
|
const validationResult = response.data[0];
|
|
1186
1186
|
if (validationResult && validationResult.response && validationResult.response.status === "OK") {
|
|
@@ -1209,7 +1209,7 @@ var ResetPasswordForm = ({ onScreenChange, onError, searchParams, onResetSuccess
|
|
|
1209
1209
|
};
|
|
1210
1210
|
validateCode(pendingValidation.email, pendingValidation.code);
|
|
1211
1211
|
}
|
|
1212
|
-
}, [
|
|
1212
|
+
}, [crudify6, pendingValidation, t, onScreenChange]);
|
|
1213
1213
|
const validatePassword = (password) => {
|
|
1214
1214
|
if (password.length < 8) {
|
|
1215
1215
|
return t("resetPassword.passwordTooShort");
|
|
@@ -1217,7 +1217,7 @@ var ResetPasswordForm = ({ onScreenChange, onError, searchParams, onResetSuccess
|
|
|
1217
1217
|
return null;
|
|
1218
1218
|
};
|
|
1219
1219
|
const handleSubmit = async () => {
|
|
1220
|
-
if (loading || !
|
|
1220
|
+
if (loading || !crudify6) return;
|
|
1221
1221
|
setErrors([]);
|
|
1222
1222
|
setHelperTextNewPassword(null);
|
|
1223
1223
|
setHelperTextConfirmPassword(null);
|
|
@@ -1248,7 +1248,7 @@ var ResetPasswordForm = ({ onScreenChange, onError, searchParams, onResetSuccess
|
|
|
1248
1248
|
data: { email, codePassword: code, newPassword }
|
|
1249
1249
|
}
|
|
1250
1250
|
];
|
|
1251
|
-
const response = await
|
|
1251
|
+
const response = await crudify6.transaction(data);
|
|
1252
1252
|
if (response.success) {
|
|
1253
1253
|
setErrors([]);
|
|
1254
1254
|
setTimeout(() => {
|
|
@@ -1359,7 +1359,7 @@ var import_react8 = require("react");
|
|
|
1359
1359
|
var import_material4 = require("@mui/material");
|
|
1360
1360
|
var import_jsx_runtime7 = require("react/jsx-runtime");
|
|
1361
1361
|
var CheckCodeForm = ({ onScreenChange, onError, searchParams }) => {
|
|
1362
|
-
const { crudify:
|
|
1362
|
+
const { crudify: crudify6 } = useCrudify();
|
|
1363
1363
|
const [code, setCode] = (0, import_react8.useState)("");
|
|
1364
1364
|
const [loading, setLoading] = (0, import_react8.useState)(false);
|
|
1365
1365
|
const [errors, setErrors] = (0, import_react8.useState)([]);
|
|
@@ -1398,7 +1398,7 @@ var CheckCodeForm = ({ onScreenChange, onError, searchParams }) => {
|
|
|
1398
1398
|
}
|
|
1399
1399
|
}, [searchParams, onScreenChange]);
|
|
1400
1400
|
const handleSubmit = async () => {
|
|
1401
|
-
if (loading || !
|
|
1401
|
+
if (loading || !crudify6) return;
|
|
1402
1402
|
setErrors([]);
|
|
1403
1403
|
setHelperTextCode(null);
|
|
1404
1404
|
if (!code) {
|
|
@@ -1417,7 +1417,7 @@ var CheckCodeForm = ({ onScreenChange, onError, searchParams }) => {
|
|
|
1417
1417
|
data: { email, codePassword: code }
|
|
1418
1418
|
}
|
|
1419
1419
|
];
|
|
1420
|
-
const response = await
|
|
1420
|
+
const response = await crudify6.transaction(data);
|
|
1421
1421
|
if (response.success) {
|
|
1422
1422
|
onScreenChange?.("resetPassword", { email, code, fromCodeVerification: "true" });
|
|
1423
1423
|
} else {
|
|
@@ -1540,1805 +1540,1831 @@ var CrudifyInitializer = ({ children, fallback }) => {
|
|
|
1540
1540
|
return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_jsx_runtime8.Fragment, { children });
|
|
1541
1541
|
};
|
|
1542
1542
|
|
|
1543
|
-
// src/
|
|
1543
|
+
// src/providers/SessionProvider.tsx
|
|
1544
|
+
var import_react10 = require("react");
|
|
1545
|
+
|
|
1546
|
+
// src/hooks/useSession.ts
|
|
1544
1547
|
var import_react9 = require("react");
|
|
1548
|
+
|
|
1549
|
+
// src/core/SessionManager.ts
|
|
1545
1550
|
var import_crudify_browser2 = __toESM(require("@nocios/crudify-browser"));
|
|
1546
|
-
var useCrudifyLogin = (config, _options = {}) => {
|
|
1547
|
-
console.log("\u{1F50D} useCrudifyLogin - Input config:", config);
|
|
1548
|
-
const finalConfig = (0, import_react9.useMemo)(() => {
|
|
1549
|
-
const publicApiKey = config.publicApiKey || import_crudify_browser2.default?.publicApiKey || import_crudify_browser2.default?.apiKey || getCookie("publicApiKey") || null;
|
|
1550
|
-
const rawEnv = config.env || getCookie("environment") || "prod";
|
|
1551
|
-
const env = ["dev", "stg", "prod"].includes(rawEnv) ? rawEnv : "prod";
|
|
1552
|
-
const appName = config.appName || getCookie("appName") || "Crudia";
|
|
1553
|
-
const loginActions = config.loginActions || (() => {
|
|
1554
|
-
try {
|
|
1555
|
-
const cookieValue = getCookie("loginActions");
|
|
1556
|
-
return cookieValue ? cookieValue.split(",").map((action) => action.trim()).filter(Boolean) : [];
|
|
1557
|
-
} catch {
|
|
1558
|
-
return [];
|
|
1559
|
-
}
|
|
1560
|
-
})();
|
|
1561
|
-
console.log("\u{1F50D} useCrudifyLogin - Resolved publicApiKey:", publicApiKey);
|
|
1562
|
-
console.log(
|
|
1563
|
-
"\u{1F50D} useCrudifyLogin - Sources - props:",
|
|
1564
|
-
config.publicApiKey,
|
|
1565
|
-
"crudify:",
|
|
1566
|
-
import_crudify_browser2.default?.publicApiKey,
|
|
1567
|
-
"cookie:",
|
|
1568
|
-
getCookie("publicApiKey")
|
|
1569
|
-
);
|
|
1570
|
-
console.log("\u{1F50D} useCrudifyLogin - Final env:", env, "from rawEnv:", rawEnv);
|
|
1571
|
-
const finalResult = {
|
|
1572
|
-
publicApiKey,
|
|
1573
|
-
env,
|
|
1574
|
-
appName,
|
|
1575
|
-
loginActions
|
|
1576
|
-
};
|
|
1577
|
-
console.log("\u{1F50D} useCrudifyLogin - Final config result:", finalResult);
|
|
1578
|
-
return finalResult;
|
|
1579
|
-
}, [config]);
|
|
1580
|
-
return { config: finalConfig };
|
|
1581
|
-
};
|
|
1582
1551
|
|
|
1583
|
-
// src/
|
|
1584
|
-
var
|
|
1585
|
-
var
|
|
1586
|
-
|
|
1587
|
-
|
|
1588
|
-
|
|
1589
|
-
|
|
1590
|
-
|
|
1591
|
-
}
|
|
1592
|
-
|
|
1593
|
-
|
|
1594
|
-
|
|
1595
|
-
|
|
1596
|
-
|
|
1597
|
-
|
|
1598
|
-
|
|
1599
|
-
|
|
1600
|
-
|
|
1601
|
-
|
|
1602
|
-
|
|
1603
|
-
|
|
1604
|
-
const renderCurrentForm = () => {
|
|
1605
|
-
const commonProps = {
|
|
1606
|
-
onScreenChange: handleScreenChange,
|
|
1607
|
-
onExternalNavigate,
|
|
1608
|
-
onError,
|
|
1609
|
-
redirectUrl
|
|
1610
|
-
};
|
|
1611
|
-
switch (state.currentScreen) {
|
|
1612
|
-
case "forgotPassword":
|
|
1613
|
-
return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(ForgotPasswordForm_default, { ...commonProps });
|
|
1614
|
-
case "checkCode":
|
|
1615
|
-
return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(CheckCodeForm_default, { ...commonProps, searchParams: state.searchParams });
|
|
1616
|
-
case "resetPassword":
|
|
1617
|
-
return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
1618
|
-
ResetPasswordForm_default,
|
|
1619
|
-
{
|
|
1620
|
-
...commonProps,
|
|
1621
|
-
searchParams: state.searchParams,
|
|
1622
|
-
onResetSuccess: () => {
|
|
1623
|
-
handleScreenChange("login");
|
|
1624
|
-
}
|
|
1625
|
-
}
|
|
1626
|
-
);
|
|
1627
|
-
default:
|
|
1628
|
-
return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(LoginForm_default, { ...commonProps, onLoginSuccess });
|
|
1552
|
+
// src/utils/tokenStorage.ts
|
|
1553
|
+
var import_crypto_js = __toESM(require("crypto-js"));
|
|
1554
|
+
var _TokenStorage = class _TokenStorage {
|
|
1555
|
+
/**
|
|
1556
|
+
* Configurar tipo de almacenamiento
|
|
1557
|
+
*/
|
|
1558
|
+
static setStorageType(type) {
|
|
1559
|
+
_TokenStorage.storageType = type;
|
|
1560
|
+
}
|
|
1561
|
+
/**
|
|
1562
|
+
* Verificar si el storage está disponible
|
|
1563
|
+
*/
|
|
1564
|
+
static isStorageAvailable(type) {
|
|
1565
|
+
try {
|
|
1566
|
+
const storage = window[type];
|
|
1567
|
+
const testKey = "__storage_test__";
|
|
1568
|
+
storage.setItem(testKey, "test");
|
|
1569
|
+
storage.removeItem(testKey);
|
|
1570
|
+
return true;
|
|
1571
|
+
} catch {
|
|
1572
|
+
return false;
|
|
1629
1573
|
}
|
|
1630
|
-
}
|
|
1631
|
-
|
|
1632
|
-
|
|
1633
|
-
|
|
1634
|
-
|
|
1635
|
-
|
|
1636
|
-
|
|
1637
|
-
|
|
1638
|
-
width: "100%",
|
|
1639
|
-
maxWidth: "150px",
|
|
1640
|
-
height: "auto"
|
|
1641
|
-
},
|
|
1642
|
-
onError: (e) => {
|
|
1643
|
-
const target = e.target;
|
|
1644
|
-
target.src = "/nocios-default.png";
|
|
1645
|
-
}
|
|
1646
|
-
}
|
|
1647
|
-
) }),
|
|
1648
|
-
state.config.appName && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
1649
|
-
import_material6.Typography,
|
|
1650
|
-
{
|
|
1651
|
-
variant: "h6",
|
|
1652
|
-
component: "h1",
|
|
1653
|
-
sx: {
|
|
1654
|
-
textAlign: "center",
|
|
1655
|
-
mb: 2,
|
|
1656
|
-
color: state.config.colors?.primaryColor || "#1066BA"
|
|
1657
|
-
},
|
|
1658
|
-
children: state.config.appName
|
|
1659
|
-
}
|
|
1660
|
-
),
|
|
1661
|
-
renderCurrentForm()
|
|
1662
|
-
] });
|
|
1663
|
-
};
|
|
1664
|
-
var CrudifyLogin = ({
|
|
1665
|
-
translations,
|
|
1666
|
-
translationsUrl,
|
|
1667
|
-
language = "en",
|
|
1668
|
-
config = {},
|
|
1669
|
-
initialScreen = "login",
|
|
1670
|
-
autoReadFromCookies = true,
|
|
1671
|
-
...props
|
|
1672
|
-
}) => {
|
|
1673
|
-
const { config: finalConfig } = useCrudifyLogin(config);
|
|
1674
|
-
return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(I18nProvider, { translations, translationsUrl, language, children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(CrudifyProvider, { config: finalConfig, children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(LoginStateProvider, { config, initialScreen, autoReadFromCookies, children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(CrudifyLoginInternal, { config, ...props }) }) }) });
|
|
1675
|
-
};
|
|
1676
|
-
var CrudifyLogin_default = CrudifyLogin;
|
|
1677
|
-
|
|
1678
|
-
// src/components/UserProfile/UserProfileDisplay.tsx
|
|
1679
|
-
var import_material7 = require("@mui/material");
|
|
1680
|
-
var import_icons_material = require("@mui/icons-material");
|
|
1681
|
-
|
|
1682
|
-
// src/hooks/useUserProfile.ts
|
|
1683
|
-
var import_react10 = require("react");
|
|
1684
|
-
var import_crudify_browser3 = __toESM(require("@nocios/crudify-browser"));
|
|
1685
|
-
|
|
1686
|
-
// src/utils/jwtUtils.ts
|
|
1687
|
-
var decodeJwtSafely = (token) => {
|
|
1688
|
-
try {
|
|
1689
|
-
const parts = token.split(".");
|
|
1690
|
-
if (parts.length !== 3) {
|
|
1691
|
-
console.warn("Invalid JWT format: token must have 3 parts");
|
|
1574
|
+
}
|
|
1575
|
+
/**
|
|
1576
|
+
* Obtener instancia de storage
|
|
1577
|
+
*/
|
|
1578
|
+
static getStorage() {
|
|
1579
|
+
if (_TokenStorage.storageType === "none") return null;
|
|
1580
|
+
if (!_TokenStorage.isStorageAvailable(_TokenStorage.storageType)) {
|
|
1581
|
+
console.warn(`Crudify: ${_TokenStorage.storageType} not available, tokens won't persist`);
|
|
1692
1582
|
return null;
|
|
1693
1583
|
}
|
|
1694
|
-
|
|
1695
|
-
const paddedPayload = payload + "=".repeat((4 - payload.length % 4) % 4);
|
|
1696
|
-
const decodedPayload = JSON.parse(atob(paddedPayload));
|
|
1697
|
-
return decodedPayload;
|
|
1698
|
-
} catch (error) {
|
|
1699
|
-
console.warn("Failed to decode JWT token:", error);
|
|
1700
|
-
return null;
|
|
1584
|
+
return window[_TokenStorage.storageType];
|
|
1701
1585
|
}
|
|
1702
|
-
|
|
1703
|
-
|
|
1704
|
-
|
|
1705
|
-
|
|
1706
|
-
|
|
1707
|
-
|
|
1708
|
-
|
|
1709
|
-
|
|
1710
|
-
|
|
1586
|
+
/**
|
|
1587
|
+
* Encriptar datos sensibles
|
|
1588
|
+
*/
|
|
1589
|
+
static encrypt(data) {
|
|
1590
|
+
try {
|
|
1591
|
+
return import_crypto_js.default.AES.encrypt(data, _TokenStorage.ENCRYPTION_KEY).toString();
|
|
1592
|
+
} catch (error) {
|
|
1593
|
+
console.error("Crudify: Encryption failed", error);
|
|
1594
|
+
return data;
|
|
1711
1595
|
}
|
|
1712
|
-
|
|
1713
|
-
|
|
1714
|
-
|
|
1596
|
+
}
|
|
1597
|
+
/**
|
|
1598
|
+
* Desencriptar datos
|
|
1599
|
+
*/
|
|
1600
|
+
static decrypt(encryptedData) {
|
|
1601
|
+
try {
|
|
1602
|
+
const bytes = import_crypto_js.default.AES.decrypt(encryptedData, _TokenStorage.ENCRYPTION_KEY);
|
|
1603
|
+
const decrypted = bytes.toString(import_crypto_js.default.enc.Utf8);
|
|
1604
|
+
return decrypted || encryptedData;
|
|
1605
|
+
} catch (error) {
|
|
1606
|
+
console.error("Crudify: Decryption failed", error);
|
|
1607
|
+
return encryptedData;
|
|
1715
1608
|
}
|
|
1716
|
-
|
|
1717
|
-
|
|
1718
|
-
|
|
1609
|
+
}
|
|
1610
|
+
/**
|
|
1611
|
+
* Guardar tokens de forma segura
|
|
1612
|
+
*/
|
|
1613
|
+
static saveTokens(tokens) {
|
|
1614
|
+
const storage = _TokenStorage.getStorage();
|
|
1615
|
+
if (!storage) return;
|
|
1616
|
+
try {
|
|
1617
|
+
const tokenData = {
|
|
1618
|
+
accessToken: tokens.accessToken,
|
|
1619
|
+
refreshToken: tokens.refreshToken,
|
|
1620
|
+
expiresAt: tokens.expiresAt,
|
|
1621
|
+
refreshExpiresAt: tokens.refreshExpiresAt,
|
|
1622
|
+
savedAt: Date.now()
|
|
1623
|
+
};
|
|
1624
|
+
const encrypted = _TokenStorage.encrypt(JSON.stringify(tokenData));
|
|
1625
|
+
storage.setItem(_TokenStorage.TOKEN_KEY, encrypted);
|
|
1626
|
+
console.debug("Crudify: Tokens saved successfully");
|
|
1627
|
+
} catch (error) {
|
|
1628
|
+
console.error("Crudify: Failed to save tokens", error);
|
|
1719
1629
|
}
|
|
1720
|
-
|
|
1721
|
-
|
|
1722
|
-
|
|
1630
|
+
}
|
|
1631
|
+
/**
|
|
1632
|
+
* Obtener tokens guardados
|
|
1633
|
+
*/
|
|
1634
|
+
static getTokens() {
|
|
1635
|
+
const storage = _TokenStorage.getStorage();
|
|
1636
|
+
if (!storage) return null;
|
|
1637
|
+
try {
|
|
1638
|
+
const encrypted = storage.getItem(_TokenStorage.TOKEN_KEY);
|
|
1639
|
+
if (!encrypted) return null;
|
|
1640
|
+
const decrypted = _TokenStorage.decrypt(encrypted);
|
|
1641
|
+
const tokenData = JSON.parse(decrypted);
|
|
1642
|
+
if (!tokenData.accessToken || !tokenData.refreshToken || !tokenData.expiresAt || !tokenData.refreshExpiresAt) {
|
|
1643
|
+
console.warn("Crudify: Incomplete token data found, clearing storage");
|
|
1644
|
+
_TokenStorage.clearTokens();
|
|
1645
|
+
return null;
|
|
1646
|
+
}
|
|
1647
|
+
if (Date.now() >= tokenData.refreshExpiresAt) {
|
|
1648
|
+
console.info("Crudify: Refresh token expired, clearing storage");
|
|
1649
|
+
_TokenStorage.clearTokens();
|
|
1650
|
+
return null;
|
|
1651
|
+
}
|
|
1652
|
+
return {
|
|
1653
|
+
accessToken: tokenData.accessToken,
|
|
1654
|
+
refreshToken: tokenData.refreshToken,
|
|
1655
|
+
expiresAt: tokenData.expiresAt,
|
|
1656
|
+
refreshExpiresAt: tokenData.refreshExpiresAt
|
|
1657
|
+
};
|
|
1658
|
+
} catch (error) {
|
|
1659
|
+
console.error("Crudify: Failed to retrieve tokens", error);
|
|
1660
|
+
_TokenStorage.clearTokens();
|
|
1723
1661
|
return null;
|
|
1724
1662
|
}
|
|
1725
|
-
const email = payload.email || payload["cognito:username"] || null;
|
|
1726
|
-
console.log("\u{1F50D} getCurrentUserEmail - Extracted email:", email);
|
|
1727
|
-
return email;
|
|
1728
|
-
} catch (error) {
|
|
1729
|
-
console.warn("Failed to get current user email:", error);
|
|
1730
|
-
return null;
|
|
1731
|
-
}
|
|
1732
|
-
};
|
|
1733
|
-
var isTokenExpired = (token) => {
|
|
1734
|
-
try {
|
|
1735
|
-
const payload = decodeJwtSafely(token);
|
|
1736
|
-
if (!payload || !payload.exp) return true;
|
|
1737
|
-
const currentTime = Math.floor(Date.now() / 1e3);
|
|
1738
|
-
return payload.exp < currentTime;
|
|
1739
|
-
} catch {
|
|
1740
|
-
return true;
|
|
1741
1663
|
}
|
|
1742
|
-
|
|
1743
|
-
|
|
1744
|
-
|
|
1745
|
-
|
|
1746
|
-
|
|
1747
|
-
|
|
1748
|
-
const [loading, setLoading] = (0, import_react10.useState)(false);
|
|
1749
|
-
const [error, setError] = (0, import_react10.useState)(null);
|
|
1750
|
-
const [extendedData, setExtendedData] = (0, import_react10.useState)({});
|
|
1751
|
-
const abortControllerRef = (0, import_react10.useRef)(null);
|
|
1752
|
-
const mountedRef = (0, import_react10.useRef)(true);
|
|
1753
|
-
const requestIdRef = (0, import_react10.useRef)(0);
|
|
1754
|
-
const retryCountRef = (0, import_react10.useRef)(0);
|
|
1755
|
-
const clearProfile = (0, import_react10.useCallback)(() => {
|
|
1756
|
-
setUserProfile(null);
|
|
1757
|
-
setError(null);
|
|
1758
|
-
setLoading(false);
|
|
1759
|
-
setExtendedData({});
|
|
1760
|
-
}, []);
|
|
1761
|
-
const refreshProfile = (0, import_react10.useCallback)(async () => {
|
|
1762
|
-
const userEmail = getCurrentUserEmail();
|
|
1763
|
-
if (!userEmail) {
|
|
1764
|
-
if (mountedRef.current) {
|
|
1765
|
-
setError("No user email available");
|
|
1766
|
-
setLoading(false);
|
|
1767
|
-
}
|
|
1768
|
-
return;
|
|
1769
|
-
}
|
|
1770
|
-
if (abortControllerRef.current) {
|
|
1771
|
-
abortControllerRef.current.abort();
|
|
1772
|
-
}
|
|
1773
|
-
const abortController = new AbortController();
|
|
1774
|
-
abortControllerRef.current = abortController;
|
|
1775
|
-
const currentRequestId = ++requestIdRef.current;
|
|
1664
|
+
/**
|
|
1665
|
+
* Limpiar tokens almacenados
|
|
1666
|
+
*/
|
|
1667
|
+
static clearTokens() {
|
|
1668
|
+
const storage = _TokenStorage.getStorage();
|
|
1669
|
+
if (!storage) return;
|
|
1776
1670
|
try {
|
|
1777
|
-
|
|
1778
|
-
|
|
1779
|
-
|
|
1780
|
-
|
|
1781
|
-
const response = await import_crudify_browser3.default.readItems("users", {
|
|
1782
|
-
filter: { email: userEmail },
|
|
1783
|
-
pagination: { limit: 1 }
|
|
1784
|
-
});
|
|
1785
|
-
if (currentRequestId === requestIdRef.current && mountedRef.current && !abortController.signal.aborted) {
|
|
1786
|
-
if (response.success && response.data && response.data.length > 0) {
|
|
1787
|
-
const userData = response.data[0];
|
|
1788
|
-
setUserProfile(userData);
|
|
1789
|
-
const additionalData = {
|
|
1790
|
-
fullProfile: userData,
|
|
1791
|
-
totalFields: Object.keys(userData).length,
|
|
1792
|
-
displayData: {
|
|
1793
|
-
id: userData.id,
|
|
1794
|
-
email: userData.email,
|
|
1795
|
-
username: userData.username,
|
|
1796
|
-
firstName: userData.firstName,
|
|
1797
|
-
lastName: userData.lastName,
|
|
1798
|
-
fullName: userData.fullName || `${userData.firstName || ""} ${userData.lastName || ""}`.trim(),
|
|
1799
|
-
role: userData.role,
|
|
1800
|
-
permissions: userData.permissions || [],
|
|
1801
|
-
isActive: userData.isActive,
|
|
1802
|
-
lastLogin: userData.lastLogin,
|
|
1803
|
-
createdAt: userData.createdAt,
|
|
1804
|
-
updatedAt: userData.updatedAt,
|
|
1805
|
-
// Include any custom fields
|
|
1806
|
-
...Object.keys(userData).filter(
|
|
1807
|
-
(key) => ![
|
|
1808
|
-
"id",
|
|
1809
|
-
"email",
|
|
1810
|
-
"username",
|
|
1811
|
-
"firstName",
|
|
1812
|
-
"lastName",
|
|
1813
|
-
"fullName",
|
|
1814
|
-
"role",
|
|
1815
|
-
"permissions",
|
|
1816
|
-
"isActive",
|
|
1817
|
-
"lastLogin",
|
|
1818
|
-
"createdAt",
|
|
1819
|
-
"updatedAt"
|
|
1820
|
-
].includes(key)
|
|
1821
|
-
).reduce((acc, key) => ({ ...acc, [key]: userData[key] }), {})
|
|
1822
|
-
}
|
|
1823
|
-
};
|
|
1824
|
-
setExtendedData(additionalData);
|
|
1825
|
-
setError(null);
|
|
1826
|
-
retryCountRef.current = 0;
|
|
1827
|
-
} else {
|
|
1828
|
-
setError("User profile not found");
|
|
1829
|
-
setUserProfile(null);
|
|
1830
|
-
setExtendedData({});
|
|
1831
|
-
}
|
|
1832
|
-
}
|
|
1833
|
-
} catch (err) {
|
|
1834
|
-
if (currentRequestId === requestIdRef.current && mountedRef.current) {
|
|
1835
|
-
const error2 = err;
|
|
1836
|
-
if (error2.name === "AbortError") {
|
|
1837
|
-
return;
|
|
1838
|
-
}
|
|
1839
|
-
const shouldRetry = retryOnError && retryCountRef.current < maxRetries && (error2.message?.includes("Network Error") || error2.message?.includes("Failed to fetch"));
|
|
1840
|
-
if (shouldRetry) {
|
|
1841
|
-
retryCountRef.current++;
|
|
1842
|
-
setTimeout(() => {
|
|
1843
|
-
if (mountedRef.current) {
|
|
1844
|
-
refreshProfile();
|
|
1845
|
-
}
|
|
1846
|
-
}, 1e3 * retryCountRef.current);
|
|
1847
|
-
} else {
|
|
1848
|
-
setError("Failed to load user profile");
|
|
1849
|
-
setUserProfile(null);
|
|
1850
|
-
setExtendedData({});
|
|
1851
|
-
}
|
|
1852
|
-
}
|
|
1853
|
-
} finally {
|
|
1854
|
-
if (currentRequestId === requestIdRef.current && mountedRef.current) {
|
|
1855
|
-
setLoading(false);
|
|
1856
|
-
}
|
|
1857
|
-
if (abortControllerRef.current === abortController) {
|
|
1858
|
-
abortControllerRef.current = null;
|
|
1859
|
-
}
|
|
1860
|
-
}
|
|
1861
|
-
}, [retryOnError, maxRetries]);
|
|
1862
|
-
(0, import_react10.useEffect)(() => {
|
|
1863
|
-
if (autoFetch) {
|
|
1864
|
-
refreshProfile();
|
|
1671
|
+
storage.removeItem(_TokenStorage.TOKEN_KEY);
|
|
1672
|
+
console.debug("Crudify: Tokens cleared from storage");
|
|
1673
|
+
} catch (error) {
|
|
1674
|
+
console.error("Crudify: Failed to clear tokens", error);
|
|
1865
1675
|
}
|
|
1866
|
-
}
|
|
1867
|
-
|
|
1868
|
-
|
|
1869
|
-
|
|
1870
|
-
|
|
1871
|
-
|
|
1872
|
-
|
|
1873
|
-
|
|
1874
|
-
|
|
1676
|
+
}
|
|
1677
|
+
/**
|
|
1678
|
+
* Verificar si hay tokens válidos guardados
|
|
1679
|
+
*/
|
|
1680
|
+
static hasValidTokens() {
|
|
1681
|
+
const tokens = _TokenStorage.getTokens();
|
|
1682
|
+
return tokens !== null;
|
|
1683
|
+
}
|
|
1684
|
+
/**
|
|
1685
|
+
* Obtener información de expiración
|
|
1686
|
+
*/
|
|
1687
|
+
static getExpirationInfo() {
|
|
1688
|
+
const tokens = _TokenStorage.getTokens();
|
|
1689
|
+
if (!tokens) return null;
|
|
1690
|
+
const now = Date.now();
|
|
1691
|
+
return {
|
|
1692
|
+
accessExpired: now >= tokens.expiresAt,
|
|
1693
|
+
refreshExpired: now >= tokens.refreshExpiresAt,
|
|
1694
|
+
accessExpiresIn: Math.max(0, tokens.expiresAt - now),
|
|
1695
|
+
refreshExpiresIn: Math.max(0, tokens.refreshExpiresAt - now)
|
|
1875
1696
|
};
|
|
1876
|
-
}
|
|
1877
|
-
|
|
1878
|
-
|
|
1879
|
-
|
|
1880
|
-
|
|
1881
|
-
|
|
1882
|
-
|
|
1883
|
-
|
|
1884
|
-
|
|
1697
|
+
}
|
|
1698
|
+
/**
|
|
1699
|
+
* Actualizar solo el access token (después de refresh)
|
|
1700
|
+
*/
|
|
1701
|
+
static updateAccessToken(newAccessToken, newExpiresAt) {
|
|
1702
|
+
const existingTokens = _TokenStorage.getTokens();
|
|
1703
|
+
if (!existingTokens) {
|
|
1704
|
+
console.warn("Crudify: Cannot update access token, no existing tokens found");
|
|
1705
|
+
return;
|
|
1706
|
+
}
|
|
1707
|
+
_TokenStorage.saveTokens({
|
|
1708
|
+
...existingTokens,
|
|
1709
|
+
accessToken: newAccessToken,
|
|
1710
|
+
expiresAt: newExpiresAt
|
|
1711
|
+
});
|
|
1712
|
+
}
|
|
1885
1713
|
};
|
|
1714
|
+
_TokenStorage.TOKEN_KEY = "crudify_tokens";
|
|
1715
|
+
_TokenStorage.ENCRYPTION_KEY = "crudify_secure_key_v1";
|
|
1716
|
+
_TokenStorage.storageType = "localStorage";
|
|
1717
|
+
var TokenStorage = _TokenStorage;
|
|
1886
1718
|
|
|
1887
|
-
// src/
|
|
1888
|
-
var
|
|
1889
|
-
|
|
1890
|
-
|
|
1891
|
-
|
|
1892
|
-
showProfileCard = true,
|
|
1893
|
-
autoRefresh = true
|
|
1894
|
-
}) => {
|
|
1895
|
-
const { userProfile, loading, error, extendedData, refreshProfile } = useUserProfile({
|
|
1896
|
-
autoFetch: autoRefresh,
|
|
1897
|
-
retryOnError: true,
|
|
1898
|
-
maxRetries: 3
|
|
1899
|
-
});
|
|
1900
|
-
const [showAllFields, setShowAllFields] = (0, import_react11.useState)(false);
|
|
1901
|
-
if (loading) {
|
|
1902
|
-
return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(import_material7.Box, { display: "flex", justifyContent: "center", alignItems: "center", p: 3, children: [
|
|
1903
|
-
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_material7.CircularProgress, {}),
|
|
1904
|
-
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_material7.Typography, { variant: "body2", sx: { ml: 2 }, children: "Cargando perfil de usuario..." })
|
|
1905
|
-
] });
|
|
1719
|
+
// src/core/SessionManager.ts
|
|
1720
|
+
var SessionManager = class _SessionManager {
|
|
1721
|
+
constructor() {
|
|
1722
|
+
this.config = {};
|
|
1723
|
+
this.initialized = false;
|
|
1906
1724
|
}
|
|
1907
|
-
|
|
1908
|
-
|
|
1909
|
-
|
|
1910
|
-
|
|
1911
|
-
|
|
1912
|
-
action: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_material7.IconButton, { color: "inherit", size: "small", onClick: refreshProfile, children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_material7.Typography, { variant: "caption", children: "Reintentar" }) }),
|
|
1913
|
-
children: [
|
|
1914
|
-
"Error al cargar el perfil: ",
|
|
1915
|
-
error
|
|
1916
|
-
]
|
|
1917
|
-
}
|
|
1918
|
-
);
|
|
1725
|
+
static getInstance() {
|
|
1726
|
+
if (!_SessionManager.instance) {
|
|
1727
|
+
_SessionManager.instance = new _SessionManager();
|
|
1728
|
+
}
|
|
1729
|
+
return _SessionManager.instance;
|
|
1919
1730
|
}
|
|
1920
|
-
|
|
1921
|
-
|
|
1731
|
+
/**
|
|
1732
|
+
* Inicializar el SessionManager
|
|
1733
|
+
*/
|
|
1734
|
+
async initialize(config = {}) {
|
|
1735
|
+
if (this.initialized) {
|
|
1736
|
+
console.warn("SessionManager: Already initialized");
|
|
1737
|
+
return;
|
|
1738
|
+
}
|
|
1739
|
+
this.config = {
|
|
1740
|
+
storageType: "localStorage",
|
|
1741
|
+
autoRestore: true,
|
|
1742
|
+
enableLogging: false,
|
|
1743
|
+
...config
|
|
1744
|
+
};
|
|
1745
|
+
TokenStorage.setStorageType(this.config.storageType || "localStorage");
|
|
1746
|
+
if (this.config.enableLogging) {
|
|
1747
|
+
}
|
|
1748
|
+
if (this.config.autoRestore) {
|
|
1749
|
+
await this.restoreSession();
|
|
1750
|
+
}
|
|
1751
|
+
this.initialized = true;
|
|
1752
|
+
this.log("SessionManager initialized successfully");
|
|
1922
1753
|
}
|
|
1923
|
-
|
|
1924
|
-
|
|
1925
|
-
|
|
1926
|
-
|
|
1754
|
+
/**
|
|
1755
|
+
* Login con persistencia automática
|
|
1756
|
+
*/
|
|
1757
|
+
async login(email, password) {
|
|
1927
1758
|
try {
|
|
1928
|
-
|
|
1929
|
-
|
|
1930
|
-
|
|
1931
|
-
|
|
1932
|
-
|
|
1933
|
-
|
|
1934
|
-
|
|
1935
|
-
|
|
1936
|
-
|
|
1937
|
-
|
|
1938
|
-
|
|
1939
|
-
|
|
1940
|
-
|
|
1941
|
-
|
|
1942
|
-
|
|
1943
|
-
|
|
1944
|
-
|
|
1945
|
-
|
|
1946
|
-
|
|
1947
|
-
|
|
1948
|
-
|
|
1949
|
-
|
|
1950
|
-
|
|
1951
|
-
|
|
1952
|
-
|
|
1953
|
-
|
|
1954
|
-
|
|
1955
|
-
|
|
1956
|
-
|
|
1957
|
-
|
|
1958
|
-
|
|
1959
|
-
|
|
1960
|
-
|
|
1961
|
-
|
|
1962
|
-
|
|
1963
|
-
|
|
1964
|
-
|
|
1965
|
-
|
|
1966
|
-
|
|
1967
|
-
|
|
1968
|
-
|
|
1969
|
-
|
|
1970
|
-
|
|
1971
|
-
|
|
1759
|
+
this.log("Attempting login...");
|
|
1760
|
+
const response = await import_crudify_browser2.default.login(email, password);
|
|
1761
|
+
if (!response.success) {
|
|
1762
|
+
this.log("Login failed:", response.errors);
|
|
1763
|
+
return {
|
|
1764
|
+
success: false,
|
|
1765
|
+
error: this.formatError(response.errors)
|
|
1766
|
+
};
|
|
1767
|
+
}
|
|
1768
|
+
const tokens = {
|
|
1769
|
+
accessToken: response.data.token,
|
|
1770
|
+
refreshToken: response.data.refreshToken,
|
|
1771
|
+
expiresAt: response.data.expiresAt,
|
|
1772
|
+
refreshExpiresAt: response.data.refreshExpiresAt
|
|
1773
|
+
};
|
|
1774
|
+
TokenStorage.saveTokens(tokens);
|
|
1775
|
+
this.log("Login successful, tokens saved");
|
|
1776
|
+
this.config.onLoginSuccess?.(tokens);
|
|
1777
|
+
return {
|
|
1778
|
+
success: true,
|
|
1779
|
+
tokens
|
|
1780
|
+
};
|
|
1781
|
+
} catch (error) {
|
|
1782
|
+
this.log("Login error:", error);
|
|
1783
|
+
return {
|
|
1784
|
+
success: false,
|
|
1785
|
+
error: error instanceof Error ? error.message : "Unknown error"
|
|
1786
|
+
};
|
|
1787
|
+
}
|
|
1788
|
+
}
|
|
1789
|
+
/**
|
|
1790
|
+
* Logout con limpieza de tokens
|
|
1791
|
+
*/
|
|
1792
|
+
async logout() {
|
|
1793
|
+
try {
|
|
1794
|
+
this.log("Logging out...");
|
|
1795
|
+
await import_crudify_browser2.default.logout();
|
|
1796
|
+
TokenStorage.clearTokens();
|
|
1797
|
+
this.log("Logout successful");
|
|
1798
|
+
this.config.onLogout?.();
|
|
1799
|
+
} catch (error) {
|
|
1800
|
+
this.log("Logout error:", error);
|
|
1801
|
+
TokenStorage.clearTokens();
|
|
1802
|
+
}
|
|
1803
|
+
}
|
|
1804
|
+
/**
|
|
1805
|
+
* Restaurar sesión desde storage
|
|
1806
|
+
*/
|
|
1807
|
+
async restoreSession() {
|
|
1808
|
+
try {
|
|
1809
|
+
this.log("Attempting to restore session...");
|
|
1810
|
+
const savedTokens = TokenStorage.getTokens();
|
|
1811
|
+
if (!savedTokens) {
|
|
1812
|
+
this.log("No valid tokens found in storage");
|
|
1813
|
+
return false;
|
|
1814
|
+
}
|
|
1815
|
+
import_crudify_browser2.default.setTokens({
|
|
1816
|
+
accessToken: savedTokens.accessToken,
|
|
1817
|
+
refreshToken: savedTokens.refreshToken,
|
|
1818
|
+
expiresAt: savedTokens.expiresAt,
|
|
1819
|
+
refreshExpiresAt: savedTokens.refreshExpiresAt
|
|
1820
|
+
});
|
|
1821
|
+
this.log("Session restored successfully");
|
|
1822
|
+
this.config.onSessionRestored?.(savedTokens);
|
|
1823
|
+
return true;
|
|
1824
|
+
} catch (error) {
|
|
1825
|
+
this.log("Session restore error:", error);
|
|
1826
|
+
TokenStorage.clearTokens();
|
|
1827
|
+
return false;
|
|
1828
|
+
}
|
|
1829
|
+
}
|
|
1830
|
+
/**
|
|
1831
|
+
* Verificar si el usuario está autenticado
|
|
1832
|
+
*/
|
|
1833
|
+
isAuthenticated() {
|
|
1834
|
+
return import_crudify_browser2.default.isLogin() || TokenStorage.hasValidTokens();
|
|
1835
|
+
}
|
|
1836
|
+
/**
|
|
1837
|
+
* Obtener información de tokens actuales
|
|
1838
|
+
*/
|
|
1839
|
+
getTokenInfo() {
|
|
1840
|
+
const crudifyTokens = import_crudify_browser2.default.getTokenData();
|
|
1841
|
+
const storageInfo = TokenStorage.getExpirationInfo();
|
|
1842
|
+
return {
|
|
1843
|
+
isLoggedIn: this.isAuthenticated(),
|
|
1844
|
+
crudifyTokens,
|
|
1845
|
+
storageInfo,
|
|
1846
|
+
hasValidTokens: TokenStorage.hasValidTokens()
|
|
1847
|
+
};
|
|
1848
|
+
}
|
|
1849
|
+
/**
|
|
1850
|
+
* Refrescar tokens manualmente
|
|
1851
|
+
*/
|
|
1852
|
+
async refreshTokens() {
|
|
1853
|
+
try {
|
|
1854
|
+
this.log("Manually refreshing tokens...");
|
|
1855
|
+
const response = await import_crudify_browser2.default.refreshAccessToken();
|
|
1856
|
+
if (!response.success) {
|
|
1857
|
+
this.log("Token refresh failed:", response.errors);
|
|
1858
|
+
TokenStorage.clearTokens();
|
|
1859
|
+
this.config.onSessionExpired?.();
|
|
1860
|
+
return false;
|
|
1861
|
+
}
|
|
1862
|
+
const newTokens = {
|
|
1863
|
+
accessToken: response.data.token,
|
|
1864
|
+
refreshToken: response.data.refreshToken,
|
|
1865
|
+
expiresAt: response.data.expiresAt,
|
|
1866
|
+
refreshExpiresAt: response.data.refreshExpiresAt
|
|
1867
|
+
};
|
|
1868
|
+
TokenStorage.saveTokens(newTokens);
|
|
1869
|
+
this.log("Tokens refreshed and saved successfully");
|
|
1870
|
+
return true;
|
|
1871
|
+
} catch (error) {
|
|
1872
|
+
this.log("Token refresh error:", error);
|
|
1873
|
+
TokenStorage.clearTokens();
|
|
1874
|
+
this.config.onSessionExpired?.();
|
|
1875
|
+
return false;
|
|
1876
|
+
}
|
|
1877
|
+
}
|
|
1878
|
+
/**
|
|
1879
|
+
* Configurar interceptor de respuesta para manejo automático de errores
|
|
1880
|
+
*/
|
|
1881
|
+
setupResponseInterceptor() {
|
|
1882
|
+
import_crudify_browser2.default.setResponseInterceptor(async (response) => {
|
|
1883
|
+
if (response.errors) {
|
|
1884
|
+
const hasAuthError = response.errors.some(
|
|
1885
|
+
(error) => error.message?.includes("Unauthorized") || error.message?.includes("Token") || error.extensions?.code === "UNAUTHENTICATED"
|
|
1886
|
+
);
|
|
1887
|
+
if (hasAuthError && TokenStorage.hasValidTokens()) {
|
|
1888
|
+
this.log("Auth error detected, attempting token refresh...");
|
|
1889
|
+
const refreshSuccess = await this.refreshTokens();
|
|
1890
|
+
if (!refreshSuccess) {
|
|
1891
|
+
this.log("Session expired, triggering callback");
|
|
1892
|
+
this.config.onSessionExpired?.();
|
|
1972
1893
|
}
|
|
1973
|
-
|
|
1974
|
-
|
|
1975
|
-
|
|
1976
|
-
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_material7.Typography, { variant: "body2", color: "text.secondary", children: displayData.role || "Usuario" }),
|
|
1977
|
-
displayData.isActive !== void 0 && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
1978
|
-
import_material7.Chip,
|
|
1979
|
-
{
|
|
1980
|
-
label: displayData.isActive ? "Activo" : "Inactivo",
|
|
1981
|
-
color: displayData.isActive ? "success" : "error",
|
|
1982
|
-
size: "small",
|
|
1983
|
-
sx: { mt: 0.5 }
|
|
1984
|
-
}
|
|
1985
|
-
)
|
|
1986
|
-
] })
|
|
1987
|
-
] }),
|
|
1988
|
-
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_material7.Box, { display: "grid", gridTemplateColumns: "repeat(auto-fit, minmax(250px, 1fr))", gap: 2, children: basicFields.map(
|
|
1989
|
-
({ key, label, icon }) => displayData[key] ? /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(import_material7.Box, { display: "flex", alignItems: "center", children: [
|
|
1990
|
-
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_material7.Box, { sx: { mr: 1, color: "text.secondary" }, children: icon }),
|
|
1991
|
-
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(import_material7.Box, { children: [
|
|
1992
|
-
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_material7.Typography, { variant: "caption", color: "text.secondary", children: label }),
|
|
1993
|
-
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_material7.Typography, { variant: "body2", children: renderFieldValue(key, displayData[key]) })
|
|
1994
|
-
] })
|
|
1995
|
-
] }, key) : null
|
|
1996
|
-
) }),
|
|
1997
|
-
displayData.permissions && Array.isArray(displayData.permissions) && displayData.permissions.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(import_material7.Box, { mt: 2, children: [
|
|
1998
|
-
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_material7.Typography, { variant: "caption", color: "text.secondary", display: "block", children: "Permisos" }),
|
|
1999
|
-
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(import_material7.Box, { display: "flex", flexWrap: "wrap", gap: 0.5, mt: 0.5, children: [
|
|
2000
|
-
displayData.permissions.slice(0, 5).map((permission, index) => /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_material7.Chip, { label: permission, size: "small", variant: "outlined" }, index)),
|
|
2001
|
-
displayData.permissions.length > 5 && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_material7.Chip, { label: `+${displayData.permissions.length - 5} m\xE1s`, size: "small" })
|
|
2002
|
-
] })
|
|
2003
|
-
] })
|
|
2004
|
-
] }) }),
|
|
2005
|
-
showExtendedData && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_material7.Card, { children: /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(import_material7.CardContent, { children: [
|
|
2006
|
-
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(import_material7.Box, { display: "flex", justifyContent: "space-between", alignItems: "center", mb: 2, children: [
|
|
2007
|
-
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(import_material7.Typography, { variant: "h6", display: "flex", alignItems: "center", children: [
|
|
2008
|
-
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_icons_material.Info, { sx: { mr: 1 } }),
|
|
2009
|
-
"Informaci\xF3n Detallada"
|
|
2010
|
-
] }),
|
|
2011
|
-
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_material7.Chip, { label: `${totalFields} campos totales`, size: "small" })
|
|
2012
|
-
] }),
|
|
2013
|
-
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(import_material7.List, { dense: true, children: [
|
|
2014
|
-
extendedFields.map(({ key, label }) => displayData[key] !== void 0 && /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(import_material7.ListItem, { divider: true, children: [
|
|
2015
|
-
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_material7.ListItemIcon, { children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_icons_material.Schedule, { fontSize: "small" }) }),
|
|
2016
|
-
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
2017
|
-
import_material7.ListItemText,
|
|
2018
|
-
{
|
|
2019
|
-
primary: label,
|
|
2020
|
-
secondary: key.includes("At") || key.includes("Login") ? formatDate(displayData[key]) : renderFieldValue(key, displayData[key])
|
|
2021
|
-
}
|
|
2022
|
-
)
|
|
2023
|
-
] }, key)),
|
|
2024
|
-
customFields.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(import_jsx_runtime10.Fragment, { children: [
|
|
2025
|
-
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_material7.Divider, { sx: { my: 1 } }),
|
|
2026
|
-
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_material7.ListItem, { children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
2027
|
-
import_material7.ListItemText,
|
|
2028
|
-
{
|
|
2029
|
-
primary: /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(import_material7.Box, { display: "flex", justifyContent: "space-between", alignItems: "center", children: [
|
|
2030
|
-
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(import_material7.Typography, { variant: "subtitle2", children: [
|
|
2031
|
-
"Campos Personalizados (",
|
|
2032
|
-
customFields.length,
|
|
2033
|
-
")"
|
|
2034
|
-
] }),
|
|
2035
|
-
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_material7.IconButton, { size: "small", onClick: () => setShowAllFields(!showAllFields), children: showAllFields ? /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_icons_material.ExpandLess, {}) : /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_icons_material.ExpandMore, {}) })
|
|
2036
|
-
] })
|
|
2037
|
-
}
|
|
2038
|
-
) }),
|
|
2039
|
-
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_material7.Collapse, { in: showAllFields, children: customFields.map(({ key, label }) => /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_material7.ListItem, { sx: { pl: 4 }, children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
2040
|
-
import_material7.ListItemText,
|
|
2041
|
-
{
|
|
2042
|
-
primary: label,
|
|
2043
|
-
secondary: renderFieldValue(key, displayData[key])
|
|
2044
|
-
}
|
|
2045
|
-
) }, key)) })
|
|
2046
|
-
] })
|
|
2047
|
-
] }),
|
|
2048
|
-
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(import_material7.Box, { mt: 2, display: "flex", justifyContent: "space-between", alignItems: "center", children: [
|
|
2049
|
-
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(import_material7.Typography, { variant: "caption", color: "text.secondary", children: [
|
|
2050
|
-
"\xDAltima actualizaci\xF3n: ",
|
|
2051
|
-
formatDate(displayData.updatedAt)
|
|
2052
|
-
] }),
|
|
2053
|
-
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_material7.IconButton, { size: "small", onClick: refreshProfile, disabled: loading, children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_material7.Typography, { variant: "caption", children: "Actualizar" }) })
|
|
2054
|
-
] })
|
|
2055
|
-
] }) })
|
|
2056
|
-
] });
|
|
2057
|
-
};
|
|
2058
|
-
var UserProfileDisplay_default = UserProfileDisplay;
|
|
2059
|
-
|
|
2060
|
-
// src/components/PublicPolicies/Policies.tsx
|
|
2061
|
-
var import_react14 = require("react");
|
|
2062
|
-
var import_react_i18next3 = require("react-i18next");
|
|
2063
|
-
var import_material10 = require("@mui/material");
|
|
2064
|
-
var import_icons_material4 = require("@mui/icons-material");
|
|
2065
|
-
|
|
2066
|
-
// src/components/PublicPolicies/PolicyItem/PolicyItem.tsx
|
|
2067
|
-
var import_react13 = require("react");
|
|
2068
|
-
var import_react_i18next2 = require("react-i18next");
|
|
2069
|
-
var import_material9 = require("@mui/material");
|
|
2070
|
-
var import_icons_material3 = require("@mui/icons-material");
|
|
2071
|
-
|
|
2072
|
-
// src/components/PublicPolicies/FieldSelector/FieldSelector.tsx
|
|
2073
|
-
var import_react12 = require("react");
|
|
2074
|
-
var import_react_i18next = require("react-i18next");
|
|
2075
|
-
var import_material8 = require("@mui/material");
|
|
2076
|
-
var import_icons_material2 = require("@mui/icons-material");
|
|
2077
|
-
var import_jsx_runtime11 = require("react/jsx-runtime");
|
|
2078
|
-
var FieldSelector = ({
|
|
2079
|
-
value,
|
|
2080
|
-
onChange,
|
|
2081
|
-
availableFields,
|
|
2082
|
-
error,
|
|
2083
|
-
disabled = false
|
|
2084
|
-
}) => {
|
|
2085
|
-
const { t } = (0, import_react_i18next.useTranslation)();
|
|
2086
|
-
const [mode, setMode] = (0, import_react12.useState)("custom");
|
|
2087
|
-
const isUpdatingRef = (0, import_react12.useRef)(false);
|
|
2088
|
-
(0, import_react12.useEffect)(() => {
|
|
2089
|
-
const current = value || { allow: [], owner_allow: [], deny: [] };
|
|
2090
|
-
const all = new Set(availableFields);
|
|
2091
|
-
const allow = (current.allow || []).filter((f) => all.has(f));
|
|
2092
|
-
const owner = (current.owner_allow || []).filter((f) => all.has(f));
|
|
2093
|
-
const deny = (current.deny || []).filter((f) => all.has(f));
|
|
2094
|
-
availableFields.forEach((f) => {
|
|
2095
|
-
if (!allow.includes(f) && !owner.includes(f) && !deny.includes(f)) deny.push(f);
|
|
1894
|
+
}
|
|
1895
|
+
}
|
|
1896
|
+
return response;
|
|
2096
1897
|
});
|
|
2097
|
-
|
|
2098
|
-
|
|
2099
|
-
|
|
1898
|
+
this.log("Response interceptor configured");
|
|
1899
|
+
}
|
|
1900
|
+
/**
|
|
1901
|
+
* Limpiar sesión completamente
|
|
1902
|
+
*/
|
|
1903
|
+
clearSession() {
|
|
1904
|
+
TokenStorage.clearTokens();
|
|
1905
|
+
import_crudify_browser2.default.logout();
|
|
1906
|
+
this.log("Session cleared completely");
|
|
1907
|
+
}
|
|
1908
|
+
// Métodos privados
|
|
1909
|
+
log(message, ...args) {
|
|
1910
|
+
if (this.config.enableLogging) {
|
|
1911
|
+
console.log(`[SessionManager] ${message}`, ...args);
|
|
2100
1912
|
}
|
|
2101
|
-
if (allow.length === availableFields.length) setMode("all");
|
|
2102
|
-
else if (deny.length === availableFields.length) setMode("none");
|
|
2103
|
-
else setMode("custom");
|
|
2104
|
-
}, [availableFields, value]);
|
|
2105
|
-
const setAllAllow = () => {
|
|
2106
|
-
isUpdatingRef.current = true;
|
|
2107
|
-
onChange({ allow: [...availableFields], owner_allow: [], deny: [] });
|
|
2108
|
-
setMode("all");
|
|
2109
|
-
setTimeout(() => {
|
|
2110
|
-
isUpdatingRef.current = false;
|
|
2111
|
-
}, 0);
|
|
2112
|
-
};
|
|
2113
|
-
const setAllDeny = () => {
|
|
2114
|
-
isUpdatingRef.current = true;
|
|
2115
|
-
onChange({ allow: [], owner_allow: [], deny: [...availableFields] });
|
|
2116
|
-
setMode("none");
|
|
2117
|
-
setTimeout(() => {
|
|
2118
|
-
isUpdatingRef.current = false;
|
|
2119
|
-
}, 0);
|
|
2120
|
-
};
|
|
2121
|
-
const getFieldState = (fieldName) => {
|
|
2122
|
-
if (value?.allow?.includes(fieldName)) return "allow";
|
|
2123
|
-
if (value?.owner_allow?.includes(fieldName)) return "owner_allow";
|
|
2124
|
-
return "deny";
|
|
2125
|
-
};
|
|
2126
|
-
const setFieldState = (fieldName, state) => {
|
|
2127
|
-
isUpdatingRef.current = true;
|
|
2128
|
-
const allow = new Set(value?.allow || []);
|
|
2129
|
-
const owner = new Set(value?.owner_allow || []);
|
|
2130
|
-
const deny = new Set(value?.deny || []);
|
|
2131
|
-
allow.delete(fieldName);
|
|
2132
|
-
owner.delete(fieldName);
|
|
2133
|
-
deny.delete(fieldName);
|
|
2134
|
-
if (state === "allow") allow.add(fieldName);
|
|
2135
|
-
if (state === "owner_allow") owner.add(fieldName);
|
|
2136
|
-
if (state === "deny") deny.add(fieldName);
|
|
2137
|
-
onChange({ allow: Array.from(allow), owner_allow: Array.from(owner), deny: Array.from(deny) });
|
|
2138
|
-
setMode("custom");
|
|
2139
|
-
setTimeout(() => {
|
|
2140
|
-
isUpdatingRef.current = false;
|
|
2141
|
-
}, 0);
|
|
2142
|
-
};
|
|
2143
|
-
if (availableFields.length === 0) {
|
|
2144
|
-
return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(import_material8.Box, { children: [
|
|
2145
|
-
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_material8.Typography, { variant: "body2", color: "text.secondary", sx: { mb: 1 }, children: t("modules.form.publicPolicies.fields.conditions.label") }),
|
|
2146
|
-
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_material8.Typography, { variant: "body2", color: "text.secondary", sx: { fontStyle: "italic" }, children: t("modules.form.publicPolicies.fields.conditions.noFieldsAvailable") }),
|
|
2147
|
-
error && /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_material8.FormHelperText, { error: true, sx: { mt: 1 }, children: error })
|
|
2148
|
-
] });
|
|
2149
1913
|
}
|
|
2150
|
-
|
|
2151
|
-
|
|
2152
|
-
|
|
2153
|
-
|
|
2154
|
-
|
|
2155
|
-
|
|
2156
|
-
|
|
2157
|
-
|
|
2158
|
-
|
|
2159
|
-
disabled,
|
|
2160
|
-
size: "small",
|
|
2161
|
-
sx: {
|
|
2162
|
-
minWidth: 120,
|
|
2163
|
-
...mode === "all" && {
|
|
2164
|
-
backgroundColor: "#16a34a",
|
|
2165
|
-
"&:hover": { backgroundColor: "#15803d" }
|
|
2166
|
-
}
|
|
2167
|
-
},
|
|
2168
|
-
children: t("modules.form.publicPolicies.fields.conditions.allFields")
|
|
2169
|
-
}
|
|
2170
|
-
),
|
|
2171
|
-
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
|
|
2172
|
-
import_material8.Button,
|
|
2173
|
-
{
|
|
2174
|
-
variant: mode === "none" ? "contained" : "outlined",
|
|
2175
|
-
startIcon: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_icons_material2.ClearAll, {}),
|
|
2176
|
-
onClick: setAllDeny,
|
|
2177
|
-
disabled,
|
|
2178
|
-
size: "small",
|
|
2179
|
-
sx: {
|
|
2180
|
-
minWidth: 120,
|
|
2181
|
-
...mode === "none" && {
|
|
2182
|
-
backgroundColor: "#cf222e",
|
|
2183
|
-
"&:hover": { backgroundColor: "#bc1f2c" }
|
|
2184
|
-
}
|
|
2185
|
-
},
|
|
2186
|
-
children: t("modules.form.publicPolicies.fields.conditions.noFields")
|
|
2187
|
-
}
|
|
2188
|
-
)
|
|
2189
|
-
] }),
|
|
2190
|
-
/* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(import_material8.Box, { sx: { p: 2, border: "1px solid #d1d9e0", borderRadius: 1, backgroundColor: "#f6f8fa" }, children: [
|
|
2191
|
-
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_material8.Typography, { variant: "body2", color: "text.secondary", sx: { mb: 2 }, children: t("modules.form.publicPolicies.fields.conditions.help") }),
|
|
2192
|
-
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_material8.Stack, { spacing: 1, children: availableFields.map((fieldName) => {
|
|
2193
|
-
const fieldState = getFieldState(fieldName);
|
|
2194
|
-
return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(import_material8.Stack, { direction: "row", spacing: 1, alignItems: "center", children: [
|
|
2195
|
-
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_material8.Typography, { variant: "body2", sx: { minWidth: 100, fontFamily: "monospace" }, children: fieldName }),
|
|
2196
|
-
/* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(import_material8.ToggleButtonGroup, { value: fieldState, exclusive: true, size: "small", children: [
|
|
2197
|
-
/* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(
|
|
2198
|
-
import_material8.ToggleButton,
|
|
2199
|
-
{
|
|
2200
|
-
value: "allow",
|
|
2201
|
-
onClick: () => setFieldState(fieldName, "allow"),
|
|
2202
|
-
disabled,
|
|
2203
|
-
sx: {
|
|
2204
|
-
px: 2,
|
|
2205
|
-
color: fieldState === "allow" ? "#ffffff" : "#6b7280",
|
|
2206
|
-
backgroundColor: fieldState === "allow" ? "#16a34a" : "#f3f4f6",
|
|
2207
|
-
borderColor: fieldState === "allow" ? "#16a34a" : "#d1d5db",
|
|
2208
|
-
"&:hover": {
|
|
2209
|
-
backgroundColor: fieldState === "allow" ? "#15803d" : "#e5e7eb",
|
|
2210
|
-
borderColor: fieldState === "allow" ? "#15803d" : "#9ca3af"
|
|
2211
|
-
},
|
|
2212
|
-
"&.Mui-selected": {
|
|
2213
|
-
backgroundColor: "#16a34a",
|
|
2214
|
-
color: "#ffffff",
|
|
2215
|
-
"&:hover": {
|
|
2216
|
-
backgroundColor: "#15803d"
|
|
2217
|
-
}
|
|
2218
|
-
}
|
|
2219
|
-
},
|
|
2220
|
-
children: [
|
|
2221
|
-
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_icons_material2.CheckCircle, { sx: { fontSize: 16, mr: 0.5 } }),
|
|
2222
|
-
t("modules.form.publicPolicies.fields.conditions.states.allow")
|
|
2223
|
-
]
|
|
2224
|
-
}
|
|
2225
|
-
),
|
|
2226
|
-
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
|
|
2227
|
-
import_material8.ToggleButton,
|
|
2228
|
-
{
|
|
2229
|
-
value: "owner_allow",
|
|
2230
|
-
onClick: () => setFieldState(fieldName, "owner_allow"),
|
|
2231
|
-
disabled,
|
|
2232
|
-
sx: {
|
|
2233
|
-
px: 2,
|
|
2234
|
-
color: fieldState === "owner_allow" ? "#ffffff" : "#6b7280",
|
|
2235
|
-
backgroundColor: fieldState === "owner_allow" ? "#0ea5e9" : "#f3f4f6",
|
|
2236
|
-
borderColor: fieldState === "owner_allow" ? "#0ea5e9" : "#d1d5db",
|
|
2237
|
-
"&:hover": {
|
|
2238
|
-
backgroundColor: fieldState === "owner_allow" ? "#0284c7" : "#e5e7eb",
|
|
2239
|
-
borderColor: fieldState === "owner_allow" ? "#0284c7" : "#9ca3af"
|
|
2240
|
-
},
|
|
2241
|
-
"&.Mui-selected": {
|
|
2242
|
-
backgroundColor: "#0ea5e9",
|
|
2243
|
-
color: "#ffffff",
|
|
2244
|
-
"&:hover": {
|
|
2245
|
-
backgroundColor: "#0284c7"
|
|
2246
|
-
}
|
|
2247
|
-
}
|
|
2248
|
-
},
|
|
2249
|
-
children: t("modules.form.publicPolicies.fields.conditions.states.ownerAllow")
|
|
2250
|
-
}
|
|
2251
|
-
),
|
|
2252
|
-
/* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(
|
|
2253
|
-
import_material8.ToggleButton,
|
|
2254
|
-
{
|
|
2255
|
-
value: "deny",
|
|
2256
|
-
onClick: () => setFieldState(fieldName, "deny"),
|
|
2257
|
-
disabled,
|
|
2258
|
-
sx: {
|
|
2259
|
-
px: 2,
|
|
2260
|
-
color: fieldState === "deny" ? "#ffffff" : "#6b7280",
|
|
2261
|
-
backgroundColor: fieldState === "deny" ? "#dc2626" : "#f3f4f6",
|
|
2262
|
-
borderColor: fieldState === "deny" ? "#dc2626" : "#d1d5db",
|
|
2263
|
-
"&:hover": {
|
|
2264
|
-
backgroundColor: fieldState === "deny" ? "#b91c1c" : "#e5e7eb",
|
|
2265
|
-
borderColor: fieldState === "deny" ? "#b91c1c" : "#9ca3af"
|
|
2266
|
-
},
|
|
2267
|
-
"&.Mui-selected": {
|
|
2268
|
-
backgroundColor: "#dc2626",
|
|
2269
|
-
color: "#ffffff",
|
|
2270
|
-
"&:hover": {
|
|
2271
|
-
backgroundColor: "#b91c1c"
|
|
2272
|
-
}
|
|
2273
|
-
}
|
|
2274
|
-
},
|
|
2275
|
-
children: [
|
|
2276
|
-
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_icons_material2.Cancel, { sx: { fontSize: 16, mr: 0.5 } }),
|
|
2277
|
-
t("modules.form.publicPolicies.fields.conditions.states.deny")
|
|
2278
|
-
]
|
|
2279
|
-
}
|
|
2280
|
-
)
|
|
2281
|
-
] })
|
|
2282
|
-
] }, fieldName);
|
|
2283
|
-
}) })
|
|
2284
|
-
] }),
|
|
2285
|
-
error && /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_material8.FormHelperText, { error: true, sx: { mt: 1 }, children: error })
|
|
2286
|
-
] });
|
|
1914
|
+
formatError(errors) {
|
|
1915
|
+
if (!errors) return "Unknown error";
|
|
1916
|
+
if (typeof errors === "string") return errors;
|
|
1917
|
+
if (typeof errors === "object") {
|
|
1918
|
+
const errorMessages = Object.values(errors).flat();
|
|
1919
|
+
return errorMessages.join(", ");
|
|
1920
|
+
}
|
|
1921
|
+
return "Authentication failed";
|
|
1922
|
+
}
|
|
2287
1923
|
};
|
|
2288
|
-
var FieldSelector_default = FieldSelector;
|
|
2289
|
-
|
|
2290
|
-
// src/components/PublicPolicies/constants.ts
|
|
2291
|
-
var POLICY_ACTIONS = ["create", "read", "update", "delete"];
|
|
2292
|
-
var PREFERRED_POLICY_ORDER = [
|
|
2293
|
-
"create",
|
|
2294
|
-
"read",
|
|
2295
|
-
"update",
|
|
2296
|
-
"delete"
|
|
2297
|
-
];
|
|
2298
1924
|
|
|
2299
|
-
// src/
|
|
2300
|
-
|
|
2301
|
-
|
|
2302
|
-
|
|
2303
|
-
|
|
2304
|
-
|
|
2305
|
-
|
|
2306
|
-
|
|
2307
|
-
|
|
2308
|
-
|
|
2309
|
-
|
|
2310
|
-
|
|
2311
|
-
|
|
2312
|
-
|
|
2313
|
-
|
|
2314
|
-
|
|
2315
|
-
|
|
2316
|
-
|
|
2317
|
-
|
|
2318
|
-
|
|
2319
|
-
|
|
2320
|
-
|
|
2321
|
-
|
|
2322
|
-
|
|
2323
|
-
|
|
2324
|
-
|
|
2325
|
-
|
|
2326
|
-
|
|
2327
|
-
|
|
2328
|
-
|
|
2329
|
-
|
|
2330
|
-
|
|
2331
|
-
|
|
2332
|
-
|
|
2333
|
-
|
|
2334
|
-
|
|
2335
|
-
|
|
2336
|
-
|
|
2337
|
-
|
|
2338
|
-
|
|
2339
|
-
|
|
2340
|
-
|
|
2341
|
-
|
|
2342
|
-
|
|
2343
|
-
|
|
2344
|
-
|
|
2345
|
-
|
|
2346
|
-
|
|
2347
|
-
|
|
2348
|
-
|
|
2349
|
-
sx: {
|
|
2350
|
-
color: "#656d76",
|
|
2351
|
-
"&:hover": {
|
|
2352
|
-
color: "#cf222e",
|
|
2353
|
-
backgroundColor: "rgba(207, 34, 46, 0.1)"
|
|
2354
|
-
}
|
|
2355
|
-
},
|
|
2356
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_icons_material3.Delete, {})
|
|
2357
|
-
}
|
|
2358
|
-
)
|
|
2359
|
-
] }),
|
|
2360
|
-
/* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(import_material9.Stack, { spacing: 3, children: [
|
|
2361
|
-
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_material9.Stack, { direction: { xs: "column", md: "row" }, spacing: 2, children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_material9.Box, { sx: { flex: 1, minWidth: 200 }, children: /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(import_material9.FormControl, { fullWidth: true, children: [
|
|
2362
|
-
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_material9.InputLabel, { children: t("modules.form.publicPolicies.fields.action.label") }),
|
|
2363
|
-
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
2364
|
-
import_material9.Select,
|
|
2365
|
-
{
|
|
2366
|
-
value: policy.action,
|
|
2367
|
-
label: t("modules.form.publicPolicies.fields.action.label"),
|
|
2368
|
-
disabled: isSubmitting,
|
|
2369
|
-
onChange: (e) => {
|
|
2370
|
-
const newAction = e.target.value;
|
|
2371
|
-
const next = { ...policy, action: newAction };
|
|
2372
|
-
if (newAction === "delete") {
|
|
2373
|
-
next.permission = "deny";
|
|
2374
|
-
delete next.fields;
|
|
2375
|
-
} else {
|
|
2376
|
-
next.fields = { allow: [], owner_allow: [], deny: availableFields };
|
|
2377
|
-
delete next.permission;
|
|
2378
|
-
}
|
|
2379
|
-
onChange(next);
|
|
2380
|
-
},
|
|
2381
|
-
sx: {
|
|
2382
|
-
backgroundColor: "#ffffff",
|
|
2383
|
-
"&:hover .MuiOutlinedInput-notchedOutline": {
|
|
2384
|
-
borderColor: "#8c959f"
|
|
2385
|
-
},
|
|
2386
|
-
"&.Mui-focused .MuiOutlinedInput-notchedOutline": {
|
|
2387
|
-
borderColor: "#0969da",
|
|
2388
|
-
borderWidth: 2
|
|
2389
|
-
}
|
|
2390
|
-
},
|
|
2391
|
-
children: actionOptions.map((option) => {
|
|
2392
|
-
const disabledOption = takenActions.has(option.value);
|
|
2393
|
-
return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_material9.MenuItem, { value: option.value, disabled: disabledOption, children: option.label }, option.value);
|
|
2394
|
-
})
|
|
2395
|
-
}
|
|
2396
|
-
),
|
|
2397
|
-
error && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_material9.FormHelperText, { error: true, children: error })
|
|
2398
|
-
] }) }) }),
|
|
2399
|
-
policy.action === "delete" ? /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(import_material9.Box, { children: [
|
|
2400
|
-
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_material9.Typography, { variant: "body2", color: "text.secondary", sx: { mb: 2 }, children: t("modules.form.publicPolicies.fields.conditions.label") }),
|
|
2401
|
-
/* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(import_material9.Stack, { direction: "row", spacing: 1, sx: { mb: 3 }, children: [
|
|
2402
|
-
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
2403
|
-
import_material9.Button,
|
|
2404
|
-
{
|
|
2405
|
-
variant: policy.permission === "*" ? "contained" : "outlined",
|
|
2406
|
-
startIcon: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_icons_material3.SelectAll, {}),
|
|
2407
|
-
onClick: () => onChange({ ...policy, permission: "*" }),
|
|
2408
|
-
disabled: isSubmitting,
|
|
2409
|
-
size: "small",
|
|
2410
|
-
sx: {
|
|
2411
|
-
minWidth: 140,
|
|
2412
|
-
whiteSpace: "nowrap",
|
|
2413
|
-
...policy.permission === "*" && {
|
|
2414
|
-
backgroundColor: "#16a34a",
|
|
2415
|
-
"&:hover": { backgroundColor: "#15803d" }
|
|
2416
|
-
}
|
|
2417
|
-
},
|
|
2418
|
-
children: t("modules.form.publicPolicies.fields.conditions.allFields")
|
|
2419
|
-
}
|
|
2420
|
-
),
|
|
2421
|
-
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
2422
|
-
import_material9.Button,
|
|
2423
|
-
{
|
|
2424
|
-
variant: policy.permission === "owner" ? "contained" : "outlined",
|
|
2425
|
-
onClick: () => onChange({ ...policy, permission: "owner" }),
|
|
2426
|
-
disabled: isSubmitting,
|
|
2427
|
-
size: "small",
|
|
2428
|
-
sx: {
|
|
2429
|
-
minWidth: 140,
|
|
2430
|
-
whiteSpace: "nowrap",
|
|
2431
|
-
...policy.permission === "owner" && {
|
|
2432
|
-
backgroundColor: "#0ea5e9",
|
|
2433
|
-
"&:hover": { backgroundColor: "#0284c7" }
|
|
2434
|
-
}
|
|
2435
|
-
},
|
|
2436
|
-
children: t("modules.form.publicPolicies.fields.conditions.states.ownerAllow")
|
|
2437
|
-
}
|
|
2438
|
-
),
|
|
2439
|
-
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
2440
|
-
import_material9.Button,
|
|
2441
|
-
{
|
|
2442
|
-
variant: policy.permission === "deny" ? "contained" : "outlined",
|
|
2443
|
-
startIcon: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_icons_material3.ClearAll, {}),
|
|
2444
|
-
onClick: () => onChange({ ...policy, permission: "deny" }),
|
|
2445
|
-
disabled: isSubmitting,
|
|
2446
|
-
size: "small",
|
|
2447
|
-
sx: {
|
|
2448
|
-
minWidth: 140,
|
|
2449
|
-
whiteSpace: "nowrap",
|
|
2450
|
-
...policy.permission === "deny" && {
|
|
2451
|
-
backgroundColor: "#cf222e",
|
|
2452
|
-
"&:hover": { backgroundColor: "#bc1f2c" }
|
|
2453
|
-
}
|
|
2454
|
-
},
|
|
2455
|
-
children: t("modules.form.publicPolicies.fields.conditions.noFields")
|
|
2456
|
-
}
|
|
2457
|
-
)
|
|
2458
|
-
] })
|
|
2459
|
-
] }) : /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
2460
|
-
FieldSelector_default,
|
|
2461
|
-
{
|
|
2462
|
-
value: policy.fields || { allow: [], owner_allow: [], deny: [] },
|
|
2463
|
-
onChange: (nextFields) => onChange({ ...policy, fields: nextFields }),
|
|
2464
|
-
availableFields,
|
|
2465
|
-
disabled: isSubmitting
|
|
2466
|
-
}
|
|
2467
|
-
),
|
|
2468
|
-
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_material9.Paper, { variant: "outlined", sx: { p: 2, backgroundColor: "#f9fafb" }, children: policy.action === "delete" ? /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(import_material9.Typography, { variant: "body2", sx: { fontFamily: "monospace", color: "text.secondary" }, children: [
|
|
2469
|
-
/* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(import_material9.Box, { component: "span", sx: {
|
|
2470
|
-
color: policy.permission === "*" ? "#16a34a" : policy.permission === "owner" ? "#0ea5e9" : "#dc2626"
|
|
2471
|
-
}, children: [
|
|
2472
|
-
t("modules.form.publicPolicies.fields.conditions.states.allow"),
|
|
2473
|
-
":"
|
|
2474
|
-
] }),
|
|
2475
|
-
" ",
|
|
2476
|
-
policy.permission || "-"
|
|
2477
|
-
] }) : /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(import_material9.Stack, { spacing: 0.5, divider: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_material9.Divider, { sx: { borderColor: "#e5e7eb" } }), children: [
|
|
2478
|
-
/* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(import_material9.Typography, { variant: "body2", sx: { fontFamily: "monospace", color: "text.secondary" }, children: [
|
|
2479
|
-
/* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(import_material9.Box, { component: "span", sx: { color: "#16a34a" }, children: [
|
|
2480
|
-
t("modules.form.publicPolicies.fields.conditions.states.allow"),
|
|
2481
|
-
":"
|
|
2482
|
-
] }),
|
|
2483
|
-
" ",
|
|
2484
|
-
(policy?.fields?.allow || []).join(", ") || "-"
|
|
2485
|
-
] }),
|
|
2486
|
-
/* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(import_material9.Typography, { variant: "body2", sx: { fontFamily: "monospace", color: "text.secondary" }, children: [
|
|
2487
|
-
/* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(import_material9.Box, { component: "span", sx: { color: "#0ea5e9" }, children: [
|
|
2488
|
-
t("modules.form.publicPolicies.fields.conditions.states.ownerAllow"),
|
|
2489
|
-
":"
|
|
2490
|
-
] }),
|
|
2491
|
-
" ",
|
|
2492
|
-
(policy?.fields?.owner_allow || []).join(", ") || "-"
|
|
2493
|
-
] }),
|
|
2494
|
-
/* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(import_material9.Typography, { variant: "body2", sx: { fontFamily: "monospace", color: "text.secondary" }, children: [
|
|
2495
|
-
/* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(import_material9.Box, { component: "span", sx: { color: "#dc2626" }, children: [
|
|
2496
|
-
t("modules.form.publicPolicies.fields.conditions.states.deny"),
|
|
2497
|
-
":"
|
|
2498
|
-
] }),
|
|
2499
|
-
" ",
|
|
2500
|
-
(policy?.fields?.deny || []).join(", ") || "-"
|
|
2501
|
-
] })
|
|
2502
|
-
] }) })
|
|
2503
|
-
] })
|
|
2504
|
-
]
|
|
2505
|
-
}
|
|
2506
|
-
);
|
|
2507
|
-
});
|
|
2508
|
-
var PolicyItem_default = PolicyItem;
|
|
2509
|
-
|
|
2510
|
-
// src/components/PublicPolicies/Policies.tsx
|
|
2511
|
-
var import_jsx_runtime13 = require("react/jsx-runtime");
|
|
2512
|
-
var generateId = () => {
|
|
2513
|
-
const c = globalThis?.crypto;
|
|
2514
|
-
if (c && typeof c.randomUUID === "function") return c.randomUUID();
|
|
2515
|
-
return `${Date.now()}-${Math.random().toString(16).slice(2)}`;
|
|
2516
|
-
};
|
|
2517
|
-
var Policies = ({
|
|
2518
|
-
policies,
|
|
2519
|
-
onChange,
|
|
2520
|
-
availableFields,
|
|
2521
|
-
errors,
|
|
2522
|
-
isSubmitting = false
|
|
2523
|
-
}) => {
|
|
2524
|
-
const { t } = (0, import_react_i18next3.useTranslation)();
|
|
2525
|
-
const policyRefs = (0, import_react14.useRef)({});
|
|
2526
|
-
const takenActions = new Set((policies || []).map((p) => p.action).filter(Boolean));
|
|
2527
|
-
const remainingActions = PREFERRED_POLICY_ORDER.filter((a) => !takenActions.has(a));
|
|
2528
|
-
const canAddPolicy = remainingActions.length > 0;
|
|
2529
|
-
const addPolicy = () => {
|
|
2530
|
-
const defaultAction = remainingActions[0] || "create";
|
|
2531
|
-
const newPolicy = {
|
|
2532
|
-
id: generateId(),
|
|
2533
|
-
action: defaultAction
|
|
2534
|
-
};
|
|
2535
|
-
if (defaultAction === "delete") {
|
|
2536
|
-
newPolicy.permission = "deny";
|
|
2537
|
-
} else {
|
|
2538
|
-
newPolicy.fields = {
|
|
2539
|
-
allow: [],
|
|
2540
|
-
owner_allow: [],
|
|
2541
|
-
deny: availableFields
|
|
1925
|
+
// src/hooks/useSession.ts
|
|
1926
|
+
function useSession(options = {}) {
|
|
1927
|
+
const [state, setState] = (0, import_react9.useState)({
|
|
1928
|
+
isAuthenticated: false,
|
|
1929
|
+
isLoading: true,
|
|
1930
|
+
isInitialized: false,
|
|
1931
|
+
tokens: null,
|
|
1932
|
+
error: null
|
|
1933
|
+
});
|
|
1934
|
+
const sessionManager = SessionManager.getInstance();
|
|
1935
|
+
const initialize = (0, import_react9.useCallback)(async () => {
|
|
1936
|
+
try {
|
|
1937
|
+
setState((prev) => ({ ...prev, isLoading: true, error: null }));
|
|
1938
|
+
const config = {
|
|
1939
|
+
autoRestore: options.autoRestore ?? true,
|
|
1940
|
+
enableLogging: options.enableLogging ?? false,
|
|
1941
|
+
onSessionExpired: () => {
|
|
1942
|
+
setState((prev) => ({
|
|
1943
|
+
...prev,
|
|
1944
|
+
isAuthenticated: false,
|
|
1945
|
+
tokens: null,
|
|
1946
|
+
error: "Session expired"
|
|
1947
|
+
}));
|
|
1948
|
+
options.onSessionExpired?.();
|
|
1949
|
+
},
|
|
1950
|
+
onSessionRestored: (tokens) => {
|
|
1951
|
+
setState((prev) => ({
|
|
1952
|
+
...prev,
|
|
1953
|
+
isAuthenticated: true,
|
|
1954
|
+
tokens,
|
|
1955
|
+
error: null
|
|
1956
|
+
}));
|
|
1957
|
+
options.onSessionRestored?.(tokens);
|
|
1958
|
+
},
|
|
1959
|
+
onLoginSuccess: (tokens) => {
|
|
1960
|
+
setState((prev) => ({
|
|
1961
|
+
...prev,
|
|
1962
|
+
isAuthenticated: true,
|
|
1963
|
+
tokens,
|
|
1964
|
+
error: null
|
|
1965
|
+
}));
|
|
1966
|
+
},
|
|
1967
|
+
onLogout: () => {
|
|
1968
|
+
setState((prev) => ({
|
|
1969
|
+
...prev,
|
|
1970
|
+
isAuthenticated: false,
|
|
1971
|
+
tokens: null,
|
|
1972
|
+
error: null
|
|
1973
|
+
}));
|
|
1974
|
+
}
|
|
2542
1975
|
};
|
|
1976
|
+
await sessionManager.initialize(config);
|
|
1977
|
+
sessionManager.setupResponseInterceptor();
|
|
1978
|
+
const isAuth = sessionManager.isAuthenticated();
|
|
1979
|
+
const tokenInfo = sessionManager.getTokenInfo();
|
|
1980
|
+
setState((prev) => ({
|
|
1981
|
+
...prev,
|
|
1982
|
+
isAuthenticated: isAuth,
|
|
1983
|
+
isInitialized: true,
|
|
1984
|
+
isLoading: false,
|
|
1985
|
+
tokens: tokenInfo.crudifyTokens.accessToken ? {
|
|
1986
|
+
accessToken: tokenInfo.crudifyTokens.accessToken,
|
|
1987
|
+
refreshToken: tokenInfo.crudifyTokens.refreshToken,
|
|
1988
|
+
expiresAt: tokenInfo.crudifyTokens.expiresAt,
|
|
1989
|
+
refreshExpiresAt: tokenInfo.crudifyTokens.refreshExpiresAt
|
|
1990
|
+
} : null
|
|
1991
|
+
}));
|
|
1992
|
+
} catch (error) {
|
|
1993
|
+
setState((prev) => ({
|
|
1994
|
+
...prev,
|
|
1995
|
+
isLoading: false,
|
|
1996
|
+
isInitialized: true,
|
|
1997
|
+
error: error instanceof Error ? error.message : "Initialization failed"
|
|
1998
|
+
}));
|
|
2543
1999
|
}
|
|
2544
|
-
|
|
2545
|
-
|
|
2546
|
-
|
|
2547
|
-
|
|
2548
|
-
const
|
|
2549
|
-
if (
|
|
2550
|
-
|
|
2000
|
+
}, [options.autoRestore, options.enableLogging, options.onSessionExpired, options.onSessionRestored]);
|
|
2001
|
+
const login = (0, import_react9.useCallback)(async (email, password) => {
|
|
2002
|
+
setState((prev) => ({ ...prev, isLoading: true, error: null }));
|
|
2003
|
+
try {
|
|
2004
|
+
const result = await sessionManager.login(email, password);
|
|
2005
|
+
if (result.success && result.tokens) {
|
|
2006
|
+
setState((prev) => ({
|
|
2007
|
+
...prev,
|
|
2008
|
+
isAuthenticated: true,
|
|
2009
|
+
tokens: result.tokens,
|
|
2010
|
+
isLoading: false,
|
|
2011
|
+
error: null
|
|
2012
|
+
}));
|
|
2013
|
+
} else {
|
|
2014
|
+
setState((prev) => ({
|
|
2015
|
+
...prev,
|
|
2016
|
+
isAuthenticated: false,
|
|
2017
|
+
tokens: null,
|
|
2018
|
+
isLoading: false,
|
|
2019
|
+
error: result.error || "Login failed"
|
|
2020
|
+
}));
|
|
2551
2021
|
}
|
|
2552
|
-
|
|
2553
|
-
};
|
|
2554
|
-
const removePolicy = (index) => {
|
|
2555
|
-
const next = [...policies];
|
|
2556
|
-
next.splice(index, 1);
|
|
2557
|
-
onChange(next);
|
|
2558
|
-
};
|
|
2559
|
-
const arrayError = (() => {
|
|
2560
|
-
if (!errors) return null;
|
|
2561
|
-
if (typeof errors === "string") return errors;
|
|
2562
|
-
const msg = errors._error;
|
|
2563
|
-
return typeof msg === "string" ? msg : null;
|
|
2564
|
-
})();
|
|
2565
|
-
const usedActions = new Set((policies || []).map((p) => p.action));
|
|
2566
|
-
return /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(import_jsx_runtime13.Fragment, { children: [
|
|
2567
|
-
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_material10.Divider, { sx: { borderColor: "#e0e4e7" } }),
|
|
2568
|
-
/* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(import_material10.Box, { children: [
|
|
2569
|
-
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_material10.Box, { display: "flex", justifyContent: "space-between", alignItems: "center", mb: 3, children: /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(import_material10.Box, { children: [
|
|
2570
|
-
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
2571
|
-
import_material10.Typography,
|
|
2572
|
-
{
|
|
2573
|
-
variant: "h6",
|
|
2574
|
-
sx: {
|
|
2575
|
-
fontWeight: 600,
|
|
2576
|
-
color: "#111418",
|
|
2577
|
-
mb: 1
|
|
2578
|
-
},
|
|
2579
|
-
children: t("modules.form.publicPolicies.title")
|
|
2580
|
-
}
|
|
2581
|
-
),
|
|
2582
|
-
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
2583
|
-
import_material10.Typography,
|
|
2584
|
-
{
|
|
2585
|
-
variant: "body2",
|
|
2586
|
-
color: "text.secondary",
|
|
2587
|
-
sx: { fontSize: "0.875rem" },
|
|
2588
|
-
children: t("modules.form.publicPolicies.description")
|
|
2589
|
-
}
|
|
2590
|
-
)
|
|
2591
|
-
] }) }),
|
|
2592
|
-
arrayError && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_material10.Alert, { severity: "error", sx: { mb: 3 }, children: arrayError }),
|
|
2593
|
-
/* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(import_material10.Stack, { spacing: 3, children: [
|
|
2594
|
-
(policies || []).length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_material10.Alert, { severity: "info", children: t("modules.form.publicPolicies.noPolicies") }) : policies.map((policy, index) => /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
2595
|
-
PolicyItem_default,
|
|
2596
|
-
{
|
|
2597
|
-
ref: (el) => {
|
|
2598
|
-
policyRefs.current[index] = el;
|
|
2599
|
-
},
|
|
2600
|
-
policy,
|
|
2601
|
-
onChange: (nextPolicy) => {
|
|
2602
|
-
const next = [...policies];
|
|
2603
|
-
next[index] = nextPolicy;
|
|
2604
|
-
onChange(next);
|
|
2605
|
-
},
|
|
2606
|
-
onRemove: () => removePolicy(index),
|
|
2607
|
-
availableFields,
|
|
2608
|
-
isSubmitting,
|
|
2609
|
-
usedActions,
|
|
2610
|
-
error: typeof errors === "object" && errors && policy.id in errors ? errors[policy.id] : void 0
|
|
2611
|
-
},
|
|
2612
|
-
policy.id
|
|
2613
|
-
)),
|
|
2614
|
-
canAddPolicy && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_material10.Box, { children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
2615
|
-
import_material10.Button,
|
|
2616
|
-
{
|
|
2617
|
-
type: "button",
|
|
2618
|
-
variant: "outlined",
|
|
2619
|
-
startIcon: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_icons_material4.Add, {}),
|
|
2620
|
-
onClick: addPolicy,
|
|
2621
|
-
disabled: isSubmitting,
|
|
2622
|
-
sx: {
|
|
2623
|
-
borderColor: "#d0d7de",
|
|
2624
|
-
color: "#656d76",
|
|
2625
|
-
"&:hover": {
|
|
2626
|
-
borderColor: "#8c959f",
|
|
2627
|
-
backgroundColor: "transparent"
|
|
2628
|
-
}
|
|
2629
|
-
},
|
|
2630
|
-
children: t("modules.form.publicPolicies.addPolicy")
|
|
2631
|
-
}
|
|
2632
|
-
) })
|
|
2633
|
-
] })
|
|
2634
|
-
] })
|
|
2635
|
-
] });
|
|
2636
|
-
};
|
|
2637
|
-
var Policies_default = Policies;
|
|
2638
|
-
|
|
2639
|
-
// src/core/SessionManager.ts
|
|
2640
|
-
var import_crudify_browser4 = __toESM(require("@nocios/crudify-browser"));
|
|
2641
|
-
|
|
2642
|
-
// src/utils/tokenStorage.ts
|
|
2643
|
-
var import_crypto_js = __toESM(require("crypto-js"));
|
|
2644
|
-
var _TokenStorage = class _TokenStorage {
|
|
2645
|
-
/**
|
|
2646
|
-
* Configurar tipo de almacenamiento
|
|
2647
|
-
*/
|
|
2648
|
-
static setStorageType(type) {
|
|
2649
|
-
_TokenStorage.storageType = type;
|
|
2650
|
-
}
|
|
2651
|
-
/**
|
|
2652
|
-
* Verificar si el storage está disponible
|
|
2653
|
-
*/
|
|
2654
|
-
static isStorageAvailable(type) {
|
|
2655
|
-
try {
|
|
2656
|
-
const storage = window[type];
|
|
2657
|
-
const testKey = "__storage_test__";
|
|
2658
|
-
storage.setItem(testKey, "test");
|
|
2659
|
-
storage.removeItem(testKey);
|
|
2660
|
-
return true;
|
|
2661
|
-
} catch {
|
|
2662
|
-
return false;
|
|
2663
|
-
}
|
|
2664
|
-
}
|
|
2665
|
-
/**
|
|
2666
|
-
* Obtener instancia de storage
|
|
2667
|
-
*/
|
|
2668
|
-
static getStorage() {
|
|
2669
|
-
if (_TokenStorage.storageType === "none") return null;
|
|
2670
|
-
if (!_TokenStorage.isStorageAvailable(_TokenStorage.storageType)) {
|
|
2671
|
-
console.warn(`Crudify: ${_TokenStorage.storageType} not available, tokens won't persist`);
|
|
2672
|
-
return null;
|
|
2673
|
-
}
|
|
2674
|
-
return window[_TokenStorage.storageType];
|
|
2675
|
-
}
|
|
2676
|
-
/**
|
|
2677
|
-
* Encriptar datos sensibles
|
|
2678
|
-
*/
|
|
2679
|
-
static encrypt(data) {
|
|
2680
|
-
try {
|
|
2681
|
-
return import_crypto_js.default.AES.encrypt(data, _TokenStorage.ENCRYPTION_KEY).toString();
|
|
2682
|
-
} catch (error) {
|
|
2683
|
-
console.error("Crudify: Encryption failed", error);
|
|
2684
|
-
return data;
|
|
2685
|
-
}
|
|
2686
|
-
}
|
|
2687
|
-
/**
|
|
2688
|
-
* Desencriptar datos
|
|
2689
|
-
*/
|
|
2690
|
-
static decrypt(encryptedData) {
|
|
2691
|
-
try {
|
|
2692
|
-
const bytes = import_crypto_js.default.AES.decrypt(encryptedData, _TokenStorage.ENCRYPTION_KEY);
|
|
2693
|
-
const decrypted = bytes.toString(import_crypto_js.default.enc.Utf8);
|
|
2694
|
-
return decrypted || encryptedData;
|
|
2022
|
+
return result;
|
|
2695
2023
|
} catch (error) {
|
|
2696
|
-
|
|
2697
|
-
|
|
2024
|
+
const errorMsg = error instanceof Error ? error.message : "Login failed";
|
|
2025
|
+
setState((prev) => ({
|
|
2026
|
+
...prev,
|
|
2027
|
+
isAuthenticated: false,
|
|
2028
|
+
tokens: null,
|
|
2029
|
+
isLoading: false,
|
|
2030
|
+
error: errorMsg
|
|
2031
|
+
}));
|
|
2032
|
+
return {
|
|
2033
|
+
success: false,
|
|
2034
|
+
error: errorMsg
|
|
2035
|
+
};
|
|
2698
2036
|
}
|
|
2699
|
-
}
|
|
2700
|
-
|
|
2701
|
-
|
|
2702
|
-
*/
|
|
2703
|
-
static saveTokens(tokens) {
|
|
2704
|
-
const storage = _TokenStorage.getStorage();
|
|
2705
|
-
if (!storage) return;
|
|
2037
|
+
}, [sessionManager]);
|
|
2038
|
+
const logout = (0, import_react9.useCallback)(async () => {
|
|
2039
|
+
setState((prev) => ({ ...prev, isLoading: true }));
|
|
2706
2040
|
try {
|
|
2707
|
-
|
|
2708
|
-
|
|
2709
|
-
|
|
2710
|
-
|
|
2711
|
-
|
|
2712
|
-
|
|
2713
|
-
|
|
2714
|
-
|
|
2715
|
-
storage.setItem(_TokenStorage.TOKEN_KEY, encrypted);
|
|
2716
|
-
console.debug("Crudify: Tokens saved successfully");
|
|
2041
|
+
await sessionManager.logout();
|
|
2042
|
+
setState((prev) => ({
|
|
2043
|
+
...prev,
|
|
2044
|
+
isAuthenticated: false,
|
|
2045
|
+
tokens: null,
|
|
2046
|
+
isLoading: false,
|
|
2047
|
+
error: null
|
|
2048
|
+
}));
|
|
2717
2049
|
} catch (error) {
|
|
2718
|
-
|
|
2050
|
+
setState((prev) => ({
|
|
2051
|
+
...prev,
|
|
2052
|
+
isAuthenticated: false,
|
|
2053
|
+
tokens: null,
|
|
2054
|
+
isLoading: false,
|
|
2055
|
+
error: error instanceof Error ? error.message : "Logout error"
|
|
2056
|
+
}));
|
|
2719
2057
|
}
|
|
2720
|
-
}
|
|
2721
|
-
|
|
2722
|
-
* Obtener tokens guardados
|
|
2723
|
-
*/
|
|
2724
|
-
static getTokens() {
|
|
2725
|
-
const storage = _TokenStorage.getStorage();
|
|
2726
|
-
if (!storage) return null;
|
|
2058
|
+
}, [sessionManager]);
|
|
2059
|
+
const refreshTokens = (0, import_react9.useCallback)(async () => {
|
|
2727
2060
|
try {
|
|
2728
|
-
const
|
|
2729
|
-
if (
|
|
2730
|
-
|
|
2731
|
-
|
|
2732
|
-
|
|
2733
|
-
|
|
2734
|
-
|
|
2735
|
-
|
|
2736
|
-
|
|
2737
|
-
|
|
2738
|
-
|
|
2739
|
-
|
|
2740
|
-
|
|
2061
|
+
const success = await sessionManager.refreshTokens();
|
|
2062
|
+
if (success) {
|
|
2063
|
+
const tokenInfo = sessionManager.getTokenInfo();
|
|
2064
|
+
setState((prev) => ({
|
|
2065
|
+
...prev,
|
|
2066
|
+
tokens: tokenInfo.crudifyTokens.accessToken ? {
|
|
2067
|
+
accessToken: tokenInfo.crudifyTokens.accessToken,
|
|
2068
|
+
refreshToken: tokenInfo.crudifyTokens.refreshToken,
|
|
2069
|
+
expiresAt: tokenInfo.crudifyTokens.expiresAt,
|
|
2070
|
+
refreshExpiresAt: tokenInfo.crudifyTokens.refreshExpiresAt
|
|
2071
|
+
} : null,
|
|
2072
|
+
error: null
|
|
2073
|
+
}));
|
|
2074
|
+
} else {
|
|
2075
|
+
setState((prev) => ({
|
|
2076
|
+
...prev,
|
|
2077
|
+
isAuthenticated: false,
|
|
2078
|
+
tokens: null,
|
|
2079
|
+
error: "Token refresh failed"
|
|
2080
|
+
}));
|
|
2741
2081
|
}
|
|
2742
|
-
return
|
|
2743
|
-
accessToken: tokenData.accessToken,
|
|
2744
|
-
refreshToken: tokenData.refreshToken,
|
|
2745
|
-
expiresAt: tokenData.expiresAt,
|
|
2746
|
-
refreshExpiresAt: tokenData.refreshExpiresAt
|
|
2747
|
-
};
|
|
2082
|
+
return success;
|
|
2748
2083
|
} catch (error) {
|
|
2749
|
-
|
|
2750
|
-
|
|
2084
|
+
setState((prev) => ({
|
|
2085
|
+
...prev,
|
|
2086
|
+
isAuthenticated: false,
|
|
2087
|
+
tokens: null,
|
|
2088
|
+
error: error instanceof Error ? error.message : "Token refresh failed"
|
|
2089
|
+
}));
|
|
2090
|
+
return false;
|
|
2091
|
+
}
|
|
2092
|
+
}, [sessionManager]);
|
|
2093
|
+
const clearError = (0, import_react9.useCallback)(() => {
|
|
2094
|
+
setState((prev) => ({ ...prev, error: null }));
|
|
2095
|
+
}, []);
|
|
2096
|
+
const getTokenInfo = (0, import_react9.useCallback)(() => {
|
|
2097
|
+
return sessionManager.getTokenInfo();
|
|
2098
|
+
}, [sessionManager]);
|
|
2099
|
+
(0, import_react9.useEffect)(() => {
|
|
2100
|
+
initialize();
|
|
2101
|
+
}, [initialize]);
|
|
2102
|
+
return {
|
|
2103
|
+
// Estado
|
|
2104
|
+
...state,
|
|
2105
|
+
// Acciones
|
|
2106
|
+
login,
|
|
2107
|
+
logout,
|
|
2108
|
+
refreshTokens,
|
|
2109
|
+
clearError,
|
|
2110
|
+
getTokenInfo,
|
|
2111
|
+
// Utilidades
|
|
2112
|
+
isExpiringSoon: state.tokens ? state.tokens.expiresAt - Date.now() < 5 * 60 * 1e3 : false,
|
|
2113
|
+
// 5 minutos
|
|
2114
|
+
expiresIn: state.tokens ? Math.max(0, state.tokens.expiresAt - Date.now()) : 0,
|
|
2115
|
+
refreshExpiresIn: state.tokens ? Math.max(0, state.tokens.refreshExpiresAt - Date.now()) : 0
|
|
2116
|
+
};
|
|
2117
|
+
}
|
|
2118
|
+
|
|
2119
|
+
// src/utils/jwtUtils.ts
|
|
2120
|
+
var decodeJwtSafely = (token) => {
|
|
2121
|
+
try {
|
|
2122
|
+
const parts = token.split(".");
|
|
2123
|
+
if (parts.length !== 3) {
|
|
2124
|
+
console.warn("Invalid JWT format: token must have 3 parts");
|
|
2751
2125
|
return null;
|
|
2752
2126
|
}
|
|
2127
|
+
const payload = parts[1];
|
|
2128
|
+
const paddedPayload = payload + "=".repeat((4 - payload.length % 4) % 4);
|
|
2129
|
+
const decodedPayload = JSON.parse(atob(paddedPayload));
|
|
2130
|
+
return decodedPayload;
|
|
2131
|
+
} catch (error) {
|
|
2132
|
+
console.warn("Failed to decode JWT token:", error);
|
|
2133
|
+
return null;
|
|
2753
2134
|
}
|
|
2754
|
-
|
|
2755
|
-
|
|
2756
|
-
|
|
2757
|
-
|
|
2758
|
-
|
|
2759
|
-
|
|
2760
|
-
|
|
2761
|
-
|
|
2762
|
-
console.
|
|
2763
|
-
} catch (error) {
|
|
2764
|
-
console.error("Crudify: Failed to clear tokens", error);
|
|
2135
|
+
};
|
|
2136
|
+
var getCurrentUserEmail = () => {
|
|
2137
|
+
try {
|
|
2138
|
+
let token = null;
|
|
2139
|
+
token = sessionStorage.getItem("authToken");
|
|
2140
|
+
console.log("\u{1F50D} getCurrentUserEmail - authToken:", token ? `${token.substring(0, 20)}...` : null);
|
|
2141
|
+
if (!token) {
|
|
2142
|
+
token = sessionStorage.getItem("token");
|
|
2143
|
+
console.log("\u{1F50D} getCurrentUserEmail - token:", token ? `${token.substring(0, 20)}...` : null);
|
|
2765
2144
|
}
|
|
2766
|
-
|
|
2767
|
-
|
|
2768
|
-
|
|
2769
|
-
*/
|
|
2770
|
-
static hasValidTokens() {
|
|
2771
|
-
const tokens = _TokenStorage.getTokens();
|
|
2772
|
-
return tokens !== null;
|
|
2773
|
-
}
|
|
2774
|
-
/**
|
|
2775
|
-
* Obtener información de expiración
|
|
2776
|
-
*/
|
|
2777
|
-
static getExpirationInfo() {
|
|
2778
|
-
const tokens = _TokenStorage.getTokens();
|
|
2779
|
-
if (!tokens) return null;
|
|
2780
|
-
const now = Date.now();
|
|
2781
|
-
return {
|
|
2782
|
-
accessExpired: now >= tokens.expiresAt,
|
|
2783
|
-
refreshExpired: now >= tokens.refreshExpiresAt,
|
|
2784
|
-
accessExpiresIn: Math.max(0, tokens.expiresAt - now),
|
|
2785
|
-
refreshExpiresIn: Math.max(0, tokens.refreshExpiresAt - now)
|
|
2786
|
-
};
|
|
2787
|
-
}
|
|
2788
|
-
/**
|
|
2789
|
-
* Actualizar solo el access token (después de refresh)
|
|
2790
|
-
*/
|
|
2791
|
-
static updateAccessToken(newAccessToken, newExpiresAt) {
|
|
2792
|
-
const existingTokens = _TokenStorage.getTokens();
|
|
2793
|
-
if (!existingTokens) {
|
|
2794
|
-
console.warn("Crudify: Cannot update access token, no existing tokens found");
|
|
2795
|
-
return;
|
|
2145
|
+
if (!token) {
|
|
2146
|
+
token = localStorage.getItem("authToken") || localStorage.getItem("token");
|
|
2147
|
+
console.log("\u{1F50D} getCurrentUserEmail - localStorage:", token ? `${token.substring(0, 20)}...` : null);
|
|
2796
2148
|
}
|
|
2797
|
-
|
|
2798
|
-
|
|
2799
|
-
|
|
2800
|
-
|
|
2801
|
-
|
|
2149
|
+
if (!token) {
|
|
2150
|
+
console.warn("\u{1F50D} getCurrentUserEmail - No token found in any storage");
|
|
2151
|
+
return null;
|
|
2152
|
+
}
|
|
2153
|
+
const payload = decodeJwtSafely(token);
|
|
2154
|
+
if (!payload) {
|
|
2155
|
+
console.warn("\u{1F50D} getCurrentUserEmail - Failed to decode token");
|
|
2156
|
+
return null;
|
|
2157
|
+
}
|
|
2158
|
+
const email = payload.email || payload["cognito:username"] || null;
|
|
2159
|
+
console.log("\u{1F50D} getCurrentUserEmail - Extracted email:", email);
|
|
2160
|
+
return email;
|
|
2161
|
+
} catch (error) {
|
|
2162
|
+
console.warn("Failed to get current user email:", error);
|
|
2163
|
+
return null;
|
|
2802
2164
|
}
|
|
2803
2165
|
};
|
|
2804
|
-
|
|
2805
|
-
|
|
2806
|
-
|
|
2807
|
-
|
|
2808
|
-
|
|
2809
|
-
|
|
2810
|
-
|
|
2811
|
-
|
|
2812
|
-
this.config = {};
|
|
2813
|
-
this.initialized = false;
|
|
2814
|
-
}
|
|
2815
|
-
static getInstance() {
|
|
2816
|
-
if (!_SessionManager.instance) {
|
|
2817
|
-
_SessionManager.instance = new _SessionManager();
|
|
2818
|
-
}
|
|
2819
|
-
return _SessionManager.instance;
|
|
2166
|
+
var isTokenExpired = (token) => {
|
|
2167
|
+
try {
|
|
2168
|
+
const payload = decodeJwtSafely(token);
|
|
2169
|
+
if (!payload || !payload.exp) return true;
|
|
2170
|
+
const currentTime = Math.floor(Date.now() / 1e3);
|
|
2171
|
+
return payload.exp < currentTime;
|
|
2172
|
+
} catch {
|
|
2173
|
+
return true;
|
|
2820
2174
|
}
|
|
2821
|
-
|
|
2822
|
-
|
|
2823
|
-
|
|
2824
|
-
|
|
2825
|
-
|
|
2826
|
-
|
|
2827
|
-
|
|
2828
|
-
|
|
2829
|
-
|
|
2830
|
-
|
|
2831
|
-
|
|
2832
|
-
|
|
2833
|
-
|
|
2175
|
+
};
|
|
2176
|
+
|
|
2177
|
+
// src/providers/SessionProvider.tsx
|
|
2178
|
+
var import_jsx_runtime9 = require("react/jsx-runtime");
|
|
2179
|
+
var SessionContext = (0, import_react10.createContext)(void 0);
|
|
2180
|
+
function SessionProvider({ children, options = {}, config: propConfig }) {
|
|
2181
|
+
const sessionHook = useSession(options);
|
|
2182
|
+
const resolvedConfig = (0, import_react10.useMemo)(() => {
|
|
2183
|
+
let publicApiKey;
|
|
2184
|
+
let env;
|
|
2185
|
+
let appName;
|
|
2186
|
+
let loginActions;
|
|
2187
|
+
let logo;
|
|
2188
|
+
let colors;
|
|
2189
|
+
let configSource = "unknown";
|
|
2190
|
+
if (propConfig?.publicApiKey) {
|
|
2191
|
+
publicApiKey = propConfig.publicApiKey;
|
|
2192
|
+
configSource = "props";
|
|
2193
|
+
}
|
|
2194
|
+
if (propConfig?.env) {
|
|
2195
|
+
env = propConfig.env;
|
|
2196
|
+
}
|
|
2197
|
+
if (propConfig?.appName) {
|
|
2198
|
+
appName = propConfig.appName;
|
|
2199
|
+
}
|
|
2200
|
+
if (propConfig?.loginActions) {
|
|
2201
|
+
loginActions = propConfig.loginActions;
|
|
2202
|
+
}
|
|
2203
|
+
if (propConfig?.logo) {
|
|
2204
|
+
logo = propConfig.logo;
|
|
2205
|
+
}
|
|
2206
|
+
if (propConfig?.colors) {
|
|
2207
|
+
colors = propConfig.colors;
|
|
2208
|
+
}
|
|
2209
|
+
if (!publicApiKey) {
|
|
2210
|
+
const cookieApiKey = getCookie("publicApiKey");
|
|
2211
|
+
const cookieEnv = getCookie("environment");
|
|
2212
|
+
const cookieAppName = getCookie("appName");
|
|
2213
|
+
const cookieLoginActions = getCookie("loginActions");
|
|
2214
|
+
if (cookieApiKey) {
|
|
2215
|
+
publicApiKey = cookieApiKey;
|
|
2216
|
+
configSource = "cookies";
|
|
2217
|
+
}
|
|
2218
|
+
if (cookieEnv && ["dev", "stg", "prod"].includes(cookieEnv)) {
|
|
2219
|
+
env = cookieEnv;
|
|
2220
|
+
}
|
|
2221
|
+
if (cookieAppName) {
|
|
2222
|
+
appName = cookieAppName;
|
|
2223
|
+
}
|
|
2224
|
+
if (cookieLoginActions) {
|
|
2225
|
+
loginActions = cookieLoginActions.split(",").map((s) => s.trim()).filter(Boolean);
|
|
2226
|
+
}
|
|
2227
|
+
}
|
|
2228
|
+
console.log("\u{1F50D} SessionProvider - Configuration Detection:");
|
|
2229
|
+
console.log(" - Config source:", configSource);
|
|
2230
|
+
console.log(" - PublicApiKey:", publicApiKey ? publicApiKey.substring(0, 15) + "..." : "undefined");
|
|
2231
|
+
console.log(" - Environment:", env);
|
|
2232
|
+
console.log(" - App name:", appName);
|
|
2233
|
+
console.log(" - Login actions:", loginActions);
|
|
2234
|
+
return {
|
|
2235
|
+
publicApiKey,
|
|
2236
|
+
env,
|
|
2237
|
+
appName,
|
|
2238
|
+
loginActions,
|
|
2239
|
+
logo,
|
|
2240
|
+
colors
|
|
2834
2241
|
};
|
|
2835
|
-
|
|
2836
|
-
|
|
2837
|
-
|
|
2838
|
-
|
|
2839
|
-
await this.restoreSession();
|
|
2242
|
+
}, [propConfig]);
|
|
2243
|
+
const sessionData = (0, import_react10.useMemo)(() => {
|
|
2244
|
+
if (!sessionHook.tokens?.accessToken || !sessionHook.isAuthenticated) {
|
|
2245
|
+
return null;
|
|
2840
2246
|
}
|
|
2841
|
-
this.initialized = true;
|
|
2842
|
-
this.log("SessionManager initialized successfully");
|
|
2843
|
-
}
|
|
2844
|
-
/**
|
|
2845
|
-
* Login con persistencia automática
|
|
2846
|
-
*/
|
|
2847
|
-
async login(email, password) {
|
|
2848
2247
|
try {
|
|
2849
|
-
|
|
2850
|
-
|
|
2851
|
-
|
|
2852
|
-
|
|
2853
|
-
|
|
2854
|
-
|
|
2855
|
-
error: this.formatError(response.errors)
|
|
2248
|
+
const decoded = decodeJwtSafely(sessionHook.tokens.accessToken);
|
|
2249
|
+
if (decoded && decoded.sub && decoded.email && decoded.subscriber) {
|
|
2250
|
+
const result = {
|
|
2251
|
+
_id: decoded.sub,
|
|
2252
|
+
email: decoded.email,
|
|
2253
|
+
subscriberKey: decoded.subscriber
|
|
2856
2254
|
};
|
|
2255
|
+
Object.keys(decoded).forEach((key) => {
|
|
2256
|
+
if (!["sub", "email", "subscriber"].includes(key)) {
|
|
2257
|
+
result[key] = decoded[key];
|
|
2258
|
+
}
|
|
2259
|
+
});
|
|
2260
|
+
return result;
|
|
2857
2261
|
}
|
|
2858
|
-
const tokens = {
|
|
2859
|
-
accessToken: response.data.token,
|
|
2860
|
-
refreshToken: response.data.refreshToken,
|
|
2861
|
-
expiresAt: response.data.expiresAt,
|
|
2862
|
-
refreshExpiresAt: response.data.refreshExpiresAt
|
|
2863
|
-
};
|
|
2864
|
-
TokenStorage.saveTokens(tokens);
|
|
2865
|
-
this.log("Login successful, tokens saved");
|
|
2866
|
-
this.config.onLoginSuccess?.(tokens);
|
|
2867
|
-
return {
|
|
2868
|
-
success: true,
|
|
2869
|
-
tokens
|
|
2870
|
-
};
|
|
2871
2262
|
} catch (error) {
|
|
2872
|
-
|
|
2873
|
-
return {
|
|
2874
|
-
success: false,
|
|
2875
|
-
error: error instanceof Error ? error.message : "Unknown error"
|
|
2876
|
-
};
|
|
2263
|
+
console.error("Error decoding JWT token for sessionData:", error);
|
|
2877
2264
|
}
|
|
2265
|
+
return null;
|
|
2266
|
+
}, [sessionHook.tokens?.accessToken, sessionHook.isAuthenticated]);
|
|
2267
|
+
const contextValue = {
|
|
2268
|
+
...sessionHook,
|
|
2269
|
+
sessionData,
|
|
2270
|
+
config: resolvedConfig
|
|
2271
|
+
};
|
|
2272
|
+
return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(SessionContext.Provider, { value: contextValue, children });
|
|
2273
|
+
}
|
|
2274
|
+
function useSessionContext() {
|
|
2275
|
+
const context = (0, import_react10.useContext)(SessionContext);
|
|
2276
|
+
if (context === void 0) {
|
|
2277
|
+
throw new Error("useSessionContext must be used within a SessionProvider");
|
|
2878
2278
|
}
|
|
2879
|
-
|
|
2880
|
-
|
|
2881
|
-
|
|
2882
|
-
|
|
2883
|
-
|
|
2884
|
-
|
|
2885
|
-
await import_crudify_browser4.default.logout();
|
|
2886
|
-
TokenStorage.clearTokens();
|
|
2887
|
-
this.log("Logout successful");
|
|
2888
|
-
this.config.onLogout?.();
|
|
2889
|
-
} catch (error) {
|
|
2890
|
-
this.log("Logout error:", error);
|
|
2891
|
-
TokenStorage.clearTokens();
|
|
2892
|
-
}
|
|
2279
|
+
return context;
|
|
2280
|
+
}
|
|
2281
|
+
function ProtectedRoute({ children, fallback = /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { children: "Please log in to access this content" }), redirectTo }) {
|
|
2282
|
+
const { isAuthenticated, isLoading, isInitialized } = useSessionContext();
|
|
2283
|
+
if (!isInitialized || isLoading) {
|
|
2284
|
+
return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { children: "Loading..." });
|
|
2893
2285
|
}
|
|
2894
|
-
|
|
2895
|
-
|
|
2896
|
-
|
|
2897
|
-
|
|
2898
|
-
try {
|
|
2899
|
-
this.log("Attempting to restore session...");
|
|
2900
|
-
const savedTokens = TokenStorage.getTokens();
|
|
2901
|
-
if (!savedTokens) {
|
|
2902
|
-
this.log("No valid tokens found in storage");
|
|
2903
|
-
return false;
|
|
2904
|
-
}
|
|
2905
|
-
import_crudify_browser4.default.setTokens({
|
|
2906
|
-
accessToken: savedTokens.accessToken,
|
|
2907
|
-
refreshToken: savedTokens.refreshToken,
|
|
2908
|
-
expiresAt: savedTokens.expiresAt,
|
|
2909
|
-
refreshExpiresAt: savedTokens.refreshExpiresAt
|
|
2910
|
-
});
|
|
2911
|
-
this.log("Session restored successfully");
|
|
2912
|
-
this.config.onSessionRestored?.(savedTokens);
|
|
2913
|
-
return true;
|
|
2914
|
-
} catch (error) {
|
|
2915
|
-
this.log("Session restore error:", error);
|
|
2916
|
-
TokenStorage.clearTokens();
|
|
2917
|
-
return false;
|
|
2286
|
+
if (!isAuthenticated) {
|
|
2287
|
+
if (redirectTo) {
|
|
2288
|
+
redirectTo();
|
|
2289
|
+
return null;
|
|
2918
2290
|
}
|
|
2291
|
+
return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_jsx_runtime9.Fragment, { children: fallback });
|
|
2919
2292
|
}
|
|
2920
|
-
|
|
2921
|
-
|
|
2922
|
-
|
|
2923
|
-
|
|
2924
|
-
|
|
2925
|
-
|
|
2926
|
-
/**
|
|
2927
|
-
* Obtener información de tokens actuales
|
|
2928
|
-
*/
|
|
2929
|
-
getTokenInfo() {
|
|
2930
|
-
const crudifyTokens = import_crudify_browser4.default.getTokenData();
|
|
2931
|
-
const storageInfo = TokenStorage.getExpirationInfo();
|
|
2932
|
-
return {
|
|
2933
|
-
isLoggedIn: this.isAuthenticated(),
|
|
2934
|
-
crudifyTokens,
|
|
2935
|
-
storageInfo,
|
|
2936
|
-
hasValidTokens: TokenStorage.hasValidTokens()
|
|
2937
|
-
};
|
|
2293
|
+
return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(import_jsx_runtime9.Fragment, { children });
|
|
2294
|
+
}
|
|
2295
|
+
function SessionDebugInfo() {
|
|
2296
|
+
const session = useSessionContext();
|
|
2297
|
+
if (!session.isInitialized) {
|
|
2298
|
+
return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { children: "Session not initialized" });
|
|
2938
2299
|
}
|
|
2939
|
-
|
|
2940
|
-
|
|
2941
|
-
|
|
2942
|
-
|
|
2943
|
-
|
|
2944
|
-
|
|
2945
|
-
|
|
2946
|
-
|
|
2947
|
-
|
|
2948
|
-
|
|
2949
|
-
|
|
2950
|
-
|
|
2951
|
-
|
|
2952
|
-
|
|
2953
|
-
|
|
2954
|
-
|
|
2955
|
-
|
|
2956
|
-
|
|
2957
|
-
|
|
2958
|
-
|
|
2959
|
-
|
|
2960
|
-
|
|
2961
|
-
|
|
2962
|
-
|
|
2963
|
-
|
|
2964
|
-
|
|
2965
|
-
|
|
2300
|
+
return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(
|
|
2301
|
+
"div",
|
|
2302
|
+
{
|
|
2303
|
+
style: {
|
|
2304
|
+
padding: "10px",
|
|
2305
|
+
margin: "10px",
|
|
2306
|
+
border: "1px solid #ccc",
|
|
2307
|
+
borderRadius: "4px",
|
|
2308
|
+
fontSize: "12px",
|
|
2309
|
+
fontFamily: "monospace"
|
|
2310
|
+
},
|
|
2311
|
+
children: [
|
|
2312
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("h4", { children: "Session Debug Info" }),
|
|
2313
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { children: [
|
|
2314
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("strong", { children: "Authenticated:" }),
|
|
2315
|
+
" ",
|
|
2316
|
+
session.isAuthenticated ? "Yes" : "No"
|
|
2317
|
+
] }),
|
|
2318
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { children: [
|
|
2319
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("strong", { children: "Loading:" }),
|
|
2320
|
+
" ",
|
|
2321
|
+
session.isLoading ? "Yes" : "No"
|
|
2322
|
+
] }),
|
|
2323
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { children: [
|
|
2324
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("strong", { children: "Error:" }),
|
|
2325
|
+
" ",
|
|
2326
|
+
session.error || "None"
|
|
2327
|
+
] }),
|
|
2328
|
+
session.tokens && /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(import_jsx_runtime9.Fragment, { children: [
|
|
2329
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { children: [
|
|
2330
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("strong", { children: "Access Token:" }),
|
|
2331
|
+
" ",
|
|
2332
|
+
session.tokens.accessToken.substring(0, 20),
|
|
2333
|
+
"..."
|
|
2334
|
+
] }),
|
|
2335
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { children: [
|
|
2336
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("strong", { children: "Refresh Token:" }),
|
|
2337
|
+
" ",
|
|
2338
|
+
session.tokens.refreshToken.substring(0, 20),
|
|
2339
|
+
"..."
|
|
2340
|
+
] }),
|
|
2341
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { children: [
|
|
2342
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("strong", { children: "Access Expires In:" }),
|
|
2343
|
+
" ",
|
|
2344
|
+
Math.round(session.expiresIn / 1e3 / 60),
|
|
2345
|
+
" minutes"
|
|
2346
|
+
] }),
|
|
2347
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { children: [
|
|
2348
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("strong", { children: "Refresh Expires In:" }),
|
|
2349
|
+
" ",
|
|
2350
|
+
Math.round(session.refreshExpiresIn / 1e3 / 60 / 60),
|
|
2351
|
+
" hours"
|
|
2352
|
+
] }),
|
|
2353
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { children: [
|
|
2354
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("strong", { children: "Expiring Soon:" }),
|
|
2355
|
+
" ",
|
|
2356
|
+
session.isExpiringSoon ? "Yes" : "No"
|
|
2357
|
+
] })
|
|
2358
|
+
] })
|
|
2359
|
+
]
|
|
2966
2360
|
}
|
|
2967
|
-
|
|
2968
|
-
|
|
2969
|
-
|
|
2970
|
-
|
|
2971
|
-
|
|
2972
|
-
|
|
2973
|
-
|
|
2974
|
-
|
|
2975
|
-
|
|
2976
|
-
|
|
2977
|
-
|
|
2978
|
-
|
|
2979
|
-
|
|
2980
|
-
|
|
2981
|
-
|
|
2982
|
-
|
|
2361
|
+
);
|
|
2362
|
+
}
|
|
2363
|
+
|
|
2364
|
+
// src/components/CrudifyLogin/index.tsx
|
|
2365
|
+
var import_jsx_runtime10 = require("react/jsx-runtime");
|
|
2366
|
+
var CrudifyLoginInternal = ({
|
|
2367
|
+
onScreenChange,
|
|
2368
|
+
onExternalNavigate,
|
|
2369
|
+
onLoginSuccess,
|
|
2370
|
+
onError,
|
|
2371
|
+
redirectUrl = "/"
|
|
2372
|
+
}) => {
|
|
2373
|
+
const { t } = useTranslation();
|
|
2374
|
+
const { state, setScreen } = useLoginState();
|
|
2375
|
+
const { config } = useSessionContext();
|
|
2376
|
+
const handleScreenChange = (screen2, params) => {
|
|
2377
|
+
let finalParams = params;
|
|
2378
|
+
if (screen2 === "login") {
|
|
2379
|
+
finalParams = {};
|
|
2380
|
+
} else if (screen2 === "forgotPassword" && !params) {
|
|
2381
|
+
finalParams = {};
|
|
2382
|
+
}
|
|
2383
|
+
setScreen(screen2, finalParams);
|
|
2384
|
+
onScreenChange?.(screen2, finalParams);
|
|
2385
|
+
};
|
|
2386
|
+
const renderCurrentForm = () => {
|
|
2387
|
+
const commonProps = {
|
|
2388
|
+
onScreenChange: handleScreenChange,
|
|
2389
|
+
onExternalNavigate,
|
|
2390
|
+
onError,
|
|
2391
|
+
redirectUrl
|
|
2392
|
+
};
|
|
2393
|
+
switch (state.currentScreen) {
|
|
2394
|
+
case "forgotPassword":
|
|
2395
|
+
return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(ForgotPasswordForm_default, { ...commonProps });
|
|
2396
|
+
case "checkCode":
|
|
2397
|
+
return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(CheckCodeForm_default, { ...commonProps, searchParams: state.searchParams });
|
|
2398
|
+
case "resetPassword":
|
|
2399
|
+
return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
2400
|
+
ResetPasswordForm_default,
|
|
2401
|
+
{
|
|
2402
|
+
...commonProps,
|
|
2403
|
+
searchParams: state.searchParams,
|
|
2404
|
+
onResetSuccess: () => {
|
|
2405
|
+
handleScreenChange("login");
|
|
2406
|
+
}
|
|
2983
2407
|
}
|
|
2408
|
+
);
|
|
2409
|
+
default:
|
|
2410
|
+
return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(LoginForm_default, { ...commonProps, onLoginSuccess });
|
|
2411
|
+
}
|
|
2412
|
+
};
|
|
2413
|
+
return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(CrudifyInitializer, { children: [
|
|
2414
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_material6.Box, { sx: { display: "flex", justifyContent: "center", mb: 3 }, children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
2415
|
+
"img",
|
|
2416
|
+
{
|
|
2417
|
+
src: config.logo || "/nocios-default.png",
|
|
2418
|
+
alt: t("login.logoAlt"),
|
|
2419
|
+
style: {
|
|
2420
|
+
width: "100%",
|
|
2421
|
+
maxWidth: "150px",
|
|
2422
|
+
height: "auto"
|
|
2423
|
+
},
|
|
2424
|
+
onError: (e) => {
|
|
2425
|
+
const target = e.target;
|
|
2426
|
+
target.src = "/nocios-default.png";
|
|
2984
2427
|
}
|
|
2985
2428
|
}
|
|
2986
|
-
|
|
2987
|
-
|
|
2988
|
-
|
|
2989
|
-
|
|
2990
|
-
|
|
2991
|
-
|
|
2992
|
-
|
|
2993
|
-
|
|
2994
|
-
|
|
2995
|
-
|
|
2996
|
-
|
|
2997
|
-
|
|
2998
|
-
|
|
2999
|
-
|
|
3000
|
-
|
|
3001
|
-
|
|
3002
|
-
|
|
3003
|
-
|
|
3004
|
-
|
|
3005
|
-
|
|
3006
|
-
|
|
3007
|
-
|
|
3008
|
-
|
|
3009
|
-
|
|
3010
|
-
|
|
3011
|
-
|
|
3012
|
-
}
|
|
2429
|
+
) }),
|
|
2430
|
+
config.appName && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
2431
|
+
import_material6.Typography,
|
|
2432
|
+
{
|
|
2433
|
+
variant: "h6",
|
|
2434
|
+
component: "h1",
|
|
2435
|
+
sx: {
|
|
2436
|
+
textAlign: "center",
|
|
2437
|
+
mb: 2,
|
|
2438
|
+
color: config.colors?.primaryColor || "#1066BA"
|
|
2439
|
+
},
|
|
2440
|
+
children: config.appName
|
|
2441
|
+
}
|
|
2442
|
+
),
|
|
2443
|
+
renderCurrentForm()
|
|
2444
|
+
] });
|
|
2445
|
+
};
|
|
2446
|
+
var CrudifyLogin = ({
|
|
2447
|
+
translations,
|
|
2448
|
+
translationsUrl,
|
|
2449
|
+
language = "en",
|
|
2450
|
+
initialScreen = "login",
|
|
2451
|
+
autoReadFromCookies = true,
|
|
2452
|
+
...props
|
|
2453
|
+
}) => {
|
|
2454
|
+
const { config } = useSessionContext();
|
|
2455
|
+
return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(I18nProvider, { translations, translationsUrl, language, children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(CrudifyProvider, { config, children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(LoginStateProvider, { config, initialScreen, autoReadFromCookies, children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(CrudifyLoginInternal, { ...props }) }) }) });
|
|
3013
2456
|
};
|
|
2457
|
+
var CrudifyLogin_default = CrudifyLogin;
|
|
3014
2458
|
|
|
3015
|
-
// src/
|
|
3016
|
-
var
|
|
3017
|
-
|
|
3018
|
-
|
|
3019
|
-
|
|
3020
|
-
|
|
3021
|
-
|
|
3022
|
-
|
|
3023
|
-
|
|
3024
|
-
|
|
3025
|
-
const
|
|
3026
|
-
const
|
|
3027
|
-
|
|
3028
|
-
|
|
3029
|
-
|
|
3030
|
-
|
|
3031
|
-
|
|
3032
|
-
|
|
3033
|
-
|
|
3034
|
-
|
|
3035
|
-
|
|
3036
|
-
|
|
3037
|
-
|
|
3038
|
-
|
|
3039
|
-
|
|
3040
|
-
|
|
3041
|
-
|
|
3042
|
-
|
|
3043
|
-
|
|
3044
|
-
|
|
3045
|
-
|
|
3046
|
-
error: null
|
|
3047
|
-
}));
|
|
3048
|
-
options.onSessionRestored?.(tokens);
|
|
3049
|
-
},
|
|
3050
|
-
onLoginSuccess: (tokens) => {
|
|
3051
|
-
setState((prev) => ({
|
|
3052
|
-
...prev,
|
|
3053
|
-
isAuthenticated: true,
|
|
3054
|
-
tokens,
|
|
3055
|
-
error: null
|
|
3056
|
-
}));
|
|
3057
|
-
},
|
|
3058
|
-
onLogout: () => {
|
|
3059
|
-
setState((prev) => ({
|
|
3060
|
-
...prev,
|
|
3061
|
-
isAuthenticated: false,
|
|
3062
|
-
tokens: null,
|
|
3063
|
-
error: null
|
|
3064
|
-
}));
|
|
3065
|
-
}
|
|
3066
|
-
};
|
|
3067
|
-
await sessionManager.initialize(config);
|
|
3068
|
-
sessionManager.setupResponseInterceptor();
|
|
3069
|
-
const isAuth = sessionManager.isAuthenticated();
|
|
3070
|
-
const tokenInfo = sessionManager.getTokenInfo();
|
|
3071
|
-
setState((prev) => ({
|
|
3072
|
-
...prev,
|
|
3073
|
-
isAuthenticated: isAuth,
|
|
3074
|
-
isInitialized: true,
|
|
3075
|
-
isLoading: false,
|
|
3076
|
-
tokens: tokenInfo.crudifyTokens.accessToken ? {
|
|
3077
|
-
accessToken: tokenInfo.crudifyTokens.accessToken,
|
|
3078
|
-
refreshToken: tokenInfo.crudifyTokens.refreshToken,
|
|
3079
|
-
expiresAt: tokenInfo.crudifyTokens.expiresAt,
|
|
3080
|
-
refreshExpiresAt: tokenInfo.crudifyTokens.refreshExpiresAt
|
|
3081
|
-
} : null
|
|
3082
|
-
}));
|
|
3083
|
-
} catch (error) {
|
|
3084
|
-
setState((prev) => ({
|
|
3085
|
-
...prev,
|
|
3086
|
-
isLoading: false,
|
|
3087
|
-
isInitialized: true,
|
|
3088
|
-
error: error instanceof Error ? error.message : "Initialization failed"
|
|
3089
|
-
}));
|
|
2459
|
+
// src/components/UserProfile/UserProfileDisplay.tsx
|
|
2460
|
+
var import_material7 = require("@mui/material");
|
|
2461
|
+
var import_icons_material = require("@mui/icons-material");
|
|
2462
|
+
|
|
2463
|
+
// src/hooks/useUserProfile.ts
|
|
2464
|
+
var import_react11 = require("react");
|
|
2465
|
+
var import_crudify_browser3 = __toESM(require("@nocios/crudify-browser"));
|
|
2466
|
+
var useUserProfile = (options = {}) => {
|
|
2467
|
+
const { autoFetch = true, retryOnError = false, maxRetries = 3 } = options;
|
|
2468
|
+
const [userProfile, setUserProfile] = (0, import_react11.useState)(null);
|
|
2469
|
+
const [loading, setLoading] = (0, import_react11.useState)(false);
|
|
2470
|
+
const [error, setError] = (0, import_react11.useState)(null);
|
|
2471
|
+
const [extendedData, setExtendedData] = (0, import_react11.useState)({});
|
|
2472
|
+
const abortControllerRef = (0, import_react11.useRef)(null);
|
|
2473
|
+
const mountedRef = (0, import_react11.useRef)(true);
|
|
2474
|
+
const requestIdRef = (0, import_react11.useRef)(0);
|
|
2475
|
+
const retryCountRef = (0, import_react11.useRef)(0);
|
|
2476
|
+
const clearProfile = (0, import_react11.useCallback)(() => {
|
|
2477
|
+
setUserProfile(null);
|
|
2478
|
+
setError(null);
|
|
2479
|
+
setLoading(false);
|
|
2480
|
+
setExtendedData({});
|
|
2481
|
+
}, []);
|
|
2482
|
+
const refreshProfile = (0, import_react11.useCallback)(async () => {
|
|
2483
|
+
const userEmail = getCurrentUserEmail();
|
|
2484
|
+
if (!userEmail) {
|
|
2485
|
+
if (mountedRef.current) {
|
|
2486
|
+
setError("No user email available");
|
|
2487
|
+
setLoading(false);
|
|
2488
|
+
}
|
|
2489
|
+
return;
|
|
3090
2490
|
}
|
|
3091
|
-
|
|
3092
|
-
|
|
3093
|
-
|
|
2491
|
+
if (abortControllerRef.current) {
|
|
2492
|
+
abortControllerRef.current.abort();
|
|
2493
|
+
}
|
|
2494
|
+
const abortController = new AbortController();
|
|
2495
|
+
abortControllerRef.current = abortController;
|
|
2496
|
+
const currentRequestId = ++requestIdRef.current;
|
|
3094
2497
|
try {
|
|
3095
|
-
|
|
3096
|
-
|
|
3097
|
-
|
|
3098
|
-
|
|
3099
|
-
|
|
3100
|
-
|
|
3101
|
-
|
|
3102
|
-
|
|
3103
|
-
|
|
3104
|
-
|
|
3105
|
-
|
|
3106
|
-
|
|
3107
|
-
|
|
3108
|
-
|
|
3109
|
-
|
|
3110
|
-
|
|
3111
|
-
|
|
2498
|
+
if (mountedRef.current) {
|
|
2499
|
+
setLoading(true);
|
|
2500
|
+
setError(null);
|
|
2501
|
+
}
|
|
2502
|
+
const response = await import_crudify_browser3.default.readItems("users", {
|
|
2503
|
+
filter: { email: userEmail },
|
|
2504
|
+
pagination: { limit: 1 }
|
|
2505
|
+
});
|
|
2506
|
+
if (currentRequestId === requestIdRef.current && mountedRef.current && !abortController.signal.aborted) {
|
|
2507
|
+
if (response.success && response.data && response.data.length > 0) {
|
|
2508
|
+
const userData = response.data[0];
|
|
2509
|
+
setUserProfile(userData);
|
|
2510
|
+
const additionalData = {
|
|
2511
|
+
fullProfile: userData,
|
|
2512
|
+
totalFields: Object.keys(userData).length,
|
|
2513
|
+
displayData: {
|
|
2514
|
+
id: userData.id,
|
|
2515
|
+
email: userData.email,
|
|
2516
|
+
username: userData.username,
|
|
2517
|
+
firstName: userData.firstName,
|
|
2518
|
+
lastName: userData.lastName,
|
|
2519
|
+
fullName: userData.fullName || `${userData.firstName || ""} ${userData.lastName || ""}`.trim(),
|
|
2520
|
+
role: userData.role,
|
|
2521
|
+
permissions: userData.permissions || [],
|
|
2522
|
+
isActive: userData.isActive,
|
|
2523
|
+
lastLogin: userData.lastLogin,
|
|
2524
|
+
createdAt: userData.createdAt,
|
|
2525
|
+
updatedAt: userData.updatedAt,
|
|
2526
|
+
// Include any custom fields
|
|
2527
|
+
...Object.keys(userData).filter(
|
|
2528
|
+
(key) => ![
|
|
2529
|
+
"id",
|
|
2530
|
+
"email",
|
|
2531
|
+
"username",
|
|
2532
|
+
"firstName",
|
|
2533
|
+
"lastName",
|
|
2534
|
+
"fullName",
|
|
2535
|
+
"role",
|
|
2536
|
+
"permissions",
|
|
2537
|
+
"isActive",
|
|
2538
|
+
"lastLogin",
|
|
2539
|
+
"createdAt",
|
|
2540
|
+
"updatedAt"
|
|
2541
|
+
].includes(key)
|
|
2542
|
+
).reduce((acc, key) => ({ ...acc, [key]: userData[key] }), {})
|
|
2543
|
+
}
|
|
2544
|
+
};
|
|
2545
|
+
setExtendedData(additionalData);
|
|
2546
|
+
setError(null);
|
|
2547
|
+
retryCountRef.current = 0;
|
|
2548
|
+
} else {
|
|
2549
|
+
setError("User profile not found");
|
|
2550
|
+
setUserProfile(null);
|
|
2551
|
+
setExtendedData({});
|
|
2552
|
+
}
|
|
2553
|
+
}
|
|
2554
|
+
} catch (err) {
|
|
2555
|
+
if (currentRequestId === requestIdRef.current && mountedRef.current) {
|
|
2556
|
+
const error2 = err;
|
|
2557
|
+
if (error2.name === "AbortError") {
|
|
2558
|
+
return;
|
|
2559
|
+
}
|
|
2560
|
+
const shouldRetry = retryOnError && retryCountRef.current < maxRetries && (error2.message?.includes("Network Error") || error2.message?.includes("Failed to fetch"));
|
|
2561
|
+
if (shouldRetry) {
|
|
2562
|
+
retryCountRef.current++;
|
|
2563
|
+
setTimeout(() => {
|
|
2564
|
+
if (mountedRef.current) {
|
|
2565
|
+
refreshProfile();
|
|
2566
|
+
}
|
|
2567
|
+
}, 1e3 * retryCountRef.current);
|
|
2568
|
+
} else {
|
|
2569
|
+
setError("Failed to load user profile");
|
|
2570
|
+
setUserProfile(null);
|
|
2571
|
+
setExtendedData({});
|
|
2572
|
+
}
|
|
2573
|
+
}
|
|
2574
|
+
} finally {
|
|
2575
|
+
if (currentRequestId === requestIdRef.current && mountedRef.current) {
|
|
2576
|
+
setLoading(false);
|
|
2577
|
+
}
|
|
2578
|
+
if (abortControllerRef.current === abortController) {
|
|
2579
|
+
abortControllerRef.current = null;
|
|
3112
2580
|
}
|
|
3113
|
-
return result;
|
|
3114
|
-
} catch (error) {
|
|
3115
|
-
const errorMsg = error instanceof Error ? error.message : "Login failed";
|
|
3116
|
-
setState((prev) => ({
|
|
3117
|
-
...prev,
|
|
3118
|
-
isAuthenticated: false,
|
|
3119
|
-
tokens: null,
|
|
3120
|
-
isLoading: false,
|
|
3121
|
-
error: errorMsg
|
|
3122
|
-
}));
|
|
3123
|
-
return {
|
|
3124
|
-
success: false,
|
|
3125
|
-
error: errorMsg
|
|
3126
|
-
};
|
|
3127
2581
|
}
|
|
3128
|
-
}, [
|
|
3129
|
-
|
|
3130
|
-
|
|
3131
|
-
|
|
3132
|
-
await sessionManager.logout();
|
|
3133
|
-
setState((prev) => ({
|
|
3134
|
-
...prev,
|
|
3135
|
-
isAuthenticated: false,
|
|
3136
|
-
tokens: null,
|
|
3137
|
-
isLoading: false,
|
|
3138
|
-
error: null
|
|
3139
|
-
}));
|
|
3140
|
-
} catch (error) {
|
|
3141
|
-
setState((prev) => ({
|
|
3142
|
-
...prev,
|
|
3143
|
-
isAuthenticated: false,
|
|
3144
|
-
tokens: null,
|
|
3145
|
-
isLoading: false,
|
|
3146
|
-
error: error instanceof Error ? error.message : "Logout error"
|
|
3147
|
-
}));
|
|
2582
|
+
}, [retryOnError, maxRetries]);
|
|
2583
|
+
(0, import_react11.useEffect)(() => {
|
|
2584
|
+
if (autoFetch) {
|
|
2585
|
+
refreshProfile();
|
|
3148
2586
|
}
|
|
3149
|
-
}, [
|
|
3150
|
-
|
|
3151
|
-
|
|
3152
|
-
|
|
3153
|
-
|
|
3154
|
-
|
|
3155
|
-
|
|
3156
|
-
|
|
3157
|
-
tokens: tokenInfo.crudifyTokens.accessToken ? {
|
|
3158
|
-
accessToken: tokenInfo.crudifyTokens.accessToken,
|
|
3159
|
-
refreshToken: tokenInfo.crudifyTokens.refreshToken,
|
|
3160
|
-
expiresAt: tokenInfo.crudifyTokens.expiresAt,
|
|
3161
|
-
refreshExpiresAt: tokenInfo.crudifyTokens.refreshExpiresAt
|
|
3162
|
-
} : null,
|
|
3163
|
-
error: null
|
|
3164
|
-
}));
|
|
3165
|
-
} else {
|
|
3166
|
-
setState((prev) => ({
|
|
3167
|
-
...prev,
|
|
3168
|
-
isAuthenticated: false,
|
|
3169
|
-
tokens: null,
|
|
3170
|
-
error: "Token refresh failed"
|
|
3171
|
-
}));
|
|
2587
|
+
}, [autoFetch, refreshProfile]);
|
|
2588
|
+
(0, import_react11.useEffect)(() => {
|
|
2589
|
+
mountedRef.current = true;
|
|
2590
|
+
return () => {
|
|
2591
|
+
mountedRef.current = false;
|
|
2592
|
+
if (abortControllerRef.current) {
|
|
2593
|
+
abortControllerRef.current.abort();
|
|
2594
|
+
abortControllerRef.current = null;
|
|
3172
2595
|
}
|
|
3173
|
-
|
|
3174
|
-
|
|
3175
|
-
|
|
3176
|
-
|
|
3177
|
-
|
|
3178
|
-
|
|
3179
|
-
|
|
3180
|
-
|
|
3181
|
-
|
|
2596
|
+
};
|
|
2597
|
+
}, []);
|
|
2598
|
+
return {
|
|
2599
|
+
userProfile,
|
|
2600
|
+
loading,
|
|
2601
|
+
error,
|
|
2602
|
+
extendedData,
|
|
2603
|
+
refreshProfile,
|
|
2604
|
+
clearProfile
|
|
2605
|
+
};
|
|
2606
|
+
};
|
|
2607
|
+
|
|
2608
|
+
// src/components/UserProfile/UserProfileDisplay.tsx
|
|
2609
|
+
var import_react12 = require("react");
|
|
2610
|
+
var import_jsx_runtime11 = require("react/jsx-runtime");
|
|
2611
|
+
var UserProfileDisplay = ({
|
|
2612
|
+
showExtendedData = true,
|
|
2613
|
+
showProfileCard = true,
|
|
2614
|
+
autoRefresh = true
|
|
2615
|
+
}) => {
|
|
2616
|
+
const { userProfile, loading, error, extendedData, refreshProfile } = useUserProfile({
|
|
2617
|
+
autoFetch: autoRefresh,
|
|
2618
|
+
retryOnError: true,
|
|
2619
|
+
maxRetries: 3
|
|
2620
|
+
});
|
|
2621
|
+
const [showAllFields, setShowAllFields] = (0, import_react12.useState)(false);
|
|
2622
|
+
if (loading) {
|
|
2623
|
+
return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(import_material7.Box, { display: "flex", justifyContent: "center", alignItems: "center", p: 3, children: [
|
|
2624
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_material7.CircularProgress, {}),
|
|
2625
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_material7.Typography, { variant: "body2", sx: { ml: 2 }, children: "Cargando perfil de usuario..." })
|
|
2626
|
+
] });
|
|
2627
|
+
}
|
|
2628
|
+
if (error) {
|
|
2629
|
+
return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(
|
|
2630
|
+
import_material7.Alert,
|
|
2631
|
+
{
|
|
2632
|
+
severity: "error",
|
|
2633
|
+
action: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_material7.IconButton, { color: "inherit", size: "small", onClick: refreshProfile, children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_material7.Typography, { variant: "caption", children: "Reintentar" }) }),
|
|
2634
|
+
children: [
|
|
2635
|
+
"Error al cargar el perfil: ",
|
|
2636
|
+
error
|
|
2637
|
+
]
|
|
2638
|
+
}
|
|
2639
|
+
);
|
|
2640
|
+
}
|
|
2641
|
+
if (!userProfile) {
|
|
2642
|
+
return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_material7.Alert, { severity: "warning", children: "No se encontr\xF3 informaci\xF3n del usuario" });
|
|
2643
|
+
}
|
|
2644
|
+
const displayData = extendedData?.displayData || {};
|
|
2645
|
+
const totalFields = extendedData?.totalFields || 0;
|
|
2646
|
+
const formatDate = (dateString) => {
|
|
2647
|
+
if (!dateString) return "No disponible";
|
|
2648
|
+
try {
|
|
2649
|
+
return new Date(dateString).toLocaleString("es-ES", {
|
|
2650
|
+
year: "numeric",
|
|
2651
|
+
month: "short",
|
|
2652
|
+
day: "numeric",
|
|
2653
|
+
hour: "2-digit",
|
|
2654
|
+
minute: "2-digit"
|
|
2655
|
+
});
|
|
2656
|
+
} catch {
|
|
2657
|
+
return dateString;
|
|
2658
|
+
}
|
|
2659
|
+
};
|
|
2660
|
+
const renderFieldValue = (key, value) => {
|
|
2661
|
+
if (value === null || value === void 0) return "No disponible";
|
|
2662
|
+
if (typeof value === "boolean") return value ? "S\xED" : "No";
|
|
2663
|
+
if (Array.isArray(value)) return value.length > 0 ? value.join(", ") : "Ninguno";
|
|
2664
|
+
if (typeof value === "object") return JSON.stringify(value, null, 2);
|
|
2665
|
+
return String(value);
|
|
2666
|
+
};
|
|
2667
|
+
const basicFields = [
|
|
2668
|
+
{ key: "id", label: "ID", icon: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_icons_material.Badge, {}) },
|
|
2669
|
+
{ key: "email", label: "Email", icon: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_icons_material.Email, {}) },
|
|
2670
|
+
{ key: "username", label: "Usuario", icon: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_icons_material.Person, {}) },
|
|
2671
|
+
{ key: "fullName", label: "Nombre completo", icon: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_icons_material.AccountCircle, {}) },
|
|
2672
|
+
{ key: "role", label: "Rol", icon: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_icons_material.Security, {}) }
|
|
2673
|
+
];
|
|
2674
|
+
const extendedFields = [
|
|
2675
|
+
{ key: "firstName", label: "Nombre" },
|
|
2676
|
+
{ key: "lastName", label: "Apellido" },
|
|
2677
|
+
{ key: "isActive", label: "Activo" },
|
|
2678
|
+
{ key: "lastLogin", label: "\xDAltimo login" },
|
|
2679
|
+
{ key: "createdAt", label: "Creado" },
|
|
2680
|
+
{ key: "updatedAt", label: "Actualizado" }
|
|
2681
|
+
];
|
|
2682
|
+
const knownFields = [...basicFields.map((f) => f.key), ...extendedFields.map((f) => f.key), "permissions"];
|
|
2683
|
+
const customFields = Object.keys(displayData).filter((key) => !knownFields.includes(key)).map((key) => ({ key, label: key }));
|
|
2684
|
+
return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(import_material7.Box, { children: [
|
|
2685
|
+
showProfileCard && /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_material7.Card, { sx: { mb: 2 }, children: /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(import_material7.CardContent, { children: [
|
|
2686
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(import_material7.Box, { display: "flex", alignItems: "center", mb: 2, children: [
|
|
2687
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
|
|
2688
|
+
import_material7.Avatar,
|
|
2689
|
+
{
|
|
2690
|
+
src: displayData.avatar,
|
|
2691
|
+
sx: { width: 56, height: 56, mr: 2 },
|
|
2692
|
+
children: displayData.fullName?.[0] || displayData.username?.[0] || displayData.email?.[0]
|
|
2693
|
+
}
|
|
2694
|
+
),
|
|
2695
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(import_material7.Box, { children: [
|
|
2696
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_material7.Typography, { variant: "h6", children: displayData.fullName || displayData.username || displayData.email }),
|
|
2697
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_material7.Typography, { variant: "body2", color: "text.secondary", children: displayData.role || "Usuario" }),
|
|
2698
|
+
displayData.isActive !== void 0 && /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
|
|
2699
|
+
import_material7.Chip,
|
|
2700
|
+
{
|
|
2701
|
+
label: displayData.isActive ? "Activo" : "Inactivo",
|
|
2702
|
+
color: displayData.isActive ? "success" : "error",
|
|
2703
|
+
size: "small",
|
|
2704
|
+
sx: { mt: 0.5 }
|
|
2705
|
+
}
|
|
2706
|
+
)
|
|
2707
|
+
] })
|
|
2708
|
+
] }),
|
|
2709
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_material7.Box, { display: "grid", gridTemplateColumns: "repeat(auto-fit, minmax(250px, 1fr))", gap: 2, children: basicFields.map(
|
|
2710
|
+
({ key, label, icon }) => displayData[key] ? /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(import_material7.Box, { display: "flex", alignItems: "center", children: [
|
|
2711
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_material7.Box, { sx: { mr: 1, color: "text.secondary" }, children: icon }),
|
|
2712
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(import_material7.Box, { children: [
|
|
2713
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_material7.Typography, { variant: "caption", color: "text.secondary", children: label }),
|
|
2714
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_material7.Typography, { variant: "body2", children: renderFieldValue(key, displayData[key]) })
|
|
2715
|
+
] })
|
|
2716
|
+
] }, key) : null
|
|
2717
|
+
) }),
|
|
2718
|
+
displayData.permissions && Array.isArray(displayData.permissions) && displayData.permissions.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(import_material7.Box, { mt: 2, children: [
|
|
2719
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_material7.Typography, { variant: "caption", color: "text.secondary", display: "block", children: "Permisos" }),
|
|
2720
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(import_material7.Box, { display: "flex", flexWrap: "wrap", gap: 0.5, mt: 0.5, children: [
|
|
2721
|
+
displayData.permissions.slice(0, 5).map((permission, index) => /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_material7.Chip, { label: permission, size: "small", variant: "outlined" }, index)),
|
|
2722
|
+
displayData.permissions.length > 5 && /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_material7.Chip, { label: `+${displayData.permissions.length - 5} m\xE1s`, size: "small" })
|
|
2723
|
+
] })
|
|
2724
|
+
] })
|
|
2725
|
+
] }) }),
|
|
2726
|
+
showExtendedData && /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_material7.Card, { children: /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(import_material7.CardContent, { children: [
|
|
2727
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(import_material7.Box, { display: "flex", justifyContent: "space-between", alignItems: "center", mb: 2, children: [
|
|
2728
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(import_material7.Typography, { variant: "h6", display: "flex", alignItems: "center", children: [
|
|
2729
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_icons_material.Info, { sx: { mr: 1 } }),
|
|
2730
|
+
"Informaci\xF3n Detallada"
|
|
2731
|
+
] }),
|
|
2732
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_material7.Chip, { label: `${totalFields} campos totales`, size: "small" })
|
|
2733
|
+
] }),
|
|
2734
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(import_material7.List, { dense: true, children: [
|
|
2735
|
+
extendedFields.map(({ key, label }) => displayData[key] !== void 0 && /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(import_material7.ListItem, { divider: true, children: [
|
|
2736
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_material7.ListItemIcon, { children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_icons_material.Schedule, { fontSize: "small" }) }),
|
|
2737
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
|
|
2738
|
+
import_material7.ListItemText,
|
|
2739
|
+
{
|
|
2740
|
+
primary: label,
|
|
2741
|
+
secondary: key.includes("At") || key.includes("Login") ? formatDate(displayData[key]) : renderFieldValue(key, displayData[key])
|
|
2742
|
+
}
|
|
2743
|
+
)
|
|
2744
|
+
] }, key)),
|
|
2745
|
+
customFields.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(import_jsx_runtime11.Fragment, { children: [
|
|
2746
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_material7.Divider, { sx: { my: 1 } }),
|
|
2747
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_material7.ListItem, { children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
|
|
2748
|
+
import_material7.ListItemText,
|
|
2749
|
+
{
|
|
2750
|
+
primary: /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(import_material7.Box, { display: "flex", justifyContent: "space-between", alignItems: "center", children: [
|
|
2751
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(import_material7.Typography, { variant: "subtitle2", children: [
|
|
2752
|
+
"Campos Personalizados (",
|
|
2753
|
+
customFields.length,
|
|
2754
|
+
")"
|
|
2755
|
+
] }),
|
|
2756
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_material7.IconButton, { size: "small", onClick: () => setShowAllFields(!showAllFields), children: showAllFields ? /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_icons_material.ExpandLess, {}) : /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_icons_material.ExpandMore, {}) })
|
|
2757
|
+
] })
|
|
2758
|
+
}
|
|
2759
|
+
) }),
|
|
2760
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_material7.Collapse, { in: showAllFields, children: customFields.map(({ key, label }) => /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_material7.ListItem, { sx: { pl: 4 }, children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
|
|
2761
|
+
import_material7.ListItemText,
|
|
2762
|
+
{
|
|
2763
|
+
primary: label,
|
|
2764
|
+
secondary: renderFieldValue(key, displayData[key])
|
|
2765
|
+
}
|
|
2766
|
+
) }, key)) })
|
|
2767
|
+
] })
|
|
2768
|
+
] }),
|
|
2769
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(import_material7.Box, { mt: 2, display: "flex", justifyContent: "space-between", alignItems: "center", children: [
|
|
2770
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(import_material7.Typography, { variant: "caption", color: "text.secondary", children: [
|
|
2771
|
+
"\xDAltima actualizaci\xF3n: ",
|
|
2772
|
+
formatDate(displayData.updatedAt)
|
|
2773
|
+
] }),
|
|
2774
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_material7.IconButton, { size: "small", onClick: refreshProfile, disabled: loading, children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_material7.Typography, { variant: "caption", children: "Actualizar" }) })
|
|
2775
|
+
] })
|
|
2776
|
+
] }) })
|
|
2777
|
+
] });
|
|
2778
|
+
};
|
|
2779
|
+
var UserProfileDisplay_default = UserProfileDisplay;
|
|
2780
|
+
|
|
2781
|
+
// src/components/PublicPolicies/Policies.tsx
|
|
2782
|
+
var import_react15 = require("react");
|
|
2783
|
+
var import_react_i18next3 = require("react-i18next");
|
|
2784
|
+
var import_material10 = require("@mui/material");
|
|
2785
|
+
var import_icons_material4 = require("@mui/icons-material");
|
|
2786
|
+
|
|
2787
|
+
// src/components/PublicPolicies/PolicyItem/PolicyItem.tsx
|
|
2788
|
+
var import_react14 = require("react");
|
|
2789
|
+
var import_react_i18next2 = require("react-i18next");
|
|
2790
|
+
var import_material9 = require("@mui/material");
|
|
2791
|
+
var import_icons_material3 = require("@mui/icons-material");
|
|
2792
|
+
|
|
2793
|
+
// src/components/PublicPolicies/FieldSelector/FieldSelector.tsx
|
|
2794
|
+
var import_react13 = require("react");
|
|
2795
|
+
var import_react_i18next = require("react-i18next");
|
|
2796
|
+
var import_material8 = require("@mui/material");
|
|
2797
|
+
var import_icons_material2 = require("@mui/icons-material");
|
|
2798
|
+
var import_jsx_runtime12 = require("react/jsx-runtime");
|
|
2799
|
+
var FieldSelector = ({
|
|
2800
|
+
value,
|
|
2801
|
+
onChange,
|
|
2802
|
+
availableFields,
|
|
2803
|
+
error,
|
|
2804
|
+
disabled = false
|
|
2805
|
+
}) => {
|
|
2806
|
+
const { t } = (0, import_react_i18next.useTranslation)();
|
|
2807
|
+
const [mode, setMode] = (0, import_react13.useState)("custom");
|
|
2808
|
+
const isUpdatingRef = (0, import_react13.useRef)(false);
|
|
2809
|
+
(0, import_react13.useEffect)(() => {
|
|
2810
|
+
const current = value || { allow: [], owner_allow: [], deny: [] };
|
|
2811
|
+
const all = new Set(availableFields);
|
|
2812
|
+
const allow = (current.allow || []).filter((f) => all.has(f));
|
|
2813
|
+
const owner = (current.owner_allow || []).filter((f) => all.has(f));
|
|
2814
|
+
const deny = (current.deny || []).filter((f) => all.has(f));
|
|
2815
|
+
availableFields.forEach((f) => {
|
|
2816
|
+
if (!allow.includes(f) && !owner.includes(f) && !deny.includes(f)) deny.push(f);
|
|
2817
|
+
});
|
|
2818
|
+
const normalized = { allow, owner_allow: owner, deny };
|
|
2819
|
+
if (JSON.stringify(normalized) !== JSON.stringify(current)) {
|
|
2820
|
+
onChange(normalized);
|
|
2821
|
+
}
|
|
2822
|
+
if (allow.length === availableFields.length) setMode("all");
|
|
2823
|
+
else if (deny.length === availableFields.length) setMode("none");
|
|
2824
|
+
else setMode("custom");
|
|
2825
|
+
}, [availableFields, value]);
|
|
2826
|
+
const setAllAllow = () => {
|
|
2827
|
+
isUpdatingRef.current = true;
|
|
2828
|
+
onChange({ allow: [...availableFields], owner_allow: [], deny: [] });
|
|
2829
|
+
setMode("all");
|
|
2830
|
+
setTimeout(() => {
|
|
2831
|
+
isUpdatingRef.current = false;
|
|
2832
|
+
}, 0);
|
|
2833
|
+
};
|
|
2834
|
+
const setAllDeny = () => {
|
|
2835
|
+
isUpdatingRef.current = true;
|
|
2836
|
+
onChange({ allow: [], owner_allow: [], deny: [...availableFields] });
|
|
2837
|
+
setMode("none");
|
|
2838
|
+
setTimeout(() => {
|
|
2839
|
+
isUpdatingRef.current = false;
|
|
2840
|
+
}, 0);
|
|
2841
|
+
};
|
|
2842
|
+
const getFieldState = (fieldName) => {
|
|
2843
|
+
if (value?.allow?.includes(fieldName)) return "allow";
|
|
2844
|
+
if (value?.owner_allow?.includes(fieldName)) return "owner_allow";
|
|
2845
|
+
return "deny";
|
|
2846
|
+
};
|
|
2847
|
+
const setFieldState = (fieldName, state) => {
|
|
2848
|
+
isUpdatingRef.current = true;
|
|
2849
|
+
const allow = new Set(value?.allow || []);
|
|
2850
|
+
const owner = new Set(value?.owner_allow || []);
|
|
2851
|
+
const deny = new Set(value?.deny || []);
|
|
2852
|
+
allow.delete(fieldName);
|
|
2853
|
+
owner.delete(fieldName);
|
|
2854
|
+
deny.delete(fieldName);
|
|
2855
|
+
if (state === "allow") allow.add(fieldName);
|
|
2856
|
+
if (state === "owner_allow") owner.add(fieldName);
|
|
2857
|
+
if (state === "deny") deny.add(fieldName);
|
|
2858
|
+
onChange({ allow: Array.from(allow), owner_allow: Array.from(owner), deny: Array.from(deny) });
|
|
2859
|
+
setMode("custom");
|
|
2860
|
+
setTimeout(() => {
|
|
2861
|
+
isUpdatingRef.current = false;
|
|
2862
|
+
}, 0);
|
|
2863
|
+
};
|
|
2864
|
+
if (availableFields.length === 0) {
|
|
2865
|
+
return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(import_material8.Box, { children: [
|
|
2866
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_material8.Typography, { variant: "body2", color: "text.secondary", sx: { mb: 1 }, children: t("modules.form.publicPolicies.fields.conditions.label") }),
|
|
2867
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_material8.Typography, { variant: "body2", color: "text.secondary", sx: { fontStyle: "italic" }, children: t("modules.form.publicPolicies.fields.conditions.noFieldsAvailable") }),
|
|
2868
|
+
error && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_material8.FormHelperText, { error: true, sx: { mt: 1 }, children: error })
|
|
2869
|
+
] });
|
|
2870
|
+
}
|
|
2871
|
+
return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(import_material8.Box, { children: [
|
|
2872
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_material8.Typography, { variant: "body2", color: "text.secondary", sx: { mb: 2 }, children: t("modules.form.publicPolicies.fields.conditions.label") }),
|
|
2873
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(import_material8.Stack, { direction: "row", spacing: 1, sx: { mb: 3 }, children: [
|
|
2874
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
2875
|
+
import_material8.Button,
|
|
2876
|
+
{
|
|
2877
|
+
variant: mode === "all" ? "contained" : "outlined",
|
|
2878
|
+
startIcon: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_icons_material2.SelectAll, {}),
|
|
2879
|
+
onClick: setAllAllow,
|
|
2880
|
+
disabled,
|
|
2881
|
+
size: "small",
|
|
2882
|
+
sx: {
|
|
2883
|
+
minWidth: 120,
|
|
2884
|
+
...mode === "all" && {
|
|
2885
|
+
backgroundColor: "#16a34a",
|
|
2886
|
+
"&:hover": { backgroundColor: "#15803d" }
|
|
2887
|
+
}
|
|
2888
|
+
},
|
|
2889
|
+
children: t("modules.form.publicPolicies.fields.conditions.allFields")
|
|
2890
|
+
}
|
|
2891
|
+
),
|
|
2892
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
2893
|
+
import_material8.Button,
|
|
2894
|
+
{
|
|
2895
|
+
variant: mode === "none" ? "contained" : "outlined",
|
|
2896
|
+
startIcon: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_icons_material2.ClearAll, {}),
|
|
2897
|
+
onClick: setAllDeny,
|
|
2898
|
+
disabled,
|
|
2899
|
+
size: "small",
|
|
2900
|
+
sx: {
|
|
2901
|
+
minWidth: 120,
|
|
2902
|
+
...mode === "none" && {
|
|
2903
|
+
backgroundColor: "#cf222e",
|
|
2904
|
+
"&:hover": { backgroundColor: "#bc1f2c" }
|
|
2905
|
+
}
|
|
2906
|
+
},
|
|
2907
|
+
children: t("modules.form.publicPolicies.fields.conditions.noFields")
|
|
2908
|
+
}
|
|
2909
|
+
)
|
|
2910
|
+
] }),
|
|
2911
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(import_material8.Box, { sx: { p: 2, border: "1px solid #d1d9e0", borderRadius: 1, backgroundColor: "#f6f8fa" }, children: [
|
|
2912
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_material8.Typography, { variant: "body2", color: "text.secondary", sx: { mb: 2 }, children: t("modules.form.publicPolicies.fields.conditions.help") }),
|
|
2913
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_material8.Stack, { spacing: 1, children: availableFields.map((fieldName) => {
|
|
2914
|
+
const fieldState = getFieldState(fieldName);
|
|
2915
|
+
return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(import_material8.Stack, { direction: "row", spacing: 1, alignItems: "center", children: [
|
|
2916
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_material8.Typography, { variant: "body2", sx: { minWidth: 100, fontFamily: "monospace" }, children: fieldName }),
|
|
2917
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(import_material8.ToggleButtonGroup, { value: fieldState, exclusive: true, size: "small", children: [
|
|
2918
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
|
|
2919
|
+
import_material8.ToggleButton,
|
|
2920
|
+
{
|
|
2921
|
+
value: "allow",
|
|
2922
|
+
onClick: () => setFieldState(fieldName, "allow"),
|
|
2923
|
+
disabled,
|
|
2924
|
+
sx: {
|
|
2925
|
+
px: 2,
|
|
2926
|
+
color: fieldState === "allow" ? "#ffffff" : "#6b7280",
|
|
2927
|
+
backgroundColor: fieldState === "allow" ? "#16a34a" : "#f3f4f6",
|
|
2928
|
+
borderColor: fieldState === "allow" ? "#16a34a" : "#d1d5db",
|
|
2929
|
+
"&:hover": {
|
|
2930
|
+
backgroundColor: fieldState === "allow" ? "#15803d" : "#e5e7eb",
|
|
2931
|
+
borderColor: fieldState === "allow" ? "#15803d" : "#9ca3af"
|
|
2932
|
+
},
|
|
2933
|
+
"&.Mui-selected": {
|
|
2934
|
+
backgroundColor: "#16a34a",
|
|
2935
|
+
color: "#ffffff",
|
|
2936
|
+
"&:hover": {
|
|
2937
|
+
backgroundColor: "#15803d"
|
|
2938
|
+
}
|
|
2939
|
+
}
|
|
2940
|
+
},
|
|
2941
|
+
children: [
|
|
2942
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_icons_material2.CheckCircle, { sx: { fontSize: 16, mr: 0.5 } }),
|
|
2943
|
+
t("modules.form.publicPolicies.fields.conditions.states.allow")
|
|
2944
|
+
]
|
|
2945
|
+
}
|
|
2946
|
+
),
|
|
2947
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
2948
|
+
import_material8.ToggleButton,
|
|
2949
|
+
{
|
|
2950
|
+
value: "owner_allow",
|
|
2951
|
+
onClick: () => setFieldState(fieldName, "owner_allow"),
|
|
2952
|
+
disabled,
|
|
2953
|
+
sx: {
|
|
2954
|
+
px: 2,
|
|
2955
|
+
color: fieldState === "owner_allow" ? "#ffffff" : "#6b7280",
|
|
2956
|
+
backgroundColor: fieldState === "owner_allow" ? "#0ea5e9" : "#f3f4f6",
|
|
2957
|
+
borderColor: fieldState === "owner_allow" ? "#0ea5e9" : "#d1d5db",
|
|
2958
|
+
"&:hover": {
|
|
2959
|
+
backgroundColor: fieldState === "owner_allow" ? "#0284c7" : "#e5e7eb",
|
|
2960
|
+
borderColor: fieldState === "owner_allow" ? "#0284c7" : "#9ca3af"
|
|
2961
|
+
},
|
|
2962
|
+
"&.Mui-selected": {
|
|
2963
|
+
backgroundColor: "#0ea5e9",
|
|
2964
|
+
color: "#ffffff",
|
|
2965
|
+
"&:hover": {
|
|
2966
|
+
backgroundColor: "#0284c7"
|
|
2967
|
+
}
|
|
2968
|
+
}
|
|
2969
|
+
},
|
|
2970
|
+
children: t("modules.form.publicPolicies.fields.conditions.states.ownerAllow")
|
|
2971
|
+
}
|
|
2972
|
+
),
|
|
2973
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
|
|
2974
|
+
import_material8.ToggleButton,
|
|
2975
|
+
{
|
|
2976
|
+
value: "deny",
|
|
2977
|
+
onClick: () => setFieldState(fieldName, "deny"),
|
|
2978
|
+
disabled,
|
|
2979
|
+
sx: {
|
|
2980
|
+
px: 2,
|
|
2981
|
+
color: fieldState === "deny" ? "#ffffff" : "#6b7280",
|
|
2982
|
+
backgroundColor: fieldState === "deny" ? "#dc2626" : "#f3f4f6",
|
|
2983
|
+
borderColor: fieldState === "deny" ? "#dc2626" : "#d1d5db",
|
|
2984
|
+
"&:hover": {
|
|
2985
|
+
backgroundColor: fieldState === "deny" ? "#b91c1c" : "#e5e7eb",
|
|
2986
|
+
borderColor: fieldState === "deny" ? "#b91c1c" : "#9ca3af"
|
|
2987
|
+
},
|
|
2988
|
+
"&.Mui-selected": {
|
|
2989
|
+
backgroundColor: "#dc2626",
|
|
2990
|
+
color: "#ffffff",
|
|
2991
|
+
"&:hover": {
|
|
2992
|
+
backgroundColor: "#b91c1c"
|
|
2993
|
+
}
|
|
2994
|
+
}
|
|
2995
|
+
},
|
|
2996
|
+
children: [
|
|
2997
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_icons_material2.Cancel, { sx: { fontSize: 16, mr: 0.5 } }),
|
|
2998
|
+
t("modules.form.publicPolicies.fields.conditions.states.deny")
|
|
2999
|
+
]
|
|
3000
|
+
}
|
|
3001
|
+
)
|
|
3002
|
+
] })
|
|
3003
|
+
] }, fieldName);
|
|
3004
|
+
}) })
|
|
3005
|
+
] }),
|
|
3006
|
+
error && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_material8.FormHelperText, { error: true, sx: { mt: 1 }, children: error })
|
|
3007
|
+
] });
|
|
3008
|
+
};
|
|
3009
|
+
var FieldSelector_default = FieldSelector;
|
|
3010
|
+
|
|
3011
|
+
// src/components/PublicPolicies/constants.ts
|
|
3012
|
+
var POLICY_ACTIONS = ["create", "read", "update", "delete"];
|
|
3013
|
+
var PREFERRED_POLICY_ORDER = [
|
|
3014
|
+
"create",
|
|
3015
|
+
"read",
|
|
3016
|
+
"update",
|
|
3017
|
+
"delete"
|
|
3018
|
+
];
|
|
3019
|
+
|
|
3020
|
+
// src/components/PublicPolicies/PolicyItem/PolicyItem.tsx
|
|
3021
|
+
var import_jsx_runtime13 = require("react/jsx-runtime");
|
|
3022
|
+
var PolicyItem = (0, import_react14.forwardRef)(({
|
|
3023
|
+
policy,
|
|
3024
|
+
onChange,
|
|
3025
|
+
onRemove,
|
|
3026
|
+
availableFields,
|
|
3027
|
+
isSubmitting = false,
|
|
3028
|
+
usedActions,
|
|
3029
|
+
error
|
|
3030
|
+
}, ref) => {
|
|
3031
|
+
const { t } = (0, import_react_i18next2.useTranslation)();
|
|
3032
|
+
const takenActions = new Set(Array.from(usedActions || []));
|
|
3033
|
+
takenActions.delete(policy.action);
|
|
3034
|
+
const actionOptions = POLICY_ACTIONS.map((a) => ({
|
|
3035
|
+
value: a,
|
|
3036
|
+
label: t(`modules.form.publicPolicies.fields.action.options.${a}`)
|
|
3037
|
+
}));
|
|
3038
|
+
return /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(
|
|
3039
|
+
import_material9.Paper,
|
|
3040
|
+
{
|
|
3041
|
+
ref,
|
|
3042
|
+
sx: {
|
|
3043
|
+
p: 3,
|
|
3044
|
+
border: "1px solid #d1d9e0",
|
|
3045
|
+
borderRadius: 2,
|
|
3046
|
+
position: "relative",
|
|
3047
|
+
backgroundColor: "#ffffff"
|
|
3048
|
+
},
|
|
3049
|
+
children: [
|
|
3050
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(import_material9.Box, { sx: { display: "flex", justifyContent: "space-between", alignItems: "flex-start", mb: 3 }, children: [
|
|
3051
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
3052
|
+
import_material9.Typography,
|
|
3053
|
+
{
|
|
3054
|
+
variant: "subtitle1",
|
|
3055
|
+
sx: {
|
|
3056
|
+
fontWeight: 600,
|
|
3057
|
+
color: "#111418",
|
|
3058
|
+
fontSize: "1rem"
|
|
3059
|
+
},
|
|
3060
|
+
children: t("modules.form.publicPolicies.policyTitle")
|
|
3061
|
+
}
|
|
3062
|
+
),
|
|
3063
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
3064
|
+
import_material9.IconButton,
|
|
3065
|
+
{
|
|
3066
|
+
onClick: onRemove,
|
|
3067
|
+
size: "small",
|
|
3068
|
+
disabled: isSubmitting,
|
|
3069
|
+
"aria-label": t("modules.form.publicPolicies.removePolicy"),
|
|
3070
|
+
sx: {
|
|
3071
|
+
color: "#656d76",
|
|
3072
|
+
"&:hover": {
|
|
3073
|
+
color: "#cf222e",
|
|
3074
|
+
backgroundColor: "rgba(207, 34, 46, 0.1)"
|
|
3075
|
+
}
|
|
3076
|
+
},
|
|
3077
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_icons_material3.Delete, {})
|
|
3078
|
+
}
|
|
3079
|
+
)
|
|
3080
|
+
] }),
|
|
3081
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(import_material9.Stack, { spacing: 3, children: [
|
|
3082
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_material9.Stack, { direction: { xs: "column", md: "row" }, spacing: 2, children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_material9.Box, { sx: { flex: 1, minWidth: 200 }, children: /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(import_material9.FormControl, { fullWidth: true, children: [
|
|
3083
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_material9.InputLabel, { children: t("modules.form.publicPolicies.fields.action.label") }),
|
|
3084
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
3085
|
+
import_material9.Select,
|
|
3086
|
+
{
|
|
3087
|
+
value: policy.action,
|
|
3088
|
+
label: t("modules.form.publicPolicies.fields.action.label"),
|
|
3089
|
+
disabled: isSubmitting,
|
|
3090
|
+
onChange: (e) => {
|
|
3091
|
+
const newAction = e.target.value;
|
|
3092
|
+
const next = { ...policy, action: newAction };
|
|
3093
|
+
if (newAction === "delete") {
|
|
3094
|
+
next.permission = "deny";
|
|
3095
|
+
delete next.fields;
|
|
3096
|
+
} else {
|
|
3097
|
+
next.fields = { allow: [], owner_allow: [], deny: availableFields };
|
|
3098
|
+
delete next.permission;
|
|
3099
|
+
}
|
|
3100
|
+
onChange(next);
|
|
3101
|
+
},
|
|
3102
|
+
sx: {
|
|
3103
|
+
backgroundColor: "#ffffff",
|
|
3104
|
+
"&:hover .MuiOutlinedInput-notchedOutline": {
|
|
3105
|
+
borderColor: "#8c959f"
|
|
3106
|
+
},
|
|
3107
|
+
"&.Mui-focused .MuiOutlinedInput-notchedOutline": {
|
|
3108
|
+
borderColor: "#0969da",
|
|
3109
|
+
borderWidth: 2
|
|
3110
|
+
}
|
|
3111
|
+
},
|
|
3112
|
+
children: actionOptions.map((option) => {
|
|
3113
|
+
const disabledOption = takenActions.has(option.value);
|
|
3114
|
+
return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_material9.MenuItem, { value: option.value, disabled: disabledOption, children: option.label }, option.value);
|
|
3115
|
+
})
|
|
3116
|
+
}
|
|
3117
|
+
),
|
|
3118
|
+
error && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_material9.FormHelperText, { error: true, children: error })
|
|
3119
|
+
] }) }) }),
|
|
3120
|
+
policy.action === "delete" ? /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(import_material9.Box, { children: [
|
|
3121
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_material9.Typography, { variant: "body2", color: "text.secondary", sx: { mb: 2 }, children: t("modules.form.publicPolicies.fields.conditions.label") }),
|
|
3122
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(import_material9.Stack, { direction: "row", spacing: 1, sx: { mb: 3 }, children: [
|
|
3123
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
3124
|
+
import_material9.Button,
|
|
3125
|
+
{
|
|
3126
|
+
variant: policy.permission === "*" ? "contained" : "outlined",
|
|
3127
|
+
startIcon: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_icons_material3.SelectAll, {}),
|
|
3128
|
+
onClick: () => onChange({ ...policy, permission: "*" }),
|
|
3129
|
+
disabled: isSubmitting,
|
|
3130
|
+
size: "small",
|
|
3131
|
+
sx: {
|
|
3132
|
+
minWidth: 140,
|
|
3133
|
+
whiteSpace: "nowrap",
|
|
3134
|
+
...policy.permission === "*" && {
|
|
3135
|
+
backgroundColor: "#16a34a",
|
|
3136
|
+
"&:hover": { backgroundColor: "#15803d" }
|
|
3137
|
+
}
|
|
3138
|
+
},
|
|
3139
|
+
children: t("modules.form.publicPolicies.fields.conditions.allFields")
|
|
3140
|
+
}
|
|
3141
|
+
),
|
|
3142
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
3143
|
+
import_material9.Button,
|
|
3144
|
+
{
|
|
3145
|
+
variant: policy.permission === "owner" ? "contained" : "outlined",
|
|
3146
|
+
onClick: () => onChange({ ...policy, permission: "owner" }),
|
|
3147
|
+
disabled: isSubmitting,
|
|
3148
|
+
size: "small",
|
|
3149
|
+
sx: {
|
|
3150
|
+
minWidth: 140,
|
|
3151
|
+
whiteSpace: "nowrap",
|
|
3152
|
+
...policy.permission === "owner" && {
|
|
3153
|
+
backgroundColor: "#0ea5e9",
|
|
3154
|
+
"&:hover": { backgroundColor: "#0284c7" }
|
|
3155
|
+
}
|
|
3156
|
+
},
|
|
3157
|
+
children: t("modules.form.publicPolicies.fields.conditions.states.ownerAllow")
|
|
3158
|
+
}
|
|
3159
|
+
),
|
|
3160
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
3161
|
+
import_material9.Button,
|
|
3162
|
+
{
|
|
3163
|
+
variant: policy.permission === "deny" ? "contained" : "outlined",
|
|
3164
|
+
startIcon: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_icons_material3.ClearAll, {}),
|
|
3165
|
+
onClick: () => onChange({ ...policy, permission: "deny" }),
|
|
3166
|
+
disabled: isSubmitting,
|
|
3167
|
+
size: "small",
|
|
3168
|
+
sx: {
|
|
3169
|
+
minWidth: 140,
|
|
3170
|
+
whiteSpace: "nowrap",
|
|
3171
|
+
...policy.permission === "deny" && {
|
|
3172
|
+
backgroundColor: "#cf222e",
|
|
3173
|
+
"&:hover": { backgroundColor: "#bc1f2c" }
|
|
3174
|
+
}
|
|
3175
|
+
},
|
|
3176
|
+
children: t("modules.form.publicPolicies.fields.conditions.noFields")
|
|
3177
|
+
}
|
|
3178
|
+
)
|
|
3179
|
+
] })
|
|
3180
|
+
] }) : /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
3181
|
+
FieldSelector_default,
|
|
3182
|
+
{
|
|
3183
|
+
value: policy.fields || { allow: [], owner_allow: [], deny: [] },
|
|
3184
|
+
onChange: (nextFields) => onChange({ ...policy, fields: nextFields }),
|
|
3185
|
+
availableFields,
|
|
3186
|
+
disabled: isSubmitting
|
|
3187
|
+
}
|
|
3188
|
+
),
|
|
3189
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_material9.Paper, { variant: "outlined", sx: { p: 2, backgroundColor: "#f9fafb" }, children: policy.action === "delete" ? /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(import_material9.Typography, { variant: "body2", sx: { fontFamily: "monospace", color: "text.secondary" }, children: [
|
|
3190
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(import_material9.Box, { component: "span", sx: {
|
|
3191
|
+
color: policy.permission === "*" ? "#16a34a" : policy.permission === "owner" ? "#0ea5e9" : "#dc2626"
|
|
3192
|
+
}, children: [
|
|
3193
|
+
t("modules.form.publicPolicies.fields.conditions.states.allow"),
|
|
3194
|
+
":"
|
|
3195
|
+
] }),
|
|
3196
|
+
" ",
|
|
3197
|
+
policy.permission || "-"
|
|
3198
|
+
] }) : /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(import_material9.Stack, { spacing: 0.5, divider: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_material9.Divider, { sx: { borderColor: "#e5e7eb" } }), children: [
|
|
3199
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(import_material9.Typography, { variant: "body2", sx: { fontFamily: "monospace", color: "text.secondary" }, children: [
|
|
3200
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(import_material9.Box, { component: "span", sx: { color: "#16a34a" }, children: [
|
|
3201
|
+
t("modules.form.publicPolicies.fields.conditions.states.allow"),
|
|
3202
|
+
":"
|
|
3203
|
+
] }),
|
|
3204
|
+
" ",
|
|
3205
|
+
(policy?.fields?.allow || []).join(", ") || "-"
|
|
3206
|
+
] }),
|
|
3207
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(import_material9.Typography, { variant: "body2", sx: { fontFamily: "monospace", color: "text.secondary" }, children: [
|
|
3208
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(import_material9.Box, { component: "span", sx: { color: "#0ea5e9" }, children: [
|
|
3209
|
+
t("modules.form.publicPolicies.fields.conditions.states.ownerAllow"),
|
|
3210
|
+
":"
|
|
3211
|
+
] }),
|
|
3212
|
+
" ",
|
|
3213
|
+
(policy?.fields?.owner_allow || []).join(", ") || "-"
|
|
3214
|
+
] }),
|
|
3215
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(import_material9.Typography, { variant: "body2", sx: { fontFamily: "monospace", color: "text.secondary" }, children: [
|
|
3216
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(import_material9.Box, { component: "span", sx: { color: "#dc2626" }, children: [
|
|
3217
|
+
t("modules.form.publicPolicies.fields.conditions.states.deny"),
|
|
3218
|
+
":"
|
|
3219
|
+
] }),
|
|
3220
|
+
" ",
|
|
3221
|
+
(policy?.fields?.deny || []).join(", ") || "-"
|
|
3222
|
+
] })
|
|
3223
|
+
] }) })
|
|
3224
|
+
] })
|
|
3225
|
+
]
|
|
3182
3226
|
}
|
|
3183
|
-
|
|
3184
|
-
|
|
3185
|
-
|
|
3186
|
-
}, []);
|
|
3187
|
-
const getTokenInfo = (0, import_react15.useCallback)(() => {
|
|
3188
|
-
return sessionManager.getTokenInfo();
|
|
3189
|
-
}, [sessionManager]);
|
|
3190
|
-
(0, import_react15.useEffect)(() => {
|
|
3191
|
-
initialize();
|
|
3192
|
-
}, [initialize]);
|
|
3193
|
-
return {
|
|
3194
|
-
// Estado
|
|
3195
|
-
...state,
|
|
3196
|
-
// Acciones
|
|
3197
|
-
login,
|
|
3198
|
-
logout,
|
|
3199
|
-
refreshTokens,
|
|
3200
|
-
clearError,
|
|
3201
|
-
getTokenInfo,
|
|
3202
|
-
// Utilidades
|
|
3203
|
-
isExpiringSoon: state.tokens ? state.tokens.expiresAt - Date.now() < 5 * 60 * 1e3 : false,
|
|
3204
|
-
// 5 minutos
|
|
3205
|
-
expiresIn: state.tokens ? Math.max(0, state.tokens.expiresAt - Date.now()) : 0,
|
|
3206
|
-
refreshExpiresIn: state.tokens ? Math.max(0, state.tokens.refreshExpiresAt - Date.now()) : 0
|
|
3207
|
-
};
|
|
3208
|
-
}
|
|
3227
|
+
);
|
|
3228
|
+
});
|
|
3229
|
+
var PolicyItem_default = PolicyItem;
|
|
3209
3230
|
|
|
3210
|
-
// src/
|
|
3211
|
-
var import_react16 = require("react");
|
|
3231
|
+
// src/components/PublicPolicies/Policies.tsx
|
|
3212
3232
|
var import_jsx_runtime14 = require("react/jsx-runtime");
|
|
3213
|
-
var
|
|
3214
|
-
|
|
3215
|
-
|
|
3216
|
-
|
|
3217
|
-
|
|
3218
|
-
|
|
3233
|
+
var generateId = () => {
|
|
3234
|
+
const c = globalThis?.crypto;
|
|
3235
|
+
if (c && typeof c.randomUUID === "function") return c.randomUUID();
|
|
3236
|
+
return `${Date.now()}-${Math.random().toString(16).slice(2)}`;
|
|
3237
|
+
};
|
|
3238
|
+
var Policies = ({
|
|
3239
|
+
policies,
|
|
3240
|
+
onChange,
|
|
3241
|
+
availableFields,
|
|
3242
|
+
errors,
|
|
3243
|
+
isSubmitting = false
|
|
3244
|
+
}) => {
|
|
3245
|
+
const { t } = (0, import_react_i18next3.useTranslation)();
|
|
3246
|
+
const policyRefs = (0, import_react15.useRef)({});
|
|
3247
|
+
const takenActions = new Set((policies || []).map((p) => p.action).filter(Boolean));
|
|
3248
|
+
const remainingActions = PREFERRED_POLICY_ORDER.filter((a) => !takenActions.has(a));
|
|
3249
|
+
const canAddPolicy = remainingActions.length > 0;
|
|
3250
|
+
const addPolicy = () => {
|
|
3251
|
+
const defaultAction = remainingActions[0] || "create";
|
|
3252
|
+
const newPolicy = {
|
|
3253
|
+
id: generateId(),
|
|
3254
|
+
action: defaultAction
|
|
3255
|
+
};
|
|
3256
|
+
if (defaultAction === "delete") {
|
|
3257
|
+
newPolicy.permission = "deny";
|
|
3258
|
+
} else {
|
|
3259
|
+
newPolicy.fields = {
|
|
3260
|
+
allow: [],
|
|
3261
|
+
owner_allow: [],
|
|
3262
|
+
deny: availableFields
|
|
3263
|
+
};
|
|
3219
3264
|
}
|
|
3220
|
-
|
|
3221
|
-
|
|
3222
|
-
|
|
3223
|
-
|
|
3224
|
-
|
|
3225
|
-
|
|
3226
|
-
|
|
3227
|
-
};
|
|
3228
|
-
Object.keys(decoded).forEach((key) => {
|
|
3229
|
-
if (!["sub", "email", "subscriber"].includes(key)) {
|
|
3230
|
-
result[key] = decoded[key];
|
|
3231
|
-
}
|
|
3232
|
-
});
|
|
3233
|
-
return result;
|
|
3265
|
+
const next = [...policies || [], newPolicy];
|
|
3266
|
+
onChange(next);
|
|
3267
|
+
setTimeout(() => {
|
|
3268
|
+
const newIndex = next.length - 1;
|
|
3269
|
+
const el = policyRefs.current[newIndex];
|
|
3270
|
+
if (el) {
|
|
3271
|
+
el.scrollIntoView({ behavior: "smooth", block: "center" });
|
|
3234
3272
|
}
|
|
3235
|
-
}
|
|
3236
|
-
console.error("Error decoding JWT token for sessionData:", error);
|
|
3237
|
-
}
|
|
3238
|
-
return null;
|
|
3239
|
-
}, [sessionHook.tokens?.accessToken, sessionHook.isAuthenticated]);
|
|
3240
|
-
const contextValue = {
|
|
3241
|
-
...sessionHook,
|
|
3242
|
-
sessionData
|
|
3273
|
+
}, 100);
|
|
3243
3274
|
};
|
|
3244
|
-
|
|
3245
|
-
|
|
3246
|
-
|
|
3247
|
-
|
|
3248
|
-
|
|
3249
|
-
|
|
3250
|
-
|
|
3251
|
-
|
|
3252
|
-
|
|
3253
|
-
|
|
3254
|
-
|
|
3255
|
-
|
|
3256
|
-
|
|
3257
|
-
|
|
3258
|
-
|
|
3259
|
-
|
|
3260
|
-
|
|
3261
|
-
|
|
3262
|
-
|
|
3263
|
-
|
|
3264
|
-
|
|
3265
|
-
|
|
3266
|
-
|
|
3267
|
-
|
|
3268
|
-
|
|
3269
|
-
|
|
3270
|
-
}
|
|
3271
|
-
|
|
3272
|
-
|
|
3273
|
-
|
|
3274
|
-
|
|
3275
|
-
|
|
3276
|
-
|
|
3277
|
-
|
|
3278
|
-
|
|
3279
|
-
|
|
3280
|
-
|
|
3281
|
-
|
|
3282
|
-
|
|
3283
|
-
|
|
3284
|
-
|
|
3285
|
-
|
|
3286
|
-
|
|
3287
|
-
|
|
3288
|
-
|
|
3289
|
-
|
|
3290
|
-
|
|
3291
|
-
|
|
3292
|
-
|
|
3293
|
-
|
|
3294
|
-
|
|
3295
|
-
|
|
3296
|
-
|
|
3297
|
-
|
|
3298
|
-
|
|
3299
|
-
|
|
3300
|
-
|
|
3301
|
-
|
|
3302
|
-
|
|
3303
|
-
|
|
3304
|
-
|
|
3305
|
-
|
|
3306
|
-
|
|
3307
|
-
|
|
3308
|
-
|
|
3309
|
-
|
|
3310
|
-
|
|
3311
|
-
|
|
3312
|
-
|
|
3313
|
-
|
|
3314
|
-
|
|
3315
|
-
|
|
3316
|
-
|
|
3317
|
-
|
|
3318
|
-
|
|
3319
|
-
|
|
3320
|
-
|
|
3321
|
-
|
|
3322
|
-
|
|
3323
|
-
" hours"
|
|
3324
|
-
] }),
|
|
3325
|
-
/* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { children: [
|
|
3326
|
-
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)("strong", { children: "Expiring Soon:" }),
|
|
3327
|
-
" ",
|
|
3328
|
-
session.isExpiringSoon ? "Yes" : "No"
|
|
3275
|
+
const removePolicy = (index) => {
|
|
3276
|
+
const next = [...policies];
|
|
3277
|
+
next.splice(index, 1);
|
|
3278
|
+
onChange(next);
|
|
3279
|
+
};
|
|
3280
|
+
const arrayError = (() => {
|
|
3281
|
+
if (!errors) return null;
|
|
3282
|
+
if (typeof errors === "string") return errors;
|
|
3283
|
+
const msg = errors._error;
|
|
3284
|
+
return typeof msg === "string" ? msg : null;
|
|
3285
|
+
})();
|
|
3286
|
+
const usedActions = new Set((policies || []).map((p) => p.action));
|
|
3287
|
+
return /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(import_jsx_runtime14.Fragment, { children: [
|
|
3288
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_material10.Divider, { sx: { borderColor: "#e0e4e7" } }),
|
|
3289
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(import_material10.Box, { children: [
|
|
3290
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_material10.Box, { display: "flex", justifyContent: "space-between", alignItems: "center", mb: 3, children: /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(import_material10.Box, { children: [
|
|
3291
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
|
|
3292
|
+
import_material10.Typography,
|
|
3293
|
+
{
|
|
3294
|
+
variant: "h6",
|
|
3295
|
+
sx: {
|
|
3296
|
+
fontWeight: 600,
|
|
3297
|
+
color: "#111418",
|
|
3298
|
+
mb: 1
|
|
3299
|
+
},
|
|
3300
|
+
children: t("modules.form.publicPolicies.title")
|
|
3301
|
+
}
|
|
3302
|
+
),
|
|
3303
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
|
|
3304
|
+
import_material10.Typography,
|
|
3305
|
+
{
|
|
3306
|
+
variant: "body2",
|
|
3307
|
+
color: "text.secondary",
|
|
3308
|
+
sx: { fontSize: "0.875rem" },
|
|
3309
|
+
children: t("modules.form.publicPolicies.description")
|
|
3310
|
+
}
|
|
3311
|
+
)
|
|
3312
|
+
] }) }),
|
|
3313
|
+
arrayError && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_material10.Alert, { severity: "error", sx: { mb: 3 }, children: arrayError }),
|
|
3314
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(import_material10.Stack, { spacing: 3, children: [
|
|
3315
|
+
(policies || []).length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_material10.Alert, { severity: "info", children: t("modules.form.publicPolicies.noPolicies") }) : policies.map((policy, index) => /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
|
|
3316
|
+
PolicyItem_default,
|
|
3317
|
+
{
|
|
3318
|
+
ref: (el) => {
|
|
3319
|
+
policyRefs.current[index] = el;
|
|
3320
|
+
},
|
|
3321
|
+
policy,
|
|
3322
|
+
onChange: (nextPolicy) => {
|
|
3323
|
+
const next = [...policies];
|
|
3324
|
+
next[index] = nextPolicy;
|
|
3325
|
+
onChange(next);
|
|
3326
|
+
},
|
|
3327
|
+
onRemove: () => removePolicy(index),
|
|
3328
|
+
availableFields,
|
|
3329
|
+
isSubmitting,
|
|
3330
|
+
usedActions,
|
|
3331
|
+
error: typeof errors === "object" && errors && policy.id in errors ? errors[policy.id] : void 0
|
|
3332
|
+
},
|
|
3333
|
+
policy.id
|
|
3334
|
+
)),
|
|
3335
|
+
canAddPolicy && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_material10.Box, { children: /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
|
|
3336
|
+
import_material10.Button,
|
|
3337
|
+
{
|
|
3338
|
+
type: "button",
|
|
3339
|
+
variant: "outlined",
|
|
3340
|
+
startIcon: /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_icons_material4.Add, {}),
|
|
3341
|
+
onClick: addPolicy,
|
|
3342
|
+
disabled: isSubmitting,
|
|
3343
|
+
sx: {
|
|
3344
|
+
borderColor: "#d0d7de",
|
|
3345
|
+
color: "#656d76",
|
|
3346
|
+
"&:hover": {
|
|
3347
|
+
borderColor: "#8c959f",
|
|
3348
|
+
backgroundColor: "transparent"
|
|
3349
|
+
}
|
|
3350
|
+
},
|
|
3351
|
+
children: t("modules.form.publicPolicies.addPolicy")
|
|
3352
|
+
}
|
|
3353
|
+
) })
|
|
3329
3354
|
] })
|
|
3330
3355
|
] })
|
|
3331
3356
|
] });
|
|
3332
|
-
}
|
|
3357
|
+
};
|
|
3358
|
+
var Policies_default = Policies;
|
|
3333
3359
|
|
|
3334
3360
|
// src/components/LoginComponent.tsx
|
|
3335
|
-
var
|
|
3361
|
+
var import_react16 = require("react");
|
|
3336
3362
|
var import_material11 = require("@mui/material");
|
|
3337
3363
|
var import_jsx_runtime15 = require("react/jsx-runtime");
|
|
3338
3364
|
function LoginComponent() {
|
|
3339
|
-
const [email, setEmail] = (0,
|
|
3340
|
-
const [password, setPassword] = (0,
|
|
3341
|
-
const [showForm, setShowForm] = (0,
|
|
3365
|
+
const [email, setEmail] = (0, import_react16.useState)("");
|
|
3366
|
+
const [password, setPassword] = (0, import_react16.useState)("");
|
|
3367
|
+
const [showForm, setShowForm] = (0, import_react16.useState)(false);
|
|
3342
3368
|
const {
|
|
3343
3369
|
isAuthenticated,
|
|
3344
3370
|
isLoading,
|
|
@@ -3485,29 +3511,29 @@ function SessionStatus() {
|
|
|
3485
3511
|
}
|
|
3486
3512
|
|
|
3487
3513
|
// src/hooks/useUserData.ts
|
|
3488
|
-
var
|
|
3489
|
-
var
|
|
3514
|
+
var import_react17 = require("react");
|
|
3515
|
+
var import_crudify_browser4 = __toESM(require("@nocios/crudify-browser"));
|
|
3490
3516
|
var useUserData = (options = {}) => {
|
|
3491
3517
|
const { autoFetch = true, retryOnError = false, maxRetries = 3 } = options;
|
|
3492
3518
|
const { isAuthenticated, isInitialized, sessionData, tokens } = useSessionContext();
|
|
3493
|
-
const [userData, setUserData] = (0,
|
|
3494
|
-
const [loading, setLoading] = (0,
|
|
3495
|
-
const [error, setError] = (0,
|
|
3496
|
-
const abortControllerRef = (0,
|
|
3497
|
-
const mountedRef = (0,
|
|
3498
|
-
const requestIdRef = (0,
|
|
3499
|
-
const retryCountRef = (0,
|
|
3500
|
-
const getUserEmail = (0,
|
|
3519
|
+
const [userData, setUserData] = (0, import_react17.useState)(null);
|
|
3520
|
+
const [loading, setLoading] = (0, import_react17.useState)(false);
|
|
3521
|
+
const [error, setError] = (0, import_react17.useState)(null);
|
|
3522
|
+
const abortControllerRef = (0, import_react17.useRef)(null);
|
|
3523
|
+
const mountedRef = (0, import_react17.useRef)(true);
|
|
3524
|
+
const requestIdRef = (0, import_react17.useRef)(0);
|
|
3525
|
+
const retryCountRef = (0, import_react17.useRef)(0);
|
|
3526
|
+
const getUserEmail = (0, import_react17.useCallback)(() => {
|
|
3501
3527
|
if (!sessionData) return null;
|
|
3502
3528
|
return sessionData.email || sessionData["cognito:username"] || null;
|
|
3503
3529
|
}, [sessionData]);
|
|
3504
|
-
const clearProfile = (0,
|
|
3530
|
+
const clearProfile = (0, import_react17.useCallback)(() => {
|
|
3505
3531
|
setUserData(null);
|
|
3506
3532
|
setError(null);
|
|
3507
3533
|
setLoading(false);
|
|
3508
3534
|
retryCountRef.current = 0;
|
|
3509
3535
|
}, []);
|
|
3510
|
-
const refreshProfile = (0,
|
|
3536
|
+
const refreshProfile = (0, import_react17.useCallback)(async () => {
|
|
3511
3537
|
const userEmail = getUserEmail();
|
|
3512
3538
|
console.log("\u{1F464} useUserData - Refreshing profile for:", userEmail);
|
|
3513
3539
|
if (!userEmail) {
|
|
@@ -3536,7 +3562,7 @@ var useUserData = (options = {}) => {
|
|
|
3536
3562
|
setError(null);
|
|
3537
3563
|
}
|
|
3538
3564
|
console.log("\u{1F464} useUserData - Fetching profile data from database");
|
|
3539
|
-
const response = await
|
|
3565
|
+
const response = await import_crudify_browser4.default.readItems("users", {
|
|
3540
3566
|
filter: { email: userEmail },
|
|
3541
3567
|
pagination: { limit: 1 }
|
|
3542
3568
|
});
|
|
@@ -3639,14 +3665,14 @@ var useUserData = (options = {}) => {
|
|
|
3639
3665
|
}
|
|
3640
3666
|
}
|
|
3641
3667
|
}, [isInitialized, getUserEmail, retryOnError, maxRetries]);
|
|
3642
|
-
(0,
|
|
3668
|
+
(0, import_react17.useEffect)(() => {
|
|
3643
3669
|
if (autoFetch && isAuthenticated && isInitialized) {
|
|
3644
3670
|
refreshProfile();
|
|
3645
3671
|
} else if (!isAuthenticated) {
|
|
3646
3672
|
clearProfile();
|
|
3647
3673
|
}
|
|
3648
3674
|
}, [autoFetch, isAuthenticated, isInitialized, refreshProfile, clearProfile]);
|
|
3649
|
-
(0,
|
|
3675
|
+
(0, import_react17.useEffect)(() => {
|
|
3650
3676
|
mountedRef.current = true;
|
|
3651
3677
|
return () => {
|
|
3652
3678
|
mountedRef.current = false;
|
|
@@ -3672,7 +3698,7 @@ var useUserData = (options = {}) => {
|
|
|
3672
3698
|
};
|
|
3673
3699
|
|
|
3674
3700
|
// src/hooks/useAuth.ts
|
|
3675
|
-
var
|
|
3701
|
+
var import_react18 = require("react");
|
|
3676
3702
|
var useAuth = () => {
|
|
3677
3703
|
const {
|
|
3678
3704
|
isAuthenticated,
|
|
@@ -3690,7 +3716,7 @@ var useAuth = () => {
|
|
|
3690
3716
|
expiresIn,
|
|
3691
3717
|
refreshExpiresIn
|
|
3692
3718
|
} = useSessionContext();
|
|
3693
|
-
const setToken = (0,
|
|
3719
|
+
const setToken = (0, import_react18.useCallback)((token) => {
|
|
3694
3720
|
if (token) {
|
|
3695
3721
|
console.warn("useAuth.setToken() is deprecated. Use login() method instead for better security.");
|
|
3696
3722
|
} else {
|
|
@@ -3725,8 +3751,8 @@ var useAuth = () => {
|
|
|
3725
3751
|
};
|
|
3726
3752
|
|
|
3727
3753
|
// src/hooks/useData.ts
|
|
3728
|
-
var
|
|
3729
|
-
var
|
|
3754
|
+
var import_react19 = require("react");
|
|
3755
|
+
var import_crudify_browser5 = __toESM(require("@nocios/crudify-browser"));
|
|
3730
3756
|
var useData = () => {
|
|
3731
3757
|
const {
|
|
3732
3758
|
isInitialized,
|
|
@@ -3735,10 +3761,10 @@ var useData = () => {
|
|
|
3735
3761
|
isAuthenticated,
|
|
3736
3762
|
login: sessionLogin
|
|
3737
3763
|
} = useSessionContext();
|
|
3738
|
-
const isReady = (0,
|
|
3764
|
+
const isReady = (0, import_react19.useCallback)(() => {
|
|
3739
3765
|
return isInitialized && !isLoading && !error;
|
|
3740
3766
|
}, [isInitialized, isLoading, error]);
|
|
3741
|
-
const waitForReady = (0,
|
|
3767
|
+
const waitForReady = (0, import_react19.useCallback)(async () => {
|
|
3742
3768
|
return new Promise((resolve, reject) => {
|
|
3743
3769
|
const checkReady = () => {
|
|
3744
3770
|
if (isReady()) {
|
|
@@ -3752,36 +3778,36 @@ var useData = () => {
|
|
|
3752
3778
|
checkReady();
|
|
3753
3779
|
});
|
|
3754
3780
|
}, [isReady, error]);
|
|
3755
|
-
const ensureReady = (0,
|
|
3781
|
+
const ensureReady = (0, import_react19.useCallback)(async () => {
|
|
3756
3782
|
if (!isReady()) {
|
|
3757
3783
|
throw new Error("System not ready. Check isInitialized, isLoading, and error states.");
|
|
3758
3784
|
}
|
|
3759
3785
|
}, [isReady]);
|
|
3760
|
-
const readItems = (0,
|
|
3786
|
+
const readItems = (0, import_react19.useCallback)(async (moduleKey, filter, options) => {
|
|
3761
3787
|
await ensureReady();
|
|
3762
|
-
return await
|
|
3788
|
+
return await import_crudify_browser5.default.readItems(moduleKey, filter || {}, options);
|
|
3763
3789
|
}, [ensureReady]);
|
|
3764
|
-
const readItem = (0,
|
|
3790
|
+
const readItem = (0, import_react19.useCallback)(async (moduleKey, filter, options) => {
|
|
3765
3791
|
await ensureReady();
|
|
3766
|
-
return await
|
|
3792
|
+
return await import_crudify_browser5.default.readItem(moduleKey, filter, options);
|
|
3767
3793
|
}, [ensureReady]);
|
|
3768
|
-
const createItem = (0,
|
|
3794
|
+
const createItem = (0, import_react19.useCallback)(async (moduleKey, data, options) => {
|
|
3769
3795
|
await ensureReady();
|
|
3770
|
-
return await
|
|
3796
|
+
return await import_crudify_browser5.default.createItem(moduleKey, data, options);
|
|
3771
3797
|
}, [ensureReady]);
|
|
3772
|
-
const updateItem = (0,
|
|
3798
|
+
const updateItem = (0, import_react19.useCallback)(async (moduleKey, data, options) => {
|
|
3773
3799
|
await ensureReady();
|
|
3774
|
-
return await
|
|
3800
|
+
return await import_crudify_browser5.default.updateItem(moduleKey, data, options);
|
|
3775
3801
|
}, [ensureReady]);
|
|
3776
|
-
const deleteItem = (0,
|
|
3802
|
+
const deleteItem = (0, import_react19.useCallback)(async (moduleKey, id, options) => {
|
|
3777
3803
|
await ensureReady();
|
|
3778
|
-
return await
|
|
3804
|
+
return await import_crudify_browser5.default.deleteItem(moduleKey, id, options);
|
|
3779
3805
|
}, [ensureReady]);
|
|
3780
|
-
const transaction = (0,
|
|
3806
|
+
const transaction = (0, import_react19.useCallback)(async (operations, options) => {
|
|
3781
3807
|
await ensureReady();
|
|
3782
|
-
return await
|
|
3808
|
+
return await import_crudify_browser5.default.transaction(operations, options);
|
|
3783
3809
|
}, [ensureReady]);
|
|
3784
|
-
const login = (0,
|
|
3810
|
+
const login = (0, import_react19.useCallback)(async (email, password) => {
|
|
3785
3811
|
try {
|
|
3786
3812
|
const result = await sessionLogin(email, password);
|
|
3787
3813
|
if (result.success) {
|