@burdenoff/microfe-auth 2026.1030.1 → 2026.1101.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/auth/AuthRoot.js +14 -11
- package/dist/auth/AuthRoot.js.map +1 -1
- package/dist/auth/AuthRoutes.js +1 -2
- package/dist/auth/AuthRoutes.js.map +1 -1
- package/dist/auth/components/AuthIcons.js +1 -2
- package/dist/auth/components/AuthIcons.js.map +1 -1
- package/dist/auth/components/AuthLayout.js +1 -2
- package/dist/auth/components/AuthLayout.js.map +1 -1
- package/dist/auth/components/CaptchaV2.js +9 -10
- package/dist/auth/components/CaptchaV2.js.map +1 -1
- package/dist/auth/components/ConfirmActionDialog.js +1 -2
- package/dist/auth/components/ConfirmActionDialog.js.map +1 -1
- package/dist/auth/components/profile/UserProfileMenu.js +7 -6
- package/dist/auth/components/profile/UserProfileMenu.js.map +1 -1
- package/dist/auth/components/workspace/WorkspaceSelector.js +1 -2
- package/dist/auth/components/workspace/WorkspaceSelector.js.map +1 -1
- package/dist/auth/constants/permissions.js +1 -2
- package/dist/auth/constants/permissions.js.map +1 -1
- package/dist/auth/constants/sessionKeys.js +1 -2
- package/dist/auth/constants/sessionKeys.js.map +1 -1
- package/dist/auth/hooks/contextDeepLink.js +1 -2
- package/dist/auth/hooks/contextDeepLink.js.map +1 -1
- package/dist/auth/hooks/index.js +12 -11
- package/dist/auth/hooks/useAccountOperations.js +1 -2
- package/dist/auth/hooks/useAccountOperations.js.map +1 -1
- package/dist/auth/hooks/useActiveContextBootstrapMirror.js +1 -2
- package/dist/auth/hooks/useActiveContextBootstrapMirror.js.map +1 -1
- package/dist/auth/hooks/useAuthOperations.js +37 -37
- package/dist/auth/hooks/useAuthOperations.js.map +1 -1
- package/dist/auth/hooks/useAuthPermissions.js +1 -2
- package/dist/auth/hooks/useAuthPermissions.js.map +1 -1
- package/dist/auth/hooks/useCaptchaV3.js +1 -2
- package/dist/auth/hooks/useCaptchaV3.js.map +1 -1
- package/dist/auth/hooks/useContextSwitcherData.js +81 -78
- package/dist/auth/hooks/useContextSwitcherData.js.map +1 -1
- package/dist/auth/hooks/useMfaOperations.js +4 -5
- package/dist/auth/hooks/useMfaOperations.js.map +1 -1
- package/dist/auth/hooks/useMyWorkspaces.js +4 -5
- package/dist/auth/hooks/useMyWorkspaces.js.map +1 -1
- package/dist/auth/hooks/useOAuthOperations.js +11 -12
- package/dist/auth/hooks/useOAuthOperations.js.map +1 -1
- package/dist/auth/hooks/usePasswordOperations.js +1 -2
- package/dist/auth/hooks/usePasswordOperations.js.map +1 -1
- package/dist/auth/hooks/useSessionOperations.js +3 -4
- package/dist/auth/hooks/useSessionOperations.js.map +1 -1
- package/dist/auth/hooks/useSignupCaptcha.js +1 -2
- package/dist/auth/hooks/useSignupCaptcha.js.map +1 -1
- package/dist/auth/hooks/useSsoOperations.js +80 -81
- package/dist/auth/hooks/useSsoOperations.js.map +1 -1
- package/dist/auth/hooks/useTokenRefresh.js +8 -12
- package/dist/auth/hooks/useTokenRefresh.js.map +1 -1
- package/dist/auth/hooks/useUserOperations.js +1 -2
- package/dist/auth/hooks/useUserOperations.js.map +1 -1
- package/dist/auth/hooks/useWorkspaceOperations.js +1 -2
- package/dist/auth/hooks/useWorkspaceOperations.js.map +1 -1
- package/dist/auth/hooks/useWorkspaceToken.js +1 -2
- package/dist/auth/hooks/useWorkspaceToken.js.map +1 -1
- package/dist/auth/index.js +19 -18
- package/dist/auth/pages/AuditLogPage.js +21 -22
- package/dist/auth/pages/AuditLogPage.js.map +1 -1
- package/dist/auth/pages/EmailVerifyPage.js +70 -64
- package/dist/auth/pages/EmailVerifyPage.js.map +1 -1
- package/dist/auth/pages/LoginPage.js +89 -105
- package/dist/auth/pages/LoginPage.js.map +1 -1
- package/dist/auth/pages/MagicLinkPage.js +30 -31
- package/dist/auth/pages/MagicLinkPage.js.map +1 -1
- package/dist/auth/pages/MfaSetupPage.js +18 -20
- package/dist/auth/pages/MfaSetupPage.js.map +1 -1
- package/dist/auth/pages/MfaVerifyPage.js +31 -35
- package/dist/auth/pages/MfaVerifyPage.js.map +1 -1
- package/dist/auth/pages/OAuthCallbackPage.js +4 -11
- package/dist/auth/pages/OAuthCallbackPage.js.map +1 -1
- package/dist/auth/pages/PasswordResetPage.js +20 -23
- package/dist/auth/pages/PasswordResetPage.js.map +1 -1
- package/dist/auth/pages/ReactivatePage.js +14 -18
- package/dist/auth/pages/ReactivatePage.js.map +1 -1
- package/dist/auth/pages/RegisterPage.js +180 -181
- package/dist/auth/pages/RegisterPage.js.map +1 -1
- package/dist/auth/pages/SSOClearPage.js +9 -10
- package/dist/auth/pages/SSOClearPage.js.map +1 -1
- package/dist/auth/pages/SSODepositPage.js +9 -13
- package/dist/auth/pages/SSODepositPage.js.map +1 -1
- package/dist/auth/pages/SSORelayCallbackPage.js +3 -7
- package/dist/auth/pages/SSORelayCallbackPage.js.map +1 -1
- package/dist/auth/pages/SSORelayPage.js +11 -10
- package/dist/auth/pages/SSORelayPage.js.map +1 -1
- package/dist/auth/pages/SecurityPage.js +19 -21
- package/dist/auth/pages/SecurityPage.js.map +1 -1
- package/dist/auth/pages/SessionBridgePage.js +9 -16
- package/dist/auth/pages/SessionBridgePage.js.map +1 -1
- package/dist/auth/pages/SessionsPage.js +17 -18
- package/dist/auth/pages/SessionsPage.js.map +1 -1
- package/dist/auth/pages/SsoCallbackPage.js +17 -22
- package/dist/auth/pages/SsoCallbackPage.js.map +1 -1
- package/dist/auth/pages/SsoConfigPage.js +69 -69
- package/dist/auth/pages/SsoConfigPage.js.map +1 -1
- package/dist/auth/pages/SsoLoginPage.js +9 -10
- package/dist/auth/pages/SsoLoginPage.js.map +1 -1
- package/dist/auth/pages/UserDetailsPage.js +16 -23
- package/dist/auth/pages/UserDetailsPage.js.map +1 -1
- package/dist/auth/pages/UserProfilePage.js +140 -141
- package/dist/auth/pages/UserProfilePage.js.map +1 -1
- package/dist/auth/pages/UsersPage.js +446 -453
- package/dist/auth/pages/UsersPage.js.map +1 -1
- package/dist/auth/providers/AuthProvider.js +1 -2
- package/dist/auth/providers/AuthProvider.js.map +1 -1
- package/dist/auth/providers/CaptchaProvider.js +1 -2
- package/dist/auth/providers/CaptchaProvider.js.map +1 -1
- package/dist/auth/store/authStore.js +5 -12
- package/dist/auth/store/authStore.js.map +1 -1
- package/dist/auth/utils/captchaConfig.js +5 -8
- package/dist/auth/utils/captchaConfig.js.map +1 -1
- package/dist/auth/utils/formatters.js +1 -2
- package/dist/auth/utils/formatters.js.map +1 -1
- package/dist/auth/utils/gatewayBaseUrls.js +1 -2
- package/dist/auth/utils/gatewayBaseUrls.js.map +1 -1
- package/dist/auth/utils/legalUrls.js +2 -3
- package/dist/auth/utils/legalUrls.js.map +1 -1
- package/dist/auth/utils/redirect.js +1 -2
- package/dist/auth/utils/redirect.js.map +1 -1
- package/dist/auth/utils/ssoOrigins.js +2 -3
- package/dist/auth/utils/ssoOrigins.js.map +1 -1
- package/dist/auth/utils/validation.js +34 -36
- package/dist/auth/utils/validation.js.map +1 -1
- package/dist/generated/global-operations.js +2 -3
- package/dist/generated/global-operations.js.map +1 -1
- package/dist/generated/wspace-operations.js +2 -3
- package/dist/generated/wspace-operations.js.map +1 -1
- package/dist/microfe-auth.css +1 -1
- package/dist/shared/hooks/useTr.js +1 -2
- package/dist/shared/hooks/useTr.js.map +1 -1
- package/dist/translations/en.js +1 -2
- package/dist/translations/en.js.map +1 -1
- package/dist/utils/nativeBridge.js +1 -2
- package/package.json +7 -3
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"EmailVerifyPage.js","names":[],"sources":["../../../src/auth/pages/EmailVerifyPage.tsx"],"sourcesContent":["import { useEffect, useState, useCallback, useRef } from \"react\";\nimport { useTr } from \"../../shared/hooks/useTr\";\nimport { useSearchParams } from \"react-router\";\nimport { useAuthOperations } from \"../hooks/useAuthOperations\";\nimport { useAuthStore } from \"../store/authStore\";\nimport { AuthLayout } from \"../components/AuthLayout\";\nimport { Button } from \"@burdenoff/fe-libs/button\";\nimport { SpinnerIcon } from \"../components/AuthIcons\";\n\nconst REDIRECT_DELAY = 5; // seconds\n\n/**\n * Navigate to login page with optional email pre-fill\n * Uses window.location.href for reliable navigation (works in new tabs)\n */\nfunction navigateToLogin(email?: string) {\n const baseUrl = \"/auth/login\";\n const url = email ? `${baseUrl}?email=${encodeURIComponent(email)}` : baseUrl;\n window.location.href = url;\n}\n\n/**\n * Email verification page with professional design\n */\nexport function EmailVerifyPage() {\n const tr = useTr();\n\n const [searchParams] = useSearchParams();\n const token = searchParams.get(\"token\");\n const urlEmail = searchParams.get(\"email\");\n const { verifyEmail, resendVerification } = useAuthOperations();\n const user = useAuthStore((state) => state.user);\n const [status, setStatus] = useState<\"verifying\" | \"success\" | \"error\">(\n \"verifying\",\n );\n const verifiedEmailRef = useRef<string | undefined>(urlEmail || undefined);\n const [isResending, setIsResending] = useState(false);\n const [resendSuccess, setResendSuccess] = useState(false);\n const [countdown, setCountdown] = useState(REDIRECT_DELAY);\n\n // Guard against duplicate calls. useRef alone resets across remounts\n // (StrictMode, Suspense resolution of the lazy Auth root, HMR), so we\n // additionally key on the token via sessionStorage — any remount for the\n // same token short-circuits instead of firing a second mutation.\n const verificationInitiatedRef = useRef(false);\n\n useEffect(() => {\n if (!token || verificationInitiatedRef.current) return;\n\n const storageKey = `auth:verifyEmail:inflight:${token}`;\n if (\n typeof window !== \"undefined\" &&\n window.sessionStorage.getItem(storageKey)\n ) {\n return;\n }\n verificationInitiatedRef.current = true;\n try {\n window.sessionStorage.setItem(storageKey, \"1\");\n } catch {\n // sessionStorage unavailable (private mode, SSR); ref guard still applies.\n }\n\n verifyEmail(token)\n .then((result) => {\n if (result.success) {\n setStatus(\"success\");\n if (result.email) verifiedEmailRef.current = result.email;\n } else {\n setStatus(\"error\");\n }\n })\n .catch(() => setStatus(\"error\"));\n }, [token, verifyEmail]);\n\n // Auto-redirect countdown after successful verification\n useEffect(() => {\n if (status !== \"success\") return;\n\n const timer = setInterval(() => {\n setCountdown((prev) => {\n if (prev <= 1) {\n clearInterval(timer);\n navigateToLogin(verifiedEmailRef.current);\n return 0;\n }\n return prev - 1;\n });\n }, 1000);\n\n return () => clearInterval(timer);\n }, [status]);\n\n const handleResend = async () => {\n const resendEmail = urlEmail || user?.email;\n if (!resendEmail) {\n console.error(\"No email available for resend\");\n return;\n }\n setIsResending(true);\n try {\n await resendVerification(resendEmail);\n setResendSuccess(true);\n } catch (err) {\n console.error(\"Failed to resend verification:\", err);\n } finally {\n setIsResending(false);\n }\n };\n\n const handleContinueToLogin = useCallback(() => {\n navigateToLogin(verifiedEmailRef.current);\n }, []);\n\n const handleBackToLogin = useCallback(() => {\n navigateToLogin();\n }, []);\n\n if (status === \"verifying\") {\n return (\n <AuthLayout\n title={tr(\"auth.emailVerify.verifyingTitle\", \"Verifying your email\")}\n subtitle={tr(\n \"auth.emailVerify.verifyingSubtitle\",\n \"Please wait while we confirm your email address\",\n )}\n >\n {/* Loading Spinner */}\n <div className=\"flex flex-col items-center justify-center py-12\">\n <div className=\"size-16 rounded-full bg-[var(--color-bg-accent)] flex items-center justify-center mb-6\">\n <SpinnerIcon className=\"size-8 text-[var(--color-text-link)] animate-spin\" />\n </div>\n <p className=\"text-[var(--color-text-secondary)]\">\n {tr(\"auth.emailVerify.moment\", \"This will only take a moment...\")}\n </p>\n </div>\n </AuthLayout>\n );\n }\n\n if (status === \"success\") {\n return (\n <AuthLayout\n title={tr(\"auth.emailVerify.verifiedTitle\", \"Email verified!\")}\n subtitle={tr(\n \"auth.emailVerify.verifiedSubtitle\",\n \"Your email address has been confirmed\",\n )}\n >\n {/* Success Icon */}\n <div className=\"flex flex-col items-center justify-center py-6\">\n <div className=\"size-20 rounded-full bg-[var(--color-status-success-bg-subtle)] flex items-center justify-center mb-6\">\n <svg\n className=\"size-10 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=\"M5 13l4 4L19 7\"\n />\n </svg>\n </div>\n\n <p className=\"text-center text-[var(--color-text-secondary)] mb-6\">\n {tr(\n \"auth.emailVerify.successMessage\",\n \"Your email has been successfully verified. You can now sign in to access all features.\",\n )}\n </p>\n\n <p className=\"text-center text-sm text-[var(--color-text-tertiary)] mb-6\">\n {tr(\"auth.emailVerify.redirecting\", \"Redirecting to sign in in\")}{\" \"}\n <span className=\"font-semibold text-[var(--color-text-primary)]\">\n {countdown}\n </span>{\" \"}\n {tr(\"auth.emailVerify.seconds\", \"seconds...\")}\n </p>\n\n <Button\n type=\"button\"\n onClick={handleContinueToLogin}\n variant=\"default\"\n size=\"lg\"\n className=\"w-full font-semibold\"\n >\n {tr(\"auth.emailVerify.continueSignIn\", \"Continue to sign in now\")}\n </Button>\n </div>\n </AuthLayout>\n );\n }\n\n // Error state\n return (\n <AuthLayout\n title={tr(\"auth.emailVerify.failedTitle\", \"Verification failed\")}\n subtitle={tr(\n \"auth.emailVerify.failedSubtitle\",\n \"We couldn't verify your email address\",\n )}\n >\n <div className=\"flex flex-col items-center justify-center py-6\">\n {/* Error Icon */}\n <div className=\"size-20 rounded-full bg-[var(--color-status-error-bg-subtle)] flex items-center justify-center mb-6\">\n <svg\n className=\"size-10 text-[var(--color-status-error-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=\"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\n <p className=\"text-center text-[var(--color-text-secondary)] mb-8\">\n {tr(\n \"auth.emailVerify.invalidLink\",\n \"The verification link is invalid or has expired. Please request a new verification email.\",\n )}\n </p>\n\n {resendSuccess ? (\n <div className=\"w-full p-4 rounded-xl bg-[var(--color-status-success-bg-subtle)] border border-[var(--color-status-success-border)] text-center mb-4\">\n <p className=\"text-sm text-[var(--color-status-success-text)]\">\n {tr(\n \"auth.emailVerify.emailSent\",\n \"Verification email sent! Please check your inbox.\",\n )}\n </p>\n </div>\n ) : (\n <Button\n type=\"button\"\n onClick={handleResend}\n disabled={isResending}\n variant=\"default\"\n size=\"lg\"\n className=\"mb-4 w-full font-semibold\"\n >\n {isResending ? (\n <>\n <SpinnerIcon className=\"size-5 animate-spin\" />\n <span>{tr(\"auth.emailVerify.sending\", \"Sending…\")}</span>\n </>\n ) : (\n tr(\"auth.emailVerify.resend\", \"Resend verification email\")\n )}\n </Button>\n )}\n\n <button\n type=\"button\"\n onClick={handleBackToLogin}\n className=\"w-full py-3 px-4 rounded-xl border border-[var(--color-border-default)] bg-[var(--color-bg-surface)] text-[var(--color-text-primary)] font-medium hover:bg-[var(--color-bg-sunken)] transition-all\"\n >\n {tr(\"auth.emailVerify.backToSignIn\", \"Back to sign in\")}\n </button>\n </div>\n </AuthLayout>\n );\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"EmailVerifyPage.js","names":["_Fragment","REDIRECT_DELAY","pendingVerifications","navigateToLogin","baseUrl","url","email","EmailVerifyPage","tr","useTr","searchParams","useSearchParams","token","urlEmail","useAuthOperations","user","useAuthStore","state","status","setStatus","useState","verifiedEmailRef","useRef","isResending","setIsResending","resendSuccess","setResendSuccess","countdown","setCountdown","verificationRef","useEffect","request","verifyEmail","active","result","timer","prev","handleResend","resendEmail","resendVerification","err","handleContinueToLogin","useCallback","handleBackToLogin","AuthLayout","SpinnerIcon","Button","Fragment"],"sources":["../../../src/auth/pages/EmailVerifyPage.tsx"],"sourcesContent":["import { useEffect, useState, useCallback, useRef } from \"react\";\nimport { useTr } from \"../../shared/hooks/useTr\";\nimport { useSearchParams } from \"react-router\";\nimport { useAuthOperations } from \"../hooks/useAuthOperations\";\nimport { useAuthStore } from \"../store/authStore\";\nimport { AuthLayout } from \"../components/AuthLayout\";\nimport { Button } from \"@burdenoff/fe-libs/button\";\nimport { SpinnerIcon } from \"../components/AuthIcons\";\n\nconst REDIRECT_DELAY = 5; // seconds\ntype VerificationRequest = ReturnType<\n ReturnType<typeof useAuthOperations>[\"verifyEmail\"]\n>;\n// Share only pending work across remounts; never persist bearer tokens.\nconst pendingVerifications = new Map<string, VerificationRequest>();\n\n/**\n * Navigate to login page with optional email pre-fill\n * Uses window.location.href for reliable navigation (works in new tabs)\n */\nfunction navigateToLogin(email?: string) {\n const baseUrl = \"/auth/login\";\n const url = email ? `${baseUrl}?email=${encodeURIComponent(email)}` : baseUrl;\n window.location.href = url;\n}\n\n/**\n * Email verification page with professional design\n */\nexport function EmailVerifyPage() {\n const tr = useTr();\n\n const [searchParams] = useSearchParams();\n const token = searchParams.get(\"token\");\n const urlEmail = searchParams.get(\"email\");\n const { verifyEmail, resendVerification } = useAuthOperations();\n const user = useAuthStore((state) => state.user);\n const [status, setStatus] = useState<\"verifying\" | \"success\" | \"error\">(\n \"verifying\",\n );\n const verifiedEmailRef = useRef<string | undefined>(urlEmail || undefined);\n const [isResending, setIsResending] = useState(false);\n const [resendSuccess, setResendSuccess] = useState(false);\n const [countdown, setCountdown] = useState(REDIRECT_DELAY);\n\n const verificationRef = useRef<{\n token: string;\n request: VerificationRequest;\n } | null>(null);\n\n useEffect(() => {\n if (!token) return;\n try {\n // Remove the marker left by older versions, without touching other data.\n window.sessionStorage.removeItem(`auth:verifyEmail:inflight:${token}`);\n } catch {\n // Verification must also work when browser storage is unavailable.\n }\n\n if (verificationRef.current?.token !== token) {\n let request = pendingVerifications.get(token);\n if (!request) {\n request = Promise.resolve()\n .then(() => verifyEmail(token))\n .finally(() => pendingVerifications.delete(token));\n pendingVerifications.set(token, request);\n }\n verificationRef.current = { token, request };\n setStatus(\"verifying\");\n }\n\n let active = true;\n verificationRef.current.request\n .then((result) => {\n if (!active) return;\n if (result.success) {\n setStatus(\"success\");\n if (result.email) verifiedEmailRef.current = result.email;\n } else {\n setStatus(\"error\");\n }\n })\n .catch(() => {\n if (active) setStatus(\"error\");\n });\n return () => {\n active = false;\n };\n }, [token, verifyEmail]);\n\n // Auto-redirect countdown after successful verification\n useEffect(() => {\n if (status !== \"success\") return;\n\n const timer = setInterval(() => {\n setCountdown((prev) => {\n if (prev <= 1) {\n clearInterval(timer);\n navigateToLogin(verifiedEmailRef.current);\n return 0;\n }\n return prev - 1;\n });\n }, 1000);\n\n return () => clearInterval(timer);\n }, [status]);\n\n const handleResend = async () => {\n const resendEmail = urlEmail || user?.email;\n if (!resendEmail) {\n console.error(\"No email available for resend\");\n return;\n }\n setIsResending(true);\n try {\n await resendVerification(resendEmail);\n setResendSuccess(true);\n } catch (err) {\n console.error(\"Failed to resend verification:\", err);\n } finally {\n setIsResending(false);\n }\n };\n\n const handleContinueToLogin = useCallback(() => {\n navigateToLogin(verifiedEmailRef.current);\n }, []);\n\n const handleBackToLogin = useCallback(() => {\n navigateToLogin();\n }, []);\n\n if (status === \"verifying\") {\n return (\n <AuthLayout\n title={tr(\"auth.emailVerify.verifyingTitle\", \"Verifying your email\")}\n subtitle={tr(\n \"auth.emailVerify.verifyingSubtitle\",\n \"Please wait while we confirm your email address\",\n )}\n >\n {/* Loading Spinner */}\n <div className=\"flex flex-col items-center justify-center py-12\">\n <div className=\"size-16 rounded-full bg-[var(--color-bg-accent)] flex items-center justify-center mb-6\">\n <SpinnerIcon className=\"size-8 text-[var(--color-text-link)] animate-spin\" />\n </div>\n <p className=\"text-[var(--color-text-secondary)]\">\n {tr(\"auth.emailVerify.moment\", \"This will only take a moment...\")}\n </p>\n </div>\n </AuthLayout>\n );\n }\n\n if (status === \"success\") {\n return (\n <AuthLayout\n title={tr(\"auth.emailVerify.verifiedTitle\", \"Email verified!\")}\n subtitle={tr(\n \"auth.emailVerify.verifiedSubtitle\",\n \"Your email address has been confirmed\",\n )}\n >\n {/* Success Icon */}\n <div className=\"flex flex-col items-center justify-center py-6\">\n <div className=\"size-20 rounded-full bg-[var(--color-status-success-bg-subtle)] flex items-center justify-center mb-6\">\n <svg\n className=\"size-10 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=\"M5 13l4 4L19 7\"\n />\n </svg>\n </div>\n\n <p className=\"text-center text-[var(--color-text-secondary)] mb-6\">\n {tr(\n \"auth.emailVerify.successMessage\",\n \"Your email has been successfully verified. You can now sign in to access all features.\",\n )}\n </p>\n\n <p className=\"text-center text-sm text-[var(--color-text-tertiary)] mb-6\">\n {tr(\"auth.emailVerify.redirecting\", \"Redirecting to sign in in\")}{\" \"}\n <span className=\"font-semibold text-[var(--color-text-primary)]\">\n {countdown}\n </span>{\" \"}\n {tr(\"auth.emailVerify.seconds\", \"seconds...\")}\n </p>\n\n <Button\n type=\"button\"\n onClick={handleContinueToLogin}\n variant=\"default\"\n size=\"lg\"\n className=\"w-full font-semibold\"\n >\n {tr(\"auth.emailVerify.continueSignIn\", \"Continue to sign in now\")}\n </Button>\n </div>\n </AuthLayout>\n );\n }\n\n // Error state\n return (\n <AuthLayout\n title={tr(\"auth.emailVerify.failedTitle\", \"Verification failed\")}\n subtitle={tr(\n \"auth.emailVerify.failedSubtitle\",\n \"We couldn't verify your email address\",\n )}\n >\n <div className=\"flex flex-col items-center justify-center py-6\">\n {/* Error Icon */}\n <div className=\"size-20 rounded-full bg-[var(--color-status-error-bg-subtle)] flex items-center justify-center mb-6\">\n <svg\n className=\"size-10 text-[var(--color-status-error-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=\"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\n <p className=\"text-center text-[var(--color-text-secondary)] mb-8\">\n {tr(\n \"auth.emailVerify.invalidLink\",\n \"The verification link is invalid or has expired. Please request a new verification email.\",\n )}\n </p>\n\n {resendSuccess ? (\n <div className=\"w-full p-4 rounded-xl bg-[var(--color-status-success-bg-subtle)] border border-[var(--color-status-success-border)] text-center mb-4\">\n <p className=\"text-sm text-[var(--color-status-success-text)]\">\n {tr(\n \"auth.emailVerify.emailSent\",\n \"Verification email sent! Please check your inbox.\",\n )}\n </p>\n </div>\n ) : (\n <Button\n type=\"button\"\n onClick={handleResend}\n disabled={isResending}\n variant=\"default\"\n size=\"lg\"\n className=\"mb-4 w-full font-semibold\"\n >\n {isResending ? (\n <>\n <SpinnerIcon className=\"size-5 animate-spin\" />\n <span>{tr(\"auth.emailVerify.sending\", \"Sending…\")}</span>\n </>\n ) : (\n tr(\"auth.emailVerify.resend\", \"Resend verification email\")\n )}\n </Button>\n )}\n\n <button\n type=\"button\"\n onClick={handleBackToLogin}\n className=\"w-full py-3 px-4 rounded-xl border border-[var(--color-border-default)] bg-[var(--color-bg-surface)] text-[var(--color-text-primary)] font-medium hover:bg-[var(--color-bg-sunken)] transition-all\"\n >\n {tr(\"auth.emailVerify.backToSignIn\", \"Back to sign in\")}\n </button>\n </div>\n </AuthLayout>\n );\n}\n"],"mappings":"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"}
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
1
|
+
import { useTr as e } from "../../shared/hooks/useTr.js";
|
|
2
|
+
import { useAuthOperations as t } from "../hooks/useAuthOperations.js";
|
|
3
|
+
import { useMyWorkspaces as n } from "../hooks/useMyWorkspaces.js";
|
|
4
|
+
import { useOAuthOperations as r } from "../hooks/useOAuthOperations.js";
|
|
5
|
+
import { sanitizePostLoginPath as i } from "../utils/redirect.js";
|
|
6
|
+
import { useAuthStore as a } from "../store/authStore.js";
|
|
7
|
+
import { useAuth as o } from "../providers/AuthProvider.js";
|
|
8
8
|
import { AuthLayout as s } from "../components/AuthLayout.js";
|
|
9
9
|
import { AlertIcon as c, EmailIcon as l, EyeIcon as ee, EyeOffIcon as te, GoogleIcon as u, LockIcon as ne, MicrosoftIcon as d, SpinnerIcon as f } from "../components/AuthIcons.js";
|
|
10
10
|
import { useCaptchaV3 as re } from "../hooks/useCaptchaV3.js";
|
|
@@ -20,7 +20,7 @@ import { resolveGatewayUrls as ve } from "@burdenoff/fe-libs/shared/config/gatew
|
|
|
20
20
|
import { Button as ye } from "@burdenoff/fe-libs/button";
|
|
21
21
|
import { Checkbox as be, PagePurpose as xe } from "@burdenoff/fe-libs/ui";
|
|
22
22
|
import { getProfileTokens as Se, getProfileUser as Ce, getProfileWorkspaceToken as we, getProfiles as Te, resolveActiveProfileId as Ee } from "@burdenoff/fe-libs/shared/providers/shell/ProfileStorageManager";
|
|
23
|
-
|
|
23
|
+
// src/auth/pages/LoginPage.tsx
|
|
24
24
|
function y() {
|
|
25
25
|
if (typeof window > "u") return !1;
|
|
26
26
|
let e = window;
|
|
@@ -74,7 +74,7 @@ function x(e) {
|
|
|
74
74
|
}
|
|
75
75
|
}
|
|
76
76
|
function S() {
|
|
77
|
-
let b =
|
|
77
|
+
let b = e(), S = le(), C = ce(), [w] = ue(), { signIn: Ae, isLoading: T, error: E, errorCode: D, resendVerification: je } = t(), { completeAuthFlow: Me } = n(), { setWorkspace: O, setOrganization: Ne } = de(), { defaultPostLoginPath: Pe } = o(), { initiateGoogleOAuth: Fe, initiateMicrosoftOAuth: Ie, isProviderConfigured: k } = r(), Le = a((e) => e.mfaRequired), { executeRecaptcha: Re } = re(), [A, ze] = h(!1), [Be, Ve] = h(!1), He = p(async (e) => {
|
|
78
78
|
if (typeof window > "u" || y()) return e;
|
|
79
79
|
try {
|
|
80
80
|
let t = _e(), n = new URL(t.url), r = window.location.origin;
|
|
@@ -104,28 +104,23 @@ function S() {
|
|
|
104
104
|
return e;
|
|
105
105
|
}
|
|
106
106
|
}, []), j = ae(!1), M = p((e) => {
|
|
107
|
-
let t =
|
|
108
|
-
if (typeof window > "u")
|
|
109
|
-
|
|
110
|
-
|
|
107
|
+
let t = i(e);
|
|
108
|
+
if (typeof window > "u") S(t);
|
|
109
|
+
else {
|
|
110
|
+
try {
|
|
111
|
+
sessionStorage.setItem("bf-post-login-return-to", t);
|
|
112
|
+
} catch {}
|
|
113
|
+
y() ? S(De(t)) : (j.current = !0, (async () => {
|
|
114
|
+
let e = await Promise.race([He(t), new Promise((e) => {
|
|
115
|
+
window.setTimeout(() => e(t), 3e3);
|
|
116
|
+
})]);
|
|
117
|
+
e.includes("/auth/sso-deposit") ? (fe(), window.location.assign(e), window.setTimeout(() => {
|
|
118
|
+
fe(), window.location.replace(e);
|
|
119
|
+
}, 2500)) : window.location.assign(e), window.setTimeout(() => {
|
|
120
|
+
typeof window < "u" && window.location.pathname === "/auth/login" && S("/dashboard");
|
|
121
|
+
}, 3500);
|
|
122
|
+
})());
|
|
111
123
|
}
|
|
112
|
-
try {
|
|
113
|
-
sessionStorage.setItem("bf-post-login-return-to", t);
|
|
114
|
-
} catch {}
|
|
115
|
-
if (y()) {
|
|
116
|
-
S(De(t));
|
|
117
|
-
return;
|
|
118
|
-
}
|
|
119
|
-
j.current = !0, (async () => {
|
|
120
|
-
let e = await Promise.race([He(t), new Promise((e) => {
|
|
121
|
-
window.setTimeout(() => e(t), 3e3);
|
|
122
|
-
})]);
|
|
123
|
-
e.includes("/auth/sso-deposit") ? (fe(), window.location.assign(e), window.setTimeout(() => {
|
|
124
|
-
fe(), window.location.replace(e);
|
|
125
|
-
}, 2500)) : window.location.assign(e), window.setTimeout(() => {
|
|
126
|
-
typeof window < "u" && window.location.pathname === "/auth/login" && S("/dashboard");
|
|
127
|
-
}, 3500);
|
|
128
|
-
})();
|
|
129
124
|
}, [S, He]), [N, Ue] = h(!1), [P, F] = h(!1), [We, I] = h(!1), [Ge, L] = h(!1), [R, z] = h(!1), [B, V] = h(!1), [Ke, qe] = h(!1), [Je, H] = h(!1), [Ye, U] = h(null), [Xe, W] = h(null), [G, K] = h({
|
|
130
125
|
email: "",
|
|
131
126
|
password: "",
|
|
@@ -139,14 +134,14 @@ function S() {
|
|
|
139
134
|
if (X || A || j.current || me()) return;
|
|
140
135
|
let e = Ee();
|
|
141
136
|
if (e) {
|
|
142
|
-
let
|
|
143
|
-
if (
|
|
144
|
-
|
|
137
|
+
let t = Se(e), n = Ce(e);
|
|
138
|
+
if (t?.accessToken && n && Oe(t.accessToken)) {
|
|
139
|
+
a.getState().loadFromProfile(e), M(ke(Z) ?? "/");
|
|
145
140
|
return;
|
|
146
141
|
}
|
|
147
142
|
}
|
|
148
|
-
let
|
|
149
|
-
|
|
143
|
+
let t = se();
|
|
144
|
+
t && (Ve(!0), window.location.replace(t));
|
|
150
145
|
}, [
|
|
151
146
|
X,
|
|
152
147
|
A,
|
|
@@ -178,7 +173,6 @@ function S() {
|
|
|
178
173
|
case "OAUTH_ONLY_ACCOUNT": return "OAUTH_ONLY";
|
|
179
174
|
case "ACCOUNT_INACTIVE": return "INACTIVE";
|
|
180
175
|
case "EMAIL_NOT_VERIFIED": return "EMAIL_NOT_VERIFIED";
|
|
181
|
-
default: break;
|
|
182
176
|
}
|
|
183
177
|
if (!e) return null;
|
|
184
178
|
let n = e.toLowerCase();
|
|
@@ -199,77 +193,67 @@ function S() {
|
|
|
199
193
|
}, [Le, S]);
|
|
200
194
|
let $e = async (e) => {
|
|
201
195
|
e.preventDefault(), F(!1), I(!1), L(!1), z(!1), V(!1), Y(!1), H(!1), J(null);
|
|
202
|
-
let
|
|
203
|
-
if (!
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
email: n,
|
|
223
|
-
password: G.password,
|
|
224
|
-
rememberMe: G.rememberMe,
|
|
225
|
-
...e ? { recaptchaToken: e } : {}
|
|
226
|
-
});
|
|
227
|
-
if (t.requiresMFA) {
|
|
228
|
-
let e = x(Q.current || Z || (Pe ?? "/dashboard"));
|
|
229
|
-
try {
|
|
230
|
-
sessionStorage.setItem(ie, e);
|
|
231
|
-
} catch {}
|
|
232
|
-
return;
|
|
233
|
-
}
|
|
234
|
-
if (t.success) {
|
|
235
|
-
try {
|
|
236
|
-
let e = t.user?.id;
|
|
237
|
-
if (e) {
|
|
238
|
-
let t = window.location.hostname.endsWith(".local.burdenoff.com") ? ".local.burdenoff.com" : void 0, n = t ? `; domain=${t}` : "", r = window.location.protocol === "https:" ? "; secure" : "", i = JSON.stringify({
|
|
239
|
-
id: e,
|
|
240
|
-
origin: window.location.origin
|
|
241
|
-
});
|
|
242
|
-
document.cookie = `bf-sso=${encodeURIComponent(i)}${n}; path=/; samesite=lax${r}; max-age=86400`, document.cookie = `bf-sso-profile=${encodeURIComponent(i)}${n}; path=/; samesite=lax${r}; max-age=86400`;
|
|
243
|
-
}
|
|
244
|
-
} catch {}
|
|
245
|
-
try {
|
|
246
|
-
G.rememberMe ? localStorage.setItem("remembered_email", n) : localStorage.removeItem("remembered_email");
|
|
247
|
-
} catch (e) {
|
|
248
|
-
console.warn("[LoginPage] Failed to save/clear remembered email:", e);
|
|
196
|
+
let t = (G.email ?? "").trim();
|
|
197
|
+
if (!t) J(b("auth.login.enterEmailOrUsername", "Please enter your email or username"));
|
|
198
|
+
else if (t.includes("@") && !/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(t)) J(b("auth.login.invalidEmail", "Please enter a valid email address"));
|
|
199
|
+
else if (!G.password || G.password.length < 1) J(b("auth.login.enterPassword", "Please enter your password"));
|
|
200
|
+
else if (X && Te().some((e) => e.email.toLowerCase() === t.toLowerCase())) Y(!0), J(null);
|
|
201
|
+
else {
|
|
202
|
+
Y(!1);
|
|
203
|
+
try {
|
|
204
|
+
let e = await Re("login"), n = await Ae({
|
|
205
|
+
email: t,
|
|
206
|
+
password: G.password,
|
|
207
|
+
rememberMe: G.rememberMe,
|
|
208
|
+
...e ? { recaptchaToken: e } : {}
|
|
209
|
+
});
|
|
210
|
+
if (n.requiresMFA) {
|
|
211
|
+
let e = x(Q.current || Z || (Pe ?? "/dashboard"));
|
|
212
|
+
try {
|
|
213
|
+
sessionStorage.setItem(ie, e);
|
|
214
|
+
} catch {}
|
|
215
|
+
return;
|
|
249
216
|
}
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
error: "Auth flow timed out after login"
|
|
217
|
+
if (n.success) {
|
|
218
|
+
try {
|
|
219
|
+
let e = n.user?.id;
|
|
220
|
+
if (e) {
|
|
221
|
+
let t = window.location.hostname.endsWith(".local.burdenoff.com") ? ".local.burdenoff.com" : void 0, n = t ? `; domain=${t}` : "", r = window.location.protocol === "https:" ? "; secure" : "", i = JSON.stringify({
|
|
222
|
+
id: e,
|
|
223
|
+
origin: window.location.origin
|
|
258
224
|
});
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
225
|
+
document.cookie = `bf-sso=${encodeURIComponent(i)}${n}; path=/; samesite=lax${r}; max-age=86400`, document.cookie = `bf-sso-profile=${encodeURIComponent(i)}${n}; path=/; samesite=lax${r}; max-age=86400`;
|
|
226
|
+
}
|
|
227
|
+
} catch {}
|
|
228
|
+
try {
|
|
229
|
+
G.rememberMe ? localStorage.setItem("remembered_email", t) : localStorage.removeItem("remembered_email");
|
|
230
|
+
} catch (e) {
|
|
231
|
+
console.warn("[LoginPage] Failed to save/clear remembered email:", e);
|
|
232
|
+
}
|
|
233
|
+
ze(!0);
|
|
234
|
+
let e = x(Q.current || Z || (Pe ?? "/dashboard"));
|
|
235
|
+
try {
|
|
236
|
+
let t = await Promise.race([Me(n.token), new Promise((e) => {
|
|
237
|
+
window.setTimeout(() => {
|
|
238
|
+
e({
|
|
239
|
+
success: !1,
|
|
240
|
+
error: "Auth flow timed out after login"
|
|
241
|
+
});
|
|
242
|
+
}, 5e3);
|
|
243
|
+
})]);
|
|
244
|
+
t.success ? (t.workspace && (O(t.workspace.id), t.workspace.organizationId && Ne(t.workspace.organizationId)), M(e)) : t.error?.includes("No workspaces found") ? S("/onboarding/create-workspace") : (t.workspace && (O(t.workspace.id), t.workspace.organizationId && Ne(t.workspace.organizationId)), console.warn("Auth flow warning:", t.error), M(e));
|
|
245
|
+
} catch (t) {
|
|
246
|
+
console.error("Auth flow error (login succeeded):", t), M(e);
|
|
247
|
+
} finally {
|
|
248
|
+
j.current || ze(!1);
|
|
249
|
+
}
|
|
266
250
|
}
|
|
251
|
+
} catch (e) {
|
|
252
|
+
let t = e instanceof Error ? e.message : String(e);
|
|
253
|
+
t.includes("reCAPTCHA") && J(t);
|
|
254
|
+
let n = a.getState().errorCode, r = Qe(t, n);
|
|
255
|
+
r === "DELETED" ? I(!0) : r === "SUSPENDED" ? L(!0) : r === "OAUTH_ONLY" ? z(!0) : r === "INACTIVE" ? F(!0) : r === "EMAIL_NOT_VERIFIED" && V(!0);
|
|
267
256
|
}
|
|
268
|
-
} catch (e) {
|
|
269
|
-
let n = e instanceof Error ? e.message : String(e);
|
|
270
|
-
n.includes("reCAPTCHA") && J(n);
|
|
271
|
-
let r = t.getState().errorCode, i = Qe(n, r);
|
|
272
|
-
i === "DELETED" ? I(!0) : i === "SUSPENDED" ? L(!0) : i === "OAUTH_ONLY" ? z(!0) : i === "INACTIVE" ? F(!0) : i === "EMAIL_NOT_VERIFIED" && V(!0);
|
|
273
257
|
}
|
|
274
258
|
};
|
|
275
259
|
m(() => {
|
|
@@ -295,7 +279,8 @@ function S() {
|
|
|
295
279
|
}, nt = async () => {
|
|
296
280
|
qe(!0), H(!1);
|
|
297
281
|
try {
|
|
298
|
-
|
|
282
|
+
let e = (G.email ?? "").trim();
|
|
283
|
+
(await je(e)).success ? H(!0) : J(b("auth.login.resendFailed", "Failed to resend verification email. Please try again."));
|
|
299
284
|
} catch (e) {
|
|
300
285
|
console.error("Failed to resend verification email:", e), J(e instanceof Error ? e.message : b("auth.login.resendFailed", "Failed to resend verification email. Please try again."));
|
|
301
286
|
} finally {
|
|
@@ -625,7 +610,6 @@ function S() {
|
|
|
625
610
|
]
|
|
626
611
|
});
|
|
627
612
|
}
|
|
628
|
-
//#endregion
|
|
629
613
|
export { S as LoginPage };
|
|
630
614
|
|
|
631
615
|
//# sourceMappingURL=LoginPage.js.map
|