Skip to content

Commit

Permalink
Merge pull request #30746 from Expensify/monil-cleanup2FARedirect
Browse files Browse the repository at this point in the history
Redirect internally for 2FA management from bank account step
  • Loading branch information
cristipaval authored Nov 29, 2023
2 parents e909316 + 3c9085a commit 8824c8d
Show file tree
Hide file tree
Showing 12 changed files with 59 additions and 28 deletions.
5 changes: 4 additions & 1 deletion src/ROUTES.ts
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,10 @@ const ROUTES = {
getRoute: (contactMethod: string) => `settings/profile/contact-methods/${encodeURIComponent(contactMethod)}/details` as const,
},
SETTINGS_NEW_CONTACT_METHOD: 'settings/profile/contact-methods/new',
SETTINGS_2FA: 'settings/security/two-factor-auth',
SETTINGS_2FA: {
route: 'settings/security/two-factor-auth',
getRoute: (backTo?: string) => getUrlWithBackToParam('settings/security/two-factor-auth', backTo),
},
SETTINGS_STATUS: 'settings/profile/status',
SETTINGS_STATUS_SET: 'settings/profile/status/set',

Expand Down
2 changes: 1 addition & 1 deletion src/libs/Navigation/linkingConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -195,7 +195,7 @@ const linkingConfig: LinkingOptions<RootStackParamList> = {
exact: true,
},
Settings_TwoFactorAuth: {
path: ROUTES.SETTINGS_2FA,
path: ROUTES.SETTINGS_2FA.route,
exact: true,
},
Settings_Share_Code: {
Expand Down
11 changes: 6 additions & 5 deletions src/libs/actions/TwoFactorAuthActions.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
import Onyx from 'react-native-onyx';
import Navigation from '@libs/Navigation/Navigation';
import ONYXKEYS from '@src/ONYXKEYS';
import ROUTES from '@src/ROUTES';
import ROUTES, {Route} from '@src/ROUTES';
import {TwoFactorAuthStep} from '@src/types/onyx/Account';

/**
* Clear 2FA data if the flow is interrupted without finishing
*/
function clearTwoFactorAuthData() {
Onyx.merge(ONYXKEYS.ACCOUNT, {recoveryCodes: '', twoFactorAuthSecretKey: '', twoFactorAuthStep: '', codesAreCopied: false});
Onyx.merge(ONYXKEYS.ACCOUNT, {recoveryCodes: null, twoFactorAuthSecretKey: null, twoFactorAuthStep: null, codesAreCopied: false});
}
function setTwoFactorAuthStep(twoFactorAuthStep: TwoFactorAuthStep) {
Onyx.merge(ONYXKEYS.ACCOUNT, {twoFactorAuthStep});
Expand All @@ -18,9 +18,10 @@ function setCodesAreCopied() {
Onyx.merge(ONYXKEYS.ACCOUNT, {codesAreCopied: true});
}

function quitAndNavigateBackToSettings() {
function quitAndNavigateBack(backTo?: Route) {
clearTwoFactorAuthData();
Navigation.goBack(ROUTES.SETTINGS_SECURITY);
// eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing
Navigation.goBack(backTo || ROUTES.SETTINGS_SECURITY);
}

export {clearTwoFactorAuthData, setTwoFactorAuthStep, quitAndNavigateBackToSettings, setCodesAreCopied};
export {clearTwoFactorAuthData, setTwoFactorAuthStep, quitAndNavigateBack, setCodesAreCopied};
21 changes: 11 additions & 10 deletions src/pages/ReimbursementAccount/Enable2FAPrompt.js
Original file line number Diff line number Diff line change
@@ -1,43 +1,44 @@
import PropTypes from 'prop-types';
import React from 'react';
import {View} from 'react-native';
import * as Expensicons from '@components/Icon/Expensicons';
import * as Illustrations from '@components/Icon/Illustrations';
import Section from '@components/Section';
import Text from '@components/Text';
import withLocalize, {withLocalizePropTypes} from '@components/withLocalize';
import Navigation from '@navigation/Navigation';
import useThemeStyles from '@styles/useThemeStyles';
import * as Link from '@userActions/Link';
import ROUTES from '@src/ROUTES';

const propTypes = {
...withLocalizePropTypes,

/** policyID of the workspace where user is setting up bank account */
policyID: PropTypes.string.isRequired,
};
function Enable2FAPrompt(props) {

function Enable2FAPrompt({translate, policyID}) {
const styles = useThemeStyles();
const secureYourAccountUrl = encodeURI(
`settings?param={"section":"account","action":"enableTwoFactorAuth","exitTo":"${ROUTES.BANK_ACCOUNT_WITH_STEP_TO_OPEN.getRoute()}","isFromNewDot":"true"}`,
);

return (
<Section
title={props.translate('validationStep.enable2FATitle')}
title={translate('validationStep.enable2FATitle')}
icon={Illustrations.ShieldYellow}
menuItems={[
{
title: props.translate('validationStep.secureYourAccount'),
title: translate('validationStep.secureYourAccount'),
onPress: () => {
Link.openOldDotLink(secureYourAccountUrl);
Navigation.navigate(ROUTES.SETTINGS_2FA.getRoute(ROUTES.BANK_ACCOUNT_WITH_STEP_TO_OPEN.getRoute('', policyID)));
},
icon: Expensicons.Shield,
shouldShowRightIcon: true,
iconRight: Expensicons.NewWindow,
wrapperStyle: [styles.cardMenuItem],
link: () => Link.buildOldDotURL(secureYourAccountUrl),
},
]}
>
<View style={[styles.mv3]}>
<Text>{props.translate('validationStep.enable2FAText')}</Text>
<Text>{translate('validationStep.enable2FAText')}</Text>
</View>
</Section>
);
Expand Down
1 change: 1 addition & 0 deletions src/pages/ReimbursementAccount/ReimbursementAccountPage.js
Original file line number Diff line number Diff line change
Expand Up @@ -520,6 +520,7 @@ class ReimbursementAccountPage extends React.Component {
<ValidationStep
reimbursementAccount={this.props.reimbursementAccount}
onBackButtonPress={this.goBack}
policyID={policyID}
/>
);
}
Expand Down
9 changes: 6 additions & 3 deletions src/pages/ReimbursementAccount/ValidationStep.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,9 @@ const propTypes = {
/** If user has two-factor authentication enabled */
requiresTwoFactorAuth: PropTypes.bool,
}),

/** policyID of the workspace where user is setting up bank account */
policyID: PropTypes.string.isRequired,
};

const defaultProps = {
Expand Down Expand Up @@ -73,7 +76,7 @@ const filterInput = (amount) => {
return value;
};

function ValidationStep({reimbursementAccount, translate, onBackButtonPress, account}) {
function ValidationStep({reimbursementAccount, translate, onBackButtonPress, account, policyID}) {
const styles = useThemeStyles();
/**
* @param {Object} values - form input values passed by the Form component
Expand Down Expand Up @@ -180,7 +183,7 @@ function ValidationStep({reimbursementAccount, translate, onBackButtonPress, acc
</View>
{!requiresTwoFactorAuth && (
<View style={[styles.mln5, styles.mrn5]}>
<Enable2FAPrompt />
<Enable2FAPrompt policyID={policyID} />
</View>
)}
</Form>
Expand Down Expand Up @@ -211,7 +214,7 @@ function ValidationStep({reimbursementAccount, translate, onBackButtonPress, acc
/>
</Section>
{reimbursementAccount.shouldShowResetModal && <WorkspaceResetBankAccountModal reimbursementAccount={reimbursementAccount} />}
{!requiresTwoFactorAuth && <Enable2FAPrompt />}
{!requiresTwoFactorAuth && <Enable2FAPrompt policyID={policyID} />}
</ScrollView>
)}
</ScreenWrapper>
Expand Down
2 changes: 1 addition & 1 deletion src/pages/settings/Security/SecuritySettingsPage.js
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ function SecuritySettingsPage(props) {
{
translationKey: 'twoFactorAuth.headerTitle',
icon: Expensicons.Shield,
action: waitForNavigate(() => Navigation.navigate(ROUTES.SETTINGS_2FA)),
action: waitForNavigate(() => Navigation.navigate(ROUTES.SETTINGS_2FA.getRoute())),
},
{
translationKey: 'closeAccountPage.closeAccount',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import StepWrapperPropTypes from './StepWrapperPropTypes';
function StepWrapper({
title = '',
stepCounter = null,
onBackButtonPress = TwoFactorAuthActions.quitAndNavigateBackToSettings,
onBackButtonPress = () => TwoFactorAuthActions.quitAndNavigateBack(),
children = null,
shouldEnableKeyboardAvoidingView = true,
onEntryTransitionEnd,
Expand Down
3 changes: 2 additions & 1 deletion src/pages/settings/Security/TwoFactorAuth/Steps/CodesStep.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ import * as TwoFactorAuthActions from '@userActions/TwoFactorAuthActions';
import CONST from '@src/CONST';
import ONYXKEYS from '@src/ONYXKEYS';

function CodesStep({account = defaultAccount}) {
function CodesStep({account = defaultAccount, backTo}) {
const theme = useTheme();
const styles = useThemeStyles();
const {translate} = useLocalize();
Expand All @@ -50,6 +50,7 @@ function CodesStep({account = defaultAccount}) {
text: translate('twoFactorAuth.stepCodes'),
total: 3,
}}
onBackButtonPress={() => TwoFactorAuthActions.quitAndNavigateBack(backTo)}
>
<ScrollView contentContainerStyle={styles.flexGrow1}>
<Section
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ function DisabledStep() {
<Button
success
text={translate('common.buttonConfirm')}
onPress={TwoFactorAuthActions.quitAndNavigateBackToSettings}
onPress={() => TwoFactorAuthActions.quitAndNavigateBack()}
/>
</FixedFooter>
</StepWrapper>
Expand Down
19 changes: 18 additions & 1 deletion src/pages/settings/Security/TwoFactorAuth/Steps/SuccessStep.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,24 @@
import PropTypes from 'prop-types';
import React from 'react';
import ConfirmationPage from '@components/ConfirmationPage';
import LottieAnimations from '@components/LottieAnimations';
import useLocalize from '@hooks/useLocalize';
import Navigation from '@navigation/Navigation';
import StepWrapper from '@pages/settings/Security/TwoFactorAuth/StepWrapper/StepWrapper';
import useTwoFactorAuthContext from '@pages/settings/Security/TwoFactorAuth/TwoFactorAuthContext/useTwoFactorAuth';
import * as TwoFactorAuthActions from '@userActions/TwoFactorAuthActions';
import CONST from '@src/CONST';

function SuccessStep() {
const propTypes = {
/** The route where user needs to be redirected after setting up 2FA */
backTo: PropTypes.string,
};

const defaultProps = {
backTo: '',
};

function SuccessStep({backTo}) {
const {setStep} = useTwoFactorAuthContext();

const {translate} = useLocalize();
Expand All @@ -29,10 +40,16 @@ function SuccessStep() {
onButtonPress={() => {
TwoFactorAuthActions.clearTwoFactorAuthData();
setStep(CONST.TWO_FACTOR_AUTH_STEPS.ENABLED);
if (backTo) {
Navigation.navigate(backTo);
}
}}
/>
</StepWrapper>
);
}

SuccessStep.propTypes = propTypes;
SuccessStep.defaultProps = defaultProps;

export default SuccessStep;
10 changes: 7 additions & 3 deletions src/pages/settings/Security/TwoFactorAuth/TwoFactorAuthSteps.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import {useRoute} from '@react-navigation/native';
import lodashGet from 'lodash/get';
import React, {useCallback, useEffect, useMemo, useState} from 'react';
import {withOnyx} from 'react-native-onyx';
import useAnimatedStepContext from '@components/AnimatedStep/useAnimatedStepContext';
Expand All @@ -13,6 +15,8 @@ import TwoFactorAuthContext from './TwoFactorAuthContext';
import {defaultAccount, TwoFactorAuthPropTypes} from './TwoFactorAuthPropTypes';

function TwoFactorAuthSteps({account = defaultAccount}) {
const route = useRoute();
const backTo = lodashGet(route.params, 'backTo', '');
const [currentStep, setCurrentStep] = useState(CONST.TWO_FACTOR_AUTH_STEPS.CODES);

const {setAnimationDirection} = useAnimatedStepContext();
Expand Down Expand Up @@ -45,17 +49,17 @@ function TwoFactorAuthSteps({account = defaultAccount}) {
const renderStep = () => {
switch (currentStep) {
case CONST.TWO_FACTOR_AUTH_STEPS.CODES:
return <CodesStep />;
return <CodesStep backTo={backTo} />;
case CONST.TWO_FACTOR_AUTH_STEPS.VERIFY:
return <VerifyStep />;
case CONST.TWO_FACTOR_AUTH_STEPS.SUCCESS:
return <SuccessStep />;
return <SuccessStep backTo={backTo} />;
case CONST.TWO_FACTOR_AUTH_STEPS.ENABLED:
return <EnabledStep />;
case CONST.TWO_FACTOR_AUTH_STEPS.DISABLED:
return <DisabledStep />;
default:
return <CodesStep />;
return <CodesStep backTo={backTo} />;
}
};

Expand Down

0 comments on commit 8824c8d

Please sign in to comment.