strapi-identity 0.1.0 → 0.1.2

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.
Files changed (123) hide show
  1. package/dist/admin/AdminReset-C0QibZXW.js +112 -0
  2. package/dist/admin/AdminReset-H453s-DE.mjs +112 -0
  3. package/dist/admin/ProfileToggle-BFmIWCrN.js +336 -0
  4. package/dist/admin/ProfileToggle-DQeXCx34.mjs +334 -0
  5. package/dist/admin/SettingsPage-DyF7YbsX.js +5758 -0
  6. package/dist/admin/SettingsPage-OwMik_IK.mjs +5758 -0
  7. package/dist/admin/WarningAlert-DFE5euMk.js +33 -0
  8. package/dist/admin/WarningAlert-VU011LVF.mjs +34 -0
  9. package/dist/admin/ar-BXaam37U.mjs +36 -0
  10. package/dist/admin/ar-i2eiMZkz.js +36 -0
  11. package/dist/admin/ca-BVpGzY8r.js +36 -0
  12. package/dist/admin/ca-DZ9DbEcQ.mjs +36 -0
  13. package/dist/admin/cs-Gok16KLy.mjs +36 -0
  14. package/dist/admin/cs-_PZVkwt0.js +36 -0
  15. package/dist/admin/de-BuYn1AYX.mjs +26 -0
  16. package/dist/admin/de-GItli7en.js +26 -0
  17. package/dist/admin/dk-B7EOsAdU.js +36 -0
  18. package/dist/admin/dk-CI64Xmli.mjs +36 -0
  19. package/dist/admin/en-B_vJwdfS.mjs +36 -0
  20. package/dist/admin/en-D4KP9t1Y.js +36 -0
  21. package/dist/admin/es-CHwF7YK-.js +36 -0
  22. package/dist/admin/es-CqJcXo4j.mjs +36 -0
  23. package/dist/admin/eu-D-snytN8.mjs +36 -0
  24. package/dist/admin/eu-DvdbwE5E.js +36 -0
  25. package/dist/admin/fr-Bt6sS5GX.mjs +26 -0
  26. package/dist/admin/fr-CbCW6hVD.js +26 -0
  27. package/dist/admin/gu-3wJbbAmw.mjs +36 -0
  28. package/dist/admin/gu-D2LgVfMp.js +36 -0
  29. package/dist/admin/he-Bjv7eygt.mjs +36 -0
  30. package/dist/admin/he-DnhYpbvN.js +36 -0
  31. package/dist/admin/hi-CNiDezU7.mjs +36 -0
  32. package/dist/admin/hi-DDD2E3A3.js +36 -0
  33. package/dist/admin/hu-C1_YkZHU.js +36 -0
  34. package/dist/admin/hu-aLaIWmGw.mjs +36 -0
  35. package/dist/admin/id-C8WRgGm1.mjs +36 -0
  36. package/dist/admin/id-u3wVE6Rv.js +36 -0
  37. package/dist/admin/index-BXZI8nMZ.js +1543 -0
  38. package/dist/admin/index-D45I6rWF.mjs +1525 -0
  39. package/dist/admin/index.js +3 -2
  40. package/dist/admin/index.mjs +1 -1
  41. package/dist/admin/it-CDw6dG9Z.js +36 -0
  42. package/dist/admin/it-CjoRoJj1.mjs +36 -0
  43. package/dist/admin/ja-CbMXy2ym.js +36 -0
  44. package/dist/admin/ja-CewucIUY.mjs +36 -0
  45. package/dist/admin/ko-BEtJPpfJ.js +36 -0
  46. package/dist/admin/ko-D-kAxDtd.mjs +36 -0
  47. package/dist/admin/ml-0fR2_MmA.js +36 -0
  48. package/dist/admin/ml-DR3AaofF.mjs +36 -0
  49. package/dist/admin/ms-COHLS5e5.mjs +36 -0
  50. package/dist/admin/ms-DLvuGSlk.js +36 -0
  51. package/dist/admin/nl-DVtHsM2H.mjs +36 -0
  52. package/dist/admin/nl-wj6kn642.js +36 -0
  53. package/dist/admin/no-DVBgWt8q.js +36 -0
  54. package/dist/admin/no-D_0yjyCy.mjs +36 -0
  55. package/dist/admin/pl-B2ghisbC.js +36 -0
  56. package/dist/admin/pl-C3GNxjVX.mjs +36 -0
  57. package/dist/admin/pt-BR-BbKV8YoX.mjs +36 -0
  58. package/dist/admin/pt-BR-CfgNaB1-.js +36 -0
  59. package/dist/admin/pt-DKe8rRWa.js +36 -0
  60. package/dist/admin/pt-z4K3cCjf.mjs +36 -0
  61. package/dist/admin/ru-BFSm68HC.js +36 -0
  62. package/dist/admin/ru-C85izLFa.mjs +36 -0
  63. package/dist/admin/sa-B1XoTTrE.mjs +36 -0
  64. package/dist/admin/sa-BOPaqylt.js +36 -0
  65. package/dist/admin/sk-C48lUPuC.mjs +36 -0
  66. package/dist/admin/sk-Dd-S1612.js +36 -0
  67. package/dist/admin/src/index.d.ts +1 -1
  68. package/dist/admin/sv-BLma_kJl.mjs +36 -0
  69. package/dist/admin/sv-lg64Cw78.js +36 -0
  70. package/dist/admin/th-BJEu5n7q.mjs +36 -0
  71. package/dist/admin/th-DPbm5NrX.js +36 -0
  72. package/dist/admin/tokenHelpers-DagDzpso.mjs +22 -0
  73. package/dist/admin/tokenHelpers-jtoRu0q5.js +21 -0
  74. package/dist/admin/tr-Bm1QZr4v.js +36 -0
  75. package/dist/admin/tr-DkIUODKq.mjs +36 -0
  76. package/dist/admin/uk-D7ArtSe3.mjs +36 -0
  77. package/dist/admin/uk-FARzIGx4.js +36 -0
  78. package/dist/admin/vi-Bi9B6eTY.js +36 -0
  79. package/dist/admin/vi-DS0yslPP.mjs +36 -0
  80. package/dist/admin/zh-DkEx28ZA.js +36 -0
  81. package/dist/admin/zh-DwCvIPSz.mjs +36 -0
  82. package/dist/admin/zh-Hans-BwwKCR6_.js +36 -0
  83. package/dist/admin/zh-Hans-DP2xZyda.mjs +36 -0
  84. package/dist/server/index.js +10591 -10215
  85. package/dist/server/index.mjs +10589 -10214
  86. package/dist/server/src/index.d.ts +10 -10
  87. package/package.json +4 -4
  88. package/dist/admin/src/components/ConfirmModal/ConfirmModal.d.ts +0 -10
  89. package/dist/admin/src/components/ConfirmModal/index.d.ts +0 -1
  90. package/dist/admin/src/components/Initializer.d.ts +0 -5
  91. package/dist/admin/src/components/InputOTP.d.ts +0 -11
  92. package/dist/admin/src/components/RemoveModal/RemoveModal.d.ts +0 -7
  93. package/dist/admin/src/components/RemoveModal/index.d.ts +0 -1
  94. package/dist/admin/src/components/WarningAlert/WarningAlert.d.ts +0 -11
  95. package/dist/admin/src/components/WarningAlert/index.d.ts +0 -1
  96. package/dist/admin/src/injection/AdminReset.d.ts +0 -4
  97. package/dist/admin/src/injection/ProfileToggle.d.ts +0 -2
  98. package/dist/admin/src/pluginId.d.ts +0 -1
  99. package/dist/admin/src/public/VerifyPage.d.ts +0 -12
  100. package/dist/admin/src/settings/SettingsPage.d.ts +0 -1
  101. package/dist/admin/src/utils/getTranslation.d.ts +0 -2
  102. package/dist/admin/src/utils/tokenHelpers.d.ts +0 -12
  103. package/dist/server/src/bootstrap.d.ts +0 -3
  104. package/dist/server/src/config/index.d.ts +0 -3
  105. package/dist/server/src/content-types/config/index.d.ts +0 -38
  106. package/dist/server/src/content-types/index.d.ts +0 -3
  107. package/dist/server/src/content-types/mfa/index.d.ts +0 -56
  108. package/dist/server/src/content-types/temp-mfa/index.d.ts +0 -35
  109. package/dist/server/src/controllers/admin.d.ts +0 -3
  110. package/dist/server/src/controllers/config.d.ts +0 -3
  111. package/dist/server/src/controllers/controller.d.ts +0 -3
  112. package/dist/server/src/controllers/index.d.ts +0 -3
  113. package/dist/server/src/destroy.d.ts +0 -3
  114. package/dist/server/src/middlewares/index.d.ts +0 -3
  115. package/dist/server/src/policies/has-mfa.d.ts +0 -3
  116. package/dist/server/src/policies/index.d.ts +0 -3
  117. package/dist/server/src/register.d.ts +0 -3
  118. package/dist/server/src/routes/admin/index.d.ts +0 -2
  119. package/dist/server/src/routes/index.d.ts +0 -3
  120. package/dist/server/src/services/admin.d.ts +0 -11
  121. package/dist/server/src/services/config.d.ts +0 -28
  122. package/dist/server/src/services/index.d.ts +0 -3
  123. package/dist/server/src/services/mfa.d.ts +0 -50
@@ -0,0 +1,112 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
+ const jsxRuntime = require("react/jsx-runtime");
4
+ const React = require("react");
5
+ const WarningAlert = require("./WarningAlert-DFE5euMk.js");
6
+ const designSystem = require("@strapi/design-system");
7
+ const index = require("./index-BXZI8nMZ.js");
8
+ const tokenHelpers = require("./tokenHelpers-jtoRu0q5.js");
9
+ const reactIntl = require("react-intl");
10
+ const AdminReset = ({ id }) => {
11
+ const { formatMessage } = reactIntl.useIntl();
12
+ const [is2FAEnabled, setIs2FAEnabled] = React.useState(false);
13
+ const [warningOpen, setWarningOpen] = React.useState(false);
14
+ const [loading, setLoading] = React.useState(false);
15
+ const handleReset = async () => {
16
+ const token = tokenHelpers.getToken();
17
+ setLoading(true);
18
+ try {
19
+ const response = await fetch(`/strapi-identity/admin/user/${id}`, {
20
+ headers: { Authorization: `Bearer ${token}` },
21
+ method: "DELETE"
22
+ });
23
+ if (!response.ok) throw new Error("Failed to fetch 2FA status for user");
24
+ setIs2FAEnabled(false);
25
+ } catch (error) {
26
+ console.error("Error resetting 2FA for user:", error);
27
+ } finally {
28
+ setLoading(false);
29
+ setWarningOpen(false);
30
+ }
31
+ };
32
+ React.useEffect(() => {
33
+ if (!id) return;
34
+ const ac = new AbortController();
35
+ const token = tokenHelpers.getToken();
36
+ (async () => {
37
+ try {
38
+ const response = await fetch(`/strapi-identity/admin/user/${id}`, {
39
+ headers: { Authorization: `Bearer ${token}` },
40
+ signal: ac.signal
41
+ });
42
+ if (!response.ok) throw new Error("Failed to fetch 2FA status for user");
43
+ const data = await response.json();
44
+ setIs2FAEnabled(data.data);
45
+ } catch (error) {
46
+ console.error("Error fetching 2FA status for user:", error);
47
+ }
48
+ })();
49
+ }, [id]);
50
+ return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
51
+ /* @__PURE__ */ jsxRuntime.jsx(
52
+ designSystem.Box,
53
+ {
54
+ background: "neutral0",
55
+ hasRadius: true,
56
+ shadow: "filterShadow",
57
+ paddingTop: 6,
58
+ paddingBottom: 6,
59
+ paddingLeft: 7,
60
+ paddingRight: 7,
61
+ children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", alignItems: "stretch", gap: 4, children: [
62
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", alignItems: "stretch", gap: 1, children: [
63
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "delta", tag: "h2", children: formatMessage({
64
+ id: index.getTranslation("admin.title"),
65
+ defaultMessage: "Two-Factor Authentication"
66
+ }) }),
67
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { children: formatMessage({
68
+ id: index.getTranslation("admin.subtitle"),
69
+ defaultMessage: "Reset the Two-Factor Authentication for a user."
70
+ }) })
71
+ ] }),
72
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Grid.Root, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Grid.Item, { col: 6, s: 12, alignItems: "stretch", children: /* @__PURE__ */ jsxRuntime.jsx(
73
+ designSystem.Button,
74
+ {
75
+ disabled: !is2FAEnabled,
76
+ variant: "danger",
77
+ onClick: () => setWarningOpen(true),
78
+ children: formatMessage({
79
+ id: index.getTranslation("app.components.Button.reset"),
80
+ defaultMessage: "Reset"
81
+ })
82
+ }
83
+ ) }) })
84
+ ] })
85
+ }
86
+ ),
87
+ /* @__PURE__ */ jsxRuntime.jsxs(
88
+ WarningAlert.WarningAlert,
89
+ {
90
+ loading,
91
+ title: formatMessage({
92
+ id: index.getTranslation("admin.warn-title"),
93
+ defaultMessage: "Reset 2FA for this user?"
94
+ }),
95
+ open: warningOpen,
96
+ onCancel: () => setWarningOpen(false),
97
+ onConfirm: handleReset,
98
+ children: [
99
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "omega", textAlign: "center", children: formatMessage({
100
+ id: index.getTranslation("admin.warning"),
101
+ defaultMessage: "Resetting the Two-Factor Authentication will allow the user to set it up again with a new device. This action cannot be undone."
102
+ }) }),
103
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { textAlign: "center", fontWeight: "semiBold", children: formatMessage({
104
+ id: index.getTranslation("app.confirm.body"),
105
+ defaultMessage: "Are you sure?"
106
+ }) })
107
+ ]
108
+ }
109
+ )
110
+ ] });
111
+ };
112
+ exports.default = AdminReset;
@@ -0,0 +1,112 @@
1
+ import { jsxs, Fragment, jsx } from "react/jsx-runtime";
2
+ import { useState, useEffect } from "react";
3
+ import { W as WarningAlert } from "./WarningAlert-VU011LVF.mjs";
4
+ import { Box, Flex, Typography, Grid, Button } from "@strapi/design-system";
5
+ import { g as getTranslation } from "./index-D45I6rWF.mjs";
6
+ import { g as getToken } from "./tokenHelpers-DagDzpso.mjs";
7
+ import { useIntl } from "react-intl";
8
+ const AdminReset = ({ id }) => {
9
+ const { formatMessage } = useIntl();
10
+ const [is2FAEnabled, setIs2FAEnabled] = useState(false);
11
+ const [warningOpen, setWarningOpen] = useState(false);
12
+ const [loading, setLoading] = useState(false);
13
+ const handleReset = async () => {
14
+ const token = getToken();
15
+ setLoading(true);
16
+ try {
17
+ const response = await fetch(`/strapi-identity/admin/user/${id}`, {
18
+ headers: { Authorization: `Bearer ${token}` },
19
+ method: "DELETE"
20
+ });
21
+ if (!response.ok) throw new Error("Failed to fetch 2FA status for user");
22
+ setIs2FAEnabled(false);
23
+ } catch (error) {
24
+ console.error("Error resetting 2FA for user:", error);
25
+ } finally {
26
+ setLoading(false);
27
+ setWarningOpen(false);
28
+ }
29
+ };
30
+ useEffect(() => {
31
+ if (!id) return;
32
+ const ac = new AbortController();
33
+ const token = getToken();
34
+ (async () => {
35
+ try {
36
+ const response = await fetch(`/strapi-identity/admin/user/${id}`, {
37
+ headers: { Authorization: `Bearer ${token}` },
38
+ signal: ac.signal
39
+ });
40
+ if (!response.ok) throw new Error("Failed to fetch 2FA status for user");
41
+ const data = await response.json();
42
+ setIs2FAEnabled(data.data);
43
+ } catch (error) {
44
+ console.error("Error fetching 2FA status for user:", error);
45
+ }
46
+ })();
47
+ }, [id]);
48
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
49
+ /* @__PURE__ */ jsx(
50
+ Box,
51
+ {
52
+ background: "neutral0",
53
+ hasRadius: true,
54
+ shadow: "filterShadow",
55
+ paddingTop: 6,
56
+ paddingBottom: 6,
57
+ paddingLeft: 7,
58
+ paddingRight: 7,
59
+ children: /* @__PURE__ */ jsxs(Flex, { direction: "column", alignItems: "stretch", gap: 4, children: [
60
+ /* @__PURE__ */ jsxs(Flex, { direction: "column", alignItems: "stretch", gap: 1, children: [
61
+ /* @__PURE__ */ jsx(Typography, { variant: "delta", tag: "h2", children: formatMessage({
62
+ id: getTranslation("admin.title"),
63
+ defaultMessage: "Two-Factor Authentication"
64
+ }) }),
65
+ /* @__PURE__ */ jsx(Typography, { children: formatMessage({
66
+ id: getTranslation("admin.subtitle"),
67
+ defaultMessage: "Reset the Two-Factor Authentication for a user."
68
+ }) })
69
+ ] }),
70
+ /* @__PURE__ */ jsx(Grid.Root, { children: /* @__PURE__ */ jsx(Grid.Item, { col: 6, s: 12, alignItems: "stretch", children: /* @__PURE__ */ jsx(
71
+ Button,
72
+ {
73
+ disabled: !is2FAEnabled,
74
+ variant: "danger",
75
+ onClick: () => setWarningOpen(true),
76
+ children: formatMessage({
77
+ id: getTranslation("app.components.Button.reset"),
78
+ defaultMessage: "Reset"
79
+ })
80
+ }
81
+ ) }) })
82
+ ] })
83
+ }
84
+ ),
85
+ /* @__PURE__ */ jsxs(
86
+ WarningAlert,
87
+ {
88
+ loading,
89
+ title: formatMessage({
90
+ id: getTranslation("admin.warn-title"),
91
+ defaultMessage: "Reset 2FA for this user?"
92
+ }),
93
+ open: warningOpen,
94
+ onCancel: () => setWarningOpen(false),
95
+ onConfirm: handleReset,
96
+ children: [
97
+ /* @__PURE__ */ jsx(Typography, { variant: "omega", textAlign: "center", children: formatMessage({
98
+ id: getTranslation("admin.warning"),
99
+ defaultMessage: "Resetting the Two-Factor Authentication will allow the user to set it up again with a new device. This action cannot be undone."
100
+ }) }),
101
+ /* @__PURE__ */ jsx(Typography, { textAlign: "center", fontWeight: "semiBold", children: formatMessage({
102
+ id: getTranslation("app.confirm.body"),
103
+ defaultMessage: "Are you sure?"
104
+ }) })
105
+ ]
106
+ }
107
+ )
108
+ ] });
109
+ };
110
+ export {
111
+ AdminReset as default
112
+ };
@@ -0,0 +1,336 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
+ const jsxRuntime = require("react/jsx-runtime");
4
+ const React = require("react");
5
+ const designSystem = require("@strapi/design-system");
6
+ const styled = require("styled-components");
7
+ const index = require("./index-BXZI8nMZ.js");
8
+ const qrcode_react = require("qrcode.react");
9
+ const reactIntl = require("react-intl");
10
+ const tokenHelpers = require("./tokenHelpers-jtoRu0q5.js");
11
+ const _interopDefault = (e) => e && e.__esModule ? e : { default: e };
12
+ const styled__default = /* @__PURE__ */ _interopDefault(styled);
13
+ function ConfirmModal({
14
+ open,
15
+ onOpenChange,
16
+ onSubmit,
17
+ qrCodeUri,
18
+ secret,
19
+ passcodes
20
+ }) {
21
+ const { formatMessage } = reactIntl.useIntl();
22
+ return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Modal.Root, { open, onOpenChange, children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Modal.Content, { children: /* @__PURE__ */ jsxRuntime.jsxs("form", { onSubmit, children: [
23
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Modal.Header, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Modal.Title, { children: formatMessage({
24
+ id: index.getTranslation("profile.setup"),
25
+ defaultMessage: "Set up Two-Factor Authentication"
26
+ }) }) }),
27
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Modal.Body, { children: passcodes ? /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", alignItems: "center", gap: 4, marginTop: 4, marginBottom: 4, children: [
28
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { textAlign: "center", children: formatMessage({
29
+ id: index.getTranslation("profile.recovery_codes"),
30
+ defaultMessage: "Please save the following recovery codes in a safe place. Each code can only be used once to access your account if you lose access to your authenticator app."
31
+ }) }),
32
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Grid.Root, { gap: 4, marginTop: 4, marginBottom: 4, children: passcodes.map((code) => /* @__PURE__ */ jsxRuntime.jsx(designSystem.Grid.Item, { col: 6, children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "pi", children: code }) }, code)) }),
33
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "pi", textAlign: "center", children: formatMessage({
34
+ id: index.getTranslation("profile.recovery_codes_warning"),
35
+ defaultMessage: "If you lose both your authenticator app and your recovery codes, you will need to contact an administrator to regain access to your account."
36
+ }) })
37
+ ] }) : /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", children: [
38
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", alignItems: "center", gap: 4, marginTop: 4, marginBottom: 4, children: [
39
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { children: formatMessage({
40
+ id: index.getTranslation("profile.scan_qr"),
41
+ defaultMessage: "You will need an authenticator app to scan the QR code below."
42
+ }) }),
43
+ qrCodeUri && /* @__PURE__ */ jsxRuntime.jsx(qrcode_react.QRCodeCanvas, { value: qrCodeUri, size: 256 }),
44
+ secret && /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "pi", children: secret || "" })
45
+ ] }),
46
+ /* @__PURE__ */ jsxRuntime.jsx(Rule, {}),
47
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", alignItems: "center", gap: 4, marginTop: 4, marginBottom: 4, children: [
48
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { children: formatMessage({
49
+ id: index.getTranslation("profile.enter_otp"),
50
+ defaultMessage: "Enter the 6-digit code from your authenticator app to confirm."
51
+ }) }),
52
+ /* @__PURE__ */ jsxRuntime.jsxs(index.InputOTP, { maxLength: 6, name: "otp", id: "otp", autoFocus: true, children: [
53
+ /* @__PURE__ */ jsxRuntime.jsxs(index.InputOTPGroup, { children: [
54
+ /* @__PURE__ */ jsxRuntime.jsx(index.InputOTPSlot, { index: 0 }),
55
+ /* @__PURE__ */ jsxRuntime.jsx(index.InputOTPSlot, { index: 1 }),
56
+ /* @__PURE__ */ jsxRuntime.jsx(index.InputOTPSlot, { index: 2 })
57
+ ] }),
58
+ /* @__PURE__ */ jsxRuntime.jsx(index.InputOTPSeparator, {}),
59
+ /* @__PURE__ */ jsxRuntime.jsxs(index.InputOTPGroup, { children: [
60
+ /* @__PURE__ */ jsxRuntime.jsx(index.InputOTPSlot, { index: 3 }),
61
+ /* @__PURE__ */ jsxRuntime.jsx(index.InputOTPSlot, { index: 4 }),
62
+ /* @__PURE__ */ jsxRuntime.jsx(index.InputOTPSlot, { index: 5 })
63
+ ] })
64
+ ] })
65
+ ] })
66
+ ] }) }),
67
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Modal.Footer, { children: [
68
+ passcodes && /* @__PURE__ */ jsxRuntime.jsx("span", {}),
69
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Modal.Close, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { variant: passcodes ? void 0 : "tertiary", children: passcodes ? formatMessage({ id: "global.close", defaultMessage: "Close" }) : formatMessage({ id: "app.components.Button.cancel", defaultMessage: "Cancel" }) }) }),
70
+ !passcodes && /* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { type: "submit", children: formatMessage({ id: "app.components.Button.confirm", defaultMessage: "Confirm" }) })
71
+ ] })
72
+ ] }) }) });
73
+ }
74
+ const Rule = styled__default.default.hr`
75
+ height: 1px;
76
+ border: 0;
77
+ background-color: #e5e5e5;
78
+ `;
79
+ function RemoveModal({ open, onOpenChange, onSubmit }) {
80
+ const { formatMessage } = reactIntl.useIntl();
81
+ const [showRecovery, setShowRecovery] = React.useState(false);
82
+ return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Modal.Root, { open, onOpenChange, children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Modal.Content, { children: /* @__PURE__ */ jsxRuntime.jsxs("form", { onSubmit, children: [
83
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Modal.Header, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Modal.Title, { children: formatMessage({
84
+ id: index.getTranslation("profile.disable_title"),
85
+ defaultMessage: "Disable Two-Factor Authentication"
86
+ }) }) }),
87
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Modal.Body, { children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", alignItems: "center", gap: 4, marginTop: 4, marginBottom: 4, children: [
88
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { children: formatMessage({
89
+ id: index.getTranslation("profile.disable_instruction"),
90
+ defaultMessage: "Enter the 6-digit code from your authenticator app to disable Two-Factor Authentication."
91
+ }) }),
92
+ showRecovery ? /* @__PURE__ */ jsxRuntime.jsx(designSystem.TextInput, { name: "otp", id: "otp", autoFocus: true }) : /* @__PURE__ */ jsxRuntime.jsxs(index.InputOTP, { maxLength: 6, name: "otp", id: "otp", autoFocus: true, children: [
93
+ /* @__PURE__ */ jsxRuntime.jsxs(index.InputOTPGroup, { children: [
94
+ /* @__PURE__ */ jsxRuntime.jsx(index.InputOTPSlot, { index: 0 }),
95
+ /* @__PURE__ */ jsxRuntime.jsx(index.InputOTPSlot, { index: 1 }),
96
+ /* @__PURE__ */ jsxRuntime.jsx(index.InputOTPSlot, { index: 2 })
97
+ ] }),
98
+ /* @__PURE__ */ jsxRuntime.jsx(index.InputOTPSeparator, {}),
99
+ /* @__PURE__ */ jsxRuntime.jsxs(index.InputOTPGroup, { children: [
100
+ /* @__PURE__ */ jsxRuntime.jsx(index.InputOTPSlot, { index: 3 }),
101
+ /* @__PURE__ */ jsxRuntime.jsx(index.InputOTPSlot, { index: 4 }),
102
+ /* @__PURE__ */ jsxRuntime.jsx(index.InputOTPSlot, { index: 5 })
103
+ ] })
104
+ ] }),
105
+ /* @__PURE__ */ jsxRuntime.jsx(
106
+ designSystem.Button,
107
+ {
108
+ variant: "ghost",
109
+ type: "button",
110
+ onClick: () => setShowRecovery((prev) => !prev),
111
+ children: showRecovery ? formatMessage({
112
+ id: index.getTranslation("general.use_verification_code"),
113
+ defaultMessage: "Use verification code"
114
+ }) : formatMessage({
115
+ id: index.getTranslation("general.use_recovery_code"),
116
+ defaultMessage: "Use recovery code"
117
+ })
118
+ }
119
+ )
120
+ ] }) }),
121
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Modal.Footer, { children: [
122
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Modal.Close, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { variant: "tertiary", children: formatMessage({ id: "app.components.Button.cancel", defaultMessage: "Cancel" }) }) }),
123
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { type: "submit", children: formatMessage({ id: "app.components.Button.confirm", defaultMessage: "Confirm" }) })
124
+ ] })
125
+ ] }) }) });
126
+ }
127
+ const ProfileToggle = () => {
128
+ const { formatMessage } = reactIntl.useIntl();
129
+ const [enabled, setEnabled] = React.useState(null);
130
+ const [mfaEnabled, setMfaEnabled] = React.useState(false);
131
+ const [disableDialogOpen, setDisableDialogOpen] = React.useState(false);
132
+ const [modalOpen, setModalOpen] = React.useState(false);
133
+ const [uri, setUri] = React.useState(null);
134
+ const [secret, setSecret] = React.useState(null);
135
+ const [passcodes, setPasscodes] = React.useState(null);
136
+ const handleToggle = async ({ target }) => {
137
+ const token = tokenHelpers.getToken();
138
+ const enable = target?.checked || false;
139
+ if (!enable && enabled === "full") {
140
+ setDisableDialogOpen(true);
141
+ return;
142
+ }
143
+ try {
144
+ const response = await fetch("/strapi-identity/enable", {
145
+ method: "POST",
146
+ headers: { "Content-Type": "application/json", authorization: `Bearer ${token}` },
147
+ body: JSON.stringify({ enable })
148
+ });
149
+ const body = await response.json();
150
+ if (!response.ok) {
151
+ throw new Error(`${response.status} - ${body.error || "Failed to update MFA status"}`);
152
+ }
153
+ const data = body.data;
154
+ if (!data) {
155
+ throw new Error("No data returned from server");
156
+ }
157
+ if (enable) setModalOpen(true);
158
+ setUri(data?.uri || null);
159
+ setSecret(data?.secret || null);
160
+ setEnabled(enable ? "temp" : null);
161
+ } catch (error) {
162
+ console.error(error);
163
+ setEnabled(null);
164
+ }
165
+ };
166
+ const handleConfirm = async (e) => {
167
+ e.preventDefault();
168
+ const form = e.target;
169
+ const formData = new FormData(form);
170
+ const code = formData.get("otp");
171
+ const token = tokenHelpers.getToken();
172
+ try {
173
+ const response = await fetch("/strapi-identity/setup", {
174
+ method: "POST",
175
+ headers: { "Content-Type": "application/json", authorization: `Bearer ${token}` },
176
+ body: JSON.stringify({ code })
177
+ });
178
+ const body = await response.json();
179
+ if (!response.ok) {
180
+ throw new Error(`${response.status} - ${body.error || "Failed to set up MFA"}`);
181
+ }
182
+ if (body.data?.recoveryCodes) {
183
+ setPasscodes(body.data.recoveryCodes);
184
+ } else {
185
+ setModalOpen(false);
186
+ }
187
+ setUri(null);
188
+ setSecret(null);
189
+ setEnabled("full");
190
+ } catch (error) {
191
+ console.error(error);
192
+ }
193
+ };
194
+ const handleClose = () => {
195
+ if (!passcodes) setEnabled(null);
196
+ setModalOpen(false);
197
+ setUri(null);
198
+ setSecret(null);
199
+ setPasscodes(null);
200
+ };
201
+ const handleDisable = async (e) => {
202
+ e.preventDefault();
203
+ const form = e.target;
204
+ const formData = new FormData(form);
205
+ const code = formData.get("otp");
206
+ const token = tokenHelpers.getToken();
207
+ try {
208
+ const response = await fetch("/strapi-identity/disable", {
209
+ method: "POST",
210
+ headers: { "Content-Type": "application/json", authorization: `Bearer ${token}` },
211
+ body: JSON.stringify({ code })
212
+ });
213
+ const body = await response.json();
214
+ if (!response.ok) {
215
+ throw new Error(`${response.status} - ${body.error || "Failed to disable MFA"}`);
216
+ }
217
+ setDisableDialogOpen(false);
218
+ setUri(null);
219
+ setSecret(null);
220
+ setEnabled(null);
221
+ } catch (error) {
222
+ console.error(error);
223
+ }
224
+ };
225
+ React.useEffect(() => {
226
+ const ac = new AbortController();
227
+ (async () => {
228
+ const token = tokenHelpers.getToken();
229
+ try {
230
+ const [status, enabled2] = await Promise.all([
231
+ fetch("/strapi-identity/status", {
232
+ method: "GET",
233
+ headers: { "Content-Type": "application/json", authorization: `Bearer ${token}` },
234
+ signal: ac.signal
235
+ }),
236
+ fetch("/strapi-identity/config/enabled", {
237
+ method: "GET",
238
+ headers: { "Content-Type": "application/json", authorization: `Bearer ${token}` },
239
+ signal: ac.signal
240
+ })
241
+ ]);
242
+ const statusBody = await status.json();
243
+ const enabledBody = await enabled2.json();
244
+ if (!status.ok) {
245
+ throw new Error(`${status.status} - ${statusBody.error || "Failed to set up MFA"}`);
246
+ }
247
+ if (!enabled2.ok) {
248
+ throw new Error(`${enabled2.status} - ${enabledBody.error || "Failed to get MFA config"}`);
249
+ }
250
+ setMfaEnabled(enabledBody.data);
251
+ setEnabled(statusBody.data?.status || null);
252
+ } catch (error) {
253
+ if (error.name === "AbortError") return;
254
+ console.error("Failed to fetch MFA status:", error);
255
+ }
256
+ })();
257
+ return () => ac.abort();
258
+ }, []);
259
+ if (!mfaEnabled) return null;
260
+ return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
261
+ /* @__PURE__ */ jsxRuntime.jsx(
262
+ designSystem.Box,
263
+ {
264
+ background: "neutral0",
265
+ hasRadius: true,
266
+ shadow: "filterShadow",
267
+ paddingTop: 6,
268
+ paddingBottom: 6,
269
+ paddingLeft: 7,
270
+ paddingRight: 7,
271
+ children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", alignItems: "stretch", gap: 4, children: [
272
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", alignItems: "stretch", gap: 1, children: [
273
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "delta", tag: "h2", children: formatMessage({
274
+ id: index.getTranslation("profile.title"),
275
+ defaultMessage: "Two-Factor Authentication"
276
+ }) }),
277
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { children: formatMessage({
278
+ id: index.getTranslation("profile.subtitle"),
279
+ defaultMessage: "Add an additional layer of security to your account."
280
+ }) })
281
+ ] }),
282
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Grid.Root, { tag: "div", gap: 5, children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Grid.Item, { col: 6, s: 12, alignItems: "stretch", children: /* @__PURE__ */ jsxRuntime.jsxs(
283
+ designSystem.Field.Root,
284
+ {
285
+ width: "100%",
286
+ name: "two-factor-authentication",
287
+ id: "two-factor-authentication",
288
+ children: [
289
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Field.Label, { children: formatMessage({
290
+ id: index.getTranslation("profile.toggle_label"),
291
+ defaultMessage: "Enable Two-Factor Authentication"
292
+ }) }),
293
+ /* @__PURE__ */ jsxRuntime.jsx(
294
+ designSystem.Toggle,
295
+ {
296
+ offLabel: formatMessage({
297
+ id: "app.components.ToggleCheckbox.off-label",
298
+ defaultMessage: "False"
299
+ }),
300
+ onLabel: formatMessage({
301
+ id: "app.components.ToggleCheckbox.on-label",
302
+ defaultMessage: "True"
303
+ }),
304
+ checked: enabled !== null,
305
+ onChange: handleToggle
306
+ }
307
+ ),
308
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Field.Hint, {})
309
+ ]
310
+ }
311
+ ) }) })
312
+ ] })
313
+ }
314
+ ),
315
+ /* @__PURE__ */ jsxRuntime.jsx(
316
+ ConfirmModal,
317
+ {
318
+ open: modalOpen,
319
+ onOpenChange: handleClose,
320
+ qrCodeUri: uri,
321
+ secret,
322
+ passcodes,
323
+ onSubmit: handleConfirm
324
+ }
325
+ ),
326
+ /* @__PURE__ */ jsxRuntime.jsx(
327
+ RemoveModal,
328
+ {
329
+ open: disableDialogOpen,
330
+ onOpenChange: setDisableDialogOpen,
331
+ onSubmit: handleDisable
332
+ }
333
+ )
334
+ ] });
335
+ };
336
+ exports.default = ProfileToggle;