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