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

Revert "Security: app lock timeout feature" #1773

Merged
merged 1 commit into from
Oct 16, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 3 additions & 11 deletions components/DropdownSetting.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,16 @@ import {
Platform,
View,
StyleSheet,
Text,
TouchableOpacity
} from 'react-native';
import { Picker } from '@react-native-picker/picker';
import { themeColor } from './../utils/ThemeUtils';
import CaretDown from './../assets/images/SVG/Caret Down.svg';
import { localeString } from './../utils/LocaleUtils';
import Text from './Text';

interface DropdownSettingProps {
title: string;
infoText?: string;
selectedValue: string | boolean;
onValueChange: (value: any) => void;
values: Array<any>;
Expand All @@ -26,14 +25,8 @@ export default class DropdownSetting extends React.Component<
{}
> {
render() {
const {
title,
infoText,
selectedValue,
onValueChange,
values,
disabled
} = this.props;
const { title, selectedValue, onValueChange, values, disabled } =
this.props;

const pickerValuesAndroid: Array<any> = [];
const pickerValuesIOS: Array<string> = ['Cancel'];
Expand Down Expand Up @@ -68,7 +61,6 @@ export default class DropdownSetting extends React.Component<
...styles.secondaryText,
color: themeColor('secondaryText')
}}
infoText={infoText}
>
{title}
</Text>
Expand Down
17 changes: 1 addition & 16 deletions components/PinPad.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import * as React from 'react';
import { useMemo, useState } from 'react';
import { StyleSheet, Text, Pressable, View, AppState } from 'react-native';
import { StyleSheet, Text, Pressable, View } from 'react-native';
import { themeColor } from '../utils/ThemeUtils';
import { Row } from './layout/Row';
import Success from '../assets/images/SVG/Success.svg';
Expand Down Expand Up @@ -32,21 +32,6 @@ export default function PinPad({
numberHighlight = false,
amount = false
}: PinPadProps) {
React.useEffect(() => {
const subscription = AppState.addEventListener(
'change',
handleAppStateChange
);
return () => subscription.remove();
}, []);

const handleAppStateChange = (nextAppState: any) => {
if (nextAppState === 'background') {
clearValue();
clearPinValueLength();
}
};

// PinPad state only depends on pin value length, not the actual pin/amount value
// Parent component to PinPad can store pin/amount value
const [pinValueLength, setPinValueLength] = useState(0);
Expand Down
4 changes: 2 additions & 2 deletions components/Text.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { themeColor } from './../utils/ThemeUtils';
import ModalStore from '../stores/ModalStore';

interface TextProps {
ModalStore?: ModalStore;
ModalStore: ModalStore;
style?: any;
children: string;
infoText?: string | Array<string>;
Expand All @@ -22,7 +22,7 @@ export default class ZeusText extends React.Component<TextProps, {}> {
render() {
const { children, style, infoText, infoLink, infoNav, ModalStore } =
this.props;
const { toggleInfoModal } = ModalStore!;
const { toggleInfoModal } = ModalStore;

const CoreText = () => (
<Row>
Expand Down
11 changes: 0 additions & 11 deletions locales/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -229,17 +229,6 @@
"views.Settings.Security.deleteDuressPIN": "Delete Duress PIN",
"views.Settings.Security.scramblePIN": "Scramble PIN numbers",
"views.Settings.Security.loginBackground": "Require login after app returns from background",
"views.Settings.Security.appLockTimeout": "App lock timeout",
"views.Settings.Security.appLockTimeout.explainer": "Specify the time after which the app will be automatically locked after it has been exited.",
"views.Settings.Security.appLockTimeoutImmediately": "Immediately",
"views.Settings.Security.appLockTimeout15s": "15 seconds",
"views.Settings.Security.appLockTimeout30s": "30 seconds",
"views.Settings.Security.appLockTimeout1m": "1 minute",
"views.Settings.Security.appLockTimeout2m": "2 minutes",
"views.Settings.Security.appLockTimeout5m": "5 minutes",
"views.Settings.Security.appLockTimeout10m": "10 minutes",
"views.Settings.Security.appLockTimeout30m": "30 minutes",
"views.Settings.Security.appLockTimeout1h": "1 hour",
"views.SparkQRScanner.text": "Scan a Spark QR code",
"views.SparkQRScanner.error": "Error fetching Spark config",
"views.ImportAccount.title": "Import account",
Expand Down
51 changes: 0 additions & 51 deletions stores/SettingsStore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,6 @@ export interface Settings {
duressPin?: string;
scramblePin?: boolean;
loginBackground?: boolean;
appLockTimeout?: string;
authenticationAttempts?: number;
fiatEnabled?: boolean;
fiat?: string;
Expand Down Expand Up @@ -141,54 +140,6 @@ export const BLOCK_EXPLORER_KEYS = [
}
];

export const APP_LOCK_TIMEOUT_VALUES = [
{
key: '0',
value: '0',
translateKey: 'views.Settings.Security.appLockTimeoutImmediately'
},
{
key: '15',
value: '15',
translateKey: 'views.Settings.Security.appLockTimeout15s'
},
{
key: '30',
value: '30',
translateKey: 'views.Settings.Security.appLockTimeout30s'
},
{
key: '60',
value: '60',
translateKey: 'views.Settings.Security.appLockTimeout1m'
},
{
key: '120',
value: '120',
translateKey: 'views.Settings.Security.appLockTimeout2m'
},
{
key: '300',
value: '300',
translateKey: 'views.Settings.Security.appLockTimeout5m'
},
{
key: '600',
value: '600',
translateKey: 'views.Settings.Security.appLockTimeout10m'
},
{
key: '1800',
value: '1800',
translateKey: 'views.Settings.Security.appLockTimeout30m'
},
{
key: '3600',
value: '3600',
translateKey: 'views.Settings.Security.appLockTimeout1h'
}
];

export const MEMPOOL_RATES_KEYS = [
{
key: 'Fastest fee',
Expand Down Expand Up @@ -702,7 +653,6 @@ export const DEFAULT_THEME = 'dark';
export const DEFAULT_FIAT = 'USD';
export const DEFAULT_FIAT_RATES_SOURCE = 'Zeus';
export const DEFAULT_LOCALE = 'English';
export const DEFAULT_APP_LOCK_TIMEOUT = '0';

export const POS_CONF_PREF_KEYS = [
{ key: '0 conf', value: '0conf' },
Expand Down Expand Up @@ -800,7 +750,6 @@ export default class SettingsStore {
isBiometryEnabled: false,
scramblePin: true,
loginBackground: false,
appLockTimeout: DEFAULT_APP_LOCK_TIMEOUT,
fiatEnabled: false,
fiat: DEFAULT_FIAT,
fiatRatesSource: DEFAULT_FIAT_RATES_SOURCE,
Expand Down
3 changes: 1 addition & 2 deletions views/Lockscreen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -64,8 +64,7 @@ export default class Lockscreen extends React.Component<

async UNSAFE_componentWillMount() {
const { SettingsStore, navigation } = this.props;
const { getSettings } = SettingsStore;
const settings = await getSettings();
const { settings } = SettingsStore;
const modifySecurityScreen: string = navigation.getParam(
'modifySecurityScreen'
);
Expand Down
45 changes: 4 additions & 41 deletions views/Settings/Security.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,11 @@ import Header from '../../components/Header';
import Screen from '../../components/Screen';
import Switch from '../../components/Switch';

import SettingsStore, {
APP_LOCK_TIMEOUT_VALUES,
DEFAULT_APP_LOCK_TIMEOUT
} from '../../stores/SettingsStore';
import SettingsStore from '../../stores/SettingsStore';

import { verifyBiometry } from '../../utils/BiometricUtils';
import { localeString } from '../../utils/LocaleUtils';
import { themeColor } from '../../utils/ThemeUtils';
import DropdownSetting from '../../components/DropdownSetting';

interface SecurityProps {
navigation: any;
Expand All @@ -31,7 +27,6 @@ interface SecurityState {
passphraseExists: boolean;
supportedBiometryType: BiometryType | undefined;
isBiometryEnabled: boolean | undefined;
appLockTimeout: string;
}

const possibleSecurityItems = [
Expand Down Expand Up @@ -81,8 +76,7 @@ export default class Security extends React.Component<
pinExists: false,
passphraseExists: false,
supportedBiometryType: undefined,
isBiometryEnabled: undefined,
appLockTimeout: DEFAULT_APP_LOCK_TIMEOUT
isBiometryEnabled: undefined
};

async componentDidMount() {
Expand All @@ -93,7 +87,6 @@ export default class Security extends React.Component<
this.setState({
scramblePin: settings.scramblePin ?? true,
loginBackground: settings.loginBackground ?? false,
appLockTimeout: settings.appLockTimeout ?? DEFAULT_APP_LOCK_TIMEOUT,
isBiometryEnabled: settings.isBiometryEnabled,
supportedBiometryType: settings.supportedBiometryType
});
Expand Down Expand Up @@ -229,8 +222,7 @@ export default class Security extends React.Component<
pinExists,
passphraseExists,
loginBackground,
isBiometryEnabled = false,
appLockTimeout
isBiometryEnabled = false
} = this.state;
const { updateSettings, settings } = SettingsStore;

Expand Down Expand Up @@ -334,7 +326,7 @@ export default class Security extends React.Component<
</ListItem.Content>
<Switch
value={loginBackground}
onValueChange={() => {
onValueChange={async () => {
this.setState({
loginBackground: !loginBackground
});
Expand All @@ -345,35 +337,6 @@ export default class Security extends React.Component<
/>
</ListItem>
)}
{(pinExists || passphraseExists || isBiometryEnabled) &&
loginBackground && (
<View
style={{
paddingLeft: 15,
paddingRight: 15,
marginTop: 15
}}
>
<DropdownSetting
title={localeString(
'views.Settings.Security.appLockTimeout'
)}
infoText={localeString(
'views.Settings.Security.appLockTimeout.explainer'
)}
selectedValue={appLockTimeout}
values={APP_LOCK_TIMEOUT_VALUES}
onValueChange={(value) => {
this.setState({
appLockTimeout: value
});
updateSettings({
appLockTimeout: value
});
}}
/>
</View>
)}
</ScrollView>
</Screen>
);
Expand Down
29 changes: 10 additions & 19 deletions views/Wallet/Wallet.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,6 @@ interface WalletProps {
interface WalletState {
unlocked: boolean;
initialLoad: boolean;
logoutTimeout: any | undefined;
}

@inject(
Expand Down Expand Up @@ -208,31 +207,23 @@ export default class Wallet extends React.Component<WalletProps, WalletState> {
this.backPressSubscription?.remove();
}

handleAppStateChange = async (nextAppState: any) => {
handleAppStateChange = (nextAppState: any) => {
const { SettingsStore } = this.props;
const { getSettings } = SettingsStore;
const settings = await getSettings();
const { loginBackground, appLockTimeout } = settings;
const { settings } = SettingsStore;
const { loginBackground } = settings;

if (
nextAppState === 'background' &&
SettingsStore.loginMethodConfigured() &&
loginBackground
) {
const appLockTimeoutInMs = Number(appLockTimeout ?? '0') * 1000;
const logoutTimeout = setTimeout(() => {
SettingsStore.setLoginStatus(false);
this.setState({ logoutTimeout: undefined });
}, appLockTimeoutInMs);
this.setState({ logoutTimeout });
} else if (nextAppState === 'active') {
if (this.state.logoutTimeout) {
clearTimeout(this.state.logoutTimeout);
}

if (SettingsStore.loginRequired()) {
this.props.navigation.navigate('Lockscreen');
}
// In case the lock screen is visible and a valid PIN is entered and home button is pressed,
// unauthorized access would be possible because the PIN is not cleared on next launch.
// By calling pop, the lock screen is closed to clear the PIN.
this.props.navigation.pop();
SettingsStore.setLoginStatus(false);
} else if (nextAppState === 'active' && SettingsStore.loginRequired()) {
this.props.navigation.navigate('Lockscreen');
}
};

Expand Down