From 584b754693e6a16c01d8bbb6388b5db771836ce8 Mon Sep 17 00:00:00 2001 From: Reinaldo Neto Date: Wed, 30 Jun 2021 11:28:29 -0300 Subject: [PATCH 1/5] [FIX] Face ID remains enabled after re-login --- app/constants/localAuthentication.js | 1 + app/utils/localAuthentication.js | 10 +++++++++- app/views/ScreenLockConfigView.js | 10 +++++++--- 3 files changed, 17 insertions(+), 4 deletions(-) diff --git a/app/constants/localAuthentication.js b/app/constants/localAuthentication.js index 1312e57aa52..8910d3a579c 100644 --- a/app/constants/localAuthentication.js +++ b/app/constants/localAuthentication.js @@ -1,6 +1,7 @@ export const PASSCODE_KEY = 'kPasscode'; export const LOCKED_OUT_TIMER_KEY = 'kLockedOutTimer'; export const ATTEMPTS_KEY = 'kAttempts'; +export const UNLOCK_FACE_ID = 'unlockFaceId'; export const LOCAL_AUTHENTICATE_EMITTER = 'LOCAL_AUTHENTICATE'; export const CHANGE_PASSCODE_EMITTER = 'CHANGE_PASSCODE'; diff --git a/app/utils/localAuthentication.js b/app/utils/localAuthentication.js index 6e6d40dfbad..d5a73231254 100644 --- a/app/utils/localAuthentication.js +++ b/app/utils/localAuthentication.js @@ -10,7 +10,7 @@ import database from '../lib/database'; import { isIOS } from './deviceInfo'; import EventEmitter from './events'; import { - LOCAL_AUTHENTICATE_EMITTER, LOCKED_OUT_TIMER_KEY, ATTEMPTS_KEY, PASSCODE_KEY, CHANGE_PASSCODE_EMITTER + LOCAL_AUTHENTICATE_EMITTER, LOCKED_OUT_TIMER_KEY, ATTEMPTS_KEY, PASSCODE_KEY, CHANGE_PASSCODE_EMITTER, UNLOCK_FACE_ID } from '../constants/localAuthentication'; import I18n from '../i18n'; import { setLocalAuthenticated } from '../actions/login'; @@ -49,6 +49,10 @@ const openChangePasscodeModal = ({ force }) => new Promise((resolve, reject) => }); }); +export const toggleBiometrySetBoolAsync = async(value) => { + await UserPreferences.setBoolAsync(UNLOCK_FACE_ID, value); +}; + export const changePasscode = async({ force = false }) => { const passcode = await openChangePasscodeModal({ force }); await UserPreferences.setStringAsync(PASSCODE_KEY, sha256(passcode)); @@ -73,6 +77,7 @@ const checkBiometry = async(serverRecord) => { await serverRecord.update((record) => { record.biometry = !!result?.success; }); + await toggleBiometrySetBoolAsync(!!result?.success); } catch { // Do nothing } @@ -81,10 +86,13 @@ const checkBiometry = async(serverRecord) => { export const checkHasPasscode = async({ force = true, serverRecord }) => { const storedPasscode = await UserPreferences.getStringAsync(PASSCODE_KEY); + const storedBiometry = await UserPreferences.getBoolAsync(UNLOCK_FACE_ID); if (!storedPasscode) { await changePasscode({ force }); await checkBiometry(serverRecord); return Promise.resolve({ newPasscode: true }); + } else if (storedBiometry) { + await checkBiometry(serverRecord); } return Promise.resolve(); }; diff --git a/app/views/ScreenLockConfigView.js b/app/views/ScreenLockConfigView.js index 294a854a631..f1bd9688d34 100644 --- a/app/views/ScreenLockConfigView.js +++ b/app/views/ScreenLockConfigView.js @@ -9,7 +9,9 @@ import { themes, SWITCH_TRACK_COLOR } from '../constants/colors'; import StatusBar from '../containers/StatusBar'; import * as List from '../containers/List'; import database from '../lib/database'; -import { supportedBiometryLabel, changePasscode, checkHasPasscode } from '../utils/localAuthentication'; +import { + supportedBiometryLabel, changePasscode, checkHasPasscode, toggleBiometrySetBoolAsync +} from '../utils/localAuthentication'; import { DEFAULT_AUTO_LOCK } from '../constants/localAuthentication'; import SafeAreaView from '../containers/SafeAreaView'; import { events, logEvent } from '../utils/log'; @@ -133,9 +135,11 @@ class ScreenLockConfigView extends React.Component { }); } - toggleBiometry = () => { + toggleBiometry = async() => { + const { biometry } = this.state; logEvent(events.SLC_TOGGLE_BIOMETRY); - this.setState(({ biometry }) => ({ biometry: !biometry }), () => this.save()); + await toggleBiometrySetBoolAsync(!biometry); + this.setState({ biometry: !biometry }, () => this.save()); } isSelected = (value) => { From e4a51dcedae21e22b253eddec0c33e2f351180cf Mon Sep 17 00:00:00 2001 From: Reinaldo Neto Date: Thu, 1 Jul 2021 11:16:28 -0300 Subject: [PATCH 2/5] Call only checkHasBiometry --- app/utils/localAuthentication.js | 11 ++++++++--- app/views/ScreenLockConfigView.js | 3 ++- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/app/utils/localAuthentication.js b/app/utils/localAuthentication.js index d5a73231254..4e52dc8446b 100644 --- a/app/utils/localAuthentication.js +++ b/app/utils/localAuthentication.js @@ -84,15 +84,20 @@ const checkBiometry = async(serverRecord) => { }); }; +export const checkHasBiometry = async(serverRecord) => { + const storedBiometry = await UserPreferences.getBoolAsync(UNLOCK_FACE_ID); + if (storedBiometry) { + await checkBiometry(serverRecord); + } + return Promise.resolve(); +}; + export const checkHasPasscode = async({ force = true, serverRecord }) => { const storedPasscode = await UserPreferences.getStringAsync(PASSCODE_KEY); - const storedBiometry = await UserPreferences.getBoolAsync(UNLOCK_FACE_ID); if (!storedPasscode) { await changePasscode({ force }); await checkBiometry(serverRecord); return Promise.resolve({ newPasscode: true }); - } else if (storedBiometry) { - await checkBiometry(serverRecord); } return Promise.resolve(); }; diff --git a/app/views/ScreenLockConfigView.js b/app/views/ScreenLockConfigView.js index f1bd9688d34..a8cb564a86d 100644 --- a/app/views/ScreenLockConfigView.js +++ b/app/views/ScreenLockConfigView.js @@ -10,7 +10,7 @@ import StatusBar from '../containers/StatusBar'; import * as List from '../containers/List'; import database from '../lib/database'; import { - supportedBiometryLabel, changePasscode, checkHasPasscode, toggleBiometrySetBoolAsync + supportedBiometryLabel, changePasscode, checkHasPasscode, toggleBiometrySetBoolAsync, checkHasBiometry } from '../utils/localAuthentication'; import { DEFAULT_AUTO_LOCK } from '../constants/localAuthentication'; import SafeAreaView from '../containers/SafeAreaView'; @@ -127,6 +127,7 @@ class ScreenLockConfigView extends React.Component { if (autoLock) { try { await checkHasPasscode({ force: false, serverRecord: this.serverRecord }); + await checkHasBiometry(this.serverRecord); } catch { this.toggleAutoLock(); } From 0b0c69d746d32e64a245ac0555a4cf8dbb07ed14 Mon Sep 17 00:00:00 2001 From: Reinaldo Neto Date: Wed, 14 Jul 2021 18:30:04 -0300 Subject: [PATCH 3/5] Automatically re-activate the screen lock after re-login --- app/constants/localAuthentication.js | 2 + app/utils/localAuthentication.js | 56 +++++++++++++++++++++------- app/views/ScreenLockConfigView.js | 10 +++-- 3 files changed, 50 insertions(+), 18 deletions(-) diff --git a/app/constants/localAuthentication.js b/app/constants/localAuthentication.js index 8910d3a579c..5273b2a1c87 100644 --- a/app/constants/localAuthentication.js +++ b/app/constants/localAuthentication.js @@ -1,3 +1,5 @@ +export const AUTO_LOCK = 'kAutoLock'; +export const AUTO_LOCK_TIME = 'kAutoLockTime'; export const PASSCODE_KEY = 'kPasscode'; export const LOCKED_OUT_TIMER_KEY = 'kLockedOutTimer'; export const ATTEMPTS_KEY = 'kAttempts'; diff --git a/app/utils/localAuthentication.js b/app/utils/localAuthentication.js index 4e52dc8446b..e25ced3dd74 100644 --- a/app/utils/localAuthentication.js +++ b/app/utils/localAuthentication.js @@ -10,7 +10,14 @@ import database from '../lib/database'; import { isIOS } from './deviceInfo'; import EventEmitter from './events'; import { - LOCAL_AUTHENTICATE_EMITTER, LOCKED_OUT_TIMER_KEY, ATTEMPTS_KEY, PASSCODE_KEY, CHANGE_PASSCODE_EMITTER, UNLOCK_FACE_ID + LOCAL_AUTHENTICATE_EMITTER, + LOCKED_OUT_TIMER_KEY, + ATTEMPTS_KEY, + PASSCODE_KEY, + CHANGE_PASSCODE_EMITTER, + UNLOCK_FACE_ID, + AUTO_LOCK, + AUTO_LOCK_TIME } from '../constants/localAuthentication'; import I18n from '../i18n'; import { setLocalAuthenticated } from '../actions/login'; @@ -49,10 +56,6 @@ const openChangePasscodeModal = ({ force }) => new Promise((resolve, reject) => }); }); -export const toggleBiometrySetBoolAsync = async(value) => { - await UserPreferences.setBoolAsync(UNLOCK_FACE_ID, value); -}; - export const changePasscode = async({ force = false }) => { const passcode = await openChangePasscodeModal({ force }); await UserPreferences.setStringAsync(PASSCODE_KEY, sha256(passcode)); @@ -77,21 +80,12 @@ const checkBiometry = async(serverRecord) => { await serverRecord.update((record) => { record.biometry = !!result?.success; }); - await toggleBiometrySetBoolAsync(!!result?.success); } catch { // Do nothing } }); }; -export const checkHasBiometry = async(serverRecord) => { - const storedBiometry = await UserPreferences.getBoolAsync(UNLOCK_FACE_ID); - if (storedBiometry) { - await checkBiometry(serverRecord); - } - return Promise.resolve(); -}; - export const checkHasPasscode = async({ force = true, serverRecord }) => { const storedPasscode = await UserPreferences.getStringAsync(PASSCODE_KEY); if (!storedPasscode) { @@ -102,13 +96,47 @@ export const checkHasPasscode = async({ force = true, serverRecord }) => { return Promise.resolve(); }; +export const saveStatusLocalAuthentication = async({ + autoLock, autoLockTime, biometry, server +}) => { + await UserPreferences.setBoolAsync(AUTO_LOCK + server, autoLock); + await UserPreferences.setStringAsync(AUTO_LOCK_TIME + server, autoLockTime.toString()); + await UserPreferences.setBoolAsync(UNLOCK_FACE_ID + server, biometry); +}; + +export const checkAutoLockAndTime = async(server) => { + const storedAutoLock = await UserPreferences.getBoolAsync(AUTO_LOCK + server); + const storedAutoLockTime = await UserPreferences.getStringAsync(AUTO_LOCK_TIME + server); + const storedBiometry = await UserPreferences.getBoolAsync(UNLOCK_FACE_ID + server); + + return { + storedAutoLock, + storedAutoLockTime: Number.parseInt(storedAutoLockTime, 10), + storedBiometry + }; +}; + export const localAuthenticate = async(server) => { const serversDB = database.servers; const serversCollection = serversDB.get('servers'); + const { Force_Screen_Lock, Force_Screen_Lock_After } = store.getState().settings; let serverRecord; try { serverRecord = await serversCollection.find(server); + + const { storedAutoLock, storedAutoLockTime, storedBiometry } = await checkAutoLockAndTime(server); + await serversDB.action(async() => { + await serverRecord.update((record) => { + if (serverRecord.autoLock !== storedAutoLock && !Force_Screen_Lock) { + record.autoLock = storedAutoLock; + } + if (!Force_Screen_Lock || Force_Screen_Lock_After === 0) { + record.autoLockTime = storedAutoLockTime; + } + record.biometry = storedBiometry; + }); + }); } catch (error) { return Promise.reject(); } diff --git a/app/views/ScreenLockConfigView.js b/app/views/ScreenLockConfigView.js index a8cb564a86d..e09afbfed85 100644 --- a/app/views/ScreenLockConfigView.js +++ b/app/views/ScreenLockConfigView.js @@ -10,7 +10,7 @@ import StatusBar from '../containers/StatusBar'; import * as List from '../containers/List'; import database from '../lib/database'; import { - supportedBiometryLabel, changePasscode, checkHasPasscode, toggleBiometrySetBoolAsync, checkHasBiometry + supportedBiometryLabel, changePasscode, checkHasPasscode, saveStatusLocalAuthentication } from '../utils/localAuthentication'; import { DEFAULT_AUTO_LOCK } from '../constants/localAuthentication'; import SafeAreaView from '../containers/SafeAreaView'; @@ -104,7 +104,11 @@ class ScreenLockConfigView extends React.Component { save = async() => { logEvent(events.SLC_SAVE_SCREEN_LOCK); + const { server } = this.props; const { autoLock, autoLockTime, biometry } = this.state; + await saveStatusLocalAuthentication({ + autoLock, autoLockTime, biometry, server + }); const serversDB = database.servers; await serversDB.action(async() => { await this.serverRecord?.update((record) => { @@ -127,7 +131,6 @@ class ScreenLockConfigView extends React.Component { if (autoLock) { try { await checkHasPasscode({ force: false, serverRecord: this.serverRecord }); - await checkHasBiometry(this.serverRecord); } catch { this.toggleAutoLock(); } @@ -136,10 +139,9 @@ class ScreenLockConfigView extends React.Component { }); } - toggleBiometry = async() => { + toggleBiometry = () => { const { biometry } = this.state; logEvent(events.SLC_TOGGLE_BIOMETRY); - await toggleBiometrySetBoolAsync(!biometry); this.setState({ biometry: !biometry }, () => this.save()); } From 4e17175ccad3327176a192683369d2e7894607a8 Mon Sep 17 00:00:00 2001 From: Reinaldo Neto Date: Wed, 27 Oct 2021 18:04:40 -0300 Subject: [PATCH 4/5] minor tweaks --- app/constants/localAuthentication.ts | 2 +- app/lib/userPreferences.js | 13 ++++++++ app/utils/localAuthentication.js | 48 ++++++++++++++++------------ 3 files changed, 41 insertions(+), 22 deletions(-) diff --git a/app/constants/localAuthentication.ts b/app/constants/localAuthentication.ts index 5273b2a1c87..32bc61129c4 100644 --- a/app/constants/localAuthentication.ts +++ b/app/constants/localAuthentication.ts @@ -3,7 +3,7 @@ export const AUTO_LOCK_TIME = 'kAutoLockTime'; export const PASSCODE_KEY = 'kPasscode'; export const LOCKED_OUT_TIMER_KEY = 'kLockedOutTimer'; export const ATTEMPTS_KEY = 'kAttempts'; -export const UNLOCK_FACE_ID = 'unlockFaceId'; +export const UNLOCK_FACE_ID = 'kUnlockFaceId'; export const LOCAL_AUTHENTICATE_EMITTER = 'LOCAL_AUTHENTICATE'; export const CHANGE_PASSCODE_EMITTER = 'CHANGE_PASSCODE'; diff --git a/app/lib/userPreferences.js b/app/lib/userPreferences.js index 3377856d630..ec487be2337 100644 --- a/app/lib/userPreferences.js +++ b/app/lib/userPreferences.js @@ -37,6 +37,19 @@ class UserPreferences { return this.mmkv.setBoolAsync(key, value); } + async getIntAsync(key) { + try { + const value = await this.mmkv.getIntAsync(key); + return value; + } catch { + return null; + } + } + + setIntAsync(key, value) { + return this.mmkv.setIntAsync(key, value); + } + async getMapAsync(key) { try { const value = await this.mmkv.getMapAsync(key); diff --git a/app/utils/localAuthentication.js b/app/utils/localAuthentication.js index 7b32f4f409a..56ec1f24e20 100644 --- a/app/utils/localAuthentication.js +++ b/app/utils/localAuthentication.js @@ -100,19 +100,19 @@ export const checkHasPasscode = async ({ force = true, serverRecord }) => { }; export const saveStatusLocalAuthentication = async ({ autoLock, autoLockTime, biometry, server }) => { - await UserPreferences.setBoolAsync(AUTO_LOCK + server, autoLock); - await UserPreferences.setStringAsync(AUTO_LOCK_TIME + server, autoLockTime.toString()); - await UserPreferences.setBoolAsync(UNLOCK_FACE_ID + server, biometry); + await UserPreferences.setBoolAsync(`${AUTO_LOCK}${server}`, autoLock); + await UserPreferences.setIntAsync(`${AUTO_LOCK_TIME}${server}`, autoLockTime); + await UserPreferences.setBoolAsync(`${UNLOCK_FACE_ID}${server}`, biometry); }; -export const checkAutoLockAndTime = async server => { - const storedAutoLock = await UserPreferences.getBoolAsync(AUTO_LOCK + server); - const storedAutoLockTime = await UserPreferences.getStringAsync(AUTO_LOCK_TIME + server); - const storedBiometry = await UserPreferences.getBoolAsync(UNLOCK_FACE_ID + server); +export const getAutoLockAndTime = async server => { + const storedAutoLock = await UserPreferences.getBoolAsync(`${AUTO_LOCK}${server}`); + const storedAutoLockTime = await UserPreferences.getIntAsync(`${AUTO_LOCK_TIME}${server}`); + const storedBiometry = await UserPreferences.getBoolAsync(`${UNLOCK_FACE_ID}${server}`); return { storedAutoLock, - storedAutoLockTime: Number.parseInt(storedAutoLockTime, 10), + storedAutoLockTime, storedBiometry }; }; @@ -125,23 +125,29 @@ export const localAuthenticate = async server => { let serverRecord; try { serverRecord = await serversCollection.find(server); - - const { storedAutoLock, storedAutoLockTime, storedBiometry } = await checkAutoLockAndTime(server); - await serversDB.action(async () => { - await serverRecord.update(record => { - if (serverRecord.autoLock !== storedAutoLock && !Force_Screen_Lock) { - record.autoLock = storedAutoLock; - } - if (!Force_Screen_Lock || Force_Screen_Lock_After === 0) { - record.autoLockTime = storedAutoLockTime; - } - record.biometry = storedBiometry; - }); - }); } catch (error) { return Promise.reject(); } + if (serverRecord) { + const { storedAutoLock, storedAutoLockTime, storedBiometry } = await getAutoLockAndTime(server); + try { + await serversDB.action(async () => { + await serverRecord.update(record => { + if (serverRecord.autoLock !== storedAutoLock && !Force_Screen_Lock) { + record.autoLock = storedAutoLock; + } + if (!Force_Screen_Lock || Force_Screen_Lock_After === 0) { + record.autoLockTime = storedAutoLockTime; + } + record.biometry = storedBiometry; + }); + }); + } catch (error) { + return Promise.reject(); + } + } + // if screen lock is enabled if (serverRecord?.autoLock) { // Make sure splash screen has been hidden From b0802f1323669d9d02c2b276adeaa8dcdd09f524 Mon Sep 17 00:00:00 2001 From: Reinaldo Neto Date: Tue, 28 Dec 2021 00:31:54 -0300 Subject: [PATCH 5/5] change UNLOCK_FACE_ID to UNLOCK_BIOMETRY --- app/constants/localAuthentication.ts | 2 +- app/utils/localAuthentication.js | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/app/constants/localAuthentication.ts b/app/constants/localAuthentication.ts index 32bc61129c4..22c256f7e45 100644 --- a/app/constants/localAuthentication.ts +++ b/app/constants/localAuthentication.ts @@ -3,7 +3,7 @@ export const AUTO_LOCK_TIME = 'kAutoLockTime'; export const PASSCODE_KEY = 'kPasscode'; export const LOCKED_OUT_TIMER_KEY = 'kLockedOutTimer'; export const ATTEMPTS_KEY = 'kAttempts'; -export const UNLOCK_FACE_ID = 'kUnlockFaceId'; +export const UNLOCK_BIOMETRY = 'kUnlockBiometry'; export const LOCAL_AUTHENTICATE_EMITTER = 'LOCAL_AUTHENTICATE'; export const CHANGE_PASSCODE_EMITTER = 'CHANGE_PASSCODE'; diff --git a/app/utils/localAuthentication.js b/app/utils/localAuthentication.js index 56ec1f24e20..55c2a7a62f4 100644 --- a/app/utils/localAuthentication.js +++ b/app/utils/localAuthentication.js @@ -13,7 +13,7 @@ import { ATTEMPTS_KEY, PASSCODE_KEY, CHANGE_PASSCODE_EMITTER, - UNLOCK_FACE_ID, + UNLOCK_BIOMETRY, AUTO_LOCK, AUTO_LOCK_TIME } from '../constants/localAuthentication'; @@ -102,13 +102,13 @@ export const checkHasPasscode = async ({ force = true, serverRecord }) => { export const saveStatusLocalAuthentication = async ({ autoLock, autoLockTime, biometry, server }) => { await UserPreferences.setBoolAsync(`${AUTO_LOCK}${server}`, autoLock); await UserPreferences.setIntAsync(`${AUTO_LOCK_TIME}${server}`, autoLockTime); - await UserPreferences.setBoolAsync(`${UNLOCK_FACE_ID}${server}`, biometry); + await UserPreferences.setBoolAsync(`${UNLOCK_BIOMETRY}${server}`, biometry); }; export const getAutoLockAndTime = async server => { const storedAutoLock = await UserPreferences.getBoolAsync(`${AUTO_LOCK}${server}`); const storedAutoLockTime = await UserPreferences.getIntAsync(`${AUTO_LOCK_TIME}${server}`); - const storedBiometry = await UserPreferences.getBoolAsync(`${UNLOCK_FACE_ID}${server}`); + const storedBiometry = await UserPreferences.getBoolAsync(`${UNLOCK_BIOMETRY}${server}`); return { storedAutoLock,