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