@nocios/crudify-ui 3.0.56 → 3.0.60

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.mts CHANGED
@@ -751,11 +751,13 @@ interface Notification {
751
751
  severity: NotificationSeverity;
752
752
  autoHideDuration?: number;
753
753
  persistent?: boolean;
754
+ allowHtml?: boolean;
754
755
  }
755
756
  interface GlobalNotificationContextValue {
756
757
  showNotification: (message: string, severity?: NotificationSeverity, options?: {
757
758
  autoHideDuration?: number;
758
759
  persistent?: boolean;
760
+ allowHtml?: boolean;
759
761
  }) => string;
760
762
  hideNotification: (id: string) => void;
761
763
  clearAllNotifications: () => void;
package/dist/index.d.ts CHANGED
@@ -751,11 +751,13 @@ interface Notification {
751
751
  severity: NotificationSeverity;
752
752
  autoHideDuration?: number;
753
753
  persistent?: boolean;
754
+ allowHtml?: boolean;
754
755
  }
755
756
  interface GlobalNotificationContextValue {
756
757
  showNotification: (message: string, severity?: NotificationSeverity, options?: {
757
758
  autoHideDuration?: number;
758
759
  persistent?: boolean;
760
+ allowHtml?: boolean;
759
761
  }) => string;
760
762
  hideNotification: (id: string) => void;
761
763
  clearAllNotifications: () => void;
package/dist/index.js CHANGED
@@ -1401,8 +1401,24 @@ var isTokenExpired = (token) => {
1401
1401
  var import_react6 = require("react");
1402
1402
  var import_material = require("@mui/material");
1403
1403
  var import_uuid = require("uuid");
1404
+ var import_dompurify = __toESM(require("dompurify"));
1404
1405
  var import_jsx_runtime4 = require("react/jsx-runtime");
1405
1406
  var GlobalNotificationContext = (0, import_react6.createContext)(null);
1407
+ var sanitizeNotificationContent = (html) => {
1408
+ return import_dompurify.default.sanitize(html, {
1409
+ // Solo permitir tags seguros para notificaciones
1410
+ ALLOWED_TAGS: ["b", "i", "em", "strong", "br", "span"],
1411
+ ALLOWED_ATTR: ["class"],
1412
+ // Remover scripts y eventos
1413
+ FORBID_TAGS: ["script", "iframe", "object", "embed"],
1414
+ FORBID_ATTR: ["onload", "onerror", "onclick", "onmouseover", "onfocus", "onblur"],
1415
+ // Configuración adicional de seguridad
1416
+ WHOLE_DOCUMENT: false,
1417
+ RETURN_DOM: false,
1418
+ RETURN_DOM_FRAGMENT: false,
1419
+ RETURN_TRUSTED_TYPE: false
1420
+ });
1421
+ };
1406
1422
  var GlobalNotificationProvider = ({
1407
1423
  children,
1408
1424
  maxNotifications = 5,
@@ -1417,13 +1433,23 @@ var GlobalNotificationProvider = ({
1417
1433
  if (!enabled) {
1418
1434
  return "";
1419
1435
  }
1436
+ if (!message || typeof message !== "string") {
1437
+ console.warn("\u26A0\uFE0F GlobalNotificationProvider: Invalid message provided");
1438
+ return "";
1439
+ }
1440
+ if (message.length > 1e3) {
1441
+ console.warn("\u26A0\uFE0F GlobalNotificationProvider: Message too long, truncating");
1442
+ message = message.substring(0, 1e3) + "...";
1443
+ }
1420
1444
  const id = (0, import_uuid.v4)();
1421
1445
  const newNotification = {
1422
1446
  id,
1423
1447
  message,
1424
1448
  severity,
1425
1449
  autoHideDuration: options?.autoHideDuration ?? defaultAutoHideDuration,
1426
- persistent: options?.persistent ?? false
1450
+ persistent: options?.persistent ?? false,
1451
+ allowHtml: options?.allowHtml ?? false
1452
+ // Por defecto NO permitir HTML
1427
1453
  };
1428
1454
  setNotifications((prev) => {
1429
1455
  const updatedNotifications = prev.length >= maxNotifications ? prev.slice(-(maxNotifications - 1)) : prev;
@@ -1513,7 +1539,7 @@ var NotificationItem = ({ notification, onClose }) => {
1513
1539
  maxWidth: "400px",
1514
1540
  wordBreak: "break-word"
1515
1541
  },
1516
- children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { dangerouslySetInnerHTML: { __html: notification.message } })
1542
+ children: notification.allowHtml ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { dangerouslySetInnerHTML: { __html: sanitizeNotificationContent(notification.message) } }) : /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { children: notification.message })
1517
1543
  }
1518
1544
  )
1519
1545
  }
@@ -2844,6 +2870,7 @@ var CrudifyLoginInternal = ({
2844
2870
  const { t } = useTranslation();
2845
2871
  const { state, setScreen } = useLoginState();
2846
2872
  const { config } = useSessionContext();
2873
+ const { showNotification } = useGlobalNotification();
2847
2874
  const handleScreenChange = (screen2, params) => {
2848
2875
  let finalParams = params;
2849
2876
  if (screen2 === "login") {
@@ -2873,6 +2900,8 @@ var CrudifyLoginInternal = ({
2873
2900
  ...commonProps,
2874
2901
  searchParams: state.searchParams,
2875
2902
  onResetSuccess: () => {
2903
+ const message = t("resetPassword.successMessage");
2904
+ showNotification(message, "success");
2876
2905
  handleScreenChange("login");
2877
2906
  }
2878
2907
  }
@@ -4775,10 +4804,7 @@ var useCrudifyWithNotifications = (options = {}) => {
4775
4804
  moduleKey = actionConfig.moduleKey;
4776
4805
  }
4777
4806
  }
4778
- if (operation === "validateAndResetPassword") {
4779
- const message = getSafeTranslation("resetPassword.successMessage", "Contrase\xF1a restablecida exitosamente");
4780
- showNotification(message, "success", { autoHideDuration });
4781
- } else if (shouldShowSuccessNotification(operation, moduleKey)) {
4807
+ if (shouldShowSuccessNotification(operation, moduleKey)) {
4782
4808
  const message = getSuccessMessage(operation, moduleKey, actionConfig);
4783
4809
  showNotification(message, "success", { autoHideDuration });
4784
4810
  }
package/dist/index.mjs CHANGED
@@ -1328,8 +1328,24 @@ var isTokenExpired = (token) => {
1328
1328
  import { useState as useState4, createContext as createContext4, useContext as useContext4, useCallback as useCallback2, useEffect as useEffect5 } from "react";
1329
1329
  import { Snackbar, Alert, Box, Portal } from "@mui/material";
1330
1330
  import { v4 as uuidv4 } from "uuid";
1331
+ import DOMPurify from "dompurify";
1331
1332
  import { jsx as jsx4, jsxs } from "react/jsx-runtime";
1332
1333
  var GlobalNotificationContext = createContext4(null);
1334
+ var sanitizeNotificationContent = (html) => {
1335
+ return DOMPurify.sanitize(html, {
1336
+ // Solo permitir tags seguros para notificaciones
1337
+ ALLOWED_TAGS: ["b", "i", "em", "strong", "br", "span"],
1338
+ ALLOWED_ATTR: ["class"],
1339
+ // Remover scripts y eventos
1340
+ FORBID_TAGS: ["script", "iframe", "object", "embed"],
1341
+ FORBID_ATTR: ["onload", "onerror", "onclick", "onmouseover", "onfocus", "onblur"],
1342
+ // Configuración adicional de seguridad
1343
+ WHOLE_DOCUMENT: false,
1344
+ RETURN_DOM: false,
1345
+ RETURN_DOM_FRAGMENT: false,
1346
+ RETURN_TRUSTED_TYPE: false
1347
+ });
1348
+ };
1333
1349
  var GlobalNotificationProvider = ({
1334
1350
  children,
1335
1351
  maxNotifications = 5,
@@ -1344,13 +1360,23 @@ var GlobalNotificationProvider = ({
1344
1360
  if (!enabled) {
1345
1361
  return "";
1346
1362
  }
1363
+ if (!message || typeof message !== "string") {
1364
+ console.warn("\u26A0\uFE0F GlobalNotificationProvider: Invalid message provided");
1365
+ return "";
1366
+ }
1367
+ if (message.length > 1e3) {
1368
+ console.warn("\u26A0\uFE0F GlobalNotificationProvider: Message too long, truncating");
1369
+ message = message.substring(0, 1e3) + "...";
1370
+ }
1347
1371
  const id = uuidv4();
1348
1372
  const newNotification = {
1349
1373
  id,
1350
1374
  message,
1351
1375
  severity,
1352
1376
  autoHideDuration: options?.autoHideDuration ?? defaultAutoHideDuration,
1353
- persistent: options?.persistent ?? false
1377
+ persistent: options?.persistent ?? false,
1378
+ allowHtml: options?.allowHtml ?? false
1379
+ // Por defecto NO permitir HTML
1354
1380
  };
1355
1381
  setNotifications((prev) => {
1356
1382
  const updatedNotifications = prev.length >= maxNotifications ? prev.slice(-(maxNotifications - 1)) : prev;
@@ -1440,7 +1466,7 @@ var NotificationItem = ({ notification, onClose }) => {
1440
1466
  maxWidth: "400px",
1441
1467
  wordBreak: "break-word"
1442
1468
  },
1443
- children: /* @__PURE__ */ jsx4("span", { dangerouslySetInnerHTML: { __html: notification.message } })
1469
+ children: notification.allowHtml ? /* @__PURE__ */ jsx4("span", { dangerouslySetInnerHTML: { __html: sanitizeNotificationContent(notification.message) } }) : /* @__PURE__ */ jsx4("span", { children: notification.message })
1444
1470
  }
1445
1471
  )
1446
1472
  }
@@ -2771,6 +2797,7 @@ var CrudifyLoginInternal = ({
2771
2797
  const { t } = useTranslation();
2772
2798
  const { state, setScreen } = useLoginState();
2773
2799
  const { config } = useSessionContext();
2800
+ const { showNotification } = useGlobalNotification();
2774
2801
  const handleScreenChange = (screen2, params) => {
2775
2802
  let finalParams = params;
2776
2803
  if (screen2 === "login") {
@@ -2800,6 +2827,8 @@ var CrudifyLoginInternal = ({
2800
2827
  ...commonProps,
2801
2828
  searchParams: state.searchParams,
2802
2829
  onResetSuccess: () => {
2830
+ const message = t("resetPassword.successMessage");
2831
+ showNotification(message, "success");
2803
2832
  handleScreenChange("login");
2804
2833
  }
2805
2834
  }
@@ -4761,10 +4790,7 @@ var useCrudifyWithNotifications = (options = {}) => {
4761
4790
  moduleKey = actionConfig.moduleKey;
4762
4791
  }
4763
4792
  }
4764
- if (operation === "validateAndResetPassword") {
4765
- const message = getSafeTranslation("resetPassword.successMessage", "Contrase\xF1a restablecida exitosamente");
4766
- showNotification(message, "success", { autoHideDuration });
4767
- } else if (shouldShowSuccessNotification(operation, moduleKey)) {
4793
+ if (shouldShowSuccessNotification(operation, moduleKey)) {
4768
4794
  const message = getSuccessMessage(operation, moduleKey, actionConfig);
4769
4795
  showNotification(message, "success", { autoHideDuration });
4770
4796
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nocios/crudify-ui",
3
- "version": "3.0.56",
3
+ "version": "3.0.60",
4
4
  "description": "Biblioteca de componentes UI para Crudify",
5
5
  "author": "Nocios",
6
6
  "license": "MIT",
@@ -26,8 +26,10 @@
26
26
  "@mui/material": "^7.1.0",
27
27
  "@mui/x-data-grid": "^8.5.1",
28
28
  "@nocios/crudify-browser": "^2.0.6",
29
+ "@types/dompurify": "^3.0.5",
29
30
  "@types/uuid": "^10.0.0",
30
31
  "crypto-js": "^4.2.0",
32
+ "dompurify": "^3.2.7",
31
33
  "i18next-browser-languagedetector": "^8.1.0",
32
34
  "i18next-http-backend": "^3.0.2",
33
35
  "react": "^19.1.0",