From 20aa6074aae7c25a63b01f6efb7ff20347262475 Mon Sep 17 00:00:00 2001 From: Sean Li Date: Mon, 29 Apr 2019 16:32:32 +0200 Subject: [PATCH 001/148] Change iOS claims home screen to white/purple --- src/routes.ios.ts | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/src/routes.ios.ts b/src/routes.ios.ts index 04bfacbb79..5b05114e8c 100644 --- a/src/routes.ios.ts +++ b/src/routes.ios.ts @@ -22,10 +22,10 @@ const navigationOptions = { } const navOptScreenWCancel = { - headerStyle: { backgroundColor: JolocomTheme.primaryColorBlack }, + headerStyle: { backgroundColor: JolocomTheme.primaryColorWhite }, headerBackImage: backIcon, - headerBackTitleStyle: { color: JolocomTheme.primaryColorWhite }, - headerTintColor: { color: JolocomTheme.primaryColorWhite }, + headerBackTitleStyle: { color: JolocomTheme.primaryColorPurple }, + headerTintColor: JolocomTheme.primaryColorPurple, } const headerTitleStyle = { @@ -37,9 +37,10 @@ const headerTitleStyle = { const commonNavigationOptions = { headerTitleStyle, headerStyle: { - backgroundColor: JolocomTheme.primaryColorBlack, + backgroundColor: JolocomTheme.primaryColorWhite, + borderBottomWidth: 0, }, - headerTintColor: JolocomTheme.primaryColorWhite, + headerTintColor: JolocomTheme.primaryColorBlack, } export const HomeRoutes = TabNavigator( @@ -56,7 +57,7 @@ export const HomeRoutes = TabNavigator( { tabBarOptions: { upperCaseLabel: false, - activeTintColor: JolocomTheme.primaryColorSand, + activeTintColor: JolocomTheme.primaryColorPurple, inactiveTintColor: JolocomTheme.primaryColorGrey, labelStyle: { fontFamily: JolocomTheme.contentFontFamily, @@ -64,10 +65,10 @@ export const HomeRoutes = TabNavigator( textAlign: 'center', }, style: { - backgroundColor: JolocomTheme.primaryColorBlack, + backgroundColor: JolocomTheme.primaryColorWhite, }, indicatorStyle: { - backgroundColor: JolocomTheme.primaryColorSand, + backgroundColor: JolocomTheme.primaryColorPurple, }, }, tabBarComponent: TabBarTop, From b71d4ffbd43fb4d8ffdf3f12285cac0fe02e12a1 Mon Sep 17 00:00:00 2001 From: Sean Li Date: Mon, 29 Apr 2019 17:06:28 +0200 Subject: [PATCH 002/148] Make iOS status bar dark conditionally --- src/NavigatorContainer.tsx | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/src/NavigatorContainer.tsx b/src/NavigatorContainer.tsx index 2011943374..a1c9751029 100644 --- a/src/NavigatorContainer.tsx +++ b/src/NavigatorContainer.tsx @@ -96,8 +96,19 @@ export class NavigatorContainer extends React.Component { render() { const { routes, index } = this.props.navigation const currentRoute = routes[index].routeName + const darkBackgroundPages = [ + routeList.Landing, + routeList.PasswordEntry, + routeList.Entropy, + routeList.SeedPhrase, + routeList.Exception, + routeList.Loading, + ] + const barStyle = darkBackgroundPages.includes(currentRoute) + ? 'light-content' + : 'dark-content' return [ - , + , Date: Mon, 29 Apr 2019 17:39:29 +0200 Subject: [PATCH 003/148] Add white header to all iOS consent screens --- src/routes.ios.ts | 36 ++++-------------------------------- 1 file changed, 4 insertions(+), 32 deletions(-) diff --git a/src/routes.ios.ts b/src/routes.ios.ts index 5b05114e8c..40cd8ae082 100644 --- a/src/routes.ios.ts +++ b/src/routes.ios.ts @@ -87,26 +87,14 @@ export const Routes = StackNavigator({ screen: CredentialReceive, navigationOptions: { headerTitle: I18n.t('Receiving new credential'), - headerTitleStyle: { - fontFamily: JolocomTheme.contentFontFamily, - fontWeight: '100', - fontSize: JolocomTheme.headerFontSize, - }, - headerStyle: { backgroundColor: JolocomTheme.primaryColorBlack }, - headerTintColor: JolocomTheme.primaryColorWhite, + ...commonNavigationOptions, }, }, Consent: { screen: Consent, navigationOptions: { headerTitle: I18n.t('Share claims'), - headerTitleStyle: { - fontFamily: JolocomTheme.contentFontFamily, - fontWeight: '100', - fontSize: JolocomTheme.headerFontSize, - }, - headerStyle: { backgroundColor: JolocomTheme.primaryColorBlack }, - headerTintColor: JolocomTheme.primaryColorWhite, + ...commonNavigationOptions, }, }, PaymentConsent: { @@ -115,15 +103,7 @@ export const Routes = StackNavigator({ headerBackImage: backIcon, headerBackTitleStyle: { color: JolocomTheme.primaryColorWhite }, headerTitle: I18n.t('Confirm payment'), - headerTitleStyle: { - fontFamily: JolocomTheme.contentFontFamily, - fontWeight: '100', - fontSize: JolocomTheme.headerFontSize, - }, - headerStyle: { - backgroundColor: JolocomTheme.primaryColorBlack, - }, - headerTintColor: JolocomTheme.primaryColorWhite, + ...commonNavigationOptions, }, }, AuthenticationConsent: { @@ -132,15 +112,7 @@ export const Routes = StackNavigator({ headerBackImage: backIcon, headerBackTitleStyle: { color: JolocomTheme.primaryColorWhite }, headerTitle: I18n.t('Authorization request'), - headerTitleStyle: { - fontFamily: JolocomTheme.contentFontFamily, - fontWeight: '100', - fontSize: JolocomTheme.headerFontSize, - }, - headerStyle: { - backgroundColor: JolocomTheme.primaryColorBlack, - }, - headerTintColor: JolocomTheme.primaryColorWhite, + ...commonNavigationOptions, }, }, Exception: { screen: Exception, navigationOptions }, From 70fc253b6967f7eca26a13c2c252277a67c3d0f8 Mon Sep 17 00:00:00 2001 From: Sean Li Date: Tue, 30 Apr 2019 11:57:45 +0200 Subject: [PATCH 004/148] Account for the notch on XR and XS Max --- src/NavigatorContainer.tsx | 47 ++++++++++++++++++++++++-------------- 1 file changed, 30 insertions(+), 17 deletions(-) diff --git a/src/NavigatorContainer.tsx b/src/NavigatorContainer.tsx index a1c9751029..05edca059a 100644 --- a/src/NavigatorContainer.tsx +++ b/src/NavigatorContainer.tsx @@ -3,6 +3,7 @@ import { addNavigationHelpers, NavigationEventSubscription, NavigationEventCallback, + SafeAreaView, } from 'react-navigation' import { connect } from 'react-redux' import { BackHandler, Linking, Platform, StatusBar } from 'react-native' @@ -13,6 +14,7 @@ import { navigationActions, accountActions } from 'src/actions/' import { BottomActionBar } from './ui/generic/' import { routeList } from './routeList' import { LoadingSpinner } from 'src/ui/generic/loadingSpinner' +import { JolocomTheme } from './styles/jolocom-theme' const { createReduxBoundAddListener, @@ -104,23 +106,34 @@ export class NavigatorContainer extends React.Component { routeList.Exception, routeList.Loading, ] - const barStyle = darkBackgroundPages.includes(currentRoute) - ? 'light-content' - : 'dark-content' - return [ - , - , - this.props.deepLinkLoading && , - currentRoute === routeList.Home && ( - - ), - ] + const isDarkBackground = darkBackgroundPages.includes(currentRoute) + return ( + + + + + {this.props.deepLinkLoading && } + + {currentRoute === routeList.Home && ( + + )} + + ) } } From be43391cd7d72e237ea07e6a057199a9b724e1ad Mon Sep 17 00:00:00 2001 From: Sean Li Date: Fri, 10 May 2019 14:52:30 +0200 Subject: [PATCH 005/148] Update test snapshots --- .../__snapshots__/navigation.test.tsx.snap | 125 ++++++++++-------- 1 file changed, 70 insertions(+), 55 deletions(-) diff --git a/tests/ui/containers/__snapshots__/navigation.test.tsx.snap b/tests/ui/containers/__snapshots__/navigation.test.tsx.snap index faa479ccb7..45bce8fbf4 100644 --- a/tests/ui/containers/__snapshots__/navigation.test.tsx.snap +++ b/tests/ui/containers/__snapshots__/navigation.test.tsx.snap @@ -1,77 +1,92 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP exports[`NavigatorContainer correctly hides bottom action bar 1`] = ` -Array [ + , - + , - "", - "", -] + > + + + `; exports[`NavigatorContainer mounts correctly and matches snapshot 1`] = ` -Array [ + , - + , - "", + > + + , -] + /> + `; From 2f69dabfc3f598969e08399544fbe304ab486ffc Mon Sep 17 00:00:00 2001 From: Mina Nagy Zaki Date: Tue, 14 May 2019 17:42:22 +0200 Subject: [PATCH 006/148] Merge route files and use react-native Platform helper for platform specific bits --- src/routeList.ios.ts | 14 ----- src/routes.ios.ts | 147 ------------------------------------------- src/routes.ts | 66 ++++++++++++++----- 3 files changed, 50 insertions(+), 177 deletions(-) delete mode 100644 src/routeList.ios.ts delete mode 100644 src/routes.ios.ts diff --git a/src/routeList.ios.ts b/src/routeList.ios.ts deleted file mode 100644 index e77dfad1dc..0000000000 --- a/src/routeList.ios.ts +++ /dev/null @@ -1,14 +0,0 @@ -export const enum routeList { - Landing = 'Landing', - Consent = 'Consent', - Loading = 'Loading', - SeedPhrase = 'SeedPhrase', - Home = 'Home', - Claims = 'Claims', - Exception = 'Exception', - ClaimDetails = 'ClaimDetails', - CredentialDialog = 'CredentialDialog', - QRCodeScanner = 'QRCodeScanner', - PaymentConsent = 'PaymentConsent', - AuthenticationConsent = 'AuthenticationConsent', -} diff --git a/src/routes.ios.ts b/src/routes.ios.ts deleted file mode 100644 index 657ff6420a..0000000000 --- a/src/routes.ios.ts +++ /dev/null @@ -1,147 +0,0 @@ -import { StackNavigator, TabBarTop, TabNavigator } from 'react-navigation' -import { Claims, ClaimDetails } from 'src/ui/home/' -import { Landing } from 'src/ui/landing/' -import { PaymentConsent } from 'src/ui/payment' -import { SeedPhrase, Loading } from 'src/ui/registration/' -import { JolocomTheme } from 'src/styles/jolocom-theme' -import { Exception } from 'src/ui/generic/' -import { Consent } from 'src/ui/sso' -import { CredentialReceive } from 'src/ui/home' -import I18n from 'src/locales/i18n' -import { QRScannerContainer } from 'src/ui/generic/qrcodeScanner' -import { AuthenticationConsent } from 'src/ui/authentication' -const backIcon = require('src/resources/img/left-chevron.png') - -const navigationOptions = { - header: null, -} - -const navOptScreenWCancel = { - headerStyle: { backgroundColor: JolocomTheme.primaryColorBlack }, - headerBackImage: backIcon, - headerBackTitleStyle: { color: JolocomTheme.primaryColorWhite }, - headerTintColor: { color: JolocomTheme.primaryColorWhite }, -} - -const headerTitleStyle = { - fontSize: JolocomTheme.headerFontSize, - fontFamily: JolocomTheme.contentFontFamily, - fontWeight: '300', -} - -const commonNavigationOptions = { - headerTitleStyle, - headerStyle: { - backgroundColor: JolocomTheme.primaryColorBlack, - }, - headerTintColor: JolocomTheme.primaryColorWhite, -} - -export const HomeRoutes = TabNavigator( - { - Claims: { - screen: Claims, - navigationOptions: { - tabBarLabel: I18n.t('All claims'), - headerTitle: I18n.t('My identity'), - ...commonNavigationOptions, - }, - }, - }, - { - tabBarOptions: { - upperCaseLabel: false, - activeTintColor: JolocomTheme.primaryColorSand, - inactiveTintColor: JolocomTheme.primaryColorGrey, - labelStyle: { - fontFamily: JolocomTheme.contentFontFamily, - fontSize: JolocomTheme.labelFontSize, - textAlign: 'center', - }, - style: { - backgroundColor: JolocomTheme.primaryColorBlack, - }, - indicatorStyle: { - backgroundColor: JolocomTheme.primaryColorSand, - }, - }, - tabBarComponent: TabBarTop, - tabBarPosition: 'top', - }, -) - -export const Routes = StackNavigator({ - Landing: { screen: Landing, navigationOptions }, - Loading: { screen: Loading, navigationOptions }, - SeedPhrase: { screen: SeedPhrase, navigationOptions }, - Home: { screen: HomeRoutes }, - CredentialDialog: { - screen: CredentialReceive, - navigationOptions: { - headerTitle: I18n.t('Receiving new credential'), - headerTitleStyle: { - fontFamily: JolocomTheme.contentFontFamily, - fontWeight: '100', - fontSize: JolocomTheme.headerFontSize, - }, - headerStyle: { backgroundColor: JolocomTheme.primaryColorBlack }, - headerTintColor: JolocomTheme.primaryColorWhite, - }, - }, - Consent: { - screen: Consent, - navigationOptions: { - headerTitle: I18n.t('Share claims'), - headerTitleStyle: { - fontFamily: JolocomTheme.contentFontFamily, - fontWeight: '100', - fontSize: JolocomTheme.headerFontSize, - }, - headerStyle: { backgroundColor: JolocomTheme.primaryColorBlack }, - headerTintColor: JolocomTheme.primaryColorWhite, - }, - }, - PaymentConsent: { - screen: PaymentConsent, - navigationOptions: { - headerBackImage: backIcon, - headerBackTitleStyle: { color: JolocomTheme.primaryColorWhite }, - headerTitle: I18n.t('Confirm payment'), - headerTitleStyle: { - fontFamily: JolocomTheme.contentFontFamily, - fontWeight: '100', - fontSize: JolocomTheme.headerFontSize, - }, - headerStyle: { - backgroundColor: JolocomTheme.primaryColorBlack, - }, - headerTintColor: JolocomTheme.primaryColorWhite, - }, - }, - AuthenticationConsent: { - screen: AuthenticationConsent, - navigationOptions: { - headerBackImage: backIcon, - headerBackTitleStyle: { color: JolocomTheme.primaryColorWhite }, - headerTitle: I18n.t('Authorization request'), - headerTitleStyle: { - fontFamily: JolocomTheme.contentFontFamily, - fontWeight: '100', - fontSize: JolocomTheme.headerFontSize, - }, - headerStyle: { - backgroundColor: JolocomTheme.primaryColorBlack, - }, - headerTintColor: JolocomTheme.primaryColorWhite, - }, - }, - Exception: { screen: Exception, navigationOptions }, - ClaimDetails: { - screen: ClaimDetails, - navigationOptions: navOptScreenWCancel, - }, - QRCodeScanner: { - screen: QRScannerContainer, - navigationOptions: navOptScreenWCancel, - }, -}) diff --git a/src/routes.ts b/src/routes.ts index 9e37dfb652..efc01339ad 100644 --- a/src/routes.ts +++ b/src/routes.ts @@ -1,3 +1,4 @@ +import { Platform } from 'react-native' import { StackNavigator, TabBarTop, TabNavigator } from 'react-navigation' import { Claims, Interactions, ClaimDetails } from 'src/ui/home/' import { Landing } from 'src/ui/landing/' @@ -8,9 +9,12 @@ import { Exception } from 'src/ui/generic/' import { Consent } from 'src/ui/sso' import { CredentialReceive } from 'src/ui/home' import I18n from 'src/locales/i18n' -import { QRScannerContainer } from './ui/generic/qrcodeScanner' -import { AuthenticationConsent } from './ui/authentication' -const closeIcon = require('./resources/img/close.png') +import { QRScannerContainer } from 'src/ui/generic/qrcodeScanner' +import { AuthenticationConsent } from 'src/ui/authentication' + +let headerBackImage = Platform.OS == 'android' + ? require('./resources/img/close.png') + : require('src/resources/img/left-chevron.png') const navigationOptions = { header: null, @@ -18,7 +22,13 @@ const navigationOptions = { const navOptScreenWCancel = { headerStyle: { backgroundColor: JolocomTheme.primaryColorBlack }, - headerBackImage: closeIcon, + headerBackImage, + ...Platform.select({ + ios: { + headerBackTitleStyle: { color: JolocomTheme.primaryColorWhite }, + headerTintColor: { color: JolocomTheme.primaryColorWhite }, + } + }) } const headerTitleStyle = { @@ -45,14 +55,18 @@ export const HomeRoutes = TabNavigator( ...commonNavigationOptions, }, }, - Interactions: { - screen: Interactions, - navigationOptions: { - tabBarLabel: I18n.t('Documents'), - headerTitle: I18n.t('My identity'), - ...commonNavigationOptions, - }, - }, + ...Platform.select({ + android: { + Interactions: { + screen: Interactions, + navigationOptions: { + tabBarLabel: I18n.t('Documents'), + headerTitle: I18n.t('My identity'), + ...commonNavigationOptions, + }, + } + } + }) }, { tabBarOptions: { @@ -110,33 +124,53 @@ export const Routes = StackNavigator({ PaymentConsent: { screen: PaymentConsent, navigationOptions: { - headerBackImage: closeIcon, + headerBackImage, headerTitle: I18n.t('Confirm payment'), headerTitleStyle: { - color: JolocomTheme.primaryColorWhite, fontFamily: JolocomTheme.contentFontFamily, fontWeight: '100', fontSize: JolocomTheme.headerFontSize, + ...Platform.select({ + android: { + color: JolocomTheme.primaryColorWhite, + } + }) }, headerStyle: { backgroundColor: JolocomTheme.primaryColorBlack, }, + ...Platform.select({ + ios: { + headerBackTitleStyle: { color: JolocomTheme.primaryColorWhite }, + headerTintColor: JolocomTheme.primaryColorWhite, + } + }) }, }, AuthenticationConsent: { screen: AuthenticationConsent, navigationOptions: { - headerBackImage: closeIcon, + headerBackImage, headerTitle: I18n.t('Authorization request'), headerTitleStyle: { - color: JolocomTheme.primaryColorWhite, fontFamily: JolocomTheme.contentFontFamily, fontWeight: '100', fontSize: JolocomTheme.headerFontSize, + ...Platform.select({ + android: { + color: JolocomTheme.primaryColorWhite, + } + }) }, headerStyle: { backgroundColor: JolocomTheme.primaryColorBlack, }, + ...Platform.select({ + ios: { + headerBackTitleStyle: { color: JolocomTheme.primaryColorWhite }, + headerTintColor: JolocomTheme.primaryColorWhite, + } + }) }, }, Exception: { screen: Exception, navigationOptions }, From 5a54716e0c34297456cf3007b76b34202ce7073b Mon Sep 17 00:00:00 2001 From: Sean Li Date: Thu, 16 May 2019 12:10:18 +0200 Subject: [PATCH 007/148] Fix status bar icon colours --- src/NavigatorContainer.tsx | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/NavigatorContainer.tsx b/src/NavigatorContainer.tsx index 35ab60f2e4..a988c2b478 100644 --- a/src/NavigatorContainer.tsx +++ b/src/NavigatorContainer.tsx @@ -89,8 +89,6 @@ export class NavigatorContainer extends React.Component { const currentRoute = routes[index].routeName const darkBackgroundPages = [ routeList.Landing, - routeList.PasswordEntry, - routeList.Entropy, routeList.SeedPhrase, routeList.Exception, routeList.Loading, @@ -98,9 +96,7 @@ export class NavigatorContainer extends React.Component { const isDarkBackground = darkBackgroundPages.includes(currentRoute) return ( - + Date: Thu, 16 May 2019 12:14:26 +0200 Subject: [PATCH 008/148] Update test snapshot --- tests/ui/containers/__snapshots__/navigation.test.tsx.snap | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/ui/containers/__snapshots__/navigation.test.tsx.snap b/tests/ui/containers/__snapshots__/navigation.test.tsx.snap index 45bce8fbf4..268d416b5d 100644 --- a/tests/ui/containers/__snapshots__/navigation.test.tsx.snap +++ b/tests/ui/containers/__snapshots__/navigation.test.tsx.snap @@ -48,7 +48,7 @@ exports[`NavigatorContainer mounts correctly and matches snapshot 1`] = ` Date: Thu, 16 May 2019 18:03:40 +0200 Subject: [PATCH 009/148] Revert "Merge the startRegistration and createIdentity tests" This reverts commit 8184121f3f1b0bccfe1f8b19242cb145c7566e3f. --- .../__snapshots__/index.test.ts.snap | 45 ++++++++++--------- tests/actions/registration/index.test.ts | 41 ++++++++++------- 2 files changed, 49 insertions(+), 37 deletions(-) diff --git a/tests/actions/registration/__snapshots__/index.test.ts.snap b/tests/actions/registration/__snapshots__/index.test.ts.snap index ff1b67190f..a7df095e3a 100644 --- a/tests/actions/registration/__snapshots__/index.test.ts.snap +++ b/tests/actions/registration/__snapshots__/index.test.ts.snap @@ -1,22 +1,7 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`Registration action creators startRegistration should save a password and create an identity 1`] = ` +exports[`Registration action creators createIdentity should attempt to create an identity 1`] = ` Array [ - Object { - "actions": Array [ - Object { - "routeName": "Loading", - "type": "Navigation/NAVIGATE", - }, - ], - "index": 0, - "key": undefined, - "type": "Navigation/RESET", - }, - Object { - "type": "SET_LOADING_MSG", - "value": "Encrypting and storing data locally", - }, Object { "type": "SET_LOADING_MSG", "value": "Fueling with ether", @@ -50,7 +35,7 @@ Array [ ] `; -exports[`Registration action creators startRegistration should save a password and create an identity 2`] = ` +exports[`Registration action creators createIdentity should attempt to create an identity 2`] = ` Array [ Array [ Object { @@ -61,7 +46,7 @@ Array [ ] `; -exports[`Registration action creators startRegistration should save a password and create an identity 3`] = ` +exports[`Registration action creators createIdentity should attempt to create an identity 3`] = ` Array [ Array [ Object { @@ -72,9 +57,9 @@ Array [ ] `; -exports[`Registration action creators startRegistration should save a password and create an identity 4`] = `Array []`; +exports[`Registration action creators createIdentity should attempt to create an identity 4`] = `Array []`; -exports[`Registration action creators startRegistration should save a password and create an identity 5`] = ` +exports[`Registration action creators createIdentity should attempt to create an identity 5`] = ` Array [ Array [ Object { @@ -118,3 +103,23 @@ Array [ ], ] `; + +exports[`Registration action creators startRegistration should save a password and initiate the registration process 1`] = ` +Array [ + Object { + "actions": Array [ + Object { + "routeName": "Loading", + "type": "Navigation/NAVIGATE", + }, + ], + "index": 0, + "key": undefined, + "type": "Navigation/RESET", + }, + Object { + "type": "SET_LOADING_MSG", + "value": "Encrypting and storing data locally", + }, +] +`; diff --git a/tests/actions/registration/index.test.ts b/tests/actions/registration/index.test.ts index 4ea41b8d7b..ac64997695 100644 --- a/tests/actions/registration/index.test.ts +++ b/tests/actions/registration/index.test.ts @@ -12,6 +12,26 @@ describe('Registration action creators', () => { describe('startRegistration', () => { const mockGetState = () => {} + it('should save a password and initiate the registration process', async () => { + const randomPassword = 'hunter0=' + util.generateSecureRandomBytes = () => + Buffer.from(randomPassword, 'base64') + const mockStore = configureStore([thunk])({}) + const mockMiddleware = { + keyChainLib: { + savePassword: jest.fn(), + }, + } + + const asyncAction = registrationActions.startRegistration() + await asyncAction(mockStore.dispatch, mockGetState, mockMiddleware) + expect(mockMiddleware.keyChainLib.savePassword).toHaveBeenCalledTimes(1) + expect(mockMiddleware.keyChainLib.savePassword).toHaveBeenCalledWith( + randomPassword, + ) + expect(mockStore.getActions()).toMatchSnapshot() + }) + it('should display exception screen in case of error', async () => { const mockStore = configureStore([thunk])({}) const mockMiddleware = { @@ -29,22 +49,16 @@ describe('Registration action creators', () => { expect(mockStore.getActions()[0].routeName).toContain('Exception') expect(mockStore.getActions()[0].params.returnTo).toBe('Landing') }) + }) - it('should save a password and create an identity', async () => { + describe('createIdentity', () => { + it('should attempt to create an identity', async () => { MockDate.set(new Date(946681200000)) const { getPasswordResult, cipher, entropy, identityWallet } = data - const entropyBytes = Buffer.from(entropy, 'hex') - const randomPasswordBytes = Buffer.from('hunter2') - util.generateSecureRandomBytes = length => { - if (length == 32) return randomPasswordBytes - else if (length == 16) return entropyBytes - } - JolocomLib.util.fuelKeyWithEther = jest.fn() const mockBackend = { identityWallet, keyChainLib: { - savePassword: jest.fn(), getPassword: jest.fn().mockResolvedValue(getPasswordResult), }, encryptionLib: { @@ -74,12 +88,8 @@ describe('Registration action creators', () => { const mockGetState = () => {} - const asyncAction = registrationActions.startRegistration() + const asyncAction = registrationActions.createIdentity(entropy) await asyncAction(mockStore.dispatch, mockGetState, mockBackend) - expect(mockBackend.keyChainLib.savePassword).toHaveBeenCalledTimes(1) - expect(mockBackend.keyChainLib.savePassword).toHaveBeenCalledWith( - randomPasswordBytes.toString('base64'), - ) expect(mockStore.getActions()).toMatchSnapshot() @@ -92,12 +102,9 @@ describe('Registration action creators', () => { mockBackend.storageLib.store.derivedKey.mock.calls, ).toMatchSnapshot() expect(JolocomLib.util.fuelKeyWithEther.mock.calls).toMatchSnapshot() - MockDate.reset() }) - }) - describe('createIdentity', () => { it('should display exception screen in case of error', async () => { const mockEntropy = 'abcd' const mockBackend = { From 8357eb222c83981ee5e07d6cb950774cc3782851 Mon Sep 17 00:00:00 2001 From: Mina Nagy Zaki Date: Thu, 16 May 2019 18:05:02 +0200 Subject: [PATCH 010/148] Revert "Remove entropy collection screen, use device entropy" This reverts commit d06532d6a049f733ead8e90e4e838c4641707d98. Conflicts: src/actions/registration/index.ts src/routeList.ios.ts src/routes.ios.ts --- package.json | 1 + src/actions/registration/index.ts | 24 ++- src/lib/entropyGenerator.ts | 26 +++ src/locales/de.js | 2 + src/locales/nl.js | 2 + src/routeList.ts | 1 + src/routes.ts | 3 +- src/ui/registration/components/entropy.tsx | 84 ++++++++++ src/ui/registration/containers/entropy.tsx | 87 ++++++++++ src/ui/registration/index.ts | 1 + .../__snapshots__/index.test.ts.snap | 16 ++ tests/actions/registration/index.test.ts | 10 ++ tests/lib/entropyGenerator.test.ts | 40 +++++ .../__snapshots__/entropy.test.tsx.snap | 151 ++++++++++++++++++ tests/ui/components/entropy.test.tsx | 25 +++ .../__snapshots__/entropy.test.tsx.snap | 63 ++++++++ tests/ui/containers/entropy.test.tsx | 74 +++++++++ yarn.lock | 6 +- 18 files changed, 606 insertions(+), 10 deletions(-) create mode 100644 src/lib/entropyGenerator.ts create mode 100644 src/ui/registration/components/entropy.tsx create mode 100644 src/ui/registration/containers/entropy.tsx create mode 100644 tests/lib/entropyGenerator.test.ts create mode 100644 tests/ui/components/__snapshots__/entropy.test.tsx.snap create mode 100644 tests/ui/components/entropy.test.tsx create mode 100644 tests/ui/containers/__snapshots__/entropy.test.tsx.snap create mode 100644 tests/ui/containers/entropy.test.tsx diff --git a/package.json b/package.json index e14346b912..bcea6125b5 100644 --- a/package.json +++ b/package.json @@ -138,6 +138,7 @@ "react-redux": "^5.0.7", "redux": "^3.7.2", "redux-thunk": "^2.2.0", + "sjcl": "^1.0.7", "sqlite3": "^4.0.0", "squel": "^5.12.1", "wif": "^2.0.6" diff --git a/src/actions/registration/index.ts b/src/actions/registration/index.ts index 6ee83ecbf8..6ce3ca783e 100644 --- a/src/actions/registration/index.ts +++ b/src/actions/registration/index.ts @@ -15,6 +15,22 @@ export const setLoadingMsg = (loadingMsg: string) => ({ value: loadingMsg, }) +export const submitEntropy = (encodedEntropy: string) => ( + dispatch: Dispatch, +) => { + dispatch( + navigationActions.navigatorReset({ + routeName: routeList.Loading, + }), + ) + + dispatch(setLoadingMsg(loading.loadingStages[0])) + + setTimeout(() => { + dispatch(createIdentity(encodedEntropy)) + }, 2000) +} + export const startRegistration = () => async ( dispatch: Dispatch, getState: Function, @@ -22,18 +38,14 @@ export const startRegistration = () => async ( ) => { try { const randomPassword = await generateSecureRandomBytes(32) - const entropy = await generateSecureRandomBytes(16) - const encodedEntropy = entropy.toString('hex') await backendMiddleware.keyChainLib.savePassword( randomPassword.toString('base64'), ) - dispatch( + return dispatch( navigationActions.navigatorReset({ - routeName: routeList.Loading, + routeName: routeList.Entropy, }), ) - dispatch(setLoadingMsg(loading.loadingStages[0])) - return dispatch(createIdentity(encodedEntropy)) } catch (err) { return dispatch(genericActions.showErrorScreen(err, routeList.Landing)) } diff --git a/src/lib/entropyGenerator.ts b/src/lib/entropyGenerator.ts new file mode 100644 index 0000000000..f8055acd32 --- /dev/null +++ b/src/lib/entropyGenerator.ts @@ -0,0 +1,26 @@ +const sjcl = require('sjcl') + +export interface EntropyGeneratorInterface { + addFromDelta: (d: number) => void + getProgress: () => number + generateRandomString: (wordCount: number) => string +} + +export class EntropyGenerator implements EntropyGenerator { + private generator = new sjcl.prng(10) + + addFromDelta(d: number): void { + this.generator.addEntropy(d, 1, 'user') + } + + getProgress(): number { + return this.generator.getProgress() + } + + generateRandomString(wordCount: number): string { + // returns an array of length wordCount filled with random 4 byte words. + const intArray = new Int32Array(this.generator.randomWords(wordCount)) + const buf = Buffer.from(intArray.buffer) + return buf.toString('hex') + } +} diff --git a/src/locales/de.js b/src/locales/de.js index ad9f350834..701b89c591 100644 --- a/src/locales/de.js +++ b/src/locales/de.js @@ -29,6 +29,8 @@ export default { "Keep all your data with you in one place, available at any time": "Bewahren Sie alle Ihre Daten an einem Ort auf, jederzeit verfügbar", "Track where you sign in to services": "Verfolgen Sie Ihr Anmeldeverhalten", "Get started": "Loslegen", + "For security purposes, we need some randomness": "Aus Sicherheitsgründen brauchen wir zufällig erzeugte Daten", + "Please tap the screen and draw on it randomly": "Tippen Sie auf den Bildschirm und zeichnen Sie drauf los", "Continue": "Fortsetzen", "Write these words down on an analog and secure place": "Schreiben Sie diese Wörter an einem analogen und sicheren Ort auf", "Without these words, you cannot access your wallet again": "Ohne diese Wörter können Sie nicht mehr auf Ihr SmartWallet zugreifen", diff --git a/src/locales/nl.js b/src/locales/nl.js index 8ddfc81558..54e1182f33 100644 --- a/src/locales/nl.js +++ b/src/locales/nl.js @@ -29,6 +29,8 @@ export default { "Keep all your data with you in one place, available at any time": "Bewaar al uw gegevens op één plaats, altijd beschikbaar", "Track where you sign in to services": "Volg bij welke services u zich aanmeldt", "Get started": "Begin", + "For security purposes, we need some randomness": "Voor de veiligheid hebben we wat willekeur nodig", + "Please tap the screen and draw on it randomly": "Tik op het scherm en teken er willekeurig op", "Continue": "Doorgaan", "Write these words down on an analog and secure place": "Schrijf deze woorden op een analoge en veilige plaats op", "Without these words, you cannot access your wallet again": "Zonder deze woorden heeft u geen toegang meer tot uw portefeuille", diff --git a/src/routeList.ts b/src/routeList.ts index 51240e61c6..7403c5d7d0 100644 --- a/src/routeList.ts +++ b/src/routeList.ts @@ -1,6 +1,7 @@ export const enum routeList { Landing = 'Landing', Consent = 'Consent', + Entropy = 'Entropy', Loading = 'Loading', SeedPhrase = 'SeedPhrase', Home = 'Home', diff --git a/src/routes.ts b/src/routes.ts index a583bfe631..8a0c49e77e 100644 --- a/src/routes.ts +++ b/src/routes.ts @@ -3,7 +3,7 @@ import { StackNavigator, TabBarTop, TabNavigator } from 'react-navigation' import { Claims, Interactions, ClaimDetails } from 'src/ui/home/' import { Landing } from 'src/ui/landing/' import { PaymentConsent } from 'src/ui/payment' -import { SeedPhrase, Loading } from 'src/ui/registration/' +import { SeedPhrase, Loading, Entropy } from 'src/ui/registration/' import { JolocomTheme } from 'src/styles/jolocom-theme' import { Exception } from 'src/ui/generic/' import { Consent } from 'src/ui/sso' @@ -115,6 +115,7 @@ export const HomeRoutes = TabNavigator( export const Routes = StackNavigator({ Landing: { screen: Landing, navigationOptions }, + Entropy: { screen: Entropy, navigationOptions }, Loading: { screen: Loading, navigationOptions }, SeedPhrase: { screen: SeedPhrase, navigationOptions }, Home: { screen: HomeRoutes }, diff --git a/src/ui/registration/components/entropy.tsx b/src/ui/registration/components/entropy.tsx new file mode 100644 index 0000000000..7ffcd18c5c --- /dev/null +++ b/src/ui/registration/components/entropy.tsx @@ -0,0 +1,84 @@ +import React from 'react' +import { Button } from 'react-native-material-ui' +import { StyleSheet, View, Dimensions } from 'react-native' +import { JolocomTheme } from 'src/styles/jolocom-theme' +import { Block, Container, CenteredText } from 'src/ui/structure/' +import { MaskedImageComponent } from 'src/ui/registration/components/maskedImage' +import I18n from 'src/locales/i18n' + +interface Props { + addPoint: (x: number, y: number) => void + submitEntropy: () => void + readonly progress: number +} + +const viewWidth: number = Dimensions.get('window').width + +// TODO FONT WEIGHT REFERENCE FROM STYLES +const styles = StyleSheet.create({ + mainContainer: { + backgroundColor: JolocomTheme.primaryColorBlack, + padding: 0, + }, + footerButton: { + position: 'absolute', + bottom: '5%', + }, + text: { + position: 'absolute', + top: '20%', + paddingHorizontal: viewWidth / 15, + backgroundColor: JolocomTheme.primaryColorBlack, + fontSize: JolocomTheme.headerFontSize, + fontFamily: JolocomTheme.contentFontFamily, + fontWeight: '100', + color: JolocomTheme.primaryColorSand, + }, + buttonContainer: { + width: 164, + height: 48, + borderRadius: 4, + backgroundColor: JolocomTheme.primaryColorPurple, + }, + buttonText: { + paddingVertical: 15, + fontFamily: JolocomTheme.contentFontFamily, + color: JolocomTheme.primaryColorWhite, + fontSize: JolocomTheme.headerFontSize, + fontWeight: '100', + }, +}) + +export const EntropyComponent: React.SFC = props => { + const { progress, submitEntropy, addPoint } = props + + const msg = + progress === 0 + ? I18n.t('For security purposes, we need some randomness') + + '. ' + + I18n.t('Please tap the screen and draw on it randomly') + : `${Math.trunc(progress * 100)} %` + + return ( + + + + + + + {progress === 1 ? ( +