From f8656694bbc80caab6e8ff8a9ddfc4cc717ef383 Mon Sep 17 00:00:00 2001 From: Diego Mello Date: Tue, 14 Apr 2020 10:07:13 -0300 Subject: [PATCH] localAuthentication util --- app/sagas/init.js | 6 +- app/sagas/state.js | 7 +- app/utils/localAuthentication.js | 21 +++++ app/utils/review copy.js | 96 ----------------------- app/views/RoomsListView/ServerDropdown.js | 7 +- 5 files changed, 31 insertions(+), 106 deletions(-) create mode 100644 app/utils/localAuthentication.js delete mode 100644 app/utils/review copy.js diff --git a/app/sagas/init.js b/app/sagas/init.js index e5f8aa624..2d29e48c8 100644 --- a/app/sagas/init.js +++ b/app/sagas/init.js @@ -3,7 +3,6 @@ import { put, takeLatest, all } from 'redux-saga/effects'; import RNUserDefaults from 'rn-user-defaults'; import { sanitizedRaw } from '@nozbe/watermelondb/RawRecord'; import RNBootSplash from 'react-native-bootsplash'; -import * as LocalAuthentication from 'expo-local-authentication'; import * as actions from '../actions'; import { selectServerRequest } from '../actions/server'; @@ -19,6 +18,7 @@ import { import { isIOS } from '../utils/deviceInfo'; import database from '../lib/database'; import protectedFunction from '../lib/methods/helpers/protectedFunction'; +import localAuthenticate from '../utils/localAuthentication'; export const initLocalSettings = function* initLocalSettings() { const sortPreferences = yield RocketChat.getSortPreferences(); @@ -101,8 +101,8 @@ const restore = function* restore() { const serversDB = database.servers; const serverCollections = serversDB.collections.get('servers'); - const authResult = yield LocalAuthentication.authenticateAsync(); - if (authResult?.success) { + const localAuthResult = yield localAuthenticate(server); + if (localAuthResult) { const serverObj = yield serverCollections.find(server); yield put(selectServerRequest(server, serverObj && serverObj.version)); } else { diff --git a/app/sagas/state.js b/app/sagas/state.js index 2ac1ae431..4c1cc9630 100644 --- a/app/sagas/state.js +++ b/app/sagas/state.js @@ -1,10 +1,10 @@ import { takeLatest, select, put } from 'redux-saga/effects'; import { FOREGROUND, BACKGROUND } from 'redux-enhancer-react-native-appstate'; -import * as LocalAuthentication from 'expo-local-authentication'; import RocketChat from '../lib/rocketchat'; import { setBadgeCount } from '../notifications/push'; import log from '../utils/log'; +import localAuthenticate from '../utils/localAuthentication'; import * as actions from '../actions'; const appHasComeBackToForeground = function* appHasComeBackToForeground() { @@ -17,8 +17,9 @@ const appHasComeBackToForeground = function* appHasComeBackToForeground() { return; } try { - const authResult = yield LocalAuthentication.authenticateAsync(); - if (!authResult?.success) { + const server = yield select(state => state.server.server); + const localAuthResult = yield localAuthenticate(server); + if (!localAuthResult) { yield put(actions.appStart('locked')); } setBadgeCount(); diff --git a/app/utils/localAuthentication.js b/app/utils/localAuthentication.js new file mode 100644 index 000000000..b60e9c07c --- /dev/null +++ b/app/utils/localAuthentication.js @@ -0,0 +1,21 @@ +import * as LocalAuthentication from 'expo-local-authentication'; + +import database from '../lib/database'; + +const localAuthenticate = async(server) => { + const serversDB = database.servers; + const serversCollection = serversDB.collections.get('servers'); + + let serverRecord; + try { + serverRecord = await serversCollection.find(server); + console.log('localAuthenticate -> serverRecord', serverRecord); + } catch (error) { + return Promise.reject(); + } + + const authResult = await LocalAuthentication.authenticateAsync(); + return Promise.resolve(authResult?.success); +}; + +export default localAuthenticate; diff --git a/app/utils/review copy.js b/app/utils/review copy.js deleted file mode 100644 index 7e6da9d13..000000000 --- a/app/utils/review copy.js +++ /dev/null @@ -1,96 +0,0 @@ -import { Alert, Linking, AsyncStorage } from 'react-native'; - -import { isIOS } from './deviceInfo'; -import I18n from '../i18n'; -import { showErrorAlert } from './info'; -import { STORE_REVIEW_LINK } from '../constants/links'; - -const store = isIOS ? 'App Store' : 'Play Store'; - -const reviewKey = 'reviewKey'; -const reviewDelay = 2000; -const numberOfDays = 7; -const numberOfPositiveEvent = 5; - -const daysBetween = (date1, date2) => { - const one_day = 1000 * 60 * 60 * 24; - const date1_ms = date1.getTime(); - const date2_ms = date2.getTime(); - const difference_ms = date2_ms - date1_ms; - return Math.round(difference_ms / one_day); -}; - -const onCancelPress = () => { - try { - const data = JSON.stringify({ doneReview: true }); - return AsyncStorage.setItem(reviewKey, data); - } catch (e) { - // do nothing - } -}; - -export const onReviewPress = async() => { - await onCancelPress(); - try { - const supported = await Linking.canOpenURL(STORE_REVIEW_LINK); - if (supported) { - Linking.openURL(STORE_REVIEW_LINK); - } - } catch (e) { - showErrorAlert(I18n.t('Review_app_unable_store', { store })); - } -}; - -const onAskMeLaterPress = () => { - try { - const data = JSON.stringify({ lastReview: new Date().getTime() }); - return AsyncStorage.setItem(reviewKey, data); - } catch (e) { - // do nothing - } -}; - -const onReviewButton = { text: I18n.t('Review_app_yes'), onPress: onReviewPress }; -const onAskMeLaterButton = { text: I18n.t('Review_app_later'), onPress: onAskMeLaterPress }; -const onCancelButton = { text: I18n.t('Review_app_no'), onPress: onCancelPress }; - -const askReview = () => Alert.alert( - I18n.t('Review_app_title'), - I18n.t('Review_app_desc', { store }), - isIOS - ? [onReviewButton, onAskMeLaterButton, onCancelButton] - : [onAskMeLaterButton, onCancelButton, onReviewButton], - { - cancelable: true, - onDismiss: onAskMeLaterPress - } -); - -const tryReview = async() => { - const data = await AsyncStorage.getItem(reviewKey) || '{}'; - const reviewData = JSON.parse(data); - const { lastReview = 0, doneReview = false } = reviewData; - const lastReviewDate = new Date(lastReview); - - // if ask me later was pressed earlier, we can ask for review only after {{numberOfDays}} days - // if there's no review and it wasn't dismissed by the user - if (daysBetween(lastReviewDate, new Date()) >= numberOfDays && !doneReview) { - setTimeout(askReview, reviewDelay); - } -}; - -class ReviewApp { - positiveEventCount = 0; - - pushPositiveEvent = () => { - if (this.positiveEventCount >= numberOfPositiveEvent) { - return; - } - this.positiveEventCount += 1; - if (this.positiveEventCount === numberOfPositiveEvent) { - tryReview(); - } - } -} - -export const Review = new ReviewApp(); diff --git a/app/views/RoomsListView/ServerDropdown.js b/app/views/RoomsListView/ServerDropdown.js index d5c62d7b4..5b8d79eec 100644 --- a/app/views/RoomsListView/ServerDropdown.js +++ b/app/views/RoomsListView/ServerDropdown.js @@ -23,6 +23,7 @@ import { withTheme } from '../../theme'; import { KEY_COMMAND, handleCommandSelectServer } from '../../commands'; import { isTablet } from '../../utils/deviceInfo'; import { withSplit } from '../../split'; +import localAuthenticate from '../../utils/localAuthentication'; const ROW_HEIGHT = 68; const ANIMATION_DURATION = 200; @@ -148,11 +149,9 @@ class ServerDropdown extends Component { }, ANIMATION_DURATION); }, ANIMATION_DURATION); } else { - const authResult = await LocalAuthentication.authenticateAsync(); - if (authResult?.success) { + const localAuthResult = await localAuthenticate(server); + if (localAuthResult) { selectServerRequest(server); - } else { - alert('cancelled') } } }