Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix - User is able to disable 2FA when connected to Xero accounting #53948

2 changes: 2 additions & 0 deletions src/languages/en.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1356,6 +1356,8 @@ const translations = {
pleaseEnableTwoFactorAuth: 'Please enable two-factor authentication.',
twoFactorAuthIsRequiredDescription: 'For security purposes, Xero requires two-factor authentication to connect the integration.',
twoFactorAuthIsRequiredForAdminsDescription: 'Two-factor authentication is required for Xero workspace admins. Please enable two-factor authentication to continue.',
twoFactorAuthCannotDisable: 'Cannot disable 2FA',
twoFactorAuthRequired: 'Two-factor authentication (2FA) is required for your Xero connection and cannot be disabled.',
},
recoveryCodeForm: {
error: {
Expand Down
2 changes: 2 additions & 0 deletions src/languages/es.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1357,6 +1357,8 @@ const translations = {
twoFactorAuthIsRequiredDescription: 'Por razones de seguridad, Xero requiere la autenticación de dos factores para conectar la integración.',
twoFactorAuthIsRequiredForAdminsDescription:
'La autenticación de dos factores es necesaria para los administradores del área de trabajo de Xero. Activa la autenticación de dos factores para continuar.',
twoFactorAuthCannotDisable: 'No se puede desactivar la autenticación de dos factores (2FA)',
FitseTLT marked this conversation as resolved.
Show resolved Hide resolved
twoFactorAuthRequired: 'La autenticación de dos factores (2FA) es obligatoria para tu conexión a Xero y no se puede desactivar.',
Copy link
Contributor

@allgandalf allgandalf Jan 29, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These translations were confirmed here

},
recoveryCodeForm: {
error: {
Expand Down
9 changes: 9 additions & 0 deletions src/libs/PolicyUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -671,6 +671,14 @@ function getActiveAdminWorkspaces(policies: OnyxCollection<Policy> | null, curre
return activePolicies.filter((policy) => shouldShowPolicy(policy, isOfflineNetworkStore(), currentUserLogin) && isPolicyAdmin(policy, currentUserLogin));
}

/**
*
* Checks whether the current user has a policy with Xero accounting software integration
*/
function hasPolicyWithXeroConnection(currentUserLogin: string | undefined) {
return getActiveAdminWorkspaces(allPolicies, currentUserLogin)?.some((policy) => !!policy?.connections?.[CONST.POLICY.CONNECTIONS.NAME.XERO]);
}

/** Whether the user can send invoice from the workspace */
function canSendInvoiceFromWorkspace(policyID: string | undefined): boolean {
const policy = getPolicy(policyID);
Expand Down Expand Up @@ -1275,6 +1283,7 @@ export {
findSelectedInvoiceItemWithDefaultSelect,
findSelectedTaxAccountWithDefaultSelect,
findSelectedSageVendorWithDefaultSelect,
hasPolicyWithXeroConnection,
getNetSuiteVendorOptions,
canUseTaxNetSuite,
canUseProvincialTaxNetSuite,
Expand Down
27 changes: 25 additions & 2 deletions src/pages/settings/Security/TwoFactorAuth/Steps/EnabledStep.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import React from 'react';
import React, {useCallback, useState} from 'react';
import {View} from 'react-native';
import {useOnyx} from 'react-native-onyx';
import ConfirmModal from '@components/ConfirmModal';
import * as Expensicons from '@components/Icon/Expensicons';
import * as Illustrations from '@components/Icon/Illustrations';
import ScrollView from '@components/ScrollView';
Expand All @@ -8,18 +10,25 @@ import Text from '@components/Text';
import useLocalize from '@hooks/useLocalize';
import useTheme from '@hooks/useTheme';
import useThemeStyles from '@hooks/useThemeStyles';
import {hasPolicyWithXeroConnection} from '@libs/PolicyUtils';
import StepWrapper from '@pages/settings/Security/TwoFactorAuth/StepWrapper/StepWrapper';
import useTwoFactorAuthContext from '@pages/settings/Security/TwoFactorAuth/TwoFactorAuthContext/useTwoFactorAuth';
import CONST from '@src/CONST';
import ONYXKEYS from '@src/ONYXKEYS';

function EnabledStep() {
const theme = useTheme();
const styles = useThemeStyles();

const [isVisible, setIsVisible] = useState(false);
const {setStep} = useTwoFactorAuthContext();
const [currentUserLogin] = useOnyx(ONYXKEYS.SESSION, {selector: (session) => session?.email});

const {translate} = useLocalize();

const closeModal = useCallback(() => {
setIsVisible(false);
}, []);

return (
<StepWrapper title={translate('twoFactorAuth.headerTitle')}>
<ScrollView>
Expand All @@ -30,6 +39,10 @@ function EnabledStep() {
{
title: translate('twoFactorAuth.disableTwoFactorAuth'),
onPress: () => {
if (hasPolicyWithXeroConnection(currentUserLogin)) {
setIsVisible(true);
return;
}
setStep(CONST.TWO_FACTOR_AUTH_STEPS.GETCODE);
},
icon: Expensicons.Close,
Expand All @@ -43,6 +56,16 @@ function EnabledStep() {
<Text style={styles.textLabel}>{translate('twoFactorAuth.whatIsTwoFactorAuth')}</Text>
</View>
</Section>
<ConfirmModal
title={translate('twoFactorAuth.twoFactorAuthCannotDisable')}
prompt={translate('twoFactorAuth.twoFactorAuthRequired')}
confirmText={translate('common.buttonConfirm')}
onConfirm={closeModal}
shouldShowCancelButton={false}
onBackdropPress={closeModal}
onCancel={closeModal}
isVisible={isVisible}
/>
</ScrollView>
</StepWrapper>
);
Expand Down
Loading