diff --git a/packages/mobile/src/app/saga.test.ts b/packages/mobile/src/app/saga.test.ts index d2a37cb5300..419f7df6f5b 100644 --- a/packages/mobile/src/app/saga.test.ts +++ b/packages/mobile/src/app/saga.test.ts @@ -10,7 +10,7 @@ import { navigateToProperScreen, waitForRehydrate, } from 'src/app/saga' -import { waitForFirebaseAuth } from 'src/firebase/saga' +import { isAppVersionDeprecated } from 'src/firebase/firebase' import { UNLOCK_DURATION } from 'src/geth/consts' import { NavActions, navigate } from 'src/navigator/NavigationService' import { Screens, Stacks } from 'src/navigator/Screens' @@ -21,12 +21,6 @@ import { zeroSyncSelector } from 'src/web3/selectors' jest.mock('src/utils/time', () => ({ clockInSync: () => true, })) -jest.mock('src/firebase/firebase', () => ({ - ...jest.requireActual('src/firebase/firebase'), - getVersionInfo: jest.fn(async () => ({ deprecated: false })), -})) - -const { getVersionInfo } = require('src/firebase/firebase') const MockedAnalytics = CeloAnalytics as any @@ -52,7 +46,7 @@ const navigationSagaTest = (testName: string, state: any, expectedScreen: any) = }) } -describe('Upload Comment Key Saga', () => { +describe('App saga', () => { beforeEach(() => { MockedAnalytics.track = jest.fn() }) @@ -61,24 +55,15 @@ describe('Upload Comment Key Saga', () => { }) it('Version Deprecated', async () => { - getVersionInfo.mockImplementationOnce(async () => ({ deprecated: true })) await expectSaga(checkAppDeprecation) - .provide([[call(waitForRehydrate), null], [call(waitForFirebaseAuth), null]]) + .provide([[call(waitForRehydrate), null], [call(isAppVersionDeprecated), true]]) .run() expect(navigate).toHaveBeenCalledWith(Screens.UpgradeScreen) }) it('Version Not Deprecated', async () => { await expectSaga(checkAppDeprecation) - .provide([[call(waitForRehydrate), null], [call(waitForFirebaseAuth), null]]) - .run() - expect(navigate).not.toHaveBeenCalled() - }) - - it('Version info is not set', async () => { - getVersionInfo.mockImplementationOnce(async () => null) - await expectSaga(checkAppDeprecation) - .provide([[call(waitForRehydrate), null], [call(waitForFirebaseAuth), null]]) + .provide([[call(waitForRehydrate), null], [call(isAppVersionDeprecated), false]]) .run() expect(navigate).not.toHaveBeenCalled() }) diff --git a/packages/mobile/src/app/saga.ts b/packages/mobile/src/app/saga.ts index 176c14dc1e7..227136426d1 100644 --- a/packages/mobile/src/app/saga.ts +++ b/packages/mobile/src/app/saga.ts @@ -13,8 +13,7 @@ import { } from 'src/app/actions' import { ErrorMessages } from 'src/app/ErrorMessages' import { handleDappkitDeepLink } from 'src/dappkit/dappkit' -import { getVersionInfo } from 'src/firebase/firebase' -import { waitForFirebaseAuth } from 'src/firebase/saga' +import { isAppVersionDeprecated } from 'src/firebase/firebase' import { UNLOCK_DURATION } from 'src/geth/consts' import { NavActions, navigate } from 'src/navigator/NavigationService' import { Screens, Stacks } from 'src/navigator/Screens' @@ -60,12 +59,12 @@ const mapStateToProps = (state: PersistedRootState): PersistedStateProps | null export function* checkAppDeprecation() { yield call(waitForRehydrate) - yield call(waitForFirebaseAuth) - const versionInfo = yield getVersionInfo() - Logger.info(TAG, 'Version Info', JSON.stringify(versionInfo)) - if (versionInfo && versionInfo.deprecated) { - Logger.info(TAG, 'this version is deprecated') + const isDeprecated: boolean = yield call(isAppVersionDeprecated) + if (isDeprecated) { + Logger.warn(TAG, 'App version is deprecated') navigate(Screens.UpgradeScreen) + } else { + Logger.debug(TAG, 'App version is valid') } } @@ -157,9 +156,13 @@ export function* navigatePinProtected(action: NavigatePinProtected) { } } +export function* watchNavigatePinProtected() { + yield takeLatest(Actions.NAVIGATE_PIN_PROTECTED, navigatePinProtected) +} + export function* appSaga() { - yield spawn(checkAppDeprecation) yield spawn(navigateToProperScreen) yield spawn(toggleToProperSyncMode) - yield takeLatest(Actions.NAVIGATE_PIN_PROTECTED, navigatePinProtected) + yield spawn(checkAppDeprecation) + yield spawn(watchNavigatePinProtected) } diff --git a/packages/mobile/src/firebase/db-rules.json b/packages/mobile/src/firebase/db-rules.json index 4ab1c1793b1..2feb3ad4a88 100644 --- a/packages/mobile/src/firebase/db-rules.json +++ b/packages/mobile/src/firebase/db-rules.json @@ -10,10 +10,8 @@ } }, "versions": { - "$verion_string": { - ".read": true, - ".write": false - } + ".read": true, + ".write": false }, "lastBlockNotified": { ".read": false, diff --git a/packages/mobile/src/firebase/firebase.test.ts b/packages/mobile/src/firebase/firebase.test.ts index 85114fd3863..83cb95acd49 100644 --- a/packages/mobile/src/firebase/firebase.test.ts +++ b/packages/mobile/src/firebase/firebase.test.ts @@ -2,7 +2,12 @@ import { expectSaga } from 'redux-saga-test-plan' import { throwError } from 'redux-saga-test-plan/providers' import { call, select } from 'redux-saga/effects' import { currentLanguageSelector } from 'src/app/reducers' -import { initializeCloudMessaging, registerTokenToDb, setUserLanguage } from 'src/firebase/firebase' +import { + initializeCloudMessaging, + isVersionBelowMinimum, + registerTokenToDb, + setUserLanguage, +} from 'src/firebase/firebase' import { mockAccount2 } from 'test/values' const hasPermissionMock = jest.fn(() => null) @@ -79,3 +84,12 @@ describe(initializeCloudMessaging, () => { .run() }) }) + +describe('Firebase version check', () => { + it('Correctly check if version is deprecated', () => { + expect(isVersionBelowMinimum('1.5.0', '1.4.0')).toBe(false) + expect(isVersionBelowMinimum('1.4.0', '1.5.0')).toBe(true) + expect(isVersionBelowMinimum('1.4.0', '1.4.0')).toBe(false) + expect(isVersionBelowMinimum('1.4.0', '1.4.0.1')).toBe(true) + }) +}) diff --git a/packages/mobile/src/firebase/firebase.ts b/packages/mobile/src/firebase/firebase.ts index 6a616dad0b9..dea64de1ac0 100644 --- a/packages/mobile/src/firebase/firebase.ts +++ b/packages/mobile/src/firebase/firebase.ts @@ -9,6 +9,7 @@ import { NotificationReceiveState } from 'src/account' import { showError } from 'src/alert/actions' import { ErrorMessages } from 'src/app/ErrorMessages' import { currentLanguageSelector } from 'src/app/reducers' +import { FIREBASE_ENABLED } from 'src/config' import { WritePaymentRequest } from 'src/firebase/actions' import { handleNotification } from 'src/firebase/notifications' import { navigate } from 'src/navigator/NavigationService' @@ -164,14 +165,45 @@ export function* paymentRequestWriter({ paymentInfo }: WritePaymentRequest) { } } -export async function getVersionInfo() { +export function isVersionBelowMinimum(version: string, minVersion: string): boolean { + const minVersionArray = minVersion.split('.') + const versionArray = version.split('.') + const minVersionLength = Math.min(minVersionArray.length, version.length) + for (let i = 0; i < minVersionLength; i++) { + if (minVersionArray[i] > versionArray[i]) { + return true + } else if (minVersionArray[i] < versionArray[i]) { + return false + } + } + if (minVersionArray.length > versionArray.length) { + return true + } + return false +} + +/* +Get the Version deprecation information. +Firebase DB Format: + (New) Add minVersion child to versions category with a string of the mininum version as string +*/ +export async function isAppVersionDeprecated() { + if (!FIREBASE_ENABLED) { + return false + } + + Logger.info(TAG, 'Checking version info') const version = DeviceInfo.getVersion() - const versionFSPath = version.split('.').join('/') - Logger.info(TAG, `Checking version info ${version}`) - return (await firebase + + const versionsInfo = (await firebase .database() - .ref(`versions/${versionFSPath}`) + .ref('versions') .once('value')).val() + if (!versionsInfo || !versionsInfo.minVersion) { + return false + } + const minVersion: string = versionsInfo.minVersion + return isVersionBelowMinimum(version, minVersion) } export async function setUserLanguage(address: string, language: string) { diff --git a/packages/mobile/src/firebase/saga.ts b/packages/mobile/src/firebase/saga.ts index cf1f728369d..d035b3bccb2 100644 --- a/packages/mobile/src/firebase/saga.ts +++ b/packages/mobile/src/firebase/saga.ts @@ -45,7 +45,6 @@ export function* waitForFirebaseAuth() { function* initializeFirebase() { const address = yield call(getAccount) - if (!FIREBASE_ENABLED) { Logger.info(TAG, 'Firebase disabled') yield put(showError(ErrorMessages.FIREBASE_DISABLED))