diff --git a/.env.sample b/.env.sample deleted file mode 100644 index cf2c902..0000000 --- a/.env.sample +++ /dev/null @@ -1,2 +0,0 @@ -STORAGE_KEY= -SENTRY_DSN= \ No newline at end of file diff --git a/README.md b/README.md index 1d2122b..d4d3667 100644 --- a/README.md +++ b/README.md @@ -79,11 +79,19 @@ If you want to deploy to the test stores using fastlane, which is the recommende ## Available Scripts +If you are rebuilding the app, you may want to clean the cache and remove the **node_modules** folder: + +### `yarn cache clean` + +And if you are on Linux, do: + +### `rm -rf node_modules` + In the project directory, you can run: ### `yarn start` -Starts the Metro bundler to serve the Javascript code in the development environment. +Starts the Metro bundler to serve the Javascript code in the development environment. Then in a different terminal, run one of the following: ### `yarn run-ios` diff --git a/android/app/src/main/jniLibs/x86/libzenroom.so b/android/app/src/main/jniLibs/x86/libzenroom.so index 1ca419f..2bc6f66 100644 Binary files a/android/app/src/main/jniLibs/x86/libzenroom.so and b/android/app/src/main/jniLibs/x86/libzenroom.so differ diff --git a/ios/Zenroom.m b/ios/Zenroom.m index e97dbc4..69cd313 100644 --- a/ios/Zenroom.m +++ b/ios/Zenroom.m @@ -41,7 +41,7 @@ @implementation Zenroom size_t errorSize = 1024 * 128; char *z_error = (char*)malloc(errorSize * sizeof(char)); - zenroom_exec_tobuf(c, NULL, k, d, 3, z_output, outputSize, z_error, errorSize); + zenroom_exec_tobuf(c, NULL, k, d, z_output, outputSize, z_error, errorSize); NSLog(@"output: %s", z_output); NSLog(@"error: %s", z_error); diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..548a82b --- /dev/null +++ b/package-lock.json @@ -0,0 +1,14 @@ +{ + "name": "decode-app", + "version": "2.0.2", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "graceful-fs": { + "version": "4.2.4", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz", + "integrity": "sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==", + "dev": true + } + } +} diff --git a/package.json b/package.json index 9526361..6fc79b9 100644 --- a/package.json +++ b/package.json @@ -61,11 +61,15 @@ "eslint-plugin-jest": "^22.6.4", "eslint-plugin-jsx-a11y": "^6.2.1", "eslint-plugin-react": "^7.13.0", + "graceful-fs": "^4.2.4", "jest": "^24.8.0", "metro-react-native-babel-preset": "^0.54.1", "react-native-dotenv": "^0.2.0", "react-test-renderer": "16.10.2" }, + "resolutions": { + "graceful-fs": "4.2.4" + }, "jest": { "preset": "react-native", "setupFiles": [ diff --git a/src/api/zenroom/dp3t/generate-ephids.zen.js b/src/api/zenroom/dp3t/generate-ephids.zen.js new file mode 100644 index 0000000..cfe979e --- /dev/null +++ b/src/api/zenroom/dp3t/generate-ephids.zen.js @@ -0,0 +1,11 @@ +export default () => ` +scenario 'dp3t': Decentralized Privacy-Preserving Proximity Tracing +rule check version 1.0.0 +rule input encoding hex +rule output encoding hex +Given I have a valid 'secret day key' +and I have a valid number in 'moments' +When I create the ephemeral ids for each moment of the day +and I randomize the 'ephemeral ids' array +Then print the 'ephemeral ids' +`; diff --git a/src/api/zenroom/dp3t/generate-sk1.zen.js b/src/api/zenroom/dp3t/generate-sk1.zen.js new file mode 100644 index 0000000..2001c69 --- /dev/null +++ b/src/api/zenroom/dp3t/generate-sk1.zen.js @@ -0,0 +1,10 @@ +export default () => ` + rule check version 1.0.0 + rule input encoding hex + rule output encoding hex + Given nothing + When I create the random object of '256' bits + and I rename the 'random object' to 'secret day key' + Then print the 'secret day key' +`; + diff --git a/src/api/zenroom/dp3t/generate-sk2.zen.js b/src/api/zenroom/dp3t/generate-sk2.zen.js new file mode 100644 index 0000000..1336441 --- /dev/null +++ b/src/api/zenroom/dp3t/generate-sk2.zen.js @@ -0,0 +1,10 @@ +export default () => ` +scenario 'dp3t': Decentralized Privacy-Preserving Proximity Tracing +rule check version 1.0.0 +rule input encoding hex +rule output encoding hex +Given I have a valid 'secret day key' +When I renew the secret day key to a new day +Then print the 'secret day key' +`; + diff --git a/src/api/zenroom/dp3t/index.js b/src/api/zenroom/dp3t/index.js new file mode 100644 index 0000000..8bfd2bc --- /dev/null +++ b/src/api/zenroom/dp3t/index.js @@ -0,0 +1,3 @@ +export generatesk1 from './generate-sk1.zen'; +export generatesk2 from './generate-sk2.zen'; +export generateEphids from './generate-ephids.zen'; \ No newline at end of file diff --git a/src/api/zenroom/webinar/index.js b/src/api/zenroom/webinar/index.js new file mode 100644 index 0000000..fa3734d --- /dev/null +++ b/src/api/zenroom/webinar/index.js @@ -0,0 +1 @@ +export keypairGen from './keypairGen'; \ No newline at end of file diff --git a/src/api/zenroom/webinar/keypairGen.js b/src/api/zenroom/webinar/keypairGen.js new file mode 100644 index 0000000..177c62e --- /dev/null +++ b/src/api/zenroom/webinar/keypairGen.js @@ -0,0 +1,6 @@ +export default () => ` +Scenario 'ecdh': Create the keypair +Given that I am known as 'Alice' +When I create the keypair +Then print my data +`; \ No newline at end of file diff --git a/src/redux/modules/applications/covid.js b/src/redux/modules/applications/covid.js new file mode 100644 index 0000000..13c8eaa --- /dev/null +++ b/src/redux/modules/applications/covid.js @@ -0,0 +1,197 @@ +import { createSelector } from 'reselect'; +import { path, prop, append } from 'ramda'; +import moment from 'moment'; +import uuid from 'uuid/v4'; +import { toggle } from 'lib/utils'; +import loginApi from 'api/login-client'; +import { APPLICATION_ACTIONS } from './actions'; +import { debugLog } from 'lib/utils'; +import zenroom from 'api/zenroom-client'; +import { + generatesk1, + generatesk2, + generateEphids +} from 'api/zenroom/dp3t'; + +export const initialState = { + loading: false, + loggedIn: false, + selectedAttributes: [], + uses: [], + certificates: {}, + error: null, + steps: 2, + step: 1, + sk1: null, + sk2: null, + moments: { moments: '8' }, + ephids: null +}; + + +export const ACTIONS = { + SK_SUCCESS: 'SK_SUCCESS', + SK2_GENERATE: 'SK2_GENERATE', + EPHIDS_GENERATE: 'EPHIDS_GENERATE', + LOGIN_REQUEST: 'LOGIN_REQUEST', + LOGIN_SUCCESS: 'LOGIN_SUCCESS', + LOGIN_FAILURE: 'LOGIN_FAILURE', + TOGGLE_SELECTED_ATTRIBUTE: 'TOGGLE_SELECTED_ATTRIBUTE', + CLEANUP_STATE: 'CLEANUP_STATE', +}; + +export const getGeneratedEphids = (data, key) => async (dispatch) => { + + let ephids = null; + if(data && key){ + try { + const tmpData = JSON.stringify(data); + const tmpKey = JSON.stringify(key); + ephids = await zenroom.execute(generateEphids(), tmpData, tmpKey); + + } catch (e) { + console.log('********** REDUX ACTION getGeneratedEphids error found!'); + console.log(e); + } + } + + dispatch({ + type: ACTIONS.EPHIDS_GENERATE, + ephids + }); +} + +export const getGeneratedSK2 = (sk1) => async (dispatch) => { + let sk2 = null + if (sk1) { + try { + sk2 = await zenroom.execute(generatesk2(), sk1, ''); + } catch (e) { + console.log('********** REDUX ACTION generateSK2 error found!'); + console.log(e); + } + } + dispatch({ + type: ACTIONS.SK2_GENERATE, + sk2 + }); + +} + +export const getGeneratedSK1 = () => async (dispatch) => { + let sk1 = null; + try { + sk1 = await zenroom.execute(generatesk1(), '', ''); + } catch (e) { + console.log('********** REDUX ACTION callZenroom error found!'); + console.log(e); + } + dispatch({ + type: ACTIONS.SK_SUCCESS, + sk1 + }); +}; + + +const getBranch = path(['applications', 'covid']); + +export const getSk1 = createSelector( + getBranch, + prop('sk1'), +); + +export const getSk2 = createSelector( + getBranch, + prop('sk2'), +); + +export const getMoments = createSelector( + getBranch, + prop('moments'), +); + +export const getEphids = createSelector( + getBranch, + prop('ephids'), +); + + +export default (state = initialState, action) => { + switch (action.type) { + case APPLICATION_ACTIONS.INIT_APPLICATION: { + if (action.id !== 'covidtwo') return state; + return { + ...state, + loading: false, + error: null, + loggedIn: false, + step: 1, + }; + } + case ACTIONS.LOGIN_REQUEST: { + return { + ...state, + loading: true, + error: null, + loggedIn: false, + }; + } + case ACTIONS.LOGIN_SUCCESS: { + const { certificate } = action; + const { petitionId = uuid() } = certificate; + const { uses, selectedAttributes, certificates } = state; + return { + ...state, + loading: false, + loggedIn: true, + step: 2, + uses: append({ + date: +moment(), + sharedData: selectedAttributes, + }, + uses), + certificates: { + ...certificates, + [petitionId]: certificate, + }, + }; + } + case ACTIONS.LOGIN_FAILURE: { + return { + ...state, + loading: false, + error: action.error, + }; + } + case ACTIONS.TOGGLE_SELECTED_ATTRIBUTE: { + const { selectedAttributes } = state; + return { + ...state, + selectedAttributes: toggle(action.id, selectedAttributes), + }; + } + case ACTIONS.SK_SUCCESS: { + const { sk1 } = action; + return { + ...state, + sk1 + }; + } + case ACTIONS.SK2_GENERATE: { + const { sk2 } = action; + return { + ...state, + sk2 + }; + } + case ACTIONS.EPHIDS_GENERATE: { + const { ephids } = action; + return { + ...state, + ephids + }; + } + default: + return state; + } +}; diff --git a/src/redux/modules/applications/index.js b/src/redux/modules/applications/index.js index 5deff0d..b6d740e 100644 --- a/src/redux/modules/applications/index.js +++ b/src/redux/modules/applications/index.js @@ -53,6 +53,7 @@ import { listApplications, getApplication } from 'api/atlas-client'; import { upperFirst } from 'lib/utils'; import dddc, { initialState as dddcInitialState } from './dddc'; import bcnnow, { initialState as bcnnowInitialState } from './bcnnow'; +import covid, { initialState as covidInitialState } from './covid'; import { APPLICATION_ACTIONS } from './actions'; const defaultStats = { @@ -191,9 +192,11 @@ export const getProgress = applicationId => createSelector( export const initialApplicationState = { dddc: dddcInitialState, bcnnow: bcnnowInitialState, + covid: covidInitialState, }; export default combineReducers({ dddc, bcnnow, + covid, }); diff --git a/src/redux/modules/index.js b/src/redux/modules/index.js index 5329203..fd70114 100644 --- a/src/redux/modules/index.js +++ b/src/redux/modules/index.js @@ -23,3 +23,4 @@ export * as attributes from './attributes'; export * as applications from './applications'; export * as walkthrough from './walkthrough'; export * as dummy from './dummy'; +export * as webinar from './webinar'; diff --git a/src/redux/modules/webinar.js b/src/redux/modules/webinar.js new file mode 100644 index 0000000..79993b3 --- /dev/null +++ b/src/redux/modules/webinar.js @@ -0,0 +1,74 @@ +/* + * DECODE App – A mobile app to control your personal data + * + * Copyright (C) 2019 – DRIBIA Data Research S.L. + * + * DECODE App is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * DECODE App is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * email: info@dribia.com + */ + +import { createSelector } from 'reselect'; +import { prop } from 'ramda'; +import CredentialIssuerClient from 'api/credential-issuer-client'; +import zenroom from 'api/zenroom-client'; +import { + keypairGen + +} from 'api/zenroom/webinar'; +import { debugLog } from 'lib/utils'; + +const initialState = { + result: 'keypair not executed', +}; + +export const ACTIONS = { + ZENROOM_EXECUTION: 'ZENROOM_EXECUTION', +}; + +export const callZenroom = () => async (dispatch) => { + let result; + try { + result = await zenroom.execute(keypairGen(), '', ''); + } catch (e) { + debugLog('Something went wrong in webinar zenroom.') + } + dispatch({ + type: ACTIONS.ZENROOM_EXECUTION, + result + }); +} + +const getWebinar = prop('webinar'); + +export const getResult = createSelector( + getWebinar, + prop('result'), +); + + + +export default (state = initialState, action) => { + switch (action.type) { + case ACTIONS.ZENROOM_EXECUTION: { + const { result } = action; + return { + ...state, + result + }; + } + default: + return state; + } +}; diff --git a/src/screens/RootScreen/RootScreen.Component.js b/src/screens/RootScreen/RootScreen.Component.js index 0392c0a..adcc220 100644 --- a/src/screens/RootScreen/RootScreen.Component.js +++ b/src/screens/RootScreen/RootScreen.Component.js @@ -41,6 +41,8 @@ import About from 'screens/About'; import Scanner from 'screens/Scanner'; import dddcScreens from 'screens/applications/DDDC'; import bcnnowScreens from 'screens/applications/BCNNow'; +import CovidScreen from 'screens/applications/Covid'; +import WebinarScreen from 'screens/Webinar'; const defaultNavigationOptions = ({ screenProps: { theme } }) => ({ headerBackTitle: null, @@ -136,6 +138,28 @@ const DummyStack = createStackNavigator({ defaultNavigationOptions, }); +const CovidStack = createStackNavigator({ + Covid: { + screen: CovidScreen, + navigationOptions: ({ navigation }) => ({ + headerLeft: navigation.toggleDrawer()} />, + }), + }, +}, { + defaultNavigationOptions, +}); + +const WebinarStack = createStackNavigator({ + Webinar: { + screen: WebinarScreen, + navigationOptions: ({ navigation }) => ({ + headerLeft: navigation.toggleDrawer()} />, + }), + }, +}, { + defaultNavigationOptions, +}); + const DrawerNavigator = createDrawerNavigator({ AttributeStack: { screen: AttributeStack, @@ -192,6 +216,18 @@ const DrawerNavigator = createDrawerNavigator({ drawerIcon: , }), }, + CovidStack: { + screen: CovidStack, + navigationOptions: () => ({ + drawerLabel: 'Covid Test', + }), + }, + WebinarStack: { + screen: WebinarStack, + navigationOptions: () => ({ + drawerLabel: 'Webinar Test', + }), + }, // Uncomment to have a testing screen on the menu // DummyStack: { // screen: DummyStack, @@ -200,28 +236,28 @@ const DrawerNavigator = createDrawerNavigator({ // }), // }, }, -{ - defaultNavigationOptions: () => ({ - drawerLockMode: 'locked-closed', - }), - initialRouteName: 'ApplicationStack', - hideStatusBar: Platform.OS === 'ios', - drawerBackgroundColor: commonTheme.menuBackgroundColor, - contentOptions: { - activeTintColor: commonTheme.headerSecondaryColor, - inactiveTintColor: commonTheme.headerSecondaryColor, - itemStyle: { - borderBottomWidth: 1, - borderBottomColor: commonTheme.headerSecondaryColor, - }, - labelStyle: { - fontFamily: commonTheme.fontFamily, - }, - iconContainerStyle: { - marginRight: 0, + { + defaultNavigationOptions: () => ({ + drawerLockMode: 'locked-closed', + }), + initialRouteName: 'ApplicationStack', + hideStatusBar: Platform.OS === 'ios', + drawerBackgroundColor: commonTheme.menuBackgroundColor, + contentOptions: { + activeTintColor: commonTheme.headerSecondaryColor, + inactiveTintColor: commonTheme.headerSecondaryColor, + itemStyle: { + borderBottomWidth: 1, + borderBottomColor: commonTheme.headerSecondaryColor, + }, + labelStyle: { + fontFamily: commonTheme.fontFamily, + }, + iconContainerStyle: { + marginRight: 0, + }, }, - }, -}); + }); const RootNavigation = createStackNavigator({ Main: { @@ -231,11 +267,11 @@ const RootNavigation = createStackNavigator({ screen: Warning, }, }, -{ - initialRouteName: 'Main', - mode: 'modal', - headerMode: 'none', -}); + { + initialRouteName: 'Main', + mode: 'modal', + headerMode: 'none', + }); const AppContainer = createAppContainer(RootNavigation); diff --git a/src/screens/Webinar/Webinar.Component.js b/src/screens/Webinar/Webinar.Component.js new file mode 100644 index 0000000..a295c51 --- /dev/null +++ b/src/screens/Webinar/Webinar.Component.js @@ -0,0 +1,33 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import { Button, Screen, Header } from 'lib/Components'; +import { Wrapper, Heading, Line, Separator } from './Webinar.Styles'; + +const Webinar = ({ + result, callZenroom +}) => { + + return ( + + + {'Webinar Example'} + {"Show result"} +