From b1a1a25bf71e22733ce656ed8435fba1dffafde6 Mon Sep 17 00:00:00 2001 From: Myzel394 <50424412+Myzel394@users.noreply.github.com> Date: Sun, 26 Feb 2023 18:20:19 +0100 Subject: [PATCH] feat: Add recover 2fa --- public/locales/en-US/translation.json | 13 +++ src/App.tsx | 5 + src/route-widgets/LoginRoute/OTPForm.tsx | 1 + src/routes/Recover2FARoute.tsx | 123 +++++++++++++++++++++++ 4 files changed, 142 insertions(+) create mode 100644 src/routes/Recover2FARoute.tsx diff --git a/public/locales/en-US/translation.json b/public/locales/en-US/translation.json index 9057d18..7c6ebbf 100644 --- a/public/locales/en-US/translation.json +++ b/public/locales/en-US/translation.json @@ -104,6 +104,19 @@ } } }, + "Recover2FARoute": { + "title": "Recover Two-Factor-Authentication", + "description": "We are very sorry if you lost your codes. Please enter a recovery code to continue. Note that this will disable two-factor authentication for your account. You can enable it again in the settings.", + "forms": { + "recoveryCode": { + "label": "Recovery Code" + }, + "submit": "Disable 2FA" + }, + "unauthorized": "Please make sure to log in first and then reset your two-factor authentication on its screen.", + "canLoginNow": "Two-factor authentication has been disabled. You can now log in.", + "loggedIn": "Two-factor authentication has been disabled. You are now logged in." + }, "CompleteAccountRoute": { "forms": { "generateReports": { diff --git a/src/App.tsx b/src/App.tsx index 79c00e0..c54ecea 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -20,6 +20,7 @@ import GlobalSettingsRoute from "~/routes/GlobalSettingsRoute" import I18nHandler from "./I18nHandler" import LoginRoute from "~/routes/LoginRoute" import LogoutRoute from "~/routes/LogoutRoute" +import Recover2FARoute from "./routes/Recover2FARoute" import RedirectRoute from "./routes/RedirectRoute" import ReportDetailRoute from "~/routes/ReportDetailRoute" import ReportsRoute from "~/routes/ReportsRoute" @@ -53,6 +54,10 @@ const router = createBrowserRouter([ loader: getServerSettings, element: , }, + { + path: "/auth/recover-2fa", + element: , + }, { path: "/auth/signup", loader: getServerSettings, diff --git a/src/route-widgets/LoginRoute/OTPForm.tsx b/src/route-widgets/LoginRoute/OTPForm.tsx index 95ac2e2..457c21d 100644 --- a/src/route-widgets/LoginRoute/OTPForm.tsx +++ b/src/route-widgets/LoginRoute/OTPForm.tsx @@ -96,6 +96,7 @@ export default function OTPForm({ (delete2FA, { + onSuccess: async () => { + try { + const user = await getMe() + + showSuccess(t("routes.Recover2FARoute.loggedIn").toString()) + login(user) + navigate("/aliases") + } catch (error) { + showSuccess(t("routes.Recover2FARoute.canLoginNow").toString()) + navigate("/auth/login") + } + }, + onError: error => { + if (error.response?.status == 401) { + showError(t("routes.Recover2FARoute.unauthorized").toString()) + navigate("/auth/login") + } else { + showError(error) + } + }, + }) + + const schema = yup.object().shape({ + recoveryCode: yup.string().required().label(t("routes.LoginRoute.forms.otp.code.label")), + }) + + const formik = useFormik
({ + validationSchema: schema, + initialValues: { + recoveryCode: "", + }, + onSubmit: async values => + mutateAsync({ + recoveryCode: values.recoveryCode.replaceAll("-", ""), + }), + }) + + return ( + + + + + + + {t("routes.Recover2FARoute.title")} + + + + + + + + + + {t("routes.Recover2FARoute.description")} + + + + + + + } + > + {t("routes.Recover2FARoute.forms.submit")} + + + + + +
+ ) +}