@burdenoff/microfe-auth 2026.510.127
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 +12 -0
- package/dist/_virtual/_rolldown/runtime.js +13 -0
- package/dist/auth/AuthRoot.d.ts +30 -0
- package/dist/auth/AuthRoot.d.ts.map +1 -0
- package/dist/auth/AuthRoot.js +82 -0
- package/dist/auth/AuthRoot.js.map +1 -0
- package/dist/auth/AuthRoutes.d.ts +29 -0
- package/dist/auth/AuthRoutes.d.ts.map +1 -0
- package/dist/auth/AuthRoutes.js +271 -0
- package/dist/auth/AuthRoutes.js.map +1 -0
- package/dist/auth/components/AuthIcons.d.ts +17 -0
- package/dist/auth/components/AuthIcons.d.ts.map +1 -0
- package/dist/auth/components/AuthIcons.js +197 -0
- package/dist/auth/components/AuthIcons.js.map +1 -0
- package/dist/auth/components/AuthLayout.d.ts +17 -0
- package/dist/auth/components/AuthLayout.d.ts.map +1 -0
- package/dist/auth/components/AuthLayout.js +237 -0
- package/dist/auth/components/AuthLayout.js.map +1 -0
- package/dist/auth/components/CaptchaV2.d.ts +16 -0
- package/dist/auth/components/CaptchaV2.d.ts.map +1 -0
- package/dist/auth/components/CaptchaV2.js +47 -0
- package/dist/auth/components/CaptchaV2.js.map +1 -0
- package/dist/auth/components/ConfirmActionDialog.d.ts +16 -0
- package/dist/auth/components/ConfirmActionDialog.d.ts.map +1 -0
- package/dist/auth/components/ConfirmActionDialog.js +68 -0
- package/dist/auth/components/ConfirmActionDialog.js.map +1 -0
- package/dist/auth/components/index.d.ts +4 -0
- package/dist/auth/components/index.d.ts.map +1 -0
- package/dist/auth/components/profile/UserProfileMenu.d.ts +42 -0
- package/dist/auth/components/profile/UserProfileMenu.d.ts.map +1 -0
- package/dist/auth/components/profile/UserProfileMenu.js +91 -0
- package/dist/auth/components/profile/UserProfileMenu.js.map +1 -0
- package/dist/auth/components/workspace/WorkspaceSelector.d.ts +76 -0
- package/dist/auth/components/workspace/WorkspaceSelector.d.ts.map +1 -0
- package/dist/auth/components/workspace/WorkspaceSelector.js +240 -0
- package/dist/auth/components/workspace/WorkspaceSelector.js.map +1 -0
- package/dist/auth/constants/permissions.d.ts +30 -0
- package/dist/auth/constants/permissions.d.ts.map +1 -0
- package/dist/auth/constants/permissions.js +18 -0
- package/dist/auth/constants/permissions.js.map +1 -0
- package/dist/auth/constants/sessionKeys.d.ts +18 -0
- package/dist/auth/constants/sessionKeys.d.ts.map +1 -0
- package/dist/auth/constants/sessionKeys.js +6 -0
- package/dist/auth/constants/sessionKeys.js.map +1 -0
- package/dist/auth/hooks/index.d.ts +18 -0
- package/dist/auth/hooks/index.d.ts.map +1 -0
- package/dist/auth/hooks/index.js +16 -0
- package/dist/auth/hooks/useAccountOperations.d.ts +19 -0
- package/dist/auth/hooks/useAccountOperations.d.ts.map +1 -0
- package/dist/auth/hooks/useAccountOperations.js +52 -0
- package/dist/auth/hooks/useAccountOperations.js.map +1 -0
- package/dist/auth/hooks/useApiKeyOperations.d.ts +22 -0
- package/dist/auth/hooks/useApiKeyOperations.d.ts.map +1 -0
- package/dist/auth/hooks/useApiKeyOperations.js +4 -0
- package/dist/auth/hooks/useAppOperations.d.ts +26 -0
- package/dist/auth/hooks/useAppOperations.d.ts.map +1 -0
- package/dist/auth/hooks/useAppOperations.js +4 -0
- package/dist/auth/hooks/useAuthOperations.d.ts +57 -0
- package/dist/auth/hooks/useAuthOperations.d.ts.map +1 -0
- package/dist/auth/hooks/useAuthOperations.js +236 -0
- package/dist/auth/hooks/useAuthOperations.js.map +1 -0
- package/dist/auth/hooks/useAuthPermissions.d.ts +20 -0
- package/dist/auth/hooks/useAuthPermissions.d.ts.map +1 -0
- package/dist/auth/hooks/useAuthPermissions.js +22 -0
- package/dist/auth/hooks/useAuthPermissions.js.map +1 -0
- package/dist/auth/hooks/useCaptchaV3.d.ts +13 -0
- package/dist/auth/hooks/useCaptchaV3.d.ts.map +1 -0
- package/dist/auth/hooks/useCaptchaV3.js +19 -0
- package/dist/auth/hooks/useCaptchaV3.js.map +1 -0
- package/dist/auth/hooks/useContextSwitcherData.d.ts +106 -0
- package/dist/auth/hooks/useContextSwitcherData.d.ts.map +1 -0
- package/dist/auth/hooks/useContextSwitcherData.js +466 -0
- package/dist/auth/hooks/useContextSwitcherData.js.map +1 -0
- package/dist/auth/hooks/useDelegationOperations.d.ts +25 -0
- package/dist/auth/hooks/useDelegationOperations.d.ts.map +1 -0
- package/dist/auth/hooks/useDelegationOperations.js +4 -0
- package/dist/auth/hooks/useMfaOperations.d.ts +18 -0
- package/dist/auth/hooks/useMfaOperations.d.ts.map +1 -0
- package/dist/auth/hooks/useMfaOperations.js +103 -0
- package/dist/auth/hooks/useMfaOperations.js.map +1 -0
- package/dist/auth/hooks/useMyWorkspaces.d.ts +45 -0
- package/dist/auth/hooks/useMyWorkspaces.d.ts.map +1 -0
- package/dist/auth/hooks/useMyWorkspaces.js +140 -0
- package/dist/auth/hooks/useMyWorkspaces.js.map +1 -0
- package/dist/auth/hooks/useOAuthOperations.d.ts +19 -0
- package/dist/auth/hooks/useOAuthOperations.d.ts.map +1 -0
- package/dist/auth/hooks/useOAuthOperations.js +103 -0
- package/dist/auth/hooks/useOAuthOperations.js.map +1 -0
- package/dist/auth/hooks/usePasswordOperations.d.ts +13 -0
- package/dist/auth/hooks/usePasswordOperations.d.ts.map +1 -0
- package/dist/auth/hooks/usePasswordOperations.js +56 -0
- package/dist/auth/hooks/usePasswordOperations.js.map +1 -0
- package/dist/auth/hooks/useSessionOperations.d.ts +41 -0
- package/dist/auth/hooks/useSessionOperations.d.ts.map +1 -0
- package/dist/auth/hooks/useSessionOperations.js +59 -0
- package/dist/auth/hooks/useSessionOperations.js.map +1 -0
- package/dist/auth/hooks/useSsoOperations.d.ts +65 -0
- package/dist/auth/hooks/useSsoOperations.d.ts.map +1 -0
- package/dist/auth/hooks/useSsoOperations.js +236 -0
- package/dist/auth/hooks/useSsoOperations.js.map +1 -0
- package/dist/auth/hooks/useTokenRefresh.d.ts +56 -0
- package/dist/auth/hooks/useTokenRefresh.d.ts.map +1 -0
- package/dist/auth/hooks/useTokenRefresh.js +53 -0
- package/dist/auth/hooks/useTokenRefresh.js.map +1 -0
- package/dist/auth/hooks/useUserOperations.d.ts +32 -0
- package/dist/auth/hooks/useUserOperations.d.ts.map +1 -0
- package/dist/auth/hooks/useUserOperations.js +100 -0
- package/dist/auth/hooks/useUserOperations.js.map +1 -0
- package/dist/auth/hooks/useWorkspaceOperations.d.ts +35 -0
- package/dist/auth/hooks/useWorkspaceOperations.d.ts.map +1 -0
- package/dist/auth/hooks/useWorkspaceOperations.js +35 -0
- package/dist/auth/hooks/useWorkspaceOperations.js.map +1 -0
- package/dist/auth/hooks/useWorkspaceToken.d.ts +56 -0
- package/dist/auth/hooks/useWorkspaceToken.d.ts.map +1 -0
- package/dist/auth/hooks/useWorkspaceToken.js +94 -0
- package/dist/auth/hooks/useWorkspaceToken.js.map +1 -0
- package/dist/auth/index.d.ts +63 -0
- package/dist/auth/index.d.ts.map +1 -0
- package/dist/auth/index.js +18 -0
- package/dist/auth/pages/ApiKeysPage.d.ts +5 -0
- package/dist/auth/pages/ApiKeysPage.d.ts.map +1 -0
- package/dist/auth/pages/AppsPage.d.ts +5 -0
- package/dist/auth/pages/AppsPage.d.ts.map +1 -0
- package/dist/auth/pages/AuditLogPage.d.ts +5 -0
- package/dist/auth/pages/AuditLogPage.d.ts.map +1 -0
- package/dist/auth/pages/AuditLogPage.js +129 -0
- package/dist/auth/pages/AuditLogPage.js.map +1 -0
- package/dist/auth/pages/DelegationsPage.d.ts +5 -0
- package/dist/auth/pages/DelegationsPage.d.ts.map +1 -0
- package/dist/auth/pages/EmailVerifyPage.d.ts +5 -0
- package/dist/auth/pages/EmailVerifyPage.d.ts.map +1 -0
- package/dist/auth/pages/EmailVerifyPage.js +166 -0
- package/dist/auth/pages/EmailVerifyPage.js.map +1 -0
- package/dist/auth/pages/LoginPage.d.ts +6 -0
- package/dist/auth/pages/LoginPage.d.ts.map +1 -0
- package/dist/auth/pages/LoginPage.js +575 -0
- package/dist/auth/pages/LoginPage.js.map +1 -0
- package/dist/auth/pages/MagicLinkPage.d.ts +6 -0
- package/dist/auth/pages/MagicLinkPage.d.ts.map +1 -0
- package/dist/auth/pages/MagicLinkPage.js +219 -0
- package/dist/auth/pages/MagicLinkPage.js.map +1 -0
- package/dist/auth/pages/MfaSetupPage.d.ts +5 -0
- package/dist/auth/pages/MfaSetupPage.d.ts.map +1 -0
- package/dist/auth/pages/MfaSetupPage.js +341 -0
- package/dist/auth/pages/MfaSetupPage.js.map +1 -0
- package/dist/auth/pages/MfaVerifyPage.d.ts +7 -0
- package/dist/auth/pages/MfaVerifyPage.d.ts.map +1 -0
- package/dist/auth/pages/MfaVerifyPage.js +189 -0
- package/dist/auth/pages/MfaVerifyPage.js.map +1 -0
- package/dist/auth/pages/OAuthCallbackPage.d.ts +7 -0
- package/dist/auth/pages/OAuthCallbackPage.d.ts.map +1 -0
- package/dist/auth/pages/OAuthCallbackPage.js +100 -0
- package/dist/auth/pages/OAuthCallbackPage.js.map +1 -0
- package/dist/auth/pages/PasswordResetPage.d.ts +6 -0
- package/dist/auth/pages/PasswordResetPage.d.ts.map +1 -0
- package/dist/auth/pages/PasswordResetPage.js +352 -0
- package/dist/auth/pages/PasswordResetPage.js.map +1 -0
- package/dist/auth/pages/ReactivatePage.d.ts +6 -0
- package/dist/auth/pages/ReactivatePage.d.ts.map +1 -0
- package/dist/auth/pages/ReactivatePage.js +217 -0
- package/dist/auth/pages/ReactivatePage.js.map +1 -0
- package/dist/auth/pages/RegisterPage.d.ts +5 -0
- package/dist/auth/pages/RegisterPage.d.ts.map +1 -0
- package/dist/auth/pages/RegisterPage.js +439 -0
- package/dist/auth/pages/RegisterPage.js.map +1 -0
- package/dist/auth/pages/SSORelayCallbackPage.d.ts +8 -0
- package/dist/auth/pages/SSORelayCallbackPage.d.ts.map +1 -0
- package/dist/auth/pages/SSORelayCallbackPage.js +48 -0
- package/dist/auth/pages/SSORelayCallbackPage.js.map +1 -0
- package/dist/auth/pages/SSORelayPage.d.ts +18 -0
- package/dist/auth/pages/SSORelayPage.d.ts.map +1 -0
- package/dist/auth/pages/SSORelayPage.js +134 -0
- package/dist/auth/pages/SSORelayPage.js.map +1 -0
- package/dist/auth/pages/SecurityPage.d.ts +5 -0
- package/dist/auth/pages/SecurityPage.d.ts.map +1 -0
- package/dist/auth/pages/SecurityPage.js +587 -0
- package/dist/auth/pages/SecurityPage.js.map +1 -0
- package/dist/auth/pages/SessionBridgePage.d.ts +14 -0
- package/dist/auth/pages/SessionBridgePage.d.ts.map +1 -0
- package/dist/auth/pages/SessionBridgePage.js +231 -0
- package/dist/auth/pages/SessionBridgePage.js.map +1 -0
- package/dist/auth/pages/SessionsPage.d.ts +5 -0
- package/dist/auth/pages/SessionsPage.d.ts.map +1 -0
- package/dist/auth/pages/SessionsPage.js +258 -0
- package/dist/auth/pages/SessionsPage.js.map +1 -0
- package/dist/auth/pages/SsoCallbackPage.d.ts +8 -0
- package/dist/auth/pages/SsoCallbackPage.d.ts.map +1 -0
- package/dist/auth/pages/SsoCallbackPage.js +188 -0
- package/dist/auth/pages/SsoCallbackPage.js.map +1 -0
- package/dist/auth/pages/SsoConfigPage.d.ts +6 -0
- package/dist/auth/pages/SsoConfigPage.d.ts.map +1 -0
- package/dist/auth/pages/SsoConfigPage.js +1144 -0
- package/dist/auth/pages/SsoConfigPage.js.map +1 -0
- package/dist/auth/pages/SsoLoginPage.d.ts +7 -0
- package/dist/auth/pages/SsoLoginPage.d.ts.map +1 -0
- package/dist/auth/pages/SsoLoginPage.js +236 -0
- package/dist/auth/pages/SsoLoginPage.js.map +1 -0
- package/dist/auth/pages/UserDetailsPage.d.ts +11 -0
- package/dist/auth/pages/UserDetailsPage.d.ts.map +1 -0
- package/dist/auth/pages/UserDetailsPage.js +338 -0
- package/dist/auth/pages/UserDetailsPage.js.map +1 -0
- package/dist/auth/pages/UserProfilePage.d.ts +5 -0
- package/dist/auth/pages/UserProfilePage.d.ts.map +1 -0
- package/dist/auth/pages/UserProfilePage.js +445 -0
- package/dist/auth/pages/UserProfilePage.js.map +1 -0
- package/dist/auth/pages/UsersPage.d.ts +5 -0
- package/dist/auth/pages/UsersPage.d.ts.map +1 -0
- package/dist/auth/pages/UsersPage.js +899 -0
- package/dist/auth/pages/UsersPage.js.map +1 -0
- package/dist/auth/providers/AuthProvider.d.ts +18 -0
- package/dist/auth/providers/AuthProvider.d.ts.map +1 -0
- package/dist/auth/providers/AuthProvider.js +36 -0
- package/dist/auth/providers/AuthProvider.js.map +1 -0
- package/dist/auth/providers/CaptchaProvider.d.ts +13 -0
- package/dist/auth/providers/CaptchaProvider.d.ts.map +1 -0
- package/dist/auth/providers/CaptchaProvider.js +21 -0
- package/dist/auth/providers/CaptchaProvider.js.map +1 -0
- package/dist/auth/store/authStore.d.ts +91 -0
- package/dist/auth/store/authStore.d.ts.map +1 -0
- package/dist/auth/store/authStore.js +314 -0
- package/dist/auth/store/authStore.js.map +1 -0
- package/dist/auth/types/index.d.ts +636 -0
- package/dist/auth/types/index.d.ts.map +1 -0
- package/dist/auth/utils/captchaConfig.d.ts +4 -0
- package/dist/auth/utils/captchaConfig.d.ts.map +1 -0
- package/dist/auth/utils/captchaConfig.js +13 -0
- package/dist/auth/utils/captchaConfig.js.map +1 -0
- package/dist/auth/utils/formatters.d.ts +37 -0
- package/dist/auth/utils/formatters.d.ts.map +1 -0
- package/dist/auth/utils/formatters.js +48 -0
- package/dist/auth/utils/formatters.js.map +1 -0
- package/dist/auth/utils/gatewayBaseUrls.d.ts +6 -0
- package/dist/auth/utils/gatewayBaseUrls.d.ts.map +1 -0
- package/dist/auth/utils/gatewayBaseUrls.js +18 -0
- package/dist/auth/utils/gatewayBaseUrls.js.map +1 -0
- package/dist/auth/utils/index.d.ts +3 -0
- package/dist/auth/utils/index.d.ts.map +1 -0
- package/dist/auth/utils/validation.d.ts +30 -0
- package/dist/auth/utils/validation.d.ts.map +1 -0
- package/dist/auth/utils/validation.js +15 -0
- package/dist/auth/utils/validation.js.map +1 -0
- package/dist/dev/main.d.ts +2 -0
- package/dist/dev/main.d.ts.map +1 -0
- package/dist/generated/global-operations.d.ts +2978 -0
- package/dist/generated/global-operations.d.ts.map +1 -0
- package/dist/generated/global-operations.js +944 -0
- package/dist/generated/global-operations.js.map +1 -0
- package/dist/generated/global-types.d.ts +21253 -0
- package/dist/generated/global-types.d.ts.map +1 -0
- package/dist/generated/wspace-operations.d.ts +2 -0
- package/dist/generated/wspace-operations.d.ts.map +1 -0
- package/dist/generated/wspace-types.d.ts +55214 -0
- package/dist/generated/wspace-types.d.ts.map +1 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +20 -0
- package/dist/microfe-auth.css +3 -0
- package/dist/node_modules/hoist-non-react-statics/dist/hoist-non-react-statics.cjs.js +70 -0
- package/dist/node_modules/hoist-non-react-statics/dist/hoist-non-react-statics.cjs.js.map +1 -0
- package/dist/node_modules/object-assign/index.js +41 -0
- package/dist/node_modules/object-assign/index.js.map +1 -0
- package/dist/node_modules/prop-types/checkPropTypes.js +46 -0
- package/dist/node_modules/prop-types/checkPropTypes.js.map +1 -0
- package/dist/node_modules/prop-types/factoryWithThrowingShims.js +49 -0
- package/dist/node_modules/prop-types/factoryWithThrowingShims.js.map +1 -0
- package/dist/node_modules/prop-types/factoryWithTypeCheckers.js +272 -0
- package/dist/node_modules/prop-types/factoryWithTypeCheckers.js.map +1 -0
- package/dist/node_modules/prop-types/index.js +16 -0
- package/dist/node_modules/prop-types/index.js.map +1 -0
- package/dist/node_modules/prop-types/lib/ReactPropTypesSecret.js +10 -0
- package/dist/node_modules/prop-types/lib/ReactPropTypesSecret.js.map +1 -0
- package/dist/node_modules/prop-types/lib/has.js +10 -0
- package/dist/node_modules/prop-types/lib/has.js.map +1 -0
- package/dist/node_modules/qrcode.react/lib/esm/index.js +959 -0
- package/dist/node_modules/qrcode.react/lib/esm/index.js.map +1 -0
- package/dist/node_modules/react-async-script/lib/esm/async-script-loader.js +114 -0
- package/dist/node_modules/react-async-script/lib/esm/async-script-loader.js.map +1 -0
- package/dist/node_modules/react-google-recaptcha/lib/esm/index.js +8 -0
- package/dist/node_modules/react-google-recaptcha/lib/esm/index.js.map +1 -0
- package/dist/node_modules/react-google-recaptcha/lib/esm/recaptcha-wrapper.js +20 -0
- package/dist/node_modules/react-google-recaptcha/lib/esm/recaptcha-wrapper.js.map +1 -0
- package/dist/node_modules/react-google-recaptcha/lib/esm/recaptcha.js +148 -0
- package/dist/node_modules/react-google-recaptcha/lib/esm/recaptcha.js.map +1 -0
- package/dist/node_modules/react-google-recaptcha-v3/dist/react-google-recaptcha-v3.esm.js +445 -0
- package/dist/node_modules/react-google-recaptcha-v3/dist/react-google-recaptcha-v3.esm.js.map +1 -0
- package/dist/node_modules/react-is/cjs/react-is.development.js +84 -0
- package/dist/node_modules/react-is/cjs/react-is.development.js.map +1 -0
- package/dist/node_modules/react-is/cjs/react-is.production.min.js +64 -0
- package/dist/node_modules/react-is/cjs/react-is.production.min.js.map +1 -0
- package/dist/node_modules/react-is/index.js +12 -0
- package/dist/node_modules/react-is/index.js.map +1 -0
- package/dist/shared/hooks/index.d.ts +7 -0
- package/dist/shared/hooks/index.d.ts.map +1 -0
- package/dist/shared/index.d.ts +6 -0
- package/dist/shared/index.d.ts.map +1 -0
- package/dist/shared/types/index.d.ts +109 -0
- package/dist/shared/types/index.d.ts.map +1 -0
- package/dist/utils/nativeBridge.d.ts +3 -0
- package/dist/utils/nativeBridge.d.ts.map +1 -0
- package/dist/utils/nativeBridge.js +2 -0
- package/package.json +114 -0
|
@@ -0,0 +1,341 @@
|
|
|
1
|
+
import { useAuthStore as e } from "../store/authStore.js";
|
|
2
|
+
import { useMfaOperations as t } from "../hooks/useMfaOperations.js";
|
|
3
|
+
import "../hooks/index.js";
|
|
4
|
+
import { AlertIcon as n, SpinnerIcon as r } from "../components/AuthIcons.js";
|
|
5
|
+
import { QRCodeSVG as i } from "../../node_modules/qrcode.react/lib/esm/index.js";
|
|
6
|
+
import { ConfirmActionDialog as a } from "../components/ConfirmActionDialog.js";
|
|
7
|
+
import { nativeCopyText as o, nativeImpact as s, nativeNotify as c } from "../../utils/nativeBridge.js";
|
|
8
|
+
import { useState as l } from "react";
|
|
9
|
+
import { useI18n as u } from "@burdenoff/fe-libs/shared/providers/shell";
|
|
10
|
+
import { Fragment as d, jsx as f, jsxs as p } from "react/jsx-runtime";
|
|
11
|
+
//#region src/auth/pages/MfaSetupPage.tsx
|
|
12
|
+
function m() {
|
|
13
|
+
let { t: m } = u(), h = (e, t) => {
|
|
14
|
+
let n = m(e);
|
|
15
|
+
return n === e ? t : n;
|
|
16
|
+
}, { setupMFA: g, enableMFA: _, disableMFA: v, isLoading: y } = t(), b = e((e) => e.user), x = e((e) => e.isAuthenticated), [S, C] = l(null), [w, T] = l(""), [E, D] = l(null), [O, k] = l(null), [A, j] = l(!1), [M, N] = l(!1), P = async (e) => {
|
|
17
|
+
try {
|
|
18
|
+
D(null), k(null), C(await g(e));
|
|
19
|
+
} catch (e) {
|
|
20
|
+
console.error("Failed to setup MFA:", e), D(e instanceof Error ? e.message : "Failed to setup MFA. Please try again.");
|
|
21
|
+
}
|
|
22
|
+
};
|
|
23
|
+
return x ? /* @__PURE__ */ p("div", {
|
|
24
|
+
className: "max-w-2xl mx-auto p-6",
|
|
25
|
+
children: [
|
|
26
|
+
/* @__PURE__ */ f(a, {
|
|
27
|
+
open: M,
|
|
28
|
+
onOpenChange: N,
|
|
29
|
+
title: "Disable two-factor authentication?",
|
|
30
|
+
description: "Your account will become less secure and future sign-ins will only require your password until MFA is re-enabled.",
|
|
31
|
+
confirmText: "Disable MFA",
|
|
32
|
+
variant: "warning",
|
|
33
|
+
isPending: y,
|
|
34
|
+
onConfirm: async () => {
|
|
35
|
+
try {
|
|
36
|
+
D(null), k(null), await v(), k("Two-factor authentication has been disabled."), N(!1);
|
|
37
|
+
} catch (e) {
|
|
38
|
+
console.error("Failed to disable MFA:", e), D(e instanceof Error ? e.message : "Failed to disable MFA. Please try again.");
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
}),
|
|
42
|
+
/* @__PURE__ */ p("div", {
|
|
43
|
+
className: "mb-8",
|
|
44
|
+
children: [/* @__PURE__ */ f("h1", {
|
|
45
|
+
className: "text-3xl font-semibold text-[var(--color-text-primary)]",
|
|
46
|
+
children: h("auth.mfaSetup.title", "Two-Factor Authentication")
|
|
47
|
+
}), /* @__PURE__ */ f("p", {
|
|
48
|
+
className: "text-[var(--color-text-secondary)] mt-2",
|
|
49
|
+
children: h("auth.mfaSetup.subtitle", "Add an extra layer of security to your account")
|
|
50
|
+
})]
|
|
51
|
+
}),
|
|
52
|
+
O && /* @__PURE__ */ f("div", {
|
|
53
|
+
className: "mb-6 p-4 rounded-xl bg-[var(--color-status-success-bg-subtle)] border border-[var(--color-status-success-border)]",
|
|
54
|
+
children: /* @__PURE__ */ p("div", {
|
|
55
|
+
className: "flex items-center gap-3",
|
|
56
|
+
children: [/* @__PURE__ */ f("svg", {
|
|
57
|
+
className: "w-5 h-5 text-[var(--color-status-success-text)]",
|
|
58
|
+
fill: "none",
|
|
59
|
+
viewBox: "0 0 24 24",
|
|
60
|
+
stroke: "currentColor",
|
|
61
|
+
children: /* @__PURE__ */ f("path", {
|
|
62
|
+
strokeLinecap: "round",
|
|
63
|
+
strokeLinejoin: "round",
|
|
64
|
+
strokeWidth: 2,
|
|
65
|
+
d: "M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z"
|
|
66
|
+
})
|
|
67
|
+
}), /* @__PURE__ */ f("p", {
|
|
68
|
+
className: "text-[var(--color-status-success-text)]",
|
|
69
|
+
children: O
|
|
70
|
+
})]
|
|
71
|
+
})
|
|
72
|
+
}),
|
|
73
|
+
E && /* @__PURE__ */ p("div", {
|
|
74
|
+
className: "mb-6 flex items-start gap-3 p-4 rounded-xl bg-[var(--color-status-error-bg-subtle)] border border-[var(--color-status-error-border)]",
|
|
75
|
+
children: [/* @__PURE__ */ f(n, { className: "w-5 h-5 text-[var(--color-status-error-text)] flex-shrink-0 mt-0.5" }), /* @__PURE__ */ p("div", {
|
|
76
|
+
className: "flex-1",
|
|
77
|
+
children: [/* @__PURE__ */ f("p", {
|
|
78
|
+
className: "text-sm text-[var(--color-status-error-text)]",
|
|
79
|
+
children: E
|
|
80
|
+
}), /* @__PURE__ */ f("button", {
|
|
81
|
+
onClick: () => D(null),
|
|
82
|
+
className: "mt-2 text-sm text-[var(--color-status-error-text)] hover:underline transition-colors duration-200",
|
|
83
|
+
children: h("auth.mfaSetup.dismiss", "Dismiss")
|
|
84
|
+
})]
|
|
85
|
+
})]
|
|
86
|
+
}),
|
|
87
|
+
S ? /* @__PURE__ */ p("div", {
|
|
88
|
+
className: "p-6 rounded-xl border border-[var(--color-border-default)] bg-[var(--color-bg-surface)] shadow-sm",
|
|
89
|
+
children: [/* @__PURE__ */ p("div", {
|
|
90
|
+
className: "flex items-center gap-3 mb-6",
|
|
91
|
+
children: [/* @__PURE__ */ f("div", {
|
|
92
|
+
className: "w-10 h-10 rounded-full bg-[var(--color-bg-accent)] flex items-center justify-center",
|
|
93
|
+
children: /* @__PURE__ */ f("svg", {
|
|
94
|
+
className: "w-5 h-5 text-[var(--color-text-link)]",
|
|
95
|
+
fill: "none",
|
|
96
|
+
viewBox: "0 0 24 24",
|
|
97
|
+
stroke: "currentColor",
|
|
98
|
+
children: /* @__PURE__ */ f("path", {
|
|
99
|
+
strokeLinecap: "round",
|
|
100
|
+
strokeLinejoin: "round",
|
|
101
|
+
strokeWidth: 2,
|
|
102
|
+
d: "M12 15v2m-6 4h12a2 2 0 002-2v-6a2 2 0 00-2-2H6a2 2 0 00-2 2v6a2 2 0 002 2zm10-10V7a4 4 0 00-8 0v4h8z"
|
|
103
|
+
})
|
|
104
|
+
})
|
|
105
|
+
}), /* @__PURE__ */ p("div", { children: [/* @__PURE__ */ f("h2", {
|
|
106
|
+
className: "text-xl font-semibold text-[var(--color-text-primary)]",
|
|
107
|
+
children: h("auth.mfaSetup.setupAuthApp", "Setup Authenticator App")
|
|
108
|
+
}), /* @__PURE__ */ f("p", {
|
|
109
|
+
className: "text-sm text-[var(--color-text-secondary)]",
|
|
110
|
+
children: h("auth.mfaSetup.scanQr", "Scan the QR code with your authenticator app")
|
|
111
|
+
})] })]
|
|
112
|
+
}), /* @__PURE__ */ p("div", {
|
|
113
|
+
className: "space-y-6",
|
|
114
|
+
children: [
|
|
115
|
+
S.qrCode && /* @__PURE__ */ f("div", {
|
|
116
|
+
className: "flex justify-center",
|
|
117
|
+
children: /* @__PURE__ */ f("div", {
|
|
118
|
+
className: "p-4 bg-[var(--color-bg-surface)] rounded-xl border border-[var(--color-border-default)]",
|
|
119
|
+
children: /* @__PURE__ */ f(i, {
|
|
120
|
+
value: S.qrCode,
|
|
121
|
+
size: 192,
|
|
122
|
+
level: "M",
|
|
123
|
+
includeMargin: !1,
|
|
124
|
+
className: "w-48 h-48"
|
|
125
|
+
})
|
|
126
|
+
})
|
|
127
|
+
}),
|
|
128
|
+
S.secret && /* @__PURE__ */ p("div", { children: [/* @__PURE__ */ f("p", {
|
|
129
|
+
className: "text-sm text-[var(--color-text-secondary)] mb-2",
|
|
130
|
+
children: h("auth.mfaSetup.cantScan", "Can't scan the QR code? Enter this key manually:")
|
|
131
|
+
}), /* @__PURE__ */ f("code", {
|
|
132
|
+
className: "block p-3 rounded-lg bg-[var(--color-bg-muted)] text-[var(--color-text-primary)] font-mono text-sm break-all select-all",
|
|
133
|
+
children: S.secret
|
|
134
|
+
})] }),
|
|
135
|
+
S.backupCodes && S.backupCodes.length > 0 && /* @__PURE__ */ p("div", {
|
|
136
|
+
className: "p-4 rounded-xl bg-[var(--color-status-warning-bg-subtle)] border border-[var(--color-status-warning-border)]",
|
|
137
|
+
children: [
|
|
138
|
+
/* @__PURE__ */ p("div", {
|
|
139
|
+
className: "flex items-start gap-3 mb-3",
|
|
140
|
+
children: [/* @__PURE__ */ f("svg", {
|
|
141
|
+
className: "w-5 h-5 text-[var(--color-status-warning-text)] flex-shrink-0 mt-0.5",
|
|
142
|
+
fill: "none",
|
|
143
|
+
viewBox: "0 0 24 24",
|
|
144
|
+
stroke: "currentColor",
|
|
145
|
+
children: /* @__PURE__ */ f("path", {
|
|
146
|
+
strokeLinecap: "round",
|
|
147
|
+
strokeLinejoin: "round",
|
|
148
|
+
strokeWidth: 2,
|
|
149
|
+
d: "M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z"
|
|
150
|
+
})
|
|
151
|
+
}), /* @__PURE__ */ p("div", { children: [/* @__PURE__ */ f("h3", {
|
|
152
|
+
className: "font-medium text-[var(--color-status-warning-text)]",
|
|
153
|
+
children: h("auth.mfaSetup.saveBackupCodes", "Save your backup codes")
|
|
154
|
+
}), /* @__PURE__ */ f("p", {
|
|
155
|
+
className: "text-sm text-[var(--color-status-warning-text)]",
|
|
156
|
+
children: h("auth.mfaSetup.storeCodesSafely", "Store these codes safely. You can use them to access your account if you lose your authenticator device.")
|
|
157
|
+
})] })]
|
|
158
|
+
}),
|
|
159
|
+
/* @__PURE__ */ f("div", {
|
|
160
|
+
className: "p-3 rounded-lg bg-[var(--color-bg-surface)] grid grid-cols-2 gap-2 mb-3",
|
|
161
|
+
children: S.backupCodes.map((e, t) => /* @__PURE__ */ p("code", {
|
|
162
|
+
className: "text-sm text-[var(--color-text-primary)] font-mono",
|
|
163
|
+
children: [
|
|
164
|
+
t + 1,
|
|
165
|
+
". ",
|
|
166
|
+
e
|
|
167
|
+
]
|
|
168
|
+
}, t))
|
|
169
|
+
}),
|
|
170
|
+
/* @__PURE__ */ f("button", {
|
|
171
|
+
onClick: async () => {
|
|
172
|
+
S?.backupCodes && (s("light"), await o(S.backupCodes.join("\n")) ? (j(!0), c("success"), setTimeout(() => j(!1), 2e3)) : c("error"));
|
|
173
|
+
},
|
|
174
|
+
className: "text-sm font-medium text-[var(--color-status-warning-text)] hover:underline transition-colors duration-200",
|
|
175
|
+
children: A ? h("auth.mfaSetup.copied", "Copied!") : h("auth.mfaSetup.copyBackupCodes", "Copy backup codes")
|
|
176
|
+
})
|
|
177
|
+
]
|
|
178
|
+
}),
|
|
179
|
+
/* @__PURE__ */ p("div", { children: [/* @__PURE__ */ f("label", {
|
|
180
|
+
className: "block text-sm font-medium text-[var(--color-text-primary)] mb-2",
|
|
181
|
+
children: h("auth.mfaSetup.enterCode", "Enter the 6-digit code from your app")
|
|
182
|
+
}), /* @__PURE__ */ f("input", {
|
|
183
|
+
type: "text",
|
|
184
|
+
inputMode: "numeric",
|
|
185
|
+
maxLength: 6,
|
|
186
|
+
value: w,
|
|
187
|
+
onChange: (e) => T(e.target.value.replace(/\D/g, "")),
|
|
188
|
+
placeholder: "000000",
|
|
189
|
+
className: "block w-full px-4 py-3 rounded-xl border border-[var(--color-border-default)] bg-[var(--color-bg-surface)] text-[var(--color-text-primary)] text-center text-2xl tracking-widest font-mono focus:outline-none focus:ring-2 focus:ring-action-primary-bg/20 focus:border-action-primary-bg transition-all duration-300"
|
|
190
|
+
})] }),
|
|
191
|
+
/* @__PURE__ */ p("div", {
|
|
192
|
+
className: "flex gap-3",
|
|
193
|
+
children: [/* @__PURE__ */ f("button", {
|
|
194
|
+
onClick: () => {
|
|
195
|
+
C(null), T(""), D(null);
|
|
196
|
+
},
|
|
197
|
+
className: "flex-1 py-3 px-4 rounded-xl border border-[var(--color-border-default)] text-[var(--color-text-secondary)] font-medium hover:bg-[var(--color-bg-muted)] transition-colors duration-200",
|
|
198
|
+
children: h("auth.mfaSetup.cancel", "Cancel")
|
|
199
|
+
}), /* @__PURE__ */ f("button", {
|
|
200
|
+
onClick: async () => {
|
|
201
|
+
if (w.length !== 6) {
|
|
202
|
+
D(h("auth.mfaSetup.enter6Digit", "Please enter a 6-digit code"));
|
|
203
|
+
return;
|
|
204
|
+
}
|
|
205
|
+
try {
|
|
206
|
+
D(null), await _(w) && (C(null), T(""), k("Two-factor authentication has been enabled successfully!"));
|
|
207
|
+
} catch (e) {
|
|
208
|
+
console.error("Failed to verify MFA code:", e), D(e instanceof Error ? e.message : "Invalid verification code. Please try again.");
|
|
209
|
+
}
|
|
210
|
+
},
|
|
211
|
+
disabled: y || w.length !== 6,
|
|
212
|
+
className: "auth-primary-button flex flex-1 items-center justify-center gap-2 px-4 py-3 font-medium",
|
|
213
|
+
children: y ? /* @__PURE__ */ p(d, { children: [/* @__PURE__ */ f(r, { className: "w-5 h-5 animate-spin" }), /* @__PURE__ */ f("span", { children: "Verifying..." })] }) : h("auth.mfaSetup.enable2fa", "Enable 2FA")
|
|
214
|
+
})]
|
|
215
|
+
})
|
|
216
|
+
]
|
|
217
|
+
})]
|
|
218
|
+
}) : /* @__PURE__ */ f("div", {
|
|
219
|
+
className: "p-6 rounded-xl border border-[var(--color-border-default)] bg-[var(--color-bg-surface)] shadow-sm",
|
|
220
|
+
children: b?.mfaEnabled ? /* @__PURE__ */ p(d, { children: [
|
|
221
|
+
/* @__PURE__ */ p("div", {
|
|
222
|
+
className: "flex items-center gap-4 mb-6",
|
|
223
|
+
children: [/* @__PURE__ */ f("div", {
|
|
224
|
+
className: "w-12 h-12 rounded-full bg-[var(--color-status-success-bg-subtle)] flex items-center justify-center",
|
|
225
|
+
children: /* @__PURE__ */ f("svg", {
|
|
226
|
+
className: "w-6 h-6 text-[var(--color-status-success-text)]",
|
|
227
|
+
fill: "none",
|
|
228
|
+
viewBox: "0 0 24 24",
|
|
229
|
+
stroke: "currentColor",
|
|
230
|
+
children: /* @__PURE__ */ f("path", {
|
|
231
|
+
strokeLinecap: "round",
|
|
232
|
+
strokeLinejoin: "round",
|
|
233
|
+
strokeWidth: 2,
|
|
234
|
+
d: "M9 12l2 2 4-4m5.618-4.016A11.955 11.955 0 0112 2.944a11.955 11.955 0 01-8.618 3.04A12.02 12.02 0 003 9c0 5.591 3.824 10.29 9 11.622 5.176-1.332 9-6.03 9-11.622 0-1.042-.133-2.052-.382-3.016z"
|
|
235
|
+
})
|
|
236
|
+
})
|
|
237
|
+
}), /* @__PURE__ */ p("div", { children: [/* @__PURE__ */ f("h2", {
|
|
238
|
+
className: "text-xl font-semibold text-[var(--color-text-primary)]",
|
|
239
|
+
children: h("auth.mfaSetup.twoFactorOn", "Two-Factor Authentication is On")
|
|
240
|
+
}), /* @__PURE__ */ f("p", {
|
|
241
|
+
className: "text-[var(--color-text-secondary)]",
|
|
242
|
+
children: h("auth.mfaSetup.protected", "Your account is protected with an authenticator app")
|
|
243
|
+
})] })]
|
|
244
|
+
}),
|
|
245
|
+
/* @__PURE__ */ f("div", {
|
|
246
|
+
className: "mb-6 p-4 rounded-lg bg-[var(--color-status-success-bg-subtle)] border border-[var(--color-status-success-border)]",
|
|
247
|
+
children: /* @__PURE__ */ f("p", {
|
|
248
|
+
className: "text-sm text-[var(--color-status-success-text)]",
|
|
249
|
+
children: h("auth.mfaSetup.verificationOnSignIn", "You'll be asked for a verification code from your authenticator app when signing in.")
|
|
250
|
+
})
|
|
251
|
+
}),
|
|
252
|
+
/* @__PURE__ */ f("button", {
|
|
253
|
+
onClick: () => N(!0),
|
|
254
|
+
disabled: y,
|
|
255
|
+
className: "w-full py-3 px-4 rounded-xl border border-[var(--color-status-error-border)] text-[var(--color-status-error-text)] font-medium bg-[var(--color-bg-surface)] hover:bg-[var(--color-status-error-bg-subtle)] disabled:opacity-50 disabled:cursor-not-allowed transition-colors duration-200 flex items-center justify-center gap-2",
|
|
256
|
+
children: y ? /* @__PURE__ */ p(d, { children: [/* @__PURE__ */ f(r, { className: "w-5 h-5 animate-spin" }), /* @__PURE__ */ f("span", { children: "Disabling..." })] }) : h("auth.mfaSetup.disableTwoFactor", "Disable Two-Factor Authentication")
|
|
257
|
+
})
|
|
258
|
+
] }) : /* @__PURE__ */ p(d, { children: [
|
|
259
|
+
/* @__PURE__ */ p("div", {
|
|
260
|
+
className: "flex items-center gap-4 mb-6",
|
|
261
|
+
children: [/* @__PURE__ */ f("div", {
|
|
262
|
+
className: "w-12 h-12 rounded-full bg-[var(--color-bg-muted)] flex items-center justify-center",
|
|
263
|
+
children: /* @__PURE__ */ f("svg", {
|
|
264
|
+
className: "w-6 h-6 text-[var(--color-text-tertiary)]",
|
|
265
|
+
fill: "none",
|
|
266
|
+
viewBox: "0 0 24 24",
|
|
267
|
+
stroke: "currentColor",
|
|
268
|
+
children: /* @__PURE__ */ f("path", {
|
|
269
|
+
strokeLinecap: "round",
|
|
270
|
+
strokeLinejoin: "round",
|
|
271
|
+
strokeWidth: 2,
|
|
272
|
+
d: "M9 12l2 2 4-4m5.618-4.016A11.955 11.955 0 0112 2.944a11.955 11.955 0 01-8.618 3.04A12.02 12.02 0 003 9c0 5.591 3.824 10.29 9 11.622 5.176-1.332 9-6.03 9-11.622 0-1.042-.133-2.052-.382-3.016z"
|
|
273
|
+
})
|
|
274
|
+
})
|
|
275
|
+
}), /* @__PURE__ */ p("div", { children: [/* @__PURE__ */ f("h2", {
|
|
276
|
+
className: "text-xl font-semibold text-[var(--color-text-primary)]",
|
|
277
|
+
children: h("auth.mfaSetup.twoFactorOff", "Two-Factor Authentication is Off")
|
|
278
|
+
}), /* @__PURE__ */ f("p", {
|
|
279
|
+
className: "text-[var(--color-text-secondary)]",
|
|
280
|
+
children: h("auth.mfaSetup.notProtected", "Your account is not protected with 2FA")
|
|
281
|
+
})] })]
|
|
282
|
+
}),
|
|
283
|
+
/* @__PURE__ */ p("div", {
|
|
284
|
+
className: "mb-6 p-4 rounded-lg bg-[var(--color-bg-accent)] border border-[var(--color-border-default)]",
|
|
285
|
+
children: [/* @__PURE__ */ f("h3", {
|
|
286
|
+
className: "font-medium text-[var(--color-text-link)] mb-2",
|
|
287
|
+
children: h("auth.mfaSetup.whyEnable", "Why enable 2FA?")
|
|
288
|
+
}), /* @__PURE__ */ p("ul", {
|
|
289
|
+
className: "text-sm text-[var(--color-text-link)] space-y-1",
|
|
290
|
+
children: [
|
|
291
|
+
/* @__PURE__ */ f("li", { children: "• Protects your account even if your password is compromised" }),
|
|
292
|
+
/* @__PURE__ */ f("li", { children: "• Adds a second verification step during sign-in" }),
|
|
293
|
+
/* @__PURE__ */ f("li", { children: "• Works with popular authenticator apps (Google, Authy, etc.)" })
|
|
294
|
+
]
|
|
295
|
+
})]
|
|
296
|
+
}),
|
|
297
|
+
/* @__PURE__ */ f("button", {
|
|
298
|
+
onClick: () => P("TOTP"),
|
|
299
|
+
disabled: y,
|
|
300
|
+
className: "auth-primary-button flex w-full items-center justify-center gap-2 px-4 py-3 font-medium",
|
|
301
|
+
children: y ? /* @__PURE__ */ p(d, { children: [/* @__PURE__ */ f(r, { className: "w-5 h-5 animate-spin" }), /* @__PURE__ */ f("span", { children: "Setting up..." })] }) : /* @__PURE__ */ p(d, { children: [/* @__PURE__ */ f("svg", {
|
|
302
|
+
className: "w-5 h-5",
|
|
303
|
+
fill: "none",
|
|
304
|
+
viewBox: "0 0 24 24",
|
|
305
|
+
stroke: "currentColor",
|
|
306
|
+
children: /* @__PURE__ */ f("path", {
|
|
307
|
+
strokeLinecap: "round",
|
|
308
|
+
strokeLinejoin: "round",
|
|
309
|
+
strokeWidth: 2,
|
|
310
|
+
d: "M12 15v2m-6 4h12a2 2 0 002-2v-6a2 2 0 00-2-2H6a2 2 0 00-2 2v6a2 2 0 002 2zm10-10V7a4 4 0 00-8 0v4h8z"
|
|
311
|
+
})
|
|
312
|
+
}), /* @__PURE__ */ f("span", { children: h("auth.mfaSetup.enableTwoFactor", "Enable Two-Factor Authentication") })] })
|
|
313
|
+
})
|
|
314
|
+
] })
|
|
315
|
+
})
|
|
316
|
+
]
|
|
317
|
+
}) : /* @__PURE__ */ f("div", {
|
|
318
|
+
className: "max-w-2xl mx-auto p-6",
|
|
319
|
+
children: /* @__PURE__ */ p("div", {
|
|
320
|
+
className: "text-center py-16 border-2 border-dashed border-border-default rounded-xl",
|
|
321
|
+
children: [
|
|
322
|
+
/* @__PURE__ */ f("div", {
|
|
323
|
+
className: "w-16 h-16 mx-auto mb-4 rounded-full bg-status-warning-bg-subtle flex items-center justify-center",
|
|
324
|
+
children: /* @__PURE__ */ f(n, { className: "w-8 h-8 text-status-warning-text" })
|
|
325
|
+
}),
|
|
326
|
+
/* @__PURE__ */ f("h2", {
|
|
327
|
+
className: "text-xl font-semibold text-text-primary mb-2",
|
|
328
|
+
children: h("auth.mfaSetup.authRequired", "Authentication Required")
|
|
329
|
+
}),
|
|
330
|
+
/* @__PURE__ */ f("p", {
|
|
331
|
+
className: "text-text-secondary",
|
|
332
|
+
children: h("auth.mfaSetup.signInToManage", "Please sign in to manage MFA settings")
|
|
333
|
+
})
|
|
334
|
+
]
|
|
335
|
+
})
|
|
336
|
+
});
|
|
337
|
+
}
|
|
338
|
+
//#endregion
|
|
339
|
+
export { m as MfaSetupPage };
|
|
340
|
+
|
|
341
|
+
//# sourceMappingURL=MfaSetupPage.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MfaSetupPage.js","names":[],"sources":["../../../src/auth/pages/MfaSetupPage.tsx"],"sourcesContent":["import { useState } from \"react\";\nimport { useI18n } from \"@burdenoff/fe-libs/shared/providers/shell\";\nimport { QRCodeSVG } from \"qrcode.react\";\nimport { useMfaOperations } from \"../hooks\";\nimport { useAuthStore } from \"../store/authStore\";\nimport { ConfirmActionDialog } from \"../components/ConfirmActionDialog\";\nimport { SpinnerIcon, AlertIcon } from \"../components/AuthIcons\";\nimport type { MFAMethod, MFASetupResult } from \"../types\";\nimport {\n nativeCopyText,\n nativeImpact,\n nativeNotify,\n} from \"../../utils/nativeBridge\";\n\n/**\n * MFA setup and management page with professional UI\n */\nexport function MfaSetupPage() {\n const { t } = useI18n();\n const tr = (key: string, fallback: string): string => {\n const translated = t(key);\n return translated === key ? fallback : translated;\n };\n\n const { setupMFA, enableMFA, disableMFA, isLoading } = useMfaOperations();\n const user = useAuthStore((state) => state.user);\n const isAuthenticated = useAuthStore((state) => state.isAuthenticated);\n const [setupData, setSetupData] = useState<MFASetupResult | null>(null);\n const [verificationCode, setVerificationCode] = useState(\"\");\n const [error, setError] = useState<string | null>(null);\n const [successMessage, setSuccessMessage] = useState<string | null>(null);\n const [backupCodesCopied, setBackupCodesCopied] = useState(false);\n const [showDisableDialog, setShowDisableDialog] = useState(false);\n\n const handleSetupMfa = async (method: MFAMethod) => {\n try {\n setError(null);\n setSuccessMessage(null);\n const data = await setupMFA(method);\n setSetupData(data);\n } catch (err) {\n console.error(\"Failed to setup MFA:\", err);\n setError(\n err instanceof Error\n ? err.message\n : \"Failed to setup MFA. Please try again.\",\n );\n }\n };\n\n const handleVerifyAndEnable = async () => {\n if (verificationCode.length !== 6) {\n setError(tr(\"auth.mfaSetup.enter6Digit\", \"Please enter a 6-digit code\"));\n return;\n }\n\n try {\n setError(null);\n const success = await enableMFA(verificationCode);\n if (success) {\n setSetupData(null);\n setVerificationCode(\"\");\n setSuccessMessage(\n \"Two-factor authentication has been enabled successfully!\",\n );\n }\n } catch (err) {\n console.error(\"Failed to verify MFA code:\", err);\n setError(\n err instanceof Error\n ? err.message\n : \"Invalid verification code. Please try again.\",\n );\n }\n };\n\n const handleDisableMfa = async () => {\n try {\n setError(null);\n setSuccessMessage(null);\n await disableMFA();\n setSuccessMessage(\"Two-factor authentication has been disabled.\");\n setShowDisableDialog(false);\n } catch (err) {\n console.error(\"Failed to disable MFA:\", err);\n setError(\n err instanceof Error\n ? err.message\n : \"Failed to disable MFA. Please try again.\",\n );\n }\n };\n\n const copyBackupCodes = async () => {\n if (setupData?.backupCodes) {\n void nativeImpact(\"light\");\n const ok = await nativeCopyText(setupData.backupCodes.join(\"\\n\"));\n if (ok) {\n setBackupCodesCopied(true);\n void nativeNotify(\"success\");\n setTimeout(() => setBackupCodesCopied(false), 2000);\n } else {\n void nativeNotify(\"error\");\n }\n }\n };\n\n const cancelSetup = () => {\n setSetupData(null);\n setVerificationCode(\"\");\n setError(null);\n };\n\n // Authentication check\n if (!isAuthenticated) {\n return (\n <div className=\"max-w-2xl mx-auto p-6\">\n <div className=\"text-center py-16 border-2 border-dashed border-border-default rounded-xl\">\n <div className=\"w-16 h-16 mx-auto mb-4 rounded-full bg-status-warning-bg-subtle flex items-center justify-center\">\n <AlertIcon className=\"w-8 h-8 text-status-warning-text\" />\n </div>\n <h2 className=\"text-xl font-semibold text-text-primary mb-2\">\n {tr(\"auth.mfaSetup.authRequired\", \"Authentication Required\")}\n </h2>\n <p className=\"text-text-secondary\">\n {tr(\n \"auth.mfaSetup.signInToManage\",\n \"Please sign in to manage MFA settings\",\n )}\n </p>\n </div>\n </div>\n );\n }\n\n return (\n <div className=\"max-w-2xl mx-auto p-6\">\n <ConfirmActionDialog\n open={showDisableDialog}\n onOpenChange={setShowDisableDialog}\n title=\"Disable two-factor authentication?\"\n description=\"Your account will become less secure and future sign-ins will only require your password until MFA is re-enabled.\"\n confirmText=\"Disable MFA\"\n variant=\"warning\"\n isPending={isLoading}\n onConfirm={handleDisableMfa}\n />\n {/* Header */}\n <div className=\"mb-8\">\n <h1 className=\"text-3xl font-semibold text-[var(--color-text-primary)]\">\n {tr(\"auth.mfaSetup.title\", \"Two-Factor Authentication\")}\n </h1>\n <p className=\"text-[var(--color-text-secondary)] mt-2\">\n {tr(\n \"auth.mfaSetup.subtitle\",\n \"Add an extra layer of security to your account\",\n )}\n </p>\n </div>\n\n {/* Success Message */}\n {successMessage && (\n <div className=\"mb-6 p-4 rounded-xl bg-[var(--color-status-success-bg-subtle)] border border-[var(--color-status-success-border)]\">\n <div className=\"flex items-center gap-3\">\n <svg\n className=\"w-5 h-5 text-[var(--color-status-success-text)]\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z\"\n />\n </svg>\n <p className=\"text-[var(--color-status-success-text)]\">\n {successMessage}\n </p>\n </div>\n </div>\n )}\n\n {/* Error Message */}\n {error && (\n <div className=\"mb-6 flex items-start gap-3 p-4 rounded-xl bg-[var(--color-status-error-bg-subtle)] border border-[var(--color-status-error-border)]\">\n <AlertIcon className=\"w-5 h-5 text-[var(--color-status-error-text)] flex-shrink-0 mt-0.5\" />\n <div className=\"flex-1\">\n <p className=\"text-sm text-[var(--color-status-error-text)]\">\n {error}\n </p>\n <button\n onClick={() => setError(null)}\n className=\"mt-2 text-sm text-[var(--color-status-error-text)] hover:underline transition-colors duration-200\"\n >\n {tr(\"auth.mfaSetup.dismiss\", \"Dismiss\")}\n </button>\n </div>\n </div>\n )}\n\n {setupData ? (\n /* Setup Flow */\n <div className=\"p-6 rounded-xl border border-[var(--color-border-default)] bg-[var(--color-bg-surface)] shadow-sm\">\n <div className=\"flex items-center gap-3 mb-6\">\n <div className=\"w-10 h-10 rounded-full bg-[var(--color-bg-accent)] flex items-center justify-center\">\n <svg\n className=\"w-5 h-5 text-[var(--color-text-link)]\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M12 15v2m-6 4h12a2 2 0 002-2v-6a2 2 0 00-2-2H6a2 2 0 00-2 2v6a2 2 0 002 2zm10-10V7a4 4 0 00-8 0v4h8z\"\n />\n </svg>\n </div>\n <div>\n <h2 className=\"text-xl font-semibold text-[var(--color-text-primary)]\">\n {tr(\"auth.mfaSetup.setupAuthApp\", \"Setup Authenticator App\")}\n </h2>\n <p className=\"text-sm text-[var(--color-text-secondary)]\">\n {tr(\n \"auth.mfaSetup.scanQr\",\n \"Scan the QR code with your authenticator app\",\n )}\n </p>\n </div>\n </div>\n\n <div className=\"space-y-6\">\n {/* QR Code */}\n {setupData.qrCode && (\n <div className=\"flex justify-center\">\n <div className=\"p-4 bg-[var(--color-bg-surface)] rounded-xl border border-[var(--color-border-default)]\">\n <QRCodeSVG\n value={setupData.qrCode}\n size={192}\n level=\"M\"\n includeMargin={false}\n className=\"w-48 h-48\"\n />\n </div>\n </div>\n )}\n\n {/* Manual Secret */}\n {setupData.secret && (\n <div>\n <p className=\"text-sm text-[var(--color-text-secondary)] mb-2\">\n {tr(\n \"auth.mfaSetup.cantScan\",\n \"Can't scan the QR code? Enter this key manually:\",\n )}\n </p>\n <code className=\"block p-3 rounded-lg bg-[var(--color-bg-muted)] text-[var(--color-text-primary)] font-mono text-sm break-all select-all\">\n {setupData.secret}\n </code>\n </div>\n )}\n\n {/* Backup Codes */}\n {setupData.backupCodes && setupData.backupCodes.length > 0 && (\n <div className=\"p-4 rounded-xl bg-[var(--color-status-warning-bg-subtle)] border border-[var(--color-status-warning-border)]\">\n <div className=\"flex items-start gap-3 mb-3\">\n <svg\n className=\"w-5 h-5 text-[var(--color-status-warning-text)] flex-shrink-0 mt-0.5\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z\"\n />\n </svg>\n <div>\n <h3 className=\"font-medium text-[var(--color-status-warning-text)]\">\n {tr(\n \"auth.mfaSetup.saveBackupCodes\",\n \"Save your backup codes\",\n )}\n </h3>\n <p className=\"text-sm text-[var(--color-status-warning-text)]\">\n {tr(\n \"auth.mfaSetup.storeCodesSafely\",\n \"Store these codes safely. You can use them to access your account if you lose your authenticator device.\",\n )}\n </p>\n </div>\n </div>\n <div className=\"p-3 rounded-lg bg-[var(--color-bg-surface)] grid grid-cols-2 gap-2 mb-3\">\n {setupData.backupCodes.map((code, i) => (\n <code\n key={i}\n className=\"text-sm text-[var(--color-text-primary)] font-mono\"\n >\n {i + 1}. {code}\n </code>\n ))}\n </div>\n <button\n onClick={copyBackupCodes}\n className=\"text-sm font-medium text-[var(--color-status-warning-text)] hover:underline transition-colors duration-200\"\n >\n {backupCodesCopied\n ? tr(\"auth.mfaSetup.copied\", \"Copied!\")\n : tr(\"auth.mfaSetup.copyBackupCodes\", \"Copy backup codes\")}\n </button>\n </div>\n )}\n\n {/* Verification Code Input */}\n <div>\n <label className=\"block text-sm font-medium text-[var(--color-text-primary)] mb-2\">\n {tr(\n \"auth.mfaSetup.enterCode\",\n \"Enter the 6-digit code from your app\",\n )}\n </label>\n <input\n type=\"text\"\n inputMode=\"numeric\"\n maxLength={6}\n value={verificationCode}\n onChange={(e) =>\n setVerificationCode(e.target.value.replace(/\\D/g, \"\"))\n }\n placeholder=\"000000\"\n className=\"block w-full px-4 py-3 rounded-xl border border-[var(--color-border-default)] bg-[var(--color-bg-surface)] text-[var(--color-text-primary)] text-center text-2xl tracking-widest font-mono focus:outline-none focus:ring-2 focus:ring-action-primary-bg/20 focus:border-action-primary-bg transition-all duration-300\"\n />\n </div>\n\n {/* Action Buttons */}\n <div className=\"flex gap-3\">\n <button\n onClick={cancelSetup}\n className=\"flex-1 py-3 px-4 rounded-xl border border-[var(--color-border-default)] text-[var(--color-text-secondary)] font-medium hover:bg-[var(--color-bg-muted)] transition-colors duration-200\"\n >\n {tr(\"auth.mfaSetup.cancel\", \"Cancel\")}\n </button>\n <button\n onClick={handleVerifyAndEnable}\n disabled={isLoading || verificationCode.length !== 6}\n className=\"auth-primary-button flex flex-1 items-center justify-center gap-2 px-4 py-3 font-medium\"\n >\n {isLoading ? (\n <>\n <SpinnerIcon className=\"w-5 h-5 animate-spin\" />\n <span>Verifying...</span>\n </>\n ) : (\n tr(\"auth.mfaSetup.enable2fa\", \"Enable 2FA\")\n )}\n </button>\n </div>\n </div>\n </div>\n ) : (\n /* Status Display */\n <div className=\"p-6 rounded-xl border border-[var(--color-border-default)] bg-[var(--color-bg-surface)] shadow-sm\">\n {!user?.mfaEnabled ? (\n /* MFA Not Enabled */\n <>\n <div className=\"flex items-center gap-4 mb-6\">\n <div className=\"w-12 h-12 rounded-full bg-[var(--color-bg-muted)] flex items-center justify-center\">\n <svg\n className=\"w-6 h-6 text-[var(--color-text-tertiary)]\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M9 12l2 2 4-4m5.618-4.016A11.955 11.955 0 0112 2.944a11.955 11.955 0 01-8.618 3.04A12.02 12.02 0 003 9c0 5.591 3.824 10.29 9 11.622 5.176-1.332 9-6.03 9-11.622 0-1.042-.133-2.052-.382-3.016z\"\n />\n </svg>\n </div>\n <div>\n <h2 className=\"text-xl font-semibold text-[var(--color-text-primary)]\">\n {tr(\n \"auth.mfaSetup.twoFactorOff\",\n \"Two-Factor Authentication is Off\",\n )}\n </h2>\n <p className=\"text-[var(--color-text-secondary)]\">\n {tr(\n \"auth.mfaSetup.notProtected\",\n \"Your account is not protected with 2FA\",\n )}\n </p>\n </div>\n </div>\n\n <div className=\"mb-6 p-4 rounded-lg bg-[var(--color-bg-accent)] border border-[var(--color-border-default)]\">\n <h3 className=\"font-medium text-[var(--color-text-link)] mb-2\">\n {tr(\"auth.mfaSetup.whyEnable\", \"Why enable 2FA?\")}\n </h3>\n <ul className=\"text-sm text-[var(--color-text-link)] space-y-1\">\n <li>\n • Protects your account even if your password is compromised\n </li>\n <li>• Adds a second verification step during sign-in</li>\n <li>\n • Works with popular authenticator apps (Google, Authy,\n etc.)\n </li>\n </ul>\n </div>\n\n <button\n onClick={() => handleSetupMfa(\"TOTP\")}\n disabled={isLoading}\n className=\"auth-primary-button flex w-full items-center justify-center gap-2 px-4 py-3 font-medium\"\n >\n {isLoading ? (\n <>\n <SpinnerIcon className=\"w-5 h-5 animate-spin\" />\n <span>Setting up...</span>\n </>\n ) : (\n <>\n <svg\n className=\"w-5 h-5\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M12 15v2m-6 4h12a2 2 0 002-2v-6a2 2 0 00-2-2H6a2 2 0 00-2 2v6a2 2 0 002 2zm10-10V7a4 4 0 00-8 0v4h8z\"\n />\n </svg>\n <span>\n {tr(\n \"auth.mfaSetup.enableTwoFactor\",\n \"Enable Two-Factor Authentication\",\n )}\n </span>\n </>\n )}\n </button>\n </>\n ) : (\n /* MFA Enabled */\n <>\n <div className=\"flex items-center gap-4 mb-6\">\n <div className=\"w-12 h-12 rounded-full bg-[var(--color-status-success-bg-subtle)] flex items-center justify-center\">\n <svg\n className=\"w-6 h-6 text-[var(--color-status-success-text)]\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M9 12l2 2 4-4m5.618-4.016A11.955 11.955 0 0112 2.944a11.955 11.955 0 01-8.618 3.04A12.02 12.02 0 003 9c0 5.591 3.824 10.29 9 11.622 5.176-1.332 9-6.03 9-11.622 0-1.042-.133-2.052-.382-3.016z\"\n />\n </svg>\n </div>\n <div>\n <h2 className=\"text-xl font-semibold text-[var(--color-text-primary)]\">\n {tr(\n \"auth.mfaSetup.twoFactorOn\",\n \"Two-Factor Authentication is On\",\n )}\n </h2>\n <p className=\"text-[var(--color-text-secondary)]\">\n {tr(\n \"auth.mfaSetup.protected\",\n \"Your account is protected with an authenticator app\",\n )}\n </p>\n </div>\n </div>\n\n <div className=\"mb-6 p-4 rounded-lg bg-[var(--color-status-success-bg-subtle)] border border-[var(--color-status-success-border)]\">\n <p className=\"text-sm text-[var(--color-status-success-text)]\">\n {tr(\n \"auth.mfaSetup.verificationOnSignIn\",\n \"You'll be asked for a verification code from your authenticator app when signing in.\",\n )}\n </p>\n </div>\n\n <button\n onClick={() => setShowDisableDialog(true)}\n disabled={isLoading}\n className=\"w-full py-3 px-4 rounded-xl border border-[var(--color-status-error-border)] text-[var(--color-status-error-text)] font-medium bg-[var(--color-bg-surface)] hover:bg-[var(--color-status-error-bg-subtle)] disabled:opacity-50 disabled:cursor-not-allowed transition-colors duration-200 flex items-center justify-center gap-2\"\n >\n {isLoading ? (\n <>\n <SpinnerIcon className=\"w-5 h-5 animate-spin\" />\n <span>Disabling...</span>\n </>\n ) : (\n tr(\n \"auth.mfaSetup.disableTwoFactor\",\n \"Disable Two-Factor Authentication\",\n )\n )}\n </button>\n </>\n )}\n </div>\n )}\n </div>\n );\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MFA verification page with professional design
|
|
3
|
+
* Shown when user needs to verify MFA code during login
|
|
4
|
+
* Handles both regular login MFA and SSO MFA flows
|
|
5
|
+
*/
|
|
6
|
+
export declare function MfaVerifyPage(): import("react/jsx-runtime").JSX.Element;
|
|
7
|
+
//# sourceMappingURL=MfaVerifyPage.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MfaVerifyPage.d.ts","sourceRoot":"","sources":["../../../src/auth/pages/MfaVerifyPage.tsx"],"names":[],"mappings":"AAcA;;;;GAIG;AACH,wBAAgB,aAAa,4CAgT5B"}
|
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
import { useAuthStore as e } from "../store/authStore.js";
|
|
2
|
+
import { useMfaOperations as t } from "../hooks/useMfaOperations.js";
|
|
3
|
+
import { MFA_CHALLENGE_ID as n, MFA_PENDING_REFRESH as r, MFA_PENDING_TOKEN as i, MFA_REDIRECT as a } from "../constants/sessionKeys.js";
|
|
4
|
+
import "../hooks/index.js";
|
|
5
|
+
import { AuthLayout as o } from "../components/AuthLayout.js";
|
|
6
|
+
import { AlertIcon as s, SpinnerIcon as c } from "../components/AuthIcons.js";
|
|
7
|
+
import { useEffect as l, useRef as u, useState as d } from "react";
|
|
8
|
+
import { useNavigate as f } from "react-router-dom";
|
|
9
|
+
import { useI18n as p } from "@burdenoff/fe-libs/shared/providers/shell";
|
|
10
|
+
import { Fragment as m, jsx as h, jsxs as g } from "react/jsx-runtime";
|
|
11
|
+
//#region src/auth/pages/MfaVerifyPage.tsx
|
|
12
|
+
function _() {
|
|
13
|
+
let { t: _ } = p(), v = (e, t) => {
|
|
14
|
+
let n = _(e);
|
|
15
|
+
return n === e ? t : n;
|
|
16
|
+
}, y = f(), { verifyMFA: b, mfaChallengeId: x, isLoading: S } = t(), [C, w] = d([
|
|
17
|
+
"",
|
|
18
|
+
"",
|
|
19
|
+
"",
|
|
20
|
+
"",
|
|
21
|
+
"",
|
|
22
|
+
""
|
|
23
|
+
]), [T, E] = d(null), D = u([]), O = typeof window < "u" ? sessionStorage.getItem(n) : null, k = x || O;
|
|
24
|
+
l(() => {
|
|
25
|
+
D.current[0]?.focus(), sessionStorage.getItem(i), sessionStorage.getItem(a);
|
|
26
|
+
}, [O]);
|
|
27
|
+
let A = (e, t) => {
|
|
28
|
+
let n = t.replace(/\D/g, "").slice(-1), r = [...C];
|
|
29
|
+
if (r[e] = n, w(r), n && e < 5 && D.current[e + 1]?.focus(), n && e === 5) {
|
|
30
|
+
let e = r.join("");
|
|
31
|
+
e.length === 6 && N(e);
|
|
32
|
+
}
|
|
33
|
+
}, j = (e, t) => {
|
|
34
|
+
t.key === "Backspace" && !C[e] && e > 0 && D.current[e - 1]?.focus();
|
|
35
|
+
}, M = (e) => {
|
|
36
|
+
e.preventDefault();
|
|
37
|
+
let t = e.clipboardData.getData("text").replace(/\D/g, "").slice(0, 6), n = [...C];
|
|
38
|
+
t.split("").forEach((e, t) => {
|
|
39
|
+
t < 6 && (n[t] = e);
|
|
40
|
+
}), w(n);
|
|
41
|
+
let r = Math.min(t.length - 1, 5);
|
|
42
|
+
D.current[r]?.focus(), t.length === 6 && N(t);
|
|
43
|
+
}, N = async (t) => {
|
|
44
|
+
let o = t || C.join("");
|
|
45
|
+
if (o.length === 6) {
|
|
46
|
+
if (E(null), !k) {
|
|
47
|
+
E(v("auth.mfaVerify.sessionExpired", "MFA session expired. Please log in again."));
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
try {
|
|
51
|
+
let t = await b({
|
|
52
|
+
challengeId: k,
|
|
53
|
+
code: o,
|
|
54
|
+
method: "TOTP"
|
|
55
|
+
});
|
|
56
|
+
if (t.success) {
|
|
57
|
+
let e = sessionStorage.getItem(a);
|
|
58
|
+
sessionStorage.removeItem(n), sessionStorage.removeItem(i), sessionStorage.removeItem(r), sessionStorage.removeItem(a), y(e || "/", { replace: !0 });
|
|
59
|
+
} else {
|
|
60
|
+
if (t.error === "mfa_challenge_expired") {
|
|
61
|
+
sessionStorage.removeItem(n), sessionStorage.removeItem(i), sessionStorage.removeItem(r), sessionStorage.removeItem(a), e.getState().setMfaRequired(!1), y("/auth/login", {
|
|
62
|
+
replace: !0,
|
|
63
|
+
state: { message: "Your verification session expired. Please sign in again." }
|
|
64
|
+
});
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
E(t.error || v("auth.mfaVerify.invalidCode", "Invalid verification code")), w([
|
|
68
|
+
"",
|
|
69
|
+
"",
|
|
70
|
+
"",
|
|
71
|
+
"",
|
|
72
|
+
"",
|
|
73
|
+
""
|
|
74
|
+
]), D.current[0]?.focus();
|
|
75
|
+
}
|
|
76
|
+
} catch (t) {
|
|
77
|
+
if (console.error("MFA verification failed:", t), (t instanceof Error ? t.message : String(t)).includes("mfa_challenge_expired")) {
|
|
78
|
+
sessionStorage.removeItem(n), sessionStorage.removeItem(i), sessionStorage.removeItem(r), sessionStorage.removeItem(a), e.getState().setMfaRequired(!1), y("/auth/login", {
|
|
79
|
+
replace: !0,
|
|
80
|
+
state: { message: "Your verification session expired. Please sign in again." }
|
|
81
|
+
});
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
E(v("auth.mfaVerify.verificationFailed", "Verification failed. Please try again.")), w([
|
|
85
|
+
"",
|
|
86
|
+
"",
|
|
87
|
+
"",
|
|
88
|
+
"",
|
|
89
|
+
"",
|
|
90
|
+
""
|
|
91
|
+
]), D.current[0]?.focus();
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
};
|
|
95
|
+
return /* @__PURE__ */ g(o, {
|
|
96
|
+
title: v("auth.mfaVerify.title", "Two-factor authentication"),
|
|
97
|
+
subtitle: v("auth.mfaVerify.subtitle", "Enter the 6-digit code from your authenticator app"),
|
|
98
|
+
children: [
|
|
99
|
+
/* @__PURE__ */ h("div", {
|
|
100
|
+
className: "flex justify-center mb-6",
|
|
101
|
+
children: /* @__PURE__ */ h("div", {
|
|
102
|
+
className: "w-16 h-16 rounded-full bg-[var(--color-bg-accent)] flex items-center justify-center",
|
|
103
|
+
children: /* @__PURE__ */ h("svg", {
|
|
104
|
+
className: "w-8 h-8 text-[var(--color-text-link)]",
|
|
105
|
+
fill: "none",
|
|
106
|
+
viewBox: "0 0 24 24",
|
|
107
|
+
stroke: "currentColor",
|
|
108
|
+
children: /* @__PURE__ */ h("path", {
|
|
109
|
+
strokeLinecap: "round",
|
|
110
|
+
strokeLinejoin: "round",
|
|
111
|
+
strokeWidth: 2,
|
|
112
|
+
d: "M9 12l2 2 4-4m5.618-4.016A11.955 11.955 0 0112 2.944a11.955 11.955 0 01-8.618 3.04A12.02 12.02 0 003 9c0 5.591 3.824 10.29 9 11.622 5.176-1.332 9-6.03 9-11.622 0-1.042-.133-2.052-.382-3.016z"
|
|
113
|
+
})
|
|
114
|
+
})
|
|
115
|
+
})
|
|
116
|
+
}),
|
|
117
|
+
/* @__PURE__ */ g("form", {
|
|
118
|
+
onSubmit: (e) => {
|
|
119
|
+
e.preventDefault(), N();
|
|
120
|
+
},
|
|
121
|
+
className: "space-y-6",
|
|
122
|
+
children: [
|
|
123
|
+
T && /* @__PURE__ */ g("div", {
|
|
124
|
+
className: "flex items-start gap-3 p-4 rounded-xl bg-[var(--color-status-error-bg-subtle)] border border-[var(--color-status-error-border)]",
|
|
125
|
+
children: [/* @__PURE__ */ h(s, { className: "w-5 h-5 text-[var(--color-status-error-text)] flex-shrink-0 mt-0.5" }), /* @__PURE__ */ h("p", {
|
|
126
|
+
className: "text-sm text-[var(--color-status-error-text)]",
|
|
127
|
+
children: T
|
|
128
|
+
})]
|
|
129
|
+
}),
|
|
130
|
+
/* @__PURE__ */ g("div", {
|
|
131
|
+
className: "space-y-2",
|
|
132
|
+
children: [/* @__PURE__ */ h("label", {
|
|
133
|
+
className: "block text-sm font-medium text-[var(--color-text-primary)] text-center",
|
|
134
|
+
children: v("auth.mfaVerify.verificationCode", "Verification Code")
|
|
135
|
+
}), /* @__PURE__ */ h("div", {
|
|
136
|
+
className: "flex justify-center gap-2 sm:gap-3",
|
|
137
|
+
children: C.map((e, t) => /* @__PURE__ */ h("input", {
|
|
138
|
+
ref: (e) => {
|
|
139
|
+
D.current[t] = e;
|
|
140
|
+
},
|
|
141
|
+
type: "text",
|
|
142
|
+
inputMode: "numeric",
|
|
143
|
+
autoComplete: "one-time-code",
|
|
144
|
+
maxLength: 1,
|
|
145
|
+
value: e,
|
|
146
|
+
onChange: (e) => A(t, e.target.value),
|
|
147
|
+
onKeyDown: (e) => j(t, e),
|
|
148
|
+
onPaste: M,
|
|
149
|
+
className: "w-10 h-12 sm:w-12 sm:h-14 text-center text-xl sm:text-2xl font-semibold rounded-xl border border-[var(--color-border-default)] bg-[var(--color-bg-surface)] text-[var(--color-text-primary)] focus:outline-none focus:ring-2 focus:ring-action-primary-bg/20 focus:border-action-primary-bg transition-all"
|
|
150
|
+
}, t))
|
|
151
|
+
})]
|
|
152
|
+
}),
|
|
153
|
+
/* @__PURE__ */ h("button", {
|
|
154
|
+
type: "submit",
|
|
155
|
+
disabled: S || C.join("").length !== 6,
|
|
156
|
+
className: "auth-primary-button flex w-full items-center justify-center gap-2 px-4 py-3 font-semibold",
|
|
157
|
+
children: S ? /* @__PURE__ */ g(m, { children: [/* @__PURE__ */ h(c, { className: "w-5 h-5 animate-spin" }), /* @__PURE__ */ h("span", { children: "Verifying..." })] }) : v("auth.mfaVerify.verify", "Verify")
|
|
158
|
+
}),
|
|
159
|
+
/* @__PURE__ */ g("div", {
|
|
160
|
+
className: "text-center space-y-3",
|
|
161
|
+
children: [/* @__PURE__ */ h("p", {
|
|
162
|
+
className: "text-sm text-[var(--color-text-secondary)]",
|
|
163
|
+
children: v("auth.mfaVerify.cantAccess", "Can't access your authenticator app?")
|
|
164
|
+
}), /* @__PURE__ */ h("button", {
|
|
165
|
+
type: "button",
|
|
166
|
+
onClick: () => y("/auth/mfa-recovery"),
|
|
167
|
+
className: "text-sm font-medium text-text-link hover:text-text-linkHover transition-colors",
|
|
168
|
+
children: v("auth.mfaVerify.useRecoveryCode", "Use a recovery code")
|
|
169
|
+
})]
|
|
170
|
+
})
|
|
171
|
+
]
|
|
172
|
+
}),
|
|
173
|
+
/* @__PURE__ */ h("p", {
|
|
174
|
+
className: "mt-8 text-center text-sm text-[var(--color-text-secondary)]",
|
|
175
|
+
children: /* @__PURE__ */ h("button", {
|
|
176
|
+
onClick: () => {
|
|
177
|
+
sessionStorage.removeItem(n), sessionStorage.removeItem(i), sessionStorage.removeItem(r), sessionStorage.removeItem(a), e.getState().setMfaRequired(!1), y("/auth/login");
|
|
178
|
+
},
|
|
179
|
+
className: "font-semibold text-text-link hover:text-text-linkHover transition-colors",
|
|
180
|
+
children: v("auth.mfaVerify.backToSignIn", "Back to sign in")
|
|
181
|
+
})
|
|
182
|
+
})
|
|
183
|
+
]
|
|
184
|
+
});
|
|
185
|
+
}
|
|
186
|
+
//#endregion
|
|
187
|
+
export { _ as MfaVerifyPage };
|
|
188
|
+
|
|
189
|
+
//# sourceMappingURL=MfaVerifyPage.js.map
|