strapi-identity 0.1.1 → 0.2.0
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 +2 -1
- package/dist/admin/AdminReset-B-WGECOX.mjs +112 -0
- package/dist/admin/AdminReset-CqHhVBS_.js +112 -0
- package/dist/admin/ProfileToggle-BCtCsOvj.mjs +594 -0
- package/dist/admin/ProfileToggle-BRYjt5Lu.js +596 -0
- package/dist/admin/SettingsPage-7Ytl01jH.mjs +6000 -0
- package/dist/admin/SettingsPage-DAxGIv_E.js +6000 -0
- package/dist/admin/WarningAlert-DFE5euMk.js +33 -0
- package/dist/admin/WarningAlert-VU011LVF.mjs +34 -0
- package/dist/admin/ar-BYnI7Tsa.js +49 -0
- package/dist/admin/ar-DwZqj0qM.mjs +49 -0
- package/dist/admin/ca-aKVVc8iQ.mjs +49 -0
- package/dist/admin/ca-sBRHuaFU.js +49 -0
- package/dist/admin/cs--prflMHS.mjs +49 -0
- package/dist/admin/cs-gU7KP3Lx.js +49 -0
- package/dist/admin/de-BT25lv_6.mjs +49 -0
- package/dist/admin/de-CrlCAUuf.js +49 -0
- package/dist/admin/dk-BNC3WUzY.js +49 -0
- package/dist/admin/dk-Ck3AQYU7.mjs +49 -0
- package/dist/admin/en-9qzlpde0.mjs +49 -0
- package/dist/admin/en-DBj0AD5g.js +49 -0
- package/dist/admin/es-D5Sn41_H.js +49 -0
- package/dist/admin/es-lh6XoPb7.mjs +49 -0
- package/dist/admin/eu-Cuz6ijBX.mjs +49 -0
- package/dist/admin/eu-Qr3RvDPW.js +49 -0
- package/dist/admin/fr-C4pmkPYn.js +49 -0
- package/dist/admin/fr-ChlDcZsG.mjs +49 -0
- package/dist/admin/gu-B6zyD1bW.mjs +49 -0
- package/dist/admin/gu-BMZL76zM.js +49 -0
- package/dist/admin/he-C5V-qZCX.mjs +49 -0
- package/dist/admin/he-H6iBa45A.js +49 -0
- package/dist/admin/hi-Be8rPk7I.js +49 -0
- package/dist/admin/hi-czhOWo6-.mjs +49 -0
- package/dist/admin/hu-DKp6kOmc.js +49 -0
- package/dist/admin/hu-NbZ3aiYV.mjs +49 -0
- package/dist/admin/id-DO0bwFgY.js +49 -0
- package/dist/admin/id-NH9PvcR5.mjs +49 -0
- package/dist/admin/index-BfC6z9N5.mjs +1580 -0
- package/dist/admin/index-D03zlFnm.js +1598 -0
- package/dist/admin/index.js +3 -2
- package/dist/admin/index.mjs +1 -1
- package/dist/admin/it-Cmrey6tg.mjs +49 -0
- package/dist/admin/it-Df6-7-M7.js +49 -0
- package/dist/admin/ja-DH3KMqOL.mjs +49 -0
- package/dist/admin/ja-HuAq9ZwT.js +49 -0
- package/dist/admin/ko-DPN28RE8.mjs +49 -0
- package/dist/admin/ko-S9k8KA8K.js +49 -0
- package/dist/admin/ml-Bh9GGqcW.js +49 -0
- package/dist/admin/ml-MsHNacm6.mjs +49 -0
- package/dist/admin/ms-TjHAaxTd.mjs +49 -0
- package/dist/admin/ms-hO5YeEg4.js +49 -0
- package/dist/admin/nl-BF98NBwL.js +49 -0
- package/dist/admin/nl-BLILZU8-.mjs +49 -0
- package/dist/admin/no-BtVZ-siy.mjs +49 -0
- package/dist/admin/no-bl1OXlfa.js +49 -0
- package/dist/admin/pl-DCSB6LwZ.mjs +49 -0
- package/dist/admin/pl-DCnOWIDw.js +49 -0
- package/dist/admin/pt-BR-CeLqmj88.mjs +49 -0
- package/dist/admin/pt-BR-D2_UrxTp.js +49 -0
- package/dist/admin/pt-DIu8RT_X.js +49 -0
- package/dist/admin/pt-fgjdOyW5.mjs +49 -0
- package/dist/admin/ru-B_hlpAyP.mjs +49 -0
- package/dist/admin/ru-BccMCf0l.js +49 -0
- package/dist/admin/sa-BtuJ_I1t.mjs +49 -0
- package/dist/admin/sa-D3A-fo85.js +49 -0
- package/dist/admin/sk-mmuTFlCK.mjs +49 -0
- package/dist/admin/sk-uSLC6KhO.js +49 -0
- package/dist/admin/src/index.d.ts +1 -1
- package/dist/admin/sv-BlaHc5ax.mjs +49 -0
- package/dist/admin/sv-CuKk5tE-.js +49 -0
- package/dist/admin/th-Bv3NKkYO.js +49 -0
- package/dist/admin/th-BwyhFaeE.mjs +49 -0
- package/dist/admin/tokenHelpers-DagDzpso.mjs +22 -0
- package/dist/admin/tokenHelpers-jtoRu0q5.js +21 -0
- package/dist/admin/tr-BLocNlbZ.mjs +49 -0
- package/dist/admin/tr-Bmvs-Hx-.js +49 -0
- package/dist/admin/uk-BDxn-EZU.js +49 -0
- package/dist/admin/uk-CyZ10xtq.mjs +49 -0
- package/dist/admin/vi-Bx_UJ8up.mjs +49 -0
- package/dist/admin/vi-F_mqQCme.js +49 -0
- package/dist/admin/zh-CFZJPG5N.js +49 -0
- package/dist/admin/zh-CjJdRa3l.mjs +49 -0
- package/dist/admin/zh-Hans-4BhSwSQw.js +49 -0
- package/dist/admin/zh-Hans-s7G2GUHU.mjs +49 -0
- package/dist/server/index.js +11081 -10268
- package/dist/server/index.mjs +11079 -10267
- package/dist/server/src/index.d.ts +10 -10
- package/package.json +5 -4
- package/dist/admin/src/components/ConfirmModal/ConfirmModal.d.ts +0 -10
- package/dist/admin/src/components/ConfirmModal/index.d.ts +0 -1
- package/dist/admin/src/components/Initializer.d.ts +0 -5
- package/dist/admin/src/components/InputOTP.d.ts +0 -11
- package/dist/admin/src/components/RemoveModal/RemoveModal.d.ts +0 -7
- package/dist/admin/src/components/RemoveModal/index.d.ts +0 -1
- package/dist/admin/src/components/WarningAlert/WarningAlert.d.ts +0 -11
- package/dist/admin/src/components/WarningAlert/index.d.ts +0 -1
- package/dist/admin/src/injection/AdminReset.d.ts +0 -4
- package/dist/admin/src/injection/ProfileToggle.d.ts +0 -2
- package/dist/admin/src/pluginId.d.ts +0 -1
- package/dist/admin/src/public/VerifyPage.d.ts +0 -12
- package/dist/admin/src/settings/SettingsPage.d.ts +0 -1
- package/dist/admin/src/utils/getTranslation.d.ts +0 -2
- package/dist/admin/src/utils/tokenHelpers.d.ts +0 -12
- package/dist/server/src/bootstrap.d.ts +0 -3
- package/dist/server/src/config/index.d.ts +0 -3
- package/dist/server/src/content-types/config/index.d.ts +0 -38
- package/dist/server/src/content-types/index.d.ts +0 -3
- package/dist/server/src/content-types/mfa/index.d.ts +0 -56
- package/dist/server/src/content-types/temp-mfa/index.d.ts +0 -35
- package/dist/server/src/controllers/admin.d.ts +0 -3
- package/dist/server/src/controllers/config.d.ts +0 -3
- package/dist/server/src/controllers/controller.d.ts +0 -3
- package/dist/server/src/controllers/index.d.ts +0 -3
- package/dist/server/src/destroy.d.ts +0 -3
- package/dist/server/src/middlewares/index.d.ts +0 -3
- package/dist/server/src/policies/has-mfa.d.ts +0 -3
- package/dist/server/src/policies/index.d.ts +0 -3
- package/dist/server/src/register.d.ts +0 -3
- package/dist/server/src/routes/admin/index.d.ts +0 -2
- package/dist/server/src/routes/index.d.ts +0 -3
- package/dist/server/src/services/admin.d.ts +0 -11
- package/dist/server/src/services/config.d.ts +0 -28
- package/dist/server/src/services/index.d.ts +0 -3
- package/dist/server/src/services/mfa.d.ts +0 -50
package/README.md
CHANGED
|
@@ -7,6 +7,7 @@ Detailed Multi-Factor Authentication (MFA) plugin for Strapi v5+. Secure your St
|
|
|
7
7
|
- **MFA Login Interception**: Seamlessly integrates with the default Strapi login flow.
|
|
8
8
|
- **TOTP Compatibility**: Works with all major authenticator apps (Google Authenticator, Authy, 1Password, etc.).
|
|
9
9
|
- **Recovery Codes**: Generates secure recovery codes for emergency access.
|
|
10
|
+
- **Email Passcode**: Option to receive a one-time passcode via email as an alternative MFA method.
|
|
10
11
|
- **Native UI Integration**:
|
|
11
12
|
- Matches Strapi's design system.
|
|
12
13
|
- Profile integration for easy setup.
|
|
@@ -114,5 +115,5 @@ Below is the implementation status of planned features.
|
|
|
114
115
|
- [x] **Custom Issuer**: Configurable app label.
|
|
115
116
|
- [x] **Multi-language Support**: i18n ready.
|
|
116
117
|
- [x] **Admin Reset**: Allow super-admins to reset MFA for other users who lost access.
|
|
117
|
-
- [
|
|
118
|
+
- [x] **Email Passcode**: Alternative MFA method via Email.
|
|
118
119
|
- [ ] **Enforced Mode**: Mandatory MFA for specific roles or all users.
|
|
@@ -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-BfC6z9N5.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,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-D03zlFnm.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;
|