From a22000242a9f4564ec32d6fa76fbb621f16d2fcb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Karol=20S=C3=B3jko?= Date: Fri, 22 Mar 2024 09:45:15 +0100 Subject: [PATCH] chore: block disabling 2FA if U2F authenticators present - skip e2e (#2862) * chore: block disabling 2FA if U2F authenticators present * chore: remove the u2f wrapper component * chore: adjust fetching 2fa status * chore: fix property name * chore: remove wrapper --- .../Preferences/Panes/Security/Security.tsx | 26 ++++++++++++++----- .../Panes/Security/TwoFactorAuth/MfaProps.ts | 7 ----- .../TwoFactorAuthView/TwoFactorAuthView.tsx | 5 ++-- .../TwoFactorAuthView/TwoFactorSwitch.tsx | 7 +++-- .../TwoFactorAuth/TwoFactorAuthWrapper.tsx | 10 ------- .../Panes/Security/U2F/U2FProps.ts | 6 ----- .../Panes/Security/U2F/U2FView/U2FView.tsx | 9 ++++--- .../Panes/Security/U2F/U2FWrapper.tsx | 10 ------- 8 files changed, 34 insertions(+), 46 deletions(-) delete mode 100644 packages/web/src/javascripts/Components/Preferences/Panes/Security/TwoFactorAuth/MfaProps.ts delete mode 100644 packages/web/src/javascripts/Components/Preferences/Panes/Security/TwoFactorAuth/TwoFactorAuthWrapper.tsx delete mode 100644 packages/web/src/javascripts/Components/Preferences/Panes/Security/U2F/U2FProps.ts delete mode 100644 packages/web/src/javascripts/Components/Preferences/Panes/Security/U2F/U2FWrapper.tsx diff --git a/packages/web/src/javascripts/Components/Preferences/Panes/Security/Security.tsx b/packages/web/src/javascripts/Components/Preferences/Panes/Security/Security.tsx index 66e8d1430..6ed506864 100644 --- a/packages/web/src/javascripts/Components/Preferences/Panes/Security/Security.tsx +++ b/packages/web/src/javascripts/Components/Preferences/Panes/Security/Security.tsx @@ -1,8 +1,7 @@ import { NativeFeatureIdentifier, FeatureStatus } from '@standardnotes/snjs' -import { FunctionComponent, useState } from 'react' +import { FunctionComponent, useEffect, useState } from 'react' import { WebApplication } from '@/Application/WebApplication' -import TwoFactorAuthWrapper from './TwoFactorAuth/TwoFactorAuthWrapper' import Encryption from './Encryption' import PasscodeLock from './PasscodeLock' import Privacy from './Privacy' @@ -11,8 +10,9 @@ import ErroredItems from './ErroredItems' import PreferencesPane from '@/Components/Preferences/PreferencesComponents/PreferencesPane' import BiometricsLock from '@/Components/Preferences/Panes/Security/BiometricsLock' import MultitaskingPrivacy from '@/Components/Preferences/Panes/Security/MultitaskingPrivacy' -import U2FWrapper from './U2F/U2FWrapper' import { TwoFactorAuth, is2FAEnabled as checkIf2FAIsEnabled } from './TwoFactorAuth/TwoFactorAuth' +import U2FView from './U2F/U2FView/U2FView' +import TwoFactorAuthView from './TwoFactorAuth/TwoFactorAuthView/TwoFactorAuthView' interface SecurityProps { application: WebApplication @@ -21,6 +21,7 @@ interface SecurityProps { const Security: FunctionComponent = (props) => { const isNativeMobileWeb = props.application.isNativeMobileWeb() const [is2FAEnabled, setIs2FAEnabled] = useState(false) + const [canDisable2FA, setCanDisable2FA] = useState(true) const [auth] = useState( () => @@ -28,7 +29,14 @@ const Security: FunctionComponent = (props) => { setIs2FAEnabled(checkIf2FAIsEnabled(status)), ), ) - auth.fetchStatus() + + useEffect(() => { + auth.fetchStatus() + }, [auth]) + + const onU2FDevicesLoaded = (devices: Array<{ id: string; name: string }>) => { + setCanDisable2FA(devices.length === 0) + } const isU2FFeatureAvailable = props.application.features.getFeatureStatus( @@ -40,8 +48,14 @@ const Security: FunctionComponent = (props) => { {props.application.items.invalidNonVaultedItems.length > 0 && } - - {isU2FFeatureAvailable && } + + {isU2FFeatureAvailable && ( + + )} {isNativeMobileWeb && } {isNativeMobileWeb && } diff --git a/packages/web/src/javascripts/Components/Preferences/Panes/Security/TwoFactorAuth/MfaProps.ts b/packages/web/src/javascripts/Components/Preferences/Panes/Security/TwoFactorAuth/MfaProps.ts deleted file mode 100644 index 2fb45cd76..000000000 --- a/packages/web/src/javascripts/Components/Preferences/Panes/Security/TwoFactorAuth/MfaProps.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { WebApplication } from '@/Application/WebApplication' -import { TwoFactorAuth } from './TwoFactorAuth' - -export interface MfaProps { - application: WebApplication - auth: TwoFactorAuth -} diff --git a/packages/web/src/javascripts/Components/Preferences/Panes/Security/TwoFactorAuth/TwoFactorAuthView/TwoFactorAuthView.tsx b/packages/web/src/javascripts/Components/Preferences/Panes/Security/TwoFactorAuth/TwoFactorAuthView/TwoFactorAuthView.tsx index 28001198c..af63accb2 100644 --- a/packages/web/src/javascripts/Components/Preferences/Panes/Security/TwoFactorAuth/TwoFactorAuthView/TwoFactorAuthView.tsx +++ b/packages/web/src/javascripts/Components/Preferences/Panes/Security/TwoFactorAuth/TwoFactorAuthView/TwoFactorAuthView.tsx @@ -16,9 +16,10 @@ import ModalOverlay from '@/Components/Modal/ModalOverlay' type Props = { auth: TwoFactorAuth application: WebApplication + canDisable2FA: boolean } -const TwoFactorAuthView: FunctionComponent = ({ auth, application }) => { +const TwoFactorAuthView: FunctionComponent = ({ auth, application, canDisable2FA }) => { const shouldShowActivationModal = auth.status !== 'fetching' && is2FAActivation(auth.status) const activationModalTitle = shouldShowActivationModal @@ -96,7 +97,7 @@ const TwoFactorAuthView: FunctionComponent = ({ auth, application }) => { - + diff --git a/packages/web/src/javascripts/Components/Preferences/Panes/Security/TwoFactorAuth/TwoFactorAuthView/TwoFactorSwitch.tsx b/packages/web/src/javascripts/Components/Preferences/Panes/Security/TwoFactorAuth/TwoFactorAuthView/TwoFactorSwitch.tsx index eecfb8b99..dab2a2bda 100644 --- a/packages/web/src/javascripts/Components/Preferences/Panes/Security/TwoFactorAuth/TwoFactorAuthView/TwoFactorSwitch.tsx +++ b/packages/web/src/javascripts/Components/Preferences/Panes/Security/TwoFactorAuth/TwoFactorAuthView/TwoFactorSwitch.tsx @@ -6,9 +6,10 @@ import Spinner from '@/Components/Spinner/Spinner' type Props = { auth: TwoFactorAuth + canDisable2FA: boolean } -const TwoFactorSwitch: FunctionComponent = ({ auth }) => { +const TwoFactorSwitch: FunctionComponent = ({ auth, canDisable2FA }) => { if (!auth.isLoggedIn()) { return null } @@ -17,7 +18,9 @@ const TwoFactorSwitch: FunctionComponent = ({ auth }) => { return } - return + const shouldSwitchBeDisabled = auth.status === 'two-factor-enabled' && !canDisable2FA + + return } export default observer(TwoFactorSwitch) diff --git a/packages/web/src/javascripts/Components/Preferences/Panes/Security/TwoFactorAuth/TwoFactorAuthWrapper.tsx b/packages/web/src/javascripts/Components/Preferences/Panes/Security/TwoFactorAuth/TwoFactorAuthWrapper.tsx deleted file mode 100644 index 5e575beab..000000000 --- a/packages/web/src/javascripts/Components/Preferences/Panes/Security/TwoFactorAuth/TwoFactorAuthWrapper.tsx +++ /dev/null @@ -1,10 +0,0 @@ -import { FunctionComponent } from 'react' - -import { MfaProps } from './MfaProps' -import TwoFactorAuthView from './TwoFactorAuthView/TwoFactorAuthView' - -const TwoFactorAuthWrapper: FunctionComponent = (props) => { - return -} - -export default TwoFactorAuthWrapper diff --git a/packages/web/src/javascripts/Components/Preferences/Panes/Security/U2F/U2FProps.ts b/packages/web/src/javascripts/Components/Preferences/Panes/Security/U2F/U2FProps.ts deleted file mode 100644 index 20f0ab8e6..000000000 --- a/packages/web/src/javascripts/Components/Preferences/Panes/Security/U2F/U2FProps.ts +++ /dev/null @@ -1,6 +0,0 @@ -import { WebApplication } from '@/Application/WebApplication' - -export interface U2FProps { - application: WebApplication - is2FAEnabled: boolean -} diff --git a/packages/web/src/javascripts/Components/Preferences/Panes/Security/U2F/U2FView/U2FView.tsx b/packages/web/src/javascripts/Components/Preferences/Panes/Security/U2F/U2FView/U2FView.tsx index cbaa42750..e997e6698 100644 --- a/packages/web/src/javascripts/Components/Preferences/Panes/Security/U2F/U2FView/U2FView.tsx +++ b/packages/web/src/javascripts/Components/Preferences/Panes/Security/U2F/U2FView/U2FView.tsx @@ -16,9 +16,10 @@ import RecoveryCodeBanner from '@/Components/RecoveryCodeBanner/RecoveryCodeBann type Props = { application: WebApplication is2FAEnabled: boolean + loadAuthenticatorsCallback: (devices: Array<{ id: string; name: string }>) => void } -const U2FView: FunctionComponent = ({ application, is2FAEnabled }) => { +const U2FView: FunctionComponent = ({ application, is2FAEnabled, loadAuthenticatorsCallback }) => { const [showDeviceAddingModal, setShowDeviceAddingModal] = useState(false) const [devices, setDevices] = useState>([]) const [error, setError] = useState('') @@ -35,8 +36,10 @@ const U2FView: FunctionComponent = ({ application, is2FAEnabled }) => { return } - setDevices(authenticatorListOrError.getValue()) - }, [setError, setDevices, application]) + const authenticatorList = authenticatorListOrError.getValue() + setDevices(authenticatorList) + loadAuthenticatorsCallback(authenticatorList) + }, [setError, setDevices, application, loadAuthenticatorsCallback]) useEffect(() => { loadAuthenticatorDevices().catch(console.error) diff --git a/packages/web/src/javascripts/Components/Preferences/Panes/Security/U2F/U2FWrapper.tsx b/packages/web/src/javascripts/Components/Preferences/Panes/Security/U2F/U2FWrapper.tsx deleted file mode 100644 index d8d098e76..000000000 --- a/packages/web/src/javascripts/Components/Preferences/Panes/Security/U2F/U2FWrapper.tsx +++ /dev/null @@ -1,10 +0,0 @@ -import { FunctionComponent } from 'react' - -import { U2FProps } from './U2FProps' -import U2FView from './U2FView/U2FView' - -const U2FWrapper: FunctionComponent = (props) => { - return -} - -export default U2FWrapper