From 06a0010b79956fa0241478306952d246deea54ff Mon Sep 17 00:00:00 2001 From: Tim Golen Date: Mon, 26 Aug 2024 11:10:32 -0600 Subject: [PATCH 01/13] Add get codes page --- src/CONST.ts | 1 + src/languages/en.ts | 2 + src/languages/es.ts | 2 + .../TwoFactorAuth/Steps/EnabledStep.tsx | 3 +- .../Security/TwoFactorAuth/Steps/GetCode.tsx | 103 ++++++++++++++++++ .../TwoFactorAuth/TwoFactorAuthSteps.tsx | 3 + 6 files changed, 113 insertions(+), 1 deletion(-) create mode 100644 src/pages/settings/Security/TwoFactorAuth/Steps/GetCode.tsx diff --git a/src/CONST.ts b/src/CONST.ts index 7b5320e7c6ef..2c45c41be88e 100755 --- a/src/CONST.ts +++ b/src/CONST.ts @@ -3860,6 +3860,7 @@ const CONST = { SUCCESS: 'SUCCESS', ENABLED: 'ENABLED', DISABLED: 'DISABLED', + GETCODE: 'GETCODE', }, STRIPE_GBP_AUTH_STATUSES: { SUCCEEDED: 'succeeded', diff --git a/src/languages/en.ts b/src/languages/en.ts index 632da6f9c3ae..e22822bc5ace 100755 --- a/src/languages/en.ts +++ b/src/languages/en.ts @@ -1111,9 +1111,11 @@ export default { whatIsTwoFactorAuth: 'Two-factor authentication (2FA) helps keep your account safe. When logging in, you’ll need to enter a code generated by your preferred authenticator app.', disableTwoFactorAuth: 'Disable two-factor authentication', disableTwoFactorAuthConfirmation: 'Two-factor authentication keeps your account more secure. Are you sure you want to disable it?', + explainProcessToRemove: 'In order to disable Two-factor authentication, please enter a valid code from your authentication app.', disabled: 'Two-factor authentication is now disabled', noAuthenticatorApp: 'You’ll no longer require an authenticator app to log into Expensify.', stepCodes: 'Recovery codes', + gatherCode: 'Enter code', keepCodesSafe: 'Keep these recovery codes safe!', codesLoseAccess: "If you lose access to your authenticator app and don’t have these codes, you'll lose access to your account. \n\nNote: Setting up two-factor authentication will log you out of all other active sessions.", diff --git a/src/languages/es.ts b/src/languages/es.ts index 77ba5e5abf45..9423a91b0425 100644 --- a/src/languages/es.ts +++ b/src/languages/es.ts @@ -1116,9 +1116,11 @@ export default { 'La autenticación de dos factores (2FA) ayuda a mantener tu cuenta segura. Al iniciar sesión, deberás ingresar un código generado por tu aplicación de autenticación preferida.', disableTwoFactorAuth: 'Deshabilitar la autenticación de dos factores', disableTwoFactorAuthConfirmation: 'La autenticación de dos factores mantiene tu cuenta más segura. ¿Estás seguro de que quieres desactivarla?', + explainProcessToRemove: 'In order to disable Two-factor authentication, please enter a valid code from your authentication app.', disabled: 'La autenticación de dos factores está ahora deshabilitada', noAuthenticatorApp: 'Ya no necesitarás una aplicación de autenticación para iniciar sesión en Expensify.', stepCodes: 'Códigos de recuperación', + gatherCode: 'Enter code', keepCodesSafe: '¡Guarda los códigos de recuperación en un lugar seguro!', codesLoseAccess: 'Si pierdes el acceso a tu aplicación de autenticación y no tienes estos códigos, perderás el acceso a tu cuenta. \n\nNota: Configurar la autenticación de dos factores cerrará la sesión de todas las demás sesiones activas.', diff --git a/src/pages/settings/Security/TwoFactorAuth/Steps/EnabledStep.tsx b/src/pages/settings/Security/TwoFactorAuth/Steps/EnabledStep.tsx index ddd99f8fb54e..a42017a16bb8 100644 --- a/src/pages/settings/Security/TwoFactorAuth/Steps/EnabledStep.tsx +++ b/src/pages/settings/Security/TwoFactorAuth/Steps/EnabledStep.tsx @@ -33,7 +33,8 @@ function EnabledStep() { { title: translate('twoFactorAuth.disableTwoFactorAuth'), onPress: () => { - setIsConfirmModalVisible(true); + setStep(CONST.TWO_FACTOR_AUTH_STEPS.GETCODE); + // setIsConfirmModalVisible(true); }, icon: Expensicons.Close, iconFill: theme.danger, diff --git a/src/pages/settings/Security/TwoFactorAuth/Steps/GetCode.tsx b/src/pages/settings/Security/TwoFactorAuth/Steps/GetCode.tsx new file mode 100644 index 000000000000..bfb9b7cb34ce --- /dev/null +++ b/src/pages/settings/Security/TwoFactorAuth/Steps/GetCode.tsx @@ -0,0 +1,103 @@ +import type {RouteProp} from '@react-navigation/native'; +import {useRoute} from '@react-navigation/native'; +import React, {useEffect, useState, useRef} from 'react'; +import {ActivityIndicator, View} from 'react-native'; +import {withOnyx} from 'react-native-onyx'; +import Button from '@components/Button'; +import FixedFooter from '@components/FixedFooter'; +import FormHelpMessage from '@components/FormHelpMessage'; +import * as Expensicons from '@components/Icon/Expensicons'; +import * as Illustrations from '@components/Icon/Illustrations'; +import PressableWithDelayToggle from '@components/Pressable/PressableWithDelayToggle'; +import ScrollView from '@components/ScrollView'; +import Section from '@components/Section'; +import Text from '@components/Text'; +import ValidateAccountMessage from '@components/ValidateAccountMessage'; +import useLocalize from '@hooks/useLocalize'; +import useResponsiveLayout from '@hooks/useResponsiveLayout'; +import useTheme from '@hooks/useTheme'; +import useThemeStyles from '@hooks/useThemeStyles'; +import Clipboard from '@libs/Clipboard'; +import localFileDownload from '@libs/localFileDownload'; +import type {BackToParams, SettingsNavigatorParamList} from '@libs/Navigation/types'; +import StepWrapper from '@pages/settings/Security/TwoFactorAuth/StepWrapper/StepWrapper'; +import useTwoFactorAuthContext from '@pages/settings/Security/TwoFactorAuth/TwoFactorAuthContext/useTwoFactorAuth'; +import TwoFactorAuthForm from '@pages/settings/Security/TwoFactorAuth/TwoFactorAuthForm'; +import type {BaseTwoFactorAuthFormOnyxProps} from '@pages/settings/Security/TwoFactorAuth/TwoFactorAuthForm/types'; +import * as Session from '@userActions/Session'; +import * as TwoFactorAuthActions from '@userActions/TwoFactorAuthActions'; +import CONST from '@src/CONST'; +import ONYXKEYS from '@src/ONYXKEYS'; +import ROUTES from '@src/ROUTES'; +import type SCREENS from '@src/SCREENS'; + +type CodesStepProps = BaseTwoFactorAuthFormOnyxProps & BackToParams; + +function CodesStep({account, user, backTo}: CodesStepProps) { + const theme = useTheme(); + const styles = useThemeStyles(); + const {translate} = useLocalize(); + const {isExtraSmallScreenWidth, isSmallScreenWidth} = useResponsiveLayout(); + const [error, setError] = useState(''); + const isUserValidated = user?.validated; + const route = useRoute>(); + + const formRef = useRef(null); + + const {setStep} = useTwoFactorAuthContext(); + + useEffect(() => { + // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing + if (account?.requiresTwoFactorAuth || account?.recoveryCodes || !isUserValidated) { + return; + } + Session.toggleTwoFactorAuth(true); + // eslint-disable-next-line react-compiler/react-compiler, react-hooks/exhaustive-deps -- We want to run this when component mounts + }, [isUserValidated]); + + return ( + setStep(CONST.TWO_FACTOR_AUTH_STEPS.ENABLED, CONST.ANIMATION_DIRECTION.OUT)} + onEntryTransitionEnd={() => formRef.current && formRef.current.focus()} + > + + + {translate('twoFactorAuth.explainProcessToRemove')} + + + + + + +