diff --git a/android/build.gradle b/android/build.gradle index 75a0af56c4c2..f336c55df1d8 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -25,6 +25,8 @@ buildscript { allprojects { repositories { + maven { url "https://dl.bintray.com/onfido/maven" } + mavenLocal() maven { // All of React Native (JS, Obj-C sources, Android binaries) is installed from npm diff --git a/apple-app-site-association b/apple-app-site-association index 725beaea300a..59887c1f66d0 100644 --- a/apple-app-site-association +++ b/apple-app-site-association @@ -12,6 +12,7 @@ "/v/*", "/add-bank-account/*", "/iou/*", + "/enable-payments/*", ] } ] diff --git a/config/webpack/webpack.common.js b/config/webpack/webpack.common.js index 872ff9fe96a8..dcc26ce71ec6 100644 --- a/config/webpack/webpack.common.js +++ b/config/webpack/webpack.common.js @@ -122,6 +122,10 @@ const webpackConfig = { }, ], }, + { + test: /\.css$/i, + use: ['style-loader', 'css-loader'], + }, ], }, resolve: { diff --git a/ios/ExpensifyCash.xcodeproj/project.pbxproj b/ios/ExpensifyCash.xcodeproj/project.pbxproj index bcb683c206ba..6b7d7a919afc 100644 --- a/ios/ExpensifyCash.xcodeproj/project.pbxproj +++ b/ios/ExpensifyCash.xcodeproj/project.pbxproj @@ -507,11 +507,13 @@ ); inputPaths = ( "${PODS_ROOT}/Target Support Files/Pods-ExpensifyCash-ExpensifyCashTests/Pods-ExpensifyCash-ExpensifyCashTests-frameworks.sh", + "${PODS_XCFRAMEWORKS_BUILD_DIR}/Onfido/Onfido.framework/Onfido", "${PODS_XCFRAMEWORKS_BUILD_DIR}/OpenSSL/OpenSSL.framework/OpenSSL", "${PODS_XCFRAMEWORKS_BUILD_DIR}/LinkKit/LinkKit.framework/LinkKit", ); name = "[CP] Embed Pods Frameworks"; outputPaths = ( + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Onfido.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/OpenSSL.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/LinkKit.framework", ); @@ -537,11 +539,13 @@ ); inputPaths = ( "${PODS_ROOT}/Target Support Files/Pods-ExpensifyCash/Pods-ExpensifyCash-frameworks.sh", + "${PODS_XCFRAMEWORKS_BUILD_DIR}/Onfido/Onfido.framework/Onfido", "${PODS_XCFRAMEWORKS_BUILD_DIR}/OpenSSL/OpenSSL.framework/OpenSSL", "${PODS_XCFRAMEWORKS_BUILD_DIR}/LinkKit/LinkKit.framework/LinkKit", ); name = "[CP] Embed Pods Frameworks"; outputPaths = ( + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Onfido.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/OpenSSL.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/LinkKit.framework", ); diff --git a/ios/ExpensifyCash/Info.plist b/ios/ExpensifyCash/Info.plist index a58d21006572..403a68a328bf 100644 --- a/ios/ExpensifyCash/Info.plist +++ b/ios/ExpensifyCash/Info.plist @@ -63,8 +63,10 @@ + NSMicrophoneUsageDescription + Required for video capture NSCameraUsageDescription - Your camera is used to create chat attachments. + Your camera is used to create chat attachments, documents, and facial capture. NSLocationWhenInUseUsageDescription Your location is used to determine your default currency. NSPhotoLibraryAddUsageDescription diff --git a/ios/Podfile.lock b/ios/Podfile.lock index ce1061149197..5aef1f975e3c 100644 --- a/ios/Podfile.lock +++ b/ios/Podfile.lock @@ -150,6 +150,10 @@ PODS: - nanopb/encode (= 1.30906.0) - nanopb/decode (1.30906.0) - nanopb/encode (1.30906.0) + - Onfido (20.1.0) + - onfido-react-native-sdk (1.3.3): + - Onfido (= 20.1.0) + - React - OpenSSL-Universal (1.1.180) - Permission-LocationAccuracy (3.0.1): - RNPermissions @@ -473,6 +477,7 @@ DEPENDENCIES: - FlipperKit/SKIOSNetworkPlugin (= 0.75.1) - Folly (from `../node_modules/react-native/third-party-podspecs/Folly.podspec`) - glog (from `../node_modules/react-native/third-party-podspecs/glog.podspec`) + - "onfido-react-native-sdk (from `../node_modules/@onfido/react-native-sdk`)" - Permission-LocationAccuracy (from `../node_modules/react-native-permissions/ios/LocationAccuracy`) - Permission-LocationAlways (from `../node_modules/react-native-permissions/ios/LocationAlways`) - Permission-LocationWhenInUse (from `../node_modules/react-native-permissions/ios/LocationWhenInUse`) @@ -549,6 +554,7 @@ SPEC REPOS: - GoogleUtilities - libevent - nanopb + - Onfido - OpenSSL-Universal - Plaid - PromisesObjC @@ -565,6 +571,8 @@ EXTERNAL SOURCES: :podspec: "../node_modules/react-native/third-party-podspecs/Folly.podspec" glog: :podspec: "../node_modules/react-native/third-party-podspecs/glog.podspec" + onfido-react-native-sdk: + :path: "../node_modules/@onfido/react-native-sdk" Permission-LocationAccuracy: :path: "../node_modules/react-native-permissions/ios/LocationAccuracy" Permission-LocationAlways: @@ -691,6 +699,8 @@ SPEC CHECKSUMS: GoogleUtilities: 7f2f5a07f888cdb145101d6042bc4422f57e70b3 libevent: 4049cae6c81cdb3654a443be001fb9bdceff7913 nanopb: 59317e09cf1f1a0af72f12af412d54edf52603fc + Onfido: 116a268e4cb8b767c15285e8071c2e8304673cdf + onfido-react-native-sdk: b8f1b7cbe1adab6479d735275772390161630dcd OpenSSL-Universal: 1aa4f6a6ee7256b83db99ec1ccdaa80d10f9af9b Permission-LocationAccuracy: e8adff9ede1b23b43b7054a4500113d515fc87a8 Permission-LocationAlways: 7f7f373d086af7a81b2f4f20d65d29266ca2043b diff --git a/package-lock.json b/package-lock.json index d661555812ff..654b62486c5f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2308,6 +2308,15 @@ "regenerator-runtime": "^0.13.4" } }, + "@babel/runtime-corejs3": { + "version": "7.14.0", + "resolved": "https://registry.npmjs.org/@babel/runtime-corejs3/-/runtime-corejs3-7.14.0.tgz", + "integrity": "sha512-0R0HTZWHLk6G8jIk0FtoX+AatCtKnswS98VhXwGImFc759PJRp4Tru0PQYZofyijTFUr+gT8Mu7sgXVJLQ0ceg==", + "requires": { + "core-js-pure": "^3.0.0", + "regenerator-runtime": "^0.13.4" + } + }, "@babel/template": { "version": "7.10.4", "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.10.4.tgz", @@ -5187,6 +5196,11 @@ "@types/node": ">= 8" } }, + "@onfido/react-native-sdk": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/@onfido/react-native-sdk/-/react-native-sdk-1.3.3.tgz", + "integrity": "sha512-V8aU5wmYjCZWyQIkBkSxDvcuMBsxLMtzDfTOtA1o0rQ0vcw9iZ564pbtkQOMv4A0RcMErK/Gm1yUMb2GRYMmLg==" + }, "@pmmmwh/react-refresh-webpack-plugin": { "version": "0.4.3", "resolved": "https://registry.npmjs.org/@pmmmwh/react-refresh-webpack-plugin/-/react-refresh-webpack-plugin-0.4.3.tgz", @@ -5844,6 +5858,63 @@ "react-native-iphone-x-helper": "^1.3.0" } }, + "@sentry/browser": { + "version": "5.30.0", + "resolved": "https://registry.npmjs.org/@sentry/browser/-/browser-5.30.0.tgz", + "integrity": "sha512-rOb58ZNVJWh1VuMuBG1mL9r54nZqKeaIlwSlvzJfc89vyfd7n6tQ1UXMN383QBz/MS5H5z44Hy5eE+7pCrYAfw==", + "requires": { + "@sentry/core": "5.30.0", + "@sentry/types": "5.30.0", + "@sentry/utils": "5.30.0", + "tslib": "^1.9.3" + } + }, + "@sentry/core": { + "version": "5.30.0", + "resolved": "https://registry.npmjs.org/@sentry/core/-/core-5.30.0.tgz", + "integrity": "sha512-TmfrII8w1PQZSZgPpUESqjB+jC6MvZJZdLtE/0hZ+SrnKhW3x5WlYLvTXZpcWePYBku7rl2wn1RZu6uT0qCTeg==", + "requires": { + "@sentry/hub": "5.30.0", + "@sentry/minimal": "5.30.0", + "@sentry/types": "5.30.0", + "@sentry/utils": "5.30.0", + "tslib": "^1.9.3" + } + }, + "@sentry/hub": { + "version": "5.30.0", + "resolved": "https://registry.npmjs.org/@sentry/hub/-/hub-5.30.0.tgz", + "integrity": "sha512-2tYrGnzb1gKz2EkMDQcfLrDTvmGcQPuWxLnJKXJvYTQDGLlEvi2tWz1VIHjunmOvJrB5aIQLhm+dcMRwFZDCqQ==", + "requires": { + "@sentry/types": "5.30.0", + "@sentry/utils": "5.30.0", + "tslib": "^1.9.3" + } + }, + "@sentry/minimal": { + "version": "5.30.0", + "resolved": "https://registry.npmjs.org/@sentry/minimal/-/minimal-5.30.0.tgz", + "integrity": "sha512-BwWb/owZKtkDX+Sc4zCSTNcvZUq7YcH3uAVlmh/gtR9rmUvbzAA3ewLuB3myi4wWRAMEtny6+J/FN/x+2wn9Xw==", + "requires": { + "@sentry/hub": "5.30.0", + "@sentry/types": "5.30.0", + "tslib": "^1.9.3" + } + }, + "@sentry/types": { + "version": "5.30.0", + "resolved": "https://registry.npmjs.org/@sentry/types/-/types-5.30.0.tgz", + "integrity": "sha512-R8xOqlSTZ+htqrfteCWU5Nk0CDN5ApUTvrlvBuiH1DyP6czDZ4ktbZB0hAgBlVcK0U+qpD3ag3Tqqpa5Q67rPw==" + }, + "@sentry/utils": { + "version": "5.30.0", + "resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-5.30.0.tgz", + "integrity": "sha512-zaYmoH0NWWtvnJjC9/CBseXMtKHm/tm40sz3YfJRxeQjyzRqNQPgivpd9R/oDJCYj999mzdW382p/qi2ypjLww==", + "requires": { + "@sentry/types": "5.30.0", + "tslib": "^1.9.3" + } + }, "@sindresorhus/is": { "version": "0.14.0", "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-0.14.0.tgz", @@ -8829,6 +8900,27 @@ } } }, + "css-loader": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-3.6.0.tgz", + "integrity": "sha512-M5lSukoWi1If8dhQAUCvj4H8vUt3vOnwbQBH9DdTm/s4Ym2B/3dPMtYZeJmq7Q3S3Pa+I94DcZ7pc9bP14cWIQ==", + "dev": true, + "requires": { + "camelcase": "^5.3.1", + "cssesc": "^3.0.0", + "icss-utils": "^4.1.1", + "loader-utils": "^1.2.3", + "normalize-path": "^3.0.0", + "postcss": "^7.0.32", + "postcss-modules-extract-imports": "^2.0.0", + "postcss-modules-local-by-default": "^3.0.2", + "postcss-modules-scope": "^2.2.0", + "postcss-modules-values": "^3.0.0", + "postcss-value-parser": "^4.1.0", + "schema-utils": "^2.7.0", + "semver": "^6.3.0" + } + }, "electron-to-chromium": { "version": "1.3.727", "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.727.tgz", @@ -8956,6 +9048,12 @@ "integrity": "sha512-zR6HoT6LrLCRBwukmrVbHv0EpEQjksO6GmFcZQQuCAy139BEsoVKPYnf3jongYW83fAa1torLGYwxxky/p28sg==", "dev": true }, + "normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true + }, "p-limit": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", @@ -9012,6 +9110,29 @@ "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", "dev": true }, + "style-loader": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/style-loader/-/style-loader-1.3.0.tgz", + "integrity": "sha512-V7TCORko8rs9rIqkSrlMfkqA63DfoGBBJmK1kKGCcSi+BWb4cqz0SRsnp4l6rU5iwOEd0/2ePv68SV22VXon4Q==", + "dev": true, + "requires": { + "loader-utils": "^2.0.0", + "schema-utils": "^2.7.0" + }, + "dependencies": { + "loader-utils": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.0.tgz", + "integrity": "sha512-rP4F0h2RaWSvPEkD7BLDFQnvSf+nK+wr3ESUjNTyAGobqrijmW92zc+SO6d4p4B1wh7+B/Jg1mkQe5NYUEHtHQ==", + "dev": true, + "requires": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^2.1.2" + } + } + } + }, "supports-color": { "version": "5.5.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", @@ -11355,6 +11476,27 @@ "integrity": "sha512-Ne9DKPHTObRuB09Dru5AjwKjY4cJHVGu+y5f7coGn1E9Grkc3p2iBwE9AI/nJzsE29mQF7oq+mhYYRqOMFN1Bw==", "dev": true }, + "css-loader": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-3.6.0.tgz", + "integrity": "sha512-M5lSukoWi1If8dhQAUCvj4H8vUt3vOnwbQBH9DdTm/s4Ym2B/3dPMtYZeJmq7Q3S3Pa+I94DcZ7pc9bP14cWIQ==", + "dev": true, + "requires": { + "camelcase": "^5.3.1", + "cssesc": "^3.0.0", + "icss-utils": "^4.1.1", + "loader-utils": "^1.2.3", + "normalize-path": "^3.0.0", + "postcss": "^7.0.32", + "postcss-modules-extract-imports": "^2.0.0", + "postcss-modules-local-by-default": "^3.0.2", + "postcss-modules-scope": "^2.2.0", + "postcss-modules-values": "^3.0.0", + "postcss-value-parser": "^4.1.0", + "schema-utils": "^2.7.0", + "semver": "^6.3.0" + } + }, "detect-port": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/detect-port/-/detect-port-1.3.0.tgz", @@ -11497,6 +11639,12 @@ "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", "dev": true }, + "normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true + }, "p-limit": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", @@ -11624,6 +11772,29 @@ "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", "dev": true }, + "style-loader": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/style-loader/-/style-loader-1.3.0.tgz", + "integrity": "sha512-V7TCORko8rs9rIqkSrlMfkqA63DfoGBBJmK1kKGCcSi+BWb4cqz0SRsnp4l6rU5iwOEd0/2ePv68SV22VXon4Q==", + "dev": true, + "requires": { + "loader-utils": "^2.0.0", + "schema-utils": "^2.7.0" + }, + "dependencies": { + "loader-utils": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.0.tgz", + "integrity": "sha512-rP4F0h2RaWSvPEkD7BLDFQnvSf+nK+wr3ESUjNTyAGobqrijmW92zc+SO6d4p4B1wh7+B/Jg1mkQe5NYUEHtHQ==", + "dev": true, + "requires": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^2.1.2" + } + } + } + }, "supports-color": { "version": "5.5.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", @@ -12656,12 +12827,25 @@ "integrity": "sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ==", "dev": true }, + "@types/component-emitter": { + "version": "1.2.10", + "resolved": "https://registry.npmjs.org/@types/component-emitter/-/component-emitter-1.2.10.tgz", + "integrity": "sha512-bsjleuRKWmGqajMerkzox19aGbscQX5rmmvvXl3wlIp5gMG1HgkiwPxsN5p070fBDKTNSPgojVbuY1+HWMbFhg==" + }, "@types/debug": { "version": "4.1.5", "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.5.tgz", "integrity": "sha512-Q1y515GcOdTHgagaVFhHnIFQ38ygs/kmxdNpvpou+raI9UO3YZcHDngBSYKQklcKlvA7iuQlmIKbzvmxcOE9CQ==", "dev": true }, + "@types/dompurify": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/@types/dompurify/-/dompurify-2.2.2.tgz", + "integrity": "sha512-8nNWfAa8/oZjH3OLY5Wsxu9ueo0NwVUotIi353g0P2+N5BuTLJyAVOnF4xBUY0NyFUGJHY05o1pO2bqLto+lmA==", + "requires": { + "@types/trusted-types": "*" + } + }, "@types/eslint-visitor-keys": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/@types/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz", @@ -12940,6 +13124,11 @@ "integrity": "sha512-W+bw9ds02rAQaMvaLYxAbJ6cvguW/iJXNT6lTssS1ps6QdrMKttqEAMEG/b5CR8TZl3/L7/lH0ZV5nNR1LXikA==", "dev": true }, + "@types/trusted-types": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.0.tgz", + "integrity": "sha512-I8MnZqNXsOLHsU111oHbn3khtvKMi5Bn4qVFsIWSJcCP1KKDiXX5AEw8UPk0nSopeC+Hvxt6yAy1/a5PailFqg==" + }, "@types/uglify-js": { "version": "3.11.0", "resolved": "https://registry.npmjs.org/@types/uglify-js/-/uglify-js-3.11.0.tgz", @@ -13873,6 +14062,11 @@ "resolved": "https://registry.npmjs.org/array-find-index/-/array-find-index-1.0.2.tgz", "integrity": "sha1-3wEKoSh+Fku9pvlyOwqWoexBh6E=" }, + "array-flat-polyfill": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/array-flat-polyfill/-/array-flat-polyfill-1.0.1.tgz", + "integrity": "sha512-hfJmKupmQN0lwi0xG6FQ5U8Rd97RnIERplymOv/qpq8AoNKPPAnxJadjFA23FNWm88wykh9HmpLJUUwUtNU/iw==" + }, "array-flatten": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-2.1.2.tgz", @@ -14857,6 +15051,11 @@ "integrity": "sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ==", "dev": true }, + "backo2": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/backo2/-/backo2-1.0.2.tgz", + "integrity": "sha1-MasayLEpNjRj41s+u2n038+6eUc=" + }, "bail": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/bail/-/bail-1.0.5.tgz", @@ -14923,6 +15122,11 @@ "resolved": "https://registry.npmjs.org/base-64/-/base-64-0.1.0.tgz", "integrity": "sha1-eAqZyE59YAJgNhURxId2E78k9rs=" }, + "base64-arraybuffer": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-0.1.4.tgz", + "integrity": "sha1-mBjHngWbE1X5fgQooBfIOOkLqBI=" + }, "base64-js": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.1.tgz", @@ -15032,6 +15236,11 @@ "bluebird": "^3.5.5" } }, + "blueimp-load-image": { + "version": "2.29.0", + "resolved": "https://registry.npmjs.org/blueimp-load-image/-/blueimp-load-image-2.29.0.tgz", + "integrity": "sha512-psm81GlZ0ffKxVT0QN9dvhpzXMv1KxgXSg8ars0XGAcEGsTwFT2IPo59HDXlw4Lo2oImdPzwrwkliZSiLLUpIw==" + }, "bmp-js": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/bmp-js/-/bmp-js-0.1.0.tgz", @@ -15704,7 +15913,6 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", - "dev": true, "requires": { "function-bind": "^1.1.1", "get-intrinsic": "^1.0.2" @@ -16891,8 +17099,7 @@ "core-js-pure": { "version": "3.12.1", "resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.12.1.tgz", - "integrity": "sha512-1cch+qads4JnDSWsvc7d6nzlKAippwjUlf6vykkTLW53VSV+NkE6muGBToAjEA8pG90cSfcud3JgVmW2ds5TaQ==", - "dev": true + "integrity": "sha512-1cch+qads4JnDSWsvc7d6nzlKAippwjUlf6vykkTLW53VSV+NkE6muGBToAjEA8pG90cSfcud3JgVmW2ds5TaQ==" }, "core-util-is": { "version": "1.0.2", @@ -17193,67 +17400,122 @@ } }, "css-loader": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-3.6.0.tgz", - "integrity": "sha512-M5lSukoWi1If8dhQAUCvj4H8vUt3vOnwbQBH9DdTm/s4Ym2B/3dPMtYZeJmq7Q3S3Pa+I94DcZ7pc9bP14cWIQ==", + "version": "5.2.4", + "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-5.2.4.tgz", + "integrity": "sha512-OFYGyINCKkdQsTrSYxzGSFnGS4gNjcXkKkQgWxK138jgnPt+lepxdjSZNc8sHAl5vP3DhsJUxufWIjOwI8PMMw==", "dev": true, "requires": { - "camelcase": "^5.3.1", - "cssesc": "^3.0.0", - "icss-utils": "^4.1.1", - "loader-utils": "^1.2.3", - "normalize-path": "^3.0.0", - "postcss": "^7.0.32", - "postcss-modules-extract-imports": "^2.0.0", - "postcss-modules-local-by-default": "^3.0.2", - "postcss-modules-scope": "^2.2.0", - "postcss-modules-values": "^3.0.0", + "camelcase": "^6.2.0", + "icss-utils": "^5.1.0", + "loader-utils": "^2.0.0", + "postcss": "^8.2.10", + "postcss-modules-extract-imports": "^3.0.0", + "postcss-modules-local-by-default": "^4.0.0", + "postcss-modules-scope": "^3.0.0", + "postcss-modules-values": "^4.0.0", "postcss-value-parser": "^4.1.0", - "schema-utils": "^2.7.0", - "semver": "^6.3.0" + "schema-utils": "^3.0.0", + "semver": "^7.3.5" }, "dependencies": { - "json5": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", - "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", + "camelcase": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.2.0.tgz", + "integrity": "sha512-c7wVvbw3f37nuobQNtgsgG9POC9qMbNuMQmTCqZv23b6MIz0fcYpBiOlv9gEN/hdLdnZTDQhg6e9Dq5M1vKvfg==", + "dev": true + }, + "colorette": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-1.2.2.tgz", + "integrity": "sha512-MKGMzyfeuutC/ZJ1cba9NqcNpfeqMUcYmyF1ZFY6/Cn7CNSAKx6a+s48sqLqyAiZuaP2TcqMhoo+dlwFnVxT9w==", + "dev": true + }, + "icss-utils": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-5.1.0.tgz", + "integrity": "sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA==", + "dev": true + }, + "lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", "dev": true, "requires": { - "minimist": "^1.2.0" + "yallist": "^4.0.0" } }, - "loader-utils": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.0.tgz", - "integrity": "sha512-qH0WSMBtn/oHuwjy/NucEgbx5dbxxnxup9s4PVXJUDHZBQY+s0NWA9rJf53RBnQZxfch7euUui7hpoAPvALZdA==", + "nanoid": { + "version": "3.1.23", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.1.23.tgz", + "integrity": "sha512-FiB0kzdP0FFVGDKlRLEQ1BgDzU87dy5NnzjeW9YZNt+/c3+q82EQDUwniSAUxp/F0gFNI1ZhKU1FqYsMuqZVnw==", + "dev": true + }, + "postcss": { + "version": "8.2.15", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.2.15.tgz", + "integrity": "sha512-2zO3b26eJD/8rb106Qu2o7Qgg52ND5HPjcyQiK2B98O388h43A448LCslC0dI2P97wCAQRJsFvwTRcXxTKds+Q==", "dev": true, "requires": { - "big.js": "^5.2.2", - "emojis-list": "^3.0.0", - "json5": "^1.0.1" + "colorette": "^1.2.2", + "nanoid": "^3.1.23", + "source-map": "^0.6.1" } }, - "normalize-path": { + "postcss-modules-extract-imports": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", - "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.0.0.tgz", + "integrity": "sha512-bdHleFnP3kZ4NYDhuGlVK+CMrQ/pqUm8bx/oGL93K6gVwiclvX5x0n76fYMKuIGKzlABOy13zsvqjb0f92TEXw==", "dev": true }, - "schema-utils": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.7.1.tgz", - "integrity": "sha512-SHiNtMOUGWBQJwzISiVYKu82GiV4QYGePp3odlY1tuKO7gPtphAT5R/py0fA6xtbgLL/RvtJZnU9b8s0F1q0Xg==", + "postcss-modules-local-by-default": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-4.0.0.tgz", + "integrity": "sha512-sT7ihtmGSF9yhm6ggikHdV0hlziDTX7oFoXtuVWeDd3hHObNkcHRo9V3yg7vCAY7cONyxJC/XXCmmiHHcvX7bQ==", "dev": true, "requires": { - "@types/json-schema": "^7.0.5", - "ajv": "^6.12.4", - "ajv-keywords": "^3.5.2" + "icss-utils": "^5.0.0", + "postcss-selector-parser": "^6.0.2", + "postcss-value-parser": "^4.1.0" + } + }, + "postcss-modules-scope": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-3.0.0.tgz", + "integrity": "sha512-hncihwFA2yPath8oZ15PZqvWGkWf+XUfQgUGamS4LqoP1anQLOsOJw0vr7J7IwLpoY9fatA2qiGUGmuZL0Iqlg==", + "dev": true, + "requires": { + "postcss-selector-parser": "^6.0.4" + } + }, + "postcss-modules-values": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/postcss-modules-values/-/postcss-modules-values-4.0.0.tgz", + "integrity": "sha512-RDxHkAiEGI78gS2ofyvCsu7iycRv7oqw5xMWn9iMoR0N/7mf9D50ecQqUo5BZ9Zh2vH4bCUR/ktCqbB9m8vJjQ==", + "dev": true, + "requires": { + "icss-utils": "^5.0.0" } }, "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "version": "7.3.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", + "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", "dev": true } } @@ -17390,6 +17652,11 @@ "integrity": "sha512-jXKhWqXPmlUeoQnF/EhTtTl4C9SnrxSH/jZUih3jmO6lBKr99rP3/+FmrMj4EFpOXzMtXHAZkd3x0E6h6Fgflw==", "dev": true }, + "custom-event-polyfill": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/custom-event-polyfill/-/custom-event-polyfill-1.0.7.tgz", + "integrity": "sha512-TDDkd5DkaZxZFM8p+1I3yAlvM3rSr1wbrOliG4yJiwinMZN8z/iGL7BTlDkrJcYTmgUSb4ywVCc3ZaUtOtC76w==" + }, "cyclist": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/cyclist/-/cyclist-1.0.1.tgz", @@ -18100,6 +18367,11 @@ "domelementtype": "1" } }, + "dompurify": { + "version": "2.2.8", + "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-2.2.8.tgz", + "integrity": "sha512-9H0UL59EkDLgY3dUFjLV6IEUaHm5qp3mxSqWw7Yyx4Zhk2Jn2cmLe+CNPP3xy13zl8Bqg+0NehQzkdMoVhGRww==" + }, "domutils": { "version": "1.7.0", "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.7.0.tgz", @@ -18693,6 +18965,45 @@ "objectorarray": "^1.0.4" } }, + "engine.io-client": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-5.1.1.tgz", + "integrity": "sha512-jPFpw2HLL0lhZ2KY0BpZhIJdleQcUO9W1xkIpo0h3d6s+5D6+EV/xgQw9qWOmymszv2WXef/6KUUehyxEKomlQ==", + "requires": { + "base64-arraybuffer": "0.1.4", + "component-emitter": "~1.3.0", + "debug": "~4.3.1", + "engine.io-parser": "~4.0.1", + "has-cors": "1.1.0", + "parseqs": "0.0.6", + "parseuri": "0.0.6", + "ws": "~7.4.2", + "yeast": "0.1.2" + }, + "dependencies": { + "debug": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", + "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", + "requires": { + "ms": "2.1.2" + } + }, + "ws": { + "version": "7.4.5", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.4.5.tgz", + "integrity": "sha512-xzyu3hFvomRfXKH8vOFMU3OguG6oOvhXMo3xsGy3xWExqaM2dxBbVxuD99O7m3ZUFMvvscsZDqxfgMaRr/Nr1g==" + } + } + }, + "engine.io-parser": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-4.0.2.tgz", + "integrity": "sha512-sHfEQv6nmtJrq6TKuIz5kyEKH/qSdK56H/A+7DnAuUPWosnIZAS2NHNcPLmyjtY3cGS/MqJdZbUjW97JU72iYg==", + "requires": { + "base64-arraybuffer": "0.1.4" + } + }, "enhanced-resolve": { "version": "3.4.1", "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-3.4.1.tgz", @@ -18727,6 +19038,11 @@ "integrity": "sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w==", "dev": true }, + "enumerate-devices": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/enumerate-devices/-/enumerate-devices-1.1.1.tgz", + "integrity": "sha512-8zDbrc7ocusTL1ZGmvgy0cTwdyCaM7sGZoYLRmnWJalLQzmftDtce+uDU91gafOTo9MCtgjSIxyMv/F4+Hcchw==" + }, "env-paths": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", @@ -20287,6 +20603,11 @@ "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==" }, + "eventemitter2": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/eventemitter2/-/eventemitter2-2.1.3.tgz", + "integrity": "sha1-vXIB+FxZVIOA4eQ7P2pyhtTac0k=" + }, "eventemitter3": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-3.1.2.tgz", @@ -21331,6 +21652,14 @@ "integrity": "sha512-aq6gF1BEKje4a9i9+5jimNFIpq4Q1WiwBToeRK5NvZBd/TRsmW8BsJfOEGkr76TbOyPVD3OVDN910EcUNtRYEA==", "dev": true }, + "for-each": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", + "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", + "requires": { + "is-callable": "^1.1.3" + } + }, "for-in": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", @@ -21786,7 +22115,6 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz", "integrity": "sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==", - "dev": true, "requires": { "function-bind": "^1.1.1", "has": "^1.0.3", @@ -22181,8 +22509,12 @@ "has-bigints": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.1.tgz", - "integrity": "sha512-LSBS2LjbNBTf6287JEbEzvJgftkF5qFkmCo9hDRpAzKhUOlJ+hx8dd4USs00SgsUNwc4617J9ki5YtEClM2ffA==", - "dev": true + "integrity": "sha512-LSBS2LjbNBTf6287JEbEzvJgftkF5qFkmCo9hDRpAzKhUOlJ+hx8dd4USs00SgsUNwc4617J9ki5YtEClM2ffA==" + }, + "has-cors": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-cors/-/has-cors-1.1.0.tgz", + "integrity": "sha1-XkdHk/fqmEPRu5nCPu9J/xJv/zk=" }, "has-flag": { "version": "4.0.0", @@ -22410,6 +22742,28 @@ "integrity": "sha512-oFLl873u4usRM9K63j4ME9u3etNF0PLiJhSQ8rdfuL51Wn3zkD6drf9ZW0dOzjnZI22YYG24z30JcmfCZjMgYg==", "dev": true }, + "history": { + "version": "4.5.1", + "resolved": "https://registry.npmjs.org/history/-/history-4.5.1.tgz", + "integrity": "sha1-RJNaUQIeO45n66wmejVnVzKrpWk=", + "requires": { + "invariant": "^2.2.1", + "loose-envify": "^1.2.0", + "resolve-pathname": "^2.0.0", + "value-equal": "^0.2.0", + "warning": "^3.0.0" + }, + "dependencies": { + "warning": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/warning/-/warning-3.0.0.tgz", + "integrity": "sha1-MuU3fLVy3kqwR1O9+IIcAe1gW3w=", + "requires": { + "loose-envify": "^1.0.0" + } + } + } + }, "hmac-drbg": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", @@ -23013,8 +23367,7 @@ "is-bigint": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.2.tgz", - "integrity": "sha512-0JV5+SOCQkIdzjBK9buARcV804Ddu7A0Qet6sHi3FimE9ne6m4BGQZfRn+NZiXbBk4F4XmHfDZIipLj9pX8dSA==", - "dev": true + "integrity": "sha512-0JV5+SOCQkIdzjBK9buARcV804Ddu7A0Qet6sHi3FimE9ne6m4BGQZfRn+NZiXbBk4F4XmHfDZIipLj9pX8dSA==" }, "is-binary-path": { "version": "2.1.0", @@ -23028,7 +23381,6 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.1.tgz", "integrity": "sha512-bXdQWkECBUIAcCkeH1unwJLIpZYaa5VvuygSyS/c2lf719mTKZDU5UdDRlpd01UjADgmW8RfqaP+mRaVPdr/Ng==", - "dev": true, "requires": { "call-bind": "^1.0.2" } @@ -23223,8 +23575,7 @@ "is-number-object": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.5.tgz", - "integrity": "sha512-RU0lI/n95pMoUKu9v1BZP5MBcZuNSVJkMkAG2dJqC4z2GlkGUNeH68SuHuBKBD/XFe+LHZ+f9BKkLET60Niedw==", - "dev": true + "integrity": "sha512-RU0lI/n95pMoUKu9v1BZP5MBcZuNSVJkMkAG2dJqC4z2GlkGUNeH68SuHuBKBD/XFe+LHZ+f9BKkLET60Niedw==" }, "is-obj": { "version": "1.0.1", @@ -23308,8 +23659,7 @@ "is-string": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.5.tgz", - "integrity": "sha512-buY6VNRjhQMiF1qWDouloZlQbRhDPCebwxSjxMjxgemYT46YMd2NR0/H+fBhEfWX4A/w9TBJ+ol+okqJKFE6vQ==", - "dev": true + "integrity": "sha512-buY6VNRjhQMiF1qWDouloZlQbRhDPCebwxSjxMjxgemYT46YMd2NR0/H+fBhEfWX4A/w9TBJ+ol+okqJKFE6vQ==" }, "is-symbol": { "version": "1.0.3", @@ -30069,6 +30419,17 @@ } } }, + "node-polyglot": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/node-polyglot/-/node-polyglot-2.4.0.tgz", + "integrity": "sha512-KRzKwzMWm3wSAjOSop7/WwNyzaMkCe9ddkwXTQsIZEJmvEnqy/bCqLpAVw6xBszKfy4iLdYVA0d83L+cIkYPbA==", + "requires": { + "for-each": "^0.3.3", + "has": "^1.0.3", + "string.prototype.trim": "^1.1.2", + "warning": "^4.0.3" + } + }, "node-releases": { "version": "1.1.63", "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.63.tgz", @@ -30471,6 +30832,33 @@ "mimic-fn": "^1.0.0" } }, + "onfido-sdk-ui": { + "version": "6.8.0", + "resolved": "https://registry.npmjs.org/onfido-sdk-ui/-/onfido-sdk-ui-6.8.0.tgz", + "integrity": "sha512-z230fiijqX3ZZDXVzpExSsz+qDhTvYgfiqLzJu53Dv03TQM1rkitbe4icRJTuk5Y8tSvcdX59hr8RSHn0pCrcQ==", + "requires": { + "@babel/runtime-corejs3": "^7.8.7", + "@sentry/browser": "^5.14.2", + "@types/dompurify": "^2.2.1", + "array-flat-polyfill": "^1.0.1", + "blueimp-load-image": "~2.29.0", + "classnames": "~2.2.5", + "custom-event-polyfill": "^1.0.7", + "dompurify": "^2.2.6", + "enumerate-devices": "^1.1.0", + "eventemitter2": "~2.1.3", + "history": "~4.5.1", + "hoist-non-react-statics": "^3.3.2", + "node-polyglot": "^2.2.2", + "parse-unit": "~1.0.1", + "pdfobject": "~2.0.201604172", + "preact": "^10.5.4", + "redux": "^4.0.5", + "socket.io-client": "^4.0.1", + "supports-webp": "~1.0.3", + "visibilityjs": "~1.2.4" + } + }, "open": { "version": "6.4.0", "resolved": "https://registry.npmjs.org/open/-/open-6.4.0.tgz", @@ -30845,12 +31233,27 @@ "integrity": "sha1-bVuTSkVpk7I9N/QKOC1vFmao5cY=", "dev": true }, + "parse-unit": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parse-unit/-/parse-unit-1.0.1.tgz", + "integrity": "sha1-fhu21b7zh0wo45JSaiVBFwKR7s8=" + }, "parse5": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/parse5/-/parse5-5.1.1.tgz", "integrity": "sha512-ugq4DFI0Ptb+WWjAdOK16+u/nHfiIrcE+sh8kZMaM0WllQKLI9rOUq6c2b7cwPkXdzfQESqvoqK6ug7U/Yyzug==", "dev": true }, + "parseqs": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/parseqs/-/parseqs-0.0.6.tgz", + "integrity": "sha512-jeAGzMDbfSHHA091hr0r31eYfTig+29g3GKKE/PPbEQ65X0lmMwlEoqmhzu0iztID5uJpZsFlUPDP8ThPL7M8w==" + }, + "parseuri": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/parseuri/-/parseuri-0.0.6.tgz", + "integrity": "sha512-AUjen8sAkGgao7UyCX6Ahv0gIK2fABKmYjvP4xmy5JaKvcbTRueIqIPHLAfq30xJddqSE033IOMUSOMCcK3Sow==" + }, "parseurl": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", @@ -30949,6 +31352,11 @@ "resolved": "https://registry.npmjs.org/pdfjs-dist/-/pdfjs-dist-2.5.207.tgz", "integrity": "sha512-xGDUhnCYPfHy+unMXCLCJtlpZaaZ17Ew3WIL0tnSgKFUZXHAPD49GO9xScyszSsQMoutNDgRb+rfBXIaX/lJbw==" }, + "pdfobject": { + "version": "2.0.201604172", + "resolved": "https://registry.npmjs.org/pdfobject/-/pdfobject-2.0.201604172.tgz", + "integrity": "sha1-ES7fk7mL4SGl54Cwbn9feK0xqz8=" + }, "pend": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", @@ -31409,6 +31817,11 @@ "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.1.0.tgz", "integrity": "sha512-97DXOFbQJhk71ne5/Mt6cOu6yxsSfM0QGQyl0L25Gca4yGWEGJaig7l7gbCX623VqTBNGLRLaVUCnNkcedlRSQ==" }, + "preact": { + "version": "10.5.13", + "resolved": "https://registry.npmjs.org/preact/-/preact-10.5.13.tgz", + "integrity": "sha512-q/vlKIGNwzTLu+jCcvywgGrt+H/1P/oIRSD6mV4ln3hmlC+Aa34C7yfPI4+5bzW8pONyVXYS7SvXosy2dKKtWQ==" + }, "prelude-ls": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", @@ -33549,6 +33962,14 @@ "strip-indent": "^2.0.0" } }, + "redux": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/redux/-/redux-4.1.0.tgz", + "integrity": "sha512-uI2dQN43zqLWCt6B/BMGRMY6db7TTY4qeHHfGeKb3EOhmOKjU3KdWvNLJyqaHRksv/ErdNH7cFZWg9jXtewy4g==", + "requires": { + "@babel/runtime": "^7.9.2" + } + }, "refractor": { "version": "3.3.1", "resolved": "https://registry.npmjs.org/refractor/-/refractor-3.3.1.tgz", @@ -34185,6 +34606,11 @@ "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-3.0.0.tgz", "integrity": "sha1-six699nWiBvItuZTM17rywoYh0g=" }, + "resolve-pathname": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/resolve-pathname/-/resolve-pathname-2.2.0.tgz", + "integrity": "sha512-bAFz9ld18RzJfddgrO2e/0S2O81710++chRMUxHjXOYKF6jTAMrUNZrEZ1PvV0zlhfjidm08iRPdTLPno1FuRg==" + }, "resolve-url": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", @@ -34953,6 +35379,50 @@ } } }, + "socket.io-client": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-4.1.2.tgz", + "integrity": "sha512-RDpWJP4DQT1XeexmeDyDkm0vrFc0+bUsHDKiVGaNISJvJonhQQOMqV9Vwfg0ZpPJ27LCdan7iqTI92FRSOkFWQ==", + "requires": { + "@types/component-emitter": "^1.2.10", + "backo2": "~1.0.2", + "component-emitter": "~1.3.0", + "debug": "~4.3.1", + "engine.io-client": "~5.1.1", + "parseuri": "0.0.6", + "socket.io-parser": "~4.0.4" + }, + "dependencies": { + "debug": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", + "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", + "requires": { + "ms": "2.1.2" + } + } + } + }, + "socket.io-parser": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.0.4.tgz", + "integrity": "sha512-t+b0SS+IxG7Rxzda2EVvyBZbvFPBCjJoyHuE0P//7OAsN23GItzDRdWa6ALxZI/8R5ygK7jAR6t028/z+7295g==", + "requires": { + "@types/component-emitter": "^1.2.10", + "component-emitter": "~1.3.0", + "debug": "~4.3.1" + }, + "dependencies": { + "debug": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", + "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", + "requires": { + "ms": "2.1.2" + } + } + } + }, "sockjs": { "version": "0.3.20", "resolved": "https://registry.npmjs.org/sockjs/-/sockjs-0.3.20.tgz", @@ -35613,6 +36083,99 @@ } } }, + "string.prototype.trim": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.4.tgz", + "integrity": "sha512-hWCk/iqf7lp0/AgTF7/ddO1IWtSNPASjlzCicV5irAVdE1grjsneK26YG6xACMBEdCvO8fUST0UzDMh/2Qy+9Q==", + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "es-abstract": "^1.18.0-next.2" + }, + "dependencies": { + "es-abstract": { + "version": "1.18.0", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.0.tgz", + "integrity": "sha512-LJzK7MrQa8TS0ja2w3YNLzUgJCGPdPOV1yVvezjNnS89D+VR08+Szt2mz3YB2Dck/+w5tfIq/RoUAFqJJGM2yw==", + "requires": { + "call-bind": "^1.0.2", + "es-to-primitive": "^1.2.1", + "function-bind": "^1.1.1", + "get-intrinsic": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.2", + "is-callable": "^1.2.3", + "is-negative-zero": "^2.0.1", + "is-regex": "^1.1.2", + "is-string": "^1.0.5", + "object-inspect": "^1.9.0", + "object-keys": "^1.1.1", + "object.assign": "^4.1.2", + "string.prototype.trimend": "^1.0.4", + "string.prototype.trimstart": "^1.0.4", + "unbox-primitive": "^1.0.0" + } + }, + "has-symbols": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.2.tgz", + "integrity": "sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw==" + }, + "is-callable": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.3.tgz", + "integrity": "sha512-J1DcMe8UYTBSrKezuIUTUwjXsho29693unXM2YhJUTR2txK/eG47bvNa/wipPFmZFgr/N6f1GA66dv0mEyTIyQ==" + }, + "is-negative-zero": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.1.tgz", + "integrity": "sha512-2z6JzQvZRa9A2Y7xC6dQQm4FSTSTNWjKIYYTt4246eMTJmIo0Q+ZyOsU66X8lxK1AbB92dFeglPLrhwpeRKO6w==" + }, + "is-regex": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.3.tgz", + "integrity": "sha512-qSVXFz28HM7y+IWX6vLCsexdlvzT1PJNFSBuaQLQ5o0IEw8UDYW6/2+eCMVyIsbM8CNLX2a/QWmSpyxYEHY7CQ==", + "requires": { + "call-bind": "^1.0.2", + "has-symbols": "^1.0.2" + } + }, + "object-inspect": { + "version": "1.10.3", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.10.3.tgz", + "integrity": "sha512-e5mCJlSH7poANfC8z8S9s9S2IN5/4Zb3aZ33f5s8YqoazCFzNLloLU8r5VCG+G7WoqLvAAZoVMcy3tp/3X0Plw==" + }, + "object.assign": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.2.tgz", + "integrity": "sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ==", + "requires": { + "call-bind": "^1.0.0", + "define-properties": "^1.1.3", + "has-symbols": "^1.0.1", + "object-keys": "^1.1.1" + } + }, + "string.prototype.trimend": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.4.tgz", + "integrity": "sha512-y9xCjw1P23Awk8EvTpcyL2NIr1j7wJ39f+k6lvRnSMz+mz9CGz9NYPelDk42kOz6+ql8xjfK8oYzy3jAP5QU5A==", + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3" + } + }, + "string.prototype.trimstart": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.4.tgz", + "integrity": "sha512-jh6e984OBfvxS50tdY2nRZnoC5/mLFKOREQfw8t5yytkoUsJRNxvI/E39qu1sD0OtWI3OC0XgKSmcWwziwYuZw==", + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3" + } + } + } + }, "string.prototype.trimend": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.1.tgz", @@ -35719,26 +36282,13 @@ "dev": true }, "style-loader": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/style-loader/-/style-loader-1.3.0.tgz", - "integrity": "sha512-V7TCORko8rs9rIqkSrlMfkqA63DfoGBBJmK1kKGCcSi+BWb4cqz0SRsnp4l6rU5iwOEd0/2ePv68SV22VXon4Q==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/style-loader/-/style-loader-2.0.0.tgz", + "integrity": "sha512-Z0gYUJmzZ6ZdRUqpg1r8GsaFKypE+3xAzuFeMuoHgjc9KZv3wMyCRjQIWEbhoFSq7+7yoHXySDJyyWQaPajeiQ==", "dev": true, "requires": { "loader-utils": "^2.0.0", - "schema-utils": "^2.7.0" - }, - "dependencies": { - "schema-utils": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.7.1.tgz", - "integrity": "sha512-SHiNtMOUGWBQJwzISiVYKu82GiV4QYGePp3odlY1tuKO7gPtphAT5R/py0fA6xtbgLL/RvtJZnU9b8s0F1q0Xg==", - "dev": true, - "requires": { - "@types/json-schema": "^7.0.5", - "ajv": "^6.12.4", - "ajv-keywords": "^3.5.2" - } - } + "schema-utils": "^3.0.0" } }, "style-to-object": { @@ -35791,6 +36341,11 @@ "supports-color": "^7.0.0" } }, + "supports-webp": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/supports-webp/-/supports-webp-1.0.7.tgz", + "integrity": "sha512-ZlqT+sCgZKcykOLrk8DYR4t3Em+nyVSHpiV3q7uzOutLwKIYU23n88KibCLw3FzM4NCQeRorvZ55AV/77lQyOQ==" + }, "svg-parser": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/svg-parser/-/svg-parser-2.0.4.tgz", @@ -36683,8 +37238,7 @@ "tslib": { "version": "1.14.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "dev": true + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" }, "tsutils": { "version": "3.17.1", @@ -36805,7 +37359,6 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.1.tgz", "integrity": "sha512-tZU/3NqK3dA5gpE1KtyiJUrEB0lxnGkMFHptJ7q6ewdZ8s12QrODwNbhIJStmJkd1QDXa1NRA8aF2A1zk/Ypyw==", - "dev": true, "requires": { "function-bind": "^1.1.1", "has-bigints": "^1.0.1", @@ -36816,8 +37369,7 @@ "has-symbols": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.2.tgz", - "integrity": "sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw==", - "dev": true + "integrity": "sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw==" } } }, @@ -37298,6 +37850,11 @@ "spdx-expression-parse": "^3.0.0" } }, + "value-equal": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/value-equal/-/value-equal-0.2.1.tgz", + "integrity": "sha1-wiCjBDYfzmmU277ao8fhobiVhx0=" + }, "vary": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", @@ -37350,6 +37907,11 @@ "unist-util-stringify-position": "^2.0.0" } }, + "visibilityjs": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/visibilityjs/-/visibilityjs-1.2.8.tgz", + "integrity": "sha512-Y+aL3OUX88b+/VSmkmC2ApuLbf0grzbNLpCfIDSw3BzTU6PqcPsdgIOaw8b+eZoy+DdQqnVN3y/Evow9vQq9Ig==" + }, "vlq": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/vlq/-/vlq-1.0.1.tgz", @@ -37459,7 +38021,6 @@ "version": "4.0.3", "resolved": "https://registry.npmjs.org/warning/-/warning-4.0.3.tgz", "integrity": "sha512-rpJyN222KWIvHJ/F53XSZv0Zl/accqHR8et1kpaMTD/fLCRxtV8iX8czMzY7sVZupTI3zcUTg8eycS2kNF9l6w==", - "dev": true, "requires": { "loose-envify": "^1.0.0" } @@ -38640,7 +39201,6 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", - "dev": true, "requires": { "is-bigint": "^1.0.1", "is-boolean-object": "^1.1.0", @@ -38969,6 +39529,11 @@ "fd-slicer": "~1.1.0" } }, + "yeast": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/yeast/-/yeast-0.1.2.tgz", + "integrity": "sha1-AI4G2AlDIMNy28L47XagymyKxBk=" + }, "yocto-queue": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", diff --git a/package.json b/package.json index befbe74395e5..e6ea00966653 100644 --- a/package.json +++ b/package.json @@ -38,6 +38,7 @@ "@formatjs/intl-locale": "^2.4.21", "@formatjs/intl-numberformat": "^6.2.5", "@formatjs/intl-pluralrules": "^4.0.13", + "@onfido/react-native-sdk": "^1.3.3", "@react-native-community/async-storage": "^1.11.0", "@react-native-community/cli": "4.13.1", "@react-native-community/clipboard": "^1.5.1", @@ -66,6 +67,7 @@ "metro-config": "^0.64.0", "moment": "^2.27.0", "moment-timezone": "^0.5.31", + "onfido-sdk-ui": "^6.7.2", "prop-types": "^15.7.2", "pusher-js": "^7.0.0", "react": "^16.13.1", @@ -128,6 +130,7 @@ "clean-webpack-plugin": "^3.0.0", "concurrently": "^5.3.0", "copy-webpack-plugin": "^6.0.3", + "css-loader": "^5.2.4", "detox": "^17.8.3", "diff-so-fancy": "^1.3.0", "electron": "^11.4.8", @@ -151,6 +154,7 @@ "react-native-svg-transformer": "^0.14.3", "react-test-renderer": "16.13.1", "semver": "^7.3.4", + "style-loader": "^2.0.0", "wait-port": "^0.2.9", "webpack": "^4.44.1", "webpack-bundle-analyzer": "^4.4.0", diff --git a/src/CONST.js b/src/CONST.js index ae6100b1b24a..ccdbe11abab4 100755 --- a/src/CONST.js +++ b/src/CONST.js @@ -18,6 +18,10 @@ const CONST = { PRESSED: 'pressed', COMPLETE: 'complete', }, + PLATFORM: { + IOS: 'ios', + ANDROID: 'android', + }, CURRENCY: { USD: 'USD', }, @@ -152,6 +156,26 @@ const CONST = { RECONNECT: 1000, }, + WALLET: { + ERROR: { + IDENTITY_NOT_FOUND: 'Identity not found', + INVALID_SSN: 'Invalid SSN', + UNEXPECTED: 'Unexpected error', + MISSING_FIELD: 'Missing required additional details fields', + UNABLE_TO_VERIFY: 'Unable to verify identity', + }, + STEP: { + ONFIDO: 'OnfidoStep', + ADDITIONAL_DETAILS: 'AdditionalDetailsStep', + TERMS: 'TermsStep', + ACTIVATE: 'ActivateStep', + }, + STATUS: { + GOLD: 'GOLD', + SILVER: 'SILVER', + }, + }, + PLAID: { EVENT: { ERROR: 'ERROR', @@ -159,6 +183,21 @@ const CONST = { }, }, + ONFIDO: { + CONTAINER_ID: 'onfido-mount', + TYPE: { + DOCUMENT: 'document', + FACE: 'face', + }, + VARIANT: { + VIDEO: 'video', + }, + SMS_NUMBER_COUNTRY_CODE: 'US', + ERROR: { + USER_CANCELLED: 'User canceled flow', + }, + }, + OS: { WINDOWS: 'Windows', MAC_OS: 'Mac OS', diff --git a/src/ONYXKEYS.js b/src/ONYXKEYS.js index 13b64d521e4f..d7fcd65074f3 100755 --- a/src/ONYXKEYS.js +++ b/src/ONYXKEYS.js @@ -86,4 +86,16 @@ export default { // Indicates which locale should be used PREFERRED_LOCALE: 'preferredLocale', + + // User's Expensify Wallet + USER_WALLET: 'userWallet', + + // Object containing Onfido SDK Token + applicantID + WALLET_ONFIDO: 'walletOnfido', + + // Stores information about additional details form entry + WALLET_ADDITIONAL_DETAILS: 'walletAdditionalDetails', + + // Object containing Wallet terms step state + WALLET_TERMS: 'walletTerms', }; diff --git a/src/ROUTES.js b/src/ROUTES.js index 87dd0cdb4cc4..61c8542be45f 100644 --- a/src/ROUTES.js +++ b/src/ROUTES.js @@ -46,6 +46,7 @@ export default { getReportParticipantRoute: (reportID, login) => `r/${reportID}/participants/${login}`, VALIDATE_LOGIN: 'v', VALIDATE_LOGIN_WITH_VALIDATE_CODE: 'v/:accountID/:validateCode', + ENABLE_PAYMENTS: 'enable-payments', /** * @param {String} route diff --git a/src/components/Checkbox.js b/src/components/Checkbox.js index 468ad305d0da..5d42345e0b42 100644 --- a/src/components/Checkbox.js +++ b/src/components/Checkbox.js @@ -17,7 +17,7 @@ const propTypes = { }; const defaultProps = { - label: '', + label: undefined, }; const Checkbox = ({ diff --git a/src/components/FullscreenLoadingIndicator.js b/src/components/FullscreenLoadingIndicator.js index 088aa7a50855..6a203a9690bb 100644 --- a/src/components/FullscreenLoadingIndicator.js +++ b/src/components/FullscreenLoadingIndicator.js @@ -6,7 +6,11 @@ import themeColors from '../styles/themes/default'; const propTypes = { /** Controls whether the loader is mounted and displayed */ - visible: PropTypes.bool.isRequired, + visible: PropTypes.bool, +}; + +const defaultProps = { + visible: true, }; /** @@ -21,5 +25,6 @@ const FullScreenLoadingIndicator = ({visible}) => visible && ( ); FullScreenLoadingIndicator.propTypes = propTypes; +FullScreenLoadingIndicator.defaultProps = defaultProps; export default FullScreenLoadingIndicator; diff --git a/src/components/Onfido/index.css b/src/components/Onfido/index.css new file mode 100644 index 000000000000..fdee60611880 --- /dev/null +++ b/src/components/Onfido/index.css @@ -0,0 +1,13 @@ +/* These style overrides are necessary so that the Onfido modal looks nice */ +.onfido-sdk-ui-Modal-inner { + border-style: none !important; + width: 100% !important; +} +@media only screen and (max-width: 600px) { + .onfido-sdk-ui-Modal-inner { + /* This keeps the bottom of the Onfido window from being cut off on mobile web because the height was being + set to 100%, but we have a header on the top of the page that can be used to cancel out of the flow. This + spacing makes room for the header without cutting off the bottom of the Onfido window. */ + height: 92% !important; + } +} diff --git a/src/components/Onfido/index.js b/src/components/Onfido/index.js new file mode 100644 index 000000000000..1a5a64d83d1f --- /dev/null +++ b/src/components/Onfido/index.js @@ -0,0 +1,71 @@ +import './index.css'; +import React from 'react'; +import * as OnfidoSDK from 'onfido-sdk-ui'; +import withLocalize, {withLocalizePropTypes} from '../withLocalize'; +import onfidoPropTypes from './onfidoPropTypes'; +import CONST from '../../CONST'; +import Growl from '../../libs/Growl'; + +const propTypes = { + ...withLocalizePropTypes, + ...onfidoPropTypes, +}; + +class Onfido extends React.Component { + componentDidMount() { + this.onfidoOut = OnfidoSDK.init({ + token: this.props.sdkToken, + containerId: CONST.ONFIDO.CONTAINER_ID, + steps: [ + { + type: CONST.ONFIDO.TYPE.DOCUMENT, + options: { + useLiveDocumentCapture: true, + forceCrossDevice: true, + showCountrySelection: false, + documentTypes: { + national_identity_card: { + country: null, + }, + residence_permit: { + country: null, + }, + passport: true, + }, + }, + }, + { + type: CONST.ONFIDO.TYPE.FACE, + options: { + requestedVariant: CONST.ONFIDO.VARIANT.VIDEO, + uploadFallback: false, + }, + }, + ], + smsNumberCountryCode: CONST.ONFIDO.SMS_NUMBER_COUNTRY_CODE.US, + showCountrySelection: false, + onComplete: this.props.onSuccess, + onError: () => { + this.props.onUserExit(); + Growl.show(this.props.translate('onfidoStep.genericError'), CONST.GROWL.ERROR); + }, + onUserExit: this.props.onUserExit, + onModalRequestClose: () => {}, + }); + } + + componentWillUnmount() { + if (this.onfidoOut) { + this.onfidoOut.tearDown(); + } + } + + render() { + return ( +
+ ); + } +} + +Onfido.propTypes = propTypes; +export default withLocalize(Onfido); diff --git a/src/components/Onfido/index.native.js b/src/components/Onfido/index.native.js new file mode 100644 index 000000000000..9f46b56361f0 --- /dev/null +++ b/src/components/Onfido/index.native.js @@ -0,0 +1,48 @@ +import React from 'react'; +import { + Onfido as OnfidoSDK, + OnfidoCaptureType, + OnfidoDocumentType, + OnfidoCountryCode, +} from '@onfido/react-native-sdk'; +import onfidoPropTypes from './onfidoPropTypes'; +import CONST from '../../CONST'; +import withLocalize, {withLocalizePropTypes} from '../withLocalize'; +import Growl from '../../libs/Growl'; + +const propTypes = { + ...withLocalizePropTypes, + ...onfidoPropTypes, +}; + +class Onfido extends React.Component { + componentDidMount() { + OnfidoSDK.start({ + sdkToken: this.props.sdkToken, + flowSteps: { + welcome: true, + captureFace: { + type: OnfidoCaptureType.VIDEO, + }, + captureDocument: { + docType: OnfidoDocumentType.GENERIC, + countryCode: OnfidoCountryCode.USA, + }, + }, + }) + .then(this.props.onSuccess) + .catch((error) => { + if (error.message === CONST.ONFIDO.ERROR.USER_CANCELLED) { + this.props.onUserExit(); + Growl.show(this.props.translate('onfidoStep.genericError'), CONST.GROWL.ERROR); + } + }); + } + + render() { + return null; + } +} + +Onfido.propTypes = propTypes; +export default withLocalize(Onfido); diff --git a/src/components/Onfido/onfidoPropTypes.js b/src/components/Onfido/onfidoPropTypes.js new file mode 100644 index 000000000000..a45b124c1398 --- /dev/null +++ b/src/components/Onfido/onfidoPropTypes.js @@ -0,0 +1,12 @@ +import PropTypes from 'prop-types'; + +export default { + /** Token used to initialize the Onfido SDK */ + sdkToken: PropTypes.string.isRequired, + + /** Called when the user intentionally exits the flow without completing it */ + onUserExit: PropTypes.func.isRequired, + + /** Called when the user is totally done with Onfido */ + onSuccess: PropTypes.func.isRequired, +}; diff --git a/src/components/TextInputWithLabel.js b/src/components/TextInputWithLabel.js new file mode 100644 index 000000000000..e129dd6fb462 --- /dev/null +++ b/src/components/TextInputWithLabel.js @@ -0,0 +1,36 @@ +import _ from 'underscore'; +import React from 'react'; +import {Text, TextInput} from 'react-native'; +import PropTypes from 'prop-types'; +import styles from '../styles/styles'; + +const propTypes = { + /** Label text */ + label: PropTypes.string.isRequired, + + /** Text to show if there is an error */ + errorText: PropTypes.string, +}; + +const defaultProps = { + errorText: '', +}; + +const TextInputWithLabel = props => ( + <> + {props.label} + + {props.errorText !== '' && ( + {props.errorText} + )} + +); + +TextInputWithLabel.propTypes = propTypes; +TextInputWithLabel.defaultProps = defaultProps; +TextInputWithLabel.displayName = 'TextInputWithLabel'; +export default TextInputWithLabel; diff --git a/src/components/TextLink.js b/src/components/TextLink.js new file mode 100644 index 000000000000..9c538073c0e4 --- /dev/null +++ b/src/components/TextLink.js @@ -0,0 +1,44 @@ +import _ from 'underscore'; +import React from 'react'; +import PropTypes from 'prop-types'; +import {Text, Pressable} from 'react-native'; +import openURLInNewTab from '../libs/openURLInNewTab'; +import styles from '../styles/styles'; + +const propTypes = { + /** Link to open in new tab */ + href: PropTypes.string.isRequired, + + /** Text content child */ + children: PropTypes.string.isRequired, + + /** Additional style props */ + style: PropTypes.oneOfType([PropTypes.object, PropTypes.arrayOf(PropTypes.object)]), +}; + +const defaultProps = { + style: [], +}; + +const TextLink = (props) => { + const additionalStyles = _.isArray(props.style) ? props.style : [props.style]; + return ( + { + openURLInNewTab(props.href); + }} + > + {({hovered, pressed}) => ( + + {props.children} + + )} + + ); +}; + +TextLink.defaultProps = defaultProps; +TextLink.propTypes = propTypes; +TextLink.displayName = 'TextLink'; +export default TextLink; diff --git a/src/languages/en.js b/src/languages/en.js index 33fb0d8c39cd..da87f117e21b 100755 --- a/src/languages/en.js +++ b/src/languages/en.js @@ -26,6 +26,7 @@ export default { email: 'Email', and: 'and', details: 'Details', + privacyPolicy: 'Privacy Policy', delete: 'Delete', contacts: 'Contacts', recents: 'Recents', @@ -275,6 +276,45 @@ export default { noPhoneNumber: 'Please enter a phone number including the country code e.g +447814266907', maxParticipantsReached: 'You\'ve reached the maximum number of participants for a group chat.', }, + onfidoStep: { + acceptTerms: 'By continuing with the request to activate your Expensify wallet, you confirm that you have read, understand and accept ', + facialScan: 'Onfido’s Facial Scan Policy and Release', + termsOfService: 'Terms of Service', + tryAgain: 'Try Again', + verifyIdentity: 'Verify Identity', + genericError: 'There was an error while processing this step. Please try again.', + }, + additionalDetailsStep: { + headerTitle: 'Additional Details', + helpText: 'We need to confirm the following information before we can process this payment.', + helpLink: 'Learn more about why we need this.', + legalFirstNameLabel: 'Legal First Name', + legalMiddleNameLabel: 'Legal Middle Name', + legalLastNameLabel: 'Legal Last Name', + addressLabel: 'Address (no P.O. boxes)', + cityLabel: 'City', + stateLabel: 'State', + zipCodeLabel: 'Zip Code', + phoneNumberLabel: 'Phone Number', + dobLabel: 'Date of Birth', + ssnLabel: 'Social Security Number', + continueButtonText: 'Save & Continue', + isRequiredField: 'is a required field.', + }, + termsStep: { + headerTitle: 'Terms and Fees', + haveReadAndAgree: 'I have read and agree to receive ', + electronicDisclosures: 'electronic disclosures', + agreeToThe: 'I agree to the ', + walletAgreement: 'Wallet Agreement', + enablePayments: 'Enable Payments', + termsMustBeAccepted: 'Terms must be accepted', + }, + activateStep: { + headerTitle: 'Enable Payments', + activated: 'Your Expensify Wallet is ready to use.', + checkBackLater: 'We\'re still reviewing your information. Please check back later.', + }, session: { offlineMessage: 'Looks like you\'re not connected to internet. Can you check your connection and try again?', }, diff --git a/src/libs/API.js b/src/libs/API.js index 0fc178bd4473..5a3918173bbf 100644 --- a/src/libs/API.js +++ b/src/libs/API.js @@ -5,6 +5,7 @@ import CONFIG from '../CONFIG'; import ONYXKEYS from '../ONYXKEYS'; import redirectToSignIn from './actions/SignInRedirect'; import * as Network from './Network'; +import isViaExpensifyCashNative from './isViaExpensifyCashNative'; let isAuthenticating; let credentials; @@ -736,6 +737,18 @@ function CreateIOUSplit(parameters) { return Network.post(commandName, parameters); } +/** + * @returns {Promise} + */ +function Wallet_GetOnfidoSDKToken() { + return Network.post('Wallet_GetOnfidoSDKToken', { + // We need to pass this so we can request a token with the correct referrer + // This value comes from a cross-platform module which returns true for native + // platforms and false for non-native platforms. + isViaExpensifyCashNative, + }, CONST.NETWORK.METHOD.POST, true); +} + /** * @returns {Promise} */ @@ -743,6 +756,20 @@ function Plaid_GetLinkToken() { return Network.post('Plaid_GetLinkToken', {}, CONST.NETWORK.METHOD.POST, true); } +/** + * @param {Object} parameters + * @param {String} parameters.currentStep + * @param {String} [parameters.onfidoData] - JSON string + * @param {String} [parameters.personalDetails] - JSON string + * @param {Boolean} [parameters.hasAcceptedTerms] + * @returns {Promise} + */ +function Wallet_Activate(parameters) { + const commandName = 'Wallet_Activate'; + requireParameters(['currentStep'], parameters, commandName); + return Network.post(commandName, parameters, CONST.NETWORK.METHOD.POST, true); +} + /** * @param {Object} parameters * @param {String} parameters.publicToken @@ -860,6 +887,8 @@ export { CreateIOUTransaction, CreateIOUSplit, ValidateEmail, + Wallet_Activate, + Wallet_GetOnfidoSDKToken, GetPreferredCurrency, GetCurrencyList, }; diff --git a/src/libs/Navigation/AppNavigator/AuthScreens.js b/src/libs/Navigation/AppNavigator/AuthScreens.js index 5c59b384e353..1df7250464ef 100644 --- a/src/libs/Navigation/AppNavigator/AuthScreens.js +++ b/src/libs/Navigation/AppNavigator/AuthScreens.js @@ -48,6 +48,7 @@ import { NewGroupModalStackNavigator, NewChatModalStackNavigator, SettingsModalStackNavigator, + EnablePaymentsStackNavigator, AddBankAccountModalStackNavigator, } from './ModalStackNavigators'; import SCREENS from '../../../SCREENS'; @@ -253,6 +254,12 @@ class AuthScreens extends React.Component { component={IOUBillStackNavigator} listeners={modalScreenListeners} /> + { + const apiResult = lodashGet(response, ['requestorIdentityOnfido', 'apiResult'], {}); + Onyx.merge(ONYXKEYS.WALLET_ONFIDO, { + applicantID: apiResult.applicantID, + sdkToken: apiResult.sdkToken, + loading: false, + hasAcceptedPrivacyPolicy: true, + }); + }) + .catch(() => Onyx.set(ONYXKEYS.WALLET_ONFIDO, {loading: false, error: CONST.WALLET.ERROR.UNEXPECTED})); +} + +/** + * Privately used to update the additionalDetails object in Onyx (which will have various effects on the UI) + * + * @param {Boolean} loading whether we are making the API call to validate the user's provided personal details + * @param {String[]} [errorFields] an array of field names that should display errors in the UI + * @param {String} [additionalErrorMessage] an additional error message to display in the UI + * @private + */ +function setAdditionalDetailsStep(loading, errorFields = null, additionalErrorMessage = '') { + Onyx.merge(ONYXKEYS.WALLET_ADDITIONAL_DETAILS, {loading, errorFields, additionalErrorMessage}); +} + +/** + * This action can be called repeatedly with different steps until an Expensify Wallet has been activated. + * + * Possible steps: + * + * - OnfidoStep - Creates an identity check by calling Onfido's API (via Web-Secure) with data returned from the SDK + * - AdditionalDetailsStep - Validates a user's provided details against a series of checks + * - TermsStep - Ensures that a user has agreed to all of the terms and conditions + * + * The API will always return the updated userWallet in the response as a convenience so we can avoid calling + * Get&returnValueList=userWallet after we call Wallet_Activate. + * + * @param {String} currentStep + * @param {Object} parameters + * @param {String} [parameters.onfidoData] - JSON string + * @param {Object} [parameters.personalDetails] - JSON string + * @param {Boolean} [parameters.hasAcceptedTerms] + */ +function activateWallet(currentStep, parameters) { + let personalDetails; + let onfidoData; + let hasAcceptedTerms; + + if (!_.contains(CONST.WALLET.STEP, currentStep)) { + throw new Error('Invalid currentStep passed to activateWallet()'); + } + + if (currentStep === CONST.WALLET.STEP.ONFIDO) { + onfidoData = parameters.onfidoData; + Onyx.merge(ONYXKEYS.WALLET_ONFIDO, {error: '', loading: true}); + } else if (currentStep === CONST.WALLET.STEP.ADDITIONAL_DETAILS) { + setAdditionalDetailsStep(true); + + // Personal details are heavily validated on the API side. We will only do a quick check to ensure the values + // exist in some capacity and then stringify them. + const errorFields = _.reduce(CONST.WALLET.REQUIRED_ADDITIONAL_DETAILS_FIELDS, (missingFields, fieldName) => ( + !personalDetails[fieldName] ? [...missingFields, fieldName] : missingFields + ), []); + + if (!_.isEmpty(errorFields)) { + setAdditionalDetailsStep(false, errorFields); + return; + } + + personalDetails = JSON.stringify(parameters.personalDetails); + } else if (currentStep === CONST.WALLET.STEP.TERMS) { + hasAcceptedTerms = parameters.hasAcceptedTerms; + Onyx.merge(ONYXKEYS.WALLET_TERMS, {loading: true}); + } + + API.Wallet_Activate({ + currentStep, + personalDetails, + onfidoData, + hasAcceptedTerms, + }) + .then((response) => { + if (response.jsonCode !== 200) { + if (currentStep === CONST.WALLET.STEP.ONFIDO) { + Onyx.merge(ONYXKEYS.WALLET_ONFIDO, {error: response.message, loading: false}); + return; + } + + if (currentStep === CONST.WALLET.STEP.ADDITIONAL_DETAILS) { + if (response.title === CONST.WALLET.ERROR.MISSING_FIELD) { + setAdditionalDetailsStep(false, response.data.fieldNames); + return; + } + + const errorTitles = [ + CONST.WALLET.ERROR.IDENTITY_NOT_FOUND, + CONST.WALLET.ERROR.INVALID_SSN, + CONST.WALLET.ERROR.UNEXPECTED, + CONST.WALLET.ERROR.UNABLE_TO_VERIFY, + ]; + + if (errorTitles.includes(response.title)) { + setAdditionalDetailsStep(false, null, response.message); + return; + } + + setAdditionalDetailsStep(false); + return; + } + + return; + } + + Onyx.merge(ONYXKEYS.USER_WALLET, response.userWallet); + + if (currentStep === CONST.WALLET.STEP.ONFIDO) { + Onyx.merge(ONYXKEYS.WALLET_ONFIDO, {error: '', loading: true}); + } else if (currentStep === CONST.WALLET.STEP.ADDITIONAL_DETAILS) { + setAdditionalDetailsStep(false); + } else if (currentStep === CONST.WALLET.STEP.TERMS) { + Onyx.merge(ONYXKEYS.WALLET_TERMS, {loading: false}); + } + }); +} + +/** + * Fetches information about a user's Expensify Wallet + * + * @typedef {Object} UserWallet + * @property {Number} availableBalance + * @property {Number} currentBalance + * @property {String} currentStep - used to track which step of the "activate wallet" flow a user is in + * @property {('SILVER'|'GOLD')} status - will be GOLD when fully activated. SILVER is able to recieve funds only. + */ +function fetchUserWallet() { + API.Get({returnValueList: 'userWallet'}) + .then((response) => { + if (response.jsonCode !== 200) { + return; + } + + Onyx.merge(ONYXKEYS.USER_WALLET, response.userWallet); + }); +} + export { fetchPlaidLinkToken, addPlaidBankAccount, getPlaidBankAccounts, clearPlaidBankAccounts, + fetchOnfidoToken, + activateWallet, + fetchUserWallet, }; diff --git a/src/libs/getPlatform/index.android.js b/src/libs/getPlatform/index.android.js index f7dc545d49f6..1a343700a2f9 100644 --- a/src/libs/getPlatform/index.android.js +++ b/src/libs/getPlatform/index.android.js @@ -1,3 +1,5 @@ +import CONST from '../../CONST'; + export default function getPlatform() { - return 'android'; + return CONST.PLATFORM.ANDROID; } diff --git a/src/libs/getPlatform/index.ios.js b/src/libs/getPlatform/index.ios.js index a74a94edcc45..d91604a5c41a 100644 --- a/src/libs/getPlatform/index.ios.js +++ b/src/libs/getPlatform/index.ios.js @@ -1,3 +1,5 @@ +import CONST from '../../CONST'; + export default function getPlatform() { - return 'ios'; + return CONST.PLATFORM.IOS; } diff --git a/src/libs/isViaExpensifyCashNative/index.js b/src/libs/isViaExpensifyCashNative/index.js new file mode 100644 index 000000000000..21e5dd254a47 --- /dev/null +++ b/src/libs/isViaExpensifyCashNative/index.js @@ -0,0 +1,8 @@ +/** + * The API library has a request for Wallet_GetOnfidoSDKToken which needs to know if the request is coming from + * the native platform or the non-native platform. This module will return true for the native platforms and false + * for the non-native platforms + * @type {boolean} + */ +const isViaExpensifyCashNative = false; +export default isViaExpensifyCashNative; diff --git a/src/libs/isViaExpensifyCashNative/index.native.js b/src/libs/isViaExpensifyCashNative/index.native.js new file mode 100644 index 000000000000..44d4c5e456d2 --- /dev/null +++ b/src/libs/isViaExpensifyCashNative/index.native.js @@ -0,0 +1,8 @@ +/** + * The API library has a request for Wallet_GetOnfidoSDKToken which needs to know if the request is coming from + * the native platform or the non-native platform. This module will return true for the native platforms and false + * for the non-native platforms + * @type {boolean} + */ +const isViaExpensifyCashNative = true; +export default isViaExpensifyCashNative; diff --git a/src/pages/EnablePayments/ActivateStep.js b/src/pages/EnablePayments/ActivateStep.js new file mode 100644 index 000000000000..e6ab3b805547 --- /dev/null +++ b/src/pages/EnablePayments/ActivateStep.js @@ -0,0 +1,40 @@ +import React from 'react'; +import {View, Text} from 'react-native'; +import ScreenWrapper from '../../components/ScreenWrapper'; +import HeaderWithCloseButton from '../../components/HeaderWithCloseButton'; +import Navigation from '../../libs/Navigation/Navigation'; +import withLocalize, {withLocalizePropTypes} from '../../components/withLocalize'; +import styles from '../../styles/styles'; +import userWalletPropTypes from './userWalletPropTypes'; +import CONST from '../../CONST'; + +const propTypes = { + ...withLocalizePropTypes, + ...userWalletPropTypes, +}; + +const defaultProps = { + userWallet: {}, +}; + +const ActivateStep = props => ( + + Navigation.dismissModal()} + /> + + {props.userWallet.status === CONST.WALLET.STATUS.GOLD && ( + {props.translate('activateStep.activated')} + )} + {props.userWallet.status === CONST.WALLET.STATUS.SILVER && ( + {props.translate('activateStep.checkBackLater')} + )} + + +); + +ActivateStep.propTypes = propTypes; +ActivateStep.defaultProps = defaultProps; +ActivateStep.displayName = 'ActivateStep'; +export default withLocalize(ActivateStep); diff --git a/src/pages/EnablePayments/AdditionalDetailsStep.js b/src/pages/EnablePayments/AdditionalDetailsStep.js new file mode 100644 index 000000000000..b919799b1d1f --- /dev/null +++ b/src/pages/EnablePayments/AdditionalDetailsStep.js @@ -0,0 +1,173 @@ +import _ from 'underscore'; +import React from 'react'; +import PropTypes from 'prop-types'; +import {withOnyx} from 'react-native-onyx'; +import { + View, Text, ScrollView, KeyboardAvoidingView, +} from 'react-native'; +import ScreenWrapper from '../../components/ScreenWrapper'; +import HeaderWithCloseButton from '../../components/HeaderWithCloseButton'; +import withLocalize, {withLocalizePropTypes} from '../../components/withLocalize'; +import Navigation from '../../libs/Navigation/Navigation'; +import styles from '../../styles/styles'; +import Button from '../../components/Button'; +import TextInputWithLabel from '../../components/TextInputWithLabel'; +import {activateWallet} from '../../libs/actions/BankAccounts'; +import CONST from '../../CONST'; +import compose from '../../libs/compose'; +import ONYXKEYS from '../../ONYXKEYS'; +import TextLink from '../../components/TextLink'; + +const propTypes = { + ...withLocalizePropTypes, + + /** Stores additional information about the additional details step e.g. loading state and errors with fields */ + walletAdditionalDetails: PropTypes.shape({ + /** Are we waiting for a response? */ + loading: PropTypes.bool, + + /** Which field needs attention? */ + errorFields: PropTypes.arrayOf(PropTypes.string), + + /** Any additional error message to show */ + additionalErrorMessage: PropTypes.string, + }), +}; + +const defaultProps = { + walletAdditionalDetails: { + errorFields: [], + loading: false, + additionalErrorMessage: '', + }, +}; + +class AdditionalDetailsStep extends React.Component { + constructor(props) { + super(props); + + this.requiredText = props.translate('additionalDetailsStep.isRequiredField'); + this.fields = [ + { + label: props.translate('additionalDetailsStep.legalFirstNameLabel'), + fieldName: 'legalFirstName', + }, + { + label: props.translate('additionalDetailsStep.legalMiddleNameLabel'), + fieldName: 'legalMiddleName', + }, + { + label: props.translate('additionalDetailsStep.legalLastNameLabel'), + fieldName: 'legalLastName', + }, + { + label: props.translate('additionalDetailsStep.addressLabel'), + fieldName: 'addressStreet', + }, + { + label: props.translate('additionalDetailsStep.cityLabel'), + fieldName: 'addressCity', + }, + { + label: props.translate('additionalDetailsStep.stateLabel'), + fieldName: 'addressState', + }, + { + label: props.translate('additionalDetailsStep.zipCodeLabel'), + fieldName: 'addressZip', + }, + { + label: props.translate('additionalDetailsStep.phoneNumberLabel'), + fieldName: 'phoneNumber', + }, + { + label: props.translate('additionalDetailsStep.dobLabel'), + fieldName: 'dob', + }, + { + label: props.translate('additionalDetailsStep.ssnLabel'), + fieldName: 'ssn', + }, + ]; + + this.state = { + firstName: '', + legalMiddleName: '', + legalLastName: '', + address: '', + city: '', + state: '', + zipCode: '', + phoneNumber: '', + dob: '', + ssn: '', + }; + } + + render() { + const errorFields = this.props.walletAdditionalDetails.errorFields || []; + return ( + + + Navigation.dismissModal()} + /> + + + {this.props.translate('additionalDetailsStep.helpText')} + + {this.props.translate('additionalDetailsStep.helpLink')} + + + + {_.map(this.fields, field => ( + this.setState({[field.fieldName]: val})} + value={this.state[field.fieldName]} + errorText={errorFields.includes(field.fieldName) + ? `${field.label} ${this.requiredText}` + : ''} + /> + ))} + + + {this.props.walletAdditionalDetails.additionalErrorMessage.length > 0 && ( + + {this.props.walletAdditionalDetails.additionalErrorMessage} + + )} +