From 847f40dfc22ebad3764b6933a148bf29a4246393 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?nicole=20miko=C5=82ajczyk?= Date: Thu, 26 Jun 2025 12:10:48 +0200 Subject: [PATCH] pl-fe: migrate 2fa settings to tanstack query MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: nicole mikołajczyk --- packages/pl-fe/src/actions/mfa.ts | 55 ------------------- .../pl-fe/src/features/security/mfa-form.tsx | 15 ++--- .../security/mfa/disable-otp-form.tsx | 25 +++++---- .../features/security/mfa/enable-otp-form.tsx | 7 +-- .../security/mfa/otp-confirm-form.tsx | 35 ++++++------ .../pl-fe/src/pages/settings/settings.tsx | 15 ++--- .../pl-fe/src/queries/settings/use-mfa.ts | 50 +++++++++++++++++ packages/pl-fe/src/reducers/index.ts | 2 - packages/pl-fe/src/reducers/security.ts | 49 ----------------- 9 files changed, 93 insertions(+), 160 deletions(-) delete mode 100644 packages/pl-fe/src/actions/mfa.ts create mode 100644 packages/pl-fe/src/queries/settings/use-mfa.ts delete mode 100644 packages/pl-fe/src/reducers/security.ts diff --git a/packages/pl-fe/src/actions/mfa.ts b/packages/pl-fe/src/actions/mfa.ts deleted file mode 100644 index 6cb33a273..000000000 --- a/packages/pl-fe/src/actions/mfa.ts +++ /dev/null @@ -1,55 +0,0 @@ -import { getClient } from '../api'; - -import type { PlApiClient } from 'pl-api'; -import type { AppDispatch, RootState } from 'pl-fe/store'; - -const MFA_FETCH_SUCCESS = 'MFA_FETCH_SUCCESS' as const; - -const MFA_CONFIRM_SUCCESS = 'MFA_CONFIRM_SUCCESS' as const; - -const MFA_DISABLE_SUCCESS = 'MFA_DISABLE_SUCCESS' as const; - -const fetchMfa = () => - (dispatch: AppDispatch, getState: () => RootState) => - getClient(getState).settings.mfa.getMfaSettings().then((data) => { - dispatch({ type: MFA_FETCH_SUCCESS, data }); - }); - -const fetchBackupCodes = () => - (dispatch: AppDispatch, getState: () => RootState) => - getClient(getState).settings.mfa.getMfaBackupCodes(); - -const setupMfa = (method: 'totp') => - (dispatch: AppDispatch, getState: () => RootState) => - getClient(getState).settings.mfa.getMfaSetup(method); - -const confirmMfa = (method: 'totp', code: string, password: string) => - (dispatch: AppDispatch, getState: () => RootState) => - getClient(getState).settings.mfa.confirmMfaSetup(method, code, password).then((data) => { - dispatch({ type: MFA_CONFIRM_SUCCESS, method, code }); - return data; - }); - -const disableMfa = (method: 'totp', password: string) => - (dispatch: AppDispatch, getState: () => RootState) => - getClient(getState).settings.mfa.disableMfa(method, password).then((data) => { - dispatch({ type: MFA_DISABLE_SUCCESS, method }); - return data; - }); - -type MfaAction = - | { type: typeof MFA_FETCH_SUCCESS; data: Awaited)['settings']['mfa']['getMfaSettings']>> } - | { type: typeof MFA_CONFIRM_SUCCESS; method: 'totp'; code: string } - | { type: typeof MFA_DISABLE_SUCCESS; method: 'totp' } - -export { - MFA_FETCH_SUCCESS, - MFA_CONFIRM_SUCCESS, - MFA_DISABLE_SUCCESS, - fetchMfa, - fetchBackupCodes, - setupMfa, - confirmMfa, - disableMfa, - type MfaAction, -}; diff --git a/packages/pl-fe/src/features/security/mfa-form.tsx b/packages/pl-fe/src/features/security/mfa-form.tsx index 43dc9dfeb..4979ca992 100644 --- a/packages/pl-fe/src/features/security/mfa-form.tsx +++ b/packages/pl-fe/src/features/security/mfa-form.tsx @@ -1,12 +1,10 @@ -import React, { useEffect, useState } from 'react'; +import React, { useState } from 'react'; import { useIntl, defineMessages } from 'react-intl'; -import { fetchMfa } from 'pl-fe/actions/mfa'; import Column from 'pl-fe/components/ui/column'; import Stack from 'pl-fe/components/ui/stack'; -import { useAppDispatch } from 'pl-fe/hooks/use-app-dispatch'; -import { useAppSelector } from 'pl-fe/hooks/use-app-selector'; import { useFeatures } from 'pl-fe/hooks/use-features'; +import { useMfaConfig } from 'pl-fe/queries/settings/use-mfa'; import DisableOtpForm from './mfa/disable-otp-form'; import EnableOtpForm from './mfa/enable-otp-form'; @@ -18,24 +16,19 @@ const messages = defineMessages({ const MfaForm: React.FC = () => { const intl = useIntl(); - const dispatch = useAppDispatch(); const features = useFeatures(); const [displayOtpForm, setDisplayOtpForm] = useState(false); - useEffect(() => { - dispatch(fetchMfa()); - }, []); + const { data: mfa } = useMfaConfig(); const handleSetupProceedClick = (event: React.MouseEvent) => { event.preventDefault(); setDisplayOtpForm(true); }; - const mfa = useAppSelector((state) => state.security.mfa); - return ( - {mfa.settings.totp ? ( + {mfa?.settings.totp ? ( ) : ( diff --git a/packages/pl-fe/src/features/security/mfa/disable-otp-form.tsx b/packages/pl-fe/src/features/security/mfa/disable-otp-form.tsx index 4e088cb3d..bad8766be 100644 --- a/packages/pl-fe/src/features/security/mfa/disable-otp-form.tsx +++ b/packages/pl-fe/src/features/security/mfa/disable-otp-form.tsx @@ -2,7 +2,6 @@ import React, { useState, useCallback } from 'react'; import { useIntl, defineMessages, FormattedMessage } from 'react-intl'; import { useHistory } from 'react-router-dom'; -import { disableMfa } from 'pl-fe/actions/mfa'; import Button from 'pl-fe/components/ui/button'; import Form from 'pl-fe/components/ui/form'; import FormActions from 'pl-fe/components/ui/form-actions'; @@ -11,6 +10,7 @@ import Input from 'pl-fe/components/ui/input'; import Stack from 'pl-fe/components/ui/stack'; import Text from 'pl-fe/components/ui/text'; import { useAppDispatch } from 'pl-fe/hooks/use-app-dispatch'; +import { useDisableMfa } from 'pl-fe/queries/settings/use-mfa'; import toast from 'pl-fe/toast'; const messages = defineMessages({ @@ -21,22 +21,23 @@ const messages = defineMessages({ }); const DisableOtpForm: React.FC = () => { - const [isLoading, setIsLoading] = useState(false); const [password, setPassword] = useState(''); const intl = useIntl(); const dispatch = useAppDispatch(); const history = useHistory(); + const { mutate: disableMfa, isPending } = useDisableMfa(); + const handleSubmit = useCallback(() => { - setIsLoading(true); - dispatch(disableMfa('totp', password)).then(() => { - toast.success(intl.formatMessage(messages.mfaDisableSuccess)); - history.push('../auth/edit'); - }).finally(() => { - setIsLoading(false); - }).catch(() => { - toast.error(intl.formatMessage(messages.disableFail)); + disableMfa(password, { + onSuccess: () => { + toast.success(intl.formatMessage(messages.mfaDisableSuccess)); + history.push('../auth/edit'); + }, + onError: () => { + toast.error(intl.formatMessage(messages.disableFail)); + }, }); }, [password, dispatch, intl]); @@ -65,7 +66,7 @@ const DisableOtpForm: React.FC = () => { placeholder={intl.formatMessage(messages.passwordPlaceholder)} name='password' onChange={handleInputChange} - disabled={isLoading} + disabled={isPending} value={password} required /> @@ -73,7 +74,7 @@ const DisableOtpForm: React.FC = () => {