2020-04-14 13:07:13 +00:00
|
|
|
import * as LocalAuthentication from 'expo-local-authentication';
|
2020-04-14 14:07:51 +00:00
|
|
|
import moment from 'moment';
|
2020-04-22 19:58:19 +00:00
|
|
|
import RNBootSplash from 'react-native-bootsplash';
|
|
|
|
import AsyncStorage from '@react-native-community/async-storage';
|
2020-04-14 13:07:13 +00:00
|
|
|
|
|
|
|
import database from '../lib/database';
|
2020-04-16 14:30:00 +00:00
|
|
|
import { isIOS } from './deviceInfo';
|
2020-04-17 19:11:06 +00:00
|
|
|
import EventEmitter from './events';
|
2020-04-22 19:58:19 +00:00
|
|
|
import { LOCAL_AUTHENTICATE_EMITTER, LOCKED_OUT_TIMER_KEY, ATTEMPTS_KEY } from '../constants/localAuthentication';
|
2020-04-24 13:15:07 +00:00
|
|
|
import I18n from '../i18n';
|
2020-04-14 13:07:13 +00:00
|
|
|
|
2020-04-17 19:11:06 +00:00
|
|
|
export const saveLastLocalAuthenticationSession = async(server, serverRecord) => {
|
2020-04-14 14:07:51 +00:00
|
|
|
const serversDB = database.servers;
|
|
|
|
const serversCollection = serversDB.collections.get('servers');
|
|
|
|
await serversDB.action(async() => {
|
|
|
|
try {
|
2020-04-17 19:11:06 +00:00
|
|
|
if (!serverRecord) {
|
|
|
|
serverRecord = await serversCollection.find(server);
|
|
|
|
}
|
2020-04-14 14:07:51 +00:00
|
|
|
await serverRecord.update((record) => {
|
|
|
|
record.lastLocalAuthenticatedSession = new Date();
|
|
|
|
});
|
|
|
|
} catch (e) {
|
|
|
|
// Do nothing
|
|
|
|
}
|
|
|
|
});
|
|
|
|
};
|
|
|
|
|
2020-04-22 19:58:19 +00:00
|
|
|
export const resetAttempts = () => AsyncStorage.multiRemove([LOCKED_OUT_TIMER_KEY, ATTEMPTS_KEY]);
|
|
|
|
|
2020-04-17 19:11:06 +00:00
|
|
|
export const localPasscode = () => new Promise((resolve, reject) => {
|
2020-04-22 19:58:19 +00:00
|
|
|
EventEmitter.emit(LOCAL_AUTHENTICATE_EMITTER, {
|
2020-04-17 19:11:06 +00:00
|
|
|
cancel: () => reject(),
|
|
|
|
submit: () => resolve()
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
|
2020-04-14 14:07:51 +00:00
|
|
|
export const localAuthenticate = async(server) => {
|
2020-04-14 13:07:13 +00:00
|
|
|
const serversDB = database.servers;
|
|
|
|
const serversCollection = serversDB.collections.get('servers');
|
|
|
|
|
|
|
|
let serverRecord;
|
|
|
|
try {
|
|
|
|
serverRecord = await serversCollection.find(server);
|
|
|
|
} catch (error) {
|
|
|
|
return Promise.reject();
|
|
|
|
}
|
|
|
|
|
2020-04-17 19:11:06 +00:00
|
|
|
// if screen lock is enabled
|
|
|
|
if (serverRecord?.autoLock) {
|
|
|
|
// diff to last authenticated session
|
2020-04-16 13:52:56 +00:00
|
|
|
const diffToLastSession = moment().diff(serverRecord?.lastLocalAuthenticatedSession, 'seconds');
|
2020-04-17 19:11:06 +00:00
|
|
|
|
|
|
|
// if last authenticated session is older than configured auto lock time, authentication is required
|
2020-04-16 13:52:56 +00:00
|
|
|
if (diffToLastSession >= serverRecord?.autoLockTime) {
|
2020-04-20 13:09:19 +00:00
|
|
|
// Make sure splash screen has been hidden
|
|
|
|
RNBootSplash.hide();
|
|
|
|
|
2020-04-24 18:43:31 +00:00
|
|
|
// if biometry is enabled on the app
|
|
|
|
if (serverRecord?.biometry) {
|
|
|
|
const isEnrolled = await LocalAuthentication.isEnrolledAsync();
|
|
|
|
const isSupported = await LocalAuthentication.supportedAuthenticationTypesAsync();
|
2020-04-17 19:11:06 +00:00
|
|
|
|
2020-04-24 18:43:31 +00:00
|
|
|
// if biometry is enabled and enrolled on OS
|
|
|
|
if (isEnrolled && isSupported?.length) {
|
|
|
|
// opens biometry prompt
|
|
|
|
let authResult;
|
|
|
|
try {
|
|
|
|
authResult = await LocalAuthentication.authenticateAsync({ disableDeviceFallback: true });
|
|
|
|
} catch (e) {
|
|
|
|
// Do nothing
|
|
|
|
}
|
2020-04-27 12:34:56 +00:00
|
|
|
if (!authResult?.success) {
|
2020-04-24 18:43:31 +00:00
|
|
|
await localPasscode();
|
|
|
|
}
|
2020-04-24 12:17:38 +00:00
|
|
|
} else {
|
|
|
|
await localPasscode();
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
await localPasscode();
|
|
|
|
}
|
2020-04-27 12:34:56 +00:00
|
|
|
|
|
|
|
//
|
|
|
|
await resetAttempts();
|
|
|
|
await saveLastLocalAuthenticationSession(server, serverRecord);
|
2020-04-16 13:52:56 +00:00
|
|
|
}
|
|
|
|
}
|
2020-04-14 13:07:13 +00:00
|
|
|
};
|
2020-04-16 14:30:00 +00:00
|
|
|
|
2020-04-20 17:36:11 +00:00
|
|
|
export const supportedBiometryLabel = async() => {
|
2020-04-16 14:30:00 +00:00
|
|
|
const enrolled = await LocalAuthentication.isEnrolledAsync();
|
2020-04-20 17:36:11 +00:00
|
|
|
|
|
|
|
if (!enrolled) {
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
|
|
|
const supported = await LocalAuthentication.supportedAuthenticationTypesAsync();
|
2020-04-16 14:30:00 +00:00
|
|
|
|
|
|
|
if (supported.includes(LocalAuthentication.AuthenticationType.FACIAL_RECOGNITION)) {
|
2020-04-24 13:15:07 +00:00
|
|
|
return isIOS ? 'FaceID' : I18n.t('Local_authentication_facial_recognition');
|
2020-04-16 14:30:00 +00:00
|
|
|
}
|
|
|
|
if (supported.includes(LocalAuthentication.AuthenticationType.FINGERPRINT)) {
|
2020-04-24 13:15:07 +00:00
|
|
|
return isIOS ? 'TouchID' : I18n.t('Local_authentication_fingerprint');
|
2020-04-16 14:30:00 +00:00
|
|
|
}
|
|
|
|
return null;
|
|
|
|
};
|