mirror of
https://github.com/status-im/status-react.git
synced 2025-02-25 09:05:55 +00:00
parent
daacccb512
commit
090a4e7c76
@ -276,6 +276,7 @@ dependencies {
|
||||
implementation project(':react-native-securerandom')
|
||||
implementation project(':react-native-webview-bridge')
|
||||
implementation project(':react-native-webview')
|
||||
implementation project(':react-native-touch-id')
|
||||
implementation project(':react-native-config')
|
||||
implementation project(':react-native-firebase')
|
||||
implementation project(':react-native-shake')
|
||||
|
@ -18,6 +18,7 @@
|
||||
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
|
||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
|
||||
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
|
||||
<uses-permission android:name="android.permission.USE_FINGERPRINT" />
|
||||
|
||||
<!-- these permissions should be removed -->
|
||||
<!-- React Native unnecessary permissions (https://github.com/facebook/react-native/issues/5886) -->
|
||||
|
@ -17,6 +17,7 @@ import com.ocetnik.timer.BackgroundTimerPackage;
|
||||
import com.reactcommunity.rnlanguages.RNLanguagesPackage;
|
||||
import com.reactnative.ivpusic.imagepicker.PickerPackage;
|
||||
import com.rnfs.RNFSPackage;
|
||||
import com.rnfingerprint.FingerprintAuthPackage;
|
||||
|
||||
import net.rhogan.rnsecurerandom.RNSecureRandomPackage;
|
||||
|
||||
@ -74,7 +75,8 @@ public class MainApplication extends MultiDexApplication implements ReactApplica
|
||||
new RNCWebViewPackage(),
|
||||
new ReactNativeConfigPackage(),
|
||||
new KeychainPackage(),
|
||||
new RNShakeEventPackage());
|
||||
new RNShakeEventPackage(),
|
||||
new FingerprintAuthPackage());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -38,6 +38,8 @@ include ':react-native-webview-bridge'
|
||||
project(':react-native-webview-bridge').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-webview-bridge/android')
|
||||
include ':react-native-webview'
|
||||
project(':react-native-webview').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-webview/android')
|
||||
include ':react-native-touch-id'
|
||||
project(':react-native-touch-id').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-touch-id/android')
|
||||
include ':react-native-config'
|
||||
project(':react-native-config').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-config/android')
|
||||
include ':react-native-android'
|
||||
|
@ -23,6 +23,7 @@
|
||||
"react-native-webview-bridge"
|
||||
"react-native-webview"
|
||||
"react-native-firebase"
|
||||
"react-native-touch-id"
|
||||
"homoglyph-finder"
|
||||
"web3"
|
||||
"web3-utils"
|
||||
|
@ -18,6 +18,7 @@ target 'StatusIm' do
|
||||
pod 'RNKeychain', :path => '../node_modules/react-native-keychain'
|
||||
pod 'react-native-camera', path: '../node_modules/react-native-camera'
|
||||
pod 'react-native-webview', path: '../node_modules/react-native-webview'
|
||||
pod 'TouchID', path: '../node_modules/react-native-touch-id'
|
||||
pod 'SQLCipher', '~>3.0'
|
||||
pod 'SSZipArchive'
|
||||
|
||||
|
@ -78,6 +78,8 @@ PODS:
|
||||
- SQLCipher/standard (3.4.2):
|
||||
- SQLCipher/common
|
||||
- SSZipArchive (2.1.4)
|
||||
- TouchID (4.4.1):
|
||||
- React
|
||||
- yoga (0.59.3.React)
|
||||
|
||||
DEPENDENCIES:
|
||||
@ -90,6 +92,7 @@ DEPENDENCIES:
|
||||
- RNKeychain (from `../node_modules/react-native-keychain`)
|
||||
- SQLCipher (~> 3.0)
|
||||
- SSZipArchive
|
||||
- TouchID (from `../node_modules/react-native-touch-id`)
|
||||
- yoga (from `../node_modules/react-native/ReactCommon/yoga`)
|
||||
|
||||
SPEC REPOS:
|
||||
@ -117,6 +120,8 @@ EXTERNAL SOURCES:
|
||||
:path: "../node_modules/react-native-webview"
|
||||
RNKeychain:
|
||||
:path: "../node_modules/react-native-keychain"
|
||||
TouchID:
|
||||
:path: "../node_modules/react-native-touch-id"
|
||||
yoga:
|
||||
:path: "../node_modules/react-native/ReactCommon/yoga"
|
||||
|
||||
@ -137,8 +142,9 @@ SPEC CHECKSUMS:
|
||||
RNKeychain: 627c6095cef215dd3d9804a9a9cf45ab96aa3997
|
||||
SQLCipher: f9fcf29b2e59ced7defc2a2bdd0ebe79b40d4990
|
||||
SSZipArchive: 41455d4b8d2b6ab93990820b50dc697c2554a322
|
||||
TouchID: b0640fedb86fa2db2fe1df15b61594ad49e76288
|
||||
yoga: 128daf064cacaede0c3bb27424b6b4c71052e6cd
|
||||
|
||||
PODFILE CHECKSUM: 1b73a7ab29d939e99e86434864c837afaf55851c
|
||||
PODFILE CHECKSUM: 13006106aa0716d54fffebf8dcb42006f0fb8798
|
||||
|
||||
COCOAPODS: 1.5.3
|
||||
|
@ -4,6 +4,8 @@
|
||||
<dict>
|
||||
<key>CFBundleBuildUrl</key>
|
||||
<string>????</string>
|
||||
<key>NSFaceIDUsageDescription</key>
|
||||
<string>Enabling Face ID allows you quick and secure access to your account.</string>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>en</string>
|
||||
<key>CFBundleDisplayName</key>
|
||||
|
@ -60,6 +60,7 @@
|
||||
"react-native-svg": "^9.2.4",
|
||||
"react-native-svg-transformer": "^0.12.1",
|
||||
"react-native-tcp": "git+https://github.com/status-im/react-native-tcp.git#v3.3.0-1-status",
|
||||
"react-native-touch-id": "^4.4.1",
|
||||
"react-native-udp": "git+https://github.com/status-im/react-native-udp.git#2.3.1-1",
|
||||
"react-native-webview": "^5.2.1",
|
||||
"react-native-webview-bridge": "git+https://github.com/status-im/react-native-webview-bridge.git#fix/classnames-colision",
|
||||
|
@ -5635,6 +5635,11 @@ react-native-tab-view@^1.0.0:
|
||||
process "^0.11.9"
|
||||
util "^0.10.3"
|
||||
|
||||
react-native-touch-id@^4.4.1:
|
||||
version "4.4.1"
|
||||
resolved "https://registry.yarnpkg.com/react-native-touch-id/-/react-native-touch-id-4.4.1.tgz#8b1bb2d04c30bac36bb9696d2d723e719c4a8b08"
|
||||
integrity sha512-1jTl8fC+0fxvqegy/XXTyo6vMvPhjzkoDdaqoYZx0OH8AT250NuXnNPyKktvigIcys3+2acciqOeaCall7lrvg==
|
||||
|
||||
"react-native-udp@git+https://github.com/status-im/react-native-udp.git#2.3.1-1":
|
||||
version "2.3.1"
|
||||
resolved "git+https://github.com/status-im/react-native-udp.git#6e9a817326208f6ca36fa42b20f5e530c1b39d37"
|
||||
|
@ -1122,6 +1122,10 @@ class StatusModule extends ReactContextBaseJavaModule implements LifecycleEventL
|
||||
HashMap<String, Object> constants = new HashMap<String, Object>();
|
||||
|
||||
constants.put("is24Hour", this.is24Hour());
|
||||
constants.put("model", Build.MODEL);
|
||||
constants.put("brand", Build.BRAND);
|
||||
constants.put("buildId", Build.ID);
|
||||
constants.put("deviceId", Build.BOARD);
|
||||
return constants;
|
||||
}
|
||||
|
||||
|
@ -1,3 +1,4 @@
|
||||
#import <sys/utsname.h>
|
||||
#import <Foundation/Foundation.h>
|
||||
#import <React/RCTBridgeModule.h>
|
||||
#import "Statusgo/Statusgo.h"
|
||||
|
@ -548,16 +548,63 @@ RCT_EXPORT_METHOD(setBlankPreviewFlag:(BOOL *)newValue)
|
||||
[userDefaults synchronize];
|
||||
}
|
||||
|
||||
//// deviceinfo
|
||||
|
||||
- (bool) is24Hour
|
||||
{
|
||||
NSString *format = [NSDateFormatter dateFormatFromTemplate:@"j" options:0 locale:[NSLocale currentLocale]];
|
||||
return ([format rangeOfString:@"a"].location == NSNotFound);
|
||||
}
|
||||
|
||||
- (NSString *)getBuildId {
|
||||
return @"not available";
|
||||
}
|
||||
|
||||
- (NSString*) deviceId
|
||||
{
|
||||
struct utsname systemInfo;
|
||||
|
||||
uname(&systemInfo);
|
||||
|
||||
NSString* deviceId = [NSString stringWithCString:systemInfo.machine
|
||||
encoding:NSUTF8StringEncoding];
|
||||
|
||||
if ([deviceId isEqualToString:@"i386"] || [deviceId isEqualToString:@"x86_64"] ) {
|
||||
deviceId = [NSString stringWithFormat:@"%s", getenv("SIMULATOR_MODEL_IDENTIFIER")];
|
||||
}
|
||||
|
||||
return deviceId;
|
||||
}
|
||||
|
||||
- (NSString*) deviceName
|
||||
{
|
||||
|
||||
NSString* deviceName = nil;
|
||||
|
||||
if ([self.deviceId rangeOfString:@"iPod"].location != NSNotFound) {
|
||||
deviceName = @"iPod Touch";
|
||||
}
|
||||
else if([self.deviceId rangeOfString:@"iPad"].location != NSNotFound) {
|
||||
deviceName = @"iPad";
|
||||
}
|
||||
else if([self.deviceId rangeOfString:@"iPhone"].location != NSNotFound){
|
||||
deviceName = @"iPhone";
|
||||
}
|
||||
else if([self.deviceId rangeOfString:@"AppleTV"].location != NSNotFound){
|
||||
deviceName = @"Apple TV";
|
||||
}
|
||||
|
||||
return deviceName;
|
||||
}
|
||||
|
||||
- (NSDictionary *)constantsToExport
|
||||
{
|
||||
return @{
|
||||
@"is24Hour": @(self.is24Hour),
|
||||
@"model": self.deviceName ?: [NSNull null],
|
||||
@"brand": @"Apple",
|
||||
@"buildId": [self getBuildId],
|
||||
@"deviceId": self.deviceId ?: [NSNull null],
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -21,6 +21,7 @@
|
||||
(def desktop-config (js/require "react-native-desktop-config"))
|
||||
(def desktop-shortcuts (js/require "react-native-desktop-shortcuts"))
|
||||
(def react-native-firebase (fn [] #js {}))
|
||||
(def touchid (fn [] #js {}))
|
||||
(def camera (fn [] #js {:default #js {:constants {:Aspect "Portrait"}}}))
|
||||
(def status-keycard (fn [] #js {:default #js {}}))
|
||||
(def dialogs (fn [] #js {}))
|
||||
|
@ -10,6 +10,7 @@
|
||||
(def status-keycard (js-require/js-require "react-native-status-keycard"))
|
||||
(def realm (js/require "realm"))
|
||||
(def webview-bridge (js-require/js-require "react-native-webview-bridge"))
|
||||
(defn touchid [] (.-default (js/require "react-native-touch-id")))
|
||||
(def webview (js-require/js-require "react-native-webview"))
|
||||
(def securerandom (js-require/js-require "react-native-securerandom"))
|
||||
(defn secure-random [] (.-generateSecureRandom (securerandom)))
|
||||
|
@ -80,6 +80,15 @@
|
||||
(assoc settings :chaos-mode? chaos-mode?)
|
||||
{})))))
|
||||
|
||||
(fx/defn switch-biometric-auth
|
||||
{:events [:accounts.ui/switch-biometric-auth]}
|
||||
[{:keys [db] :as cofx} biometric-auth?]
|
||||
(when (:account/account db)
|
||||
(let [settings (get-in db [:account/account :settings])]
|
||||
(accounts.update/update-settings cofx
|
||||
(assoc settings :biometric-auth? biometric-auth?)
|
||||
{}))))
|
||||
|
||||
(fx/defn enable-notifications [cofx desktop-notifications?]
|
||||
(accounts.update/account-update cofx
|
||||
{:desktop-notifications? desktop-notifications?}
|
||||
|
@ -19,6 +19,7 @@
|
||||
[status-im.utils.keychain.core :as keychain]
|
||||
[status-im.utils.platform :as platform]
|
||||
[status-im.utils.security :as security]
|
||||
[status-im.biometric-auth.core :as biometric-auth]
|
||||
[status-im.utils.types :as types]
|
||||
[status-im.utils.universal-links.core :as universal-links]
|
||||
[status-im.wallet.core :as wallet]
|
||||
@ -297,7 +298,7 @@
|
||||
[_ address]
|
||||
{:keychain/can-save-user-password? nil
|
||||
:keychain/get-user-password [address
|
||||
#(re-frame/dispatch [:accounts.login.callback/get-user-password-success %])]})
|
||||
#(re-frame/dispatch [:accounts.login.callback/get-user-password-success % address])]})
|
||||
|
||||
(fx/defn open-login [{:keys [db] :as cofx} address photo-path name]
|
||||
(let [keycard-account? (get-in db [:accounts/accounts address :keycard-instance-uid])]
|
||||
@ -315,13 +316,26 @@
|
||||
(get-user-password address)))))
|
||||
|
||||
(fx/defn open-login-callback
|
||||
[{:keys [db] :as cofx} password]
|
||||
(if password
|
||||
{:events [:accounts.login.callback/biometric-auth-done]}
|
||||
[{:keys [db] :as cofx} password biometric-auth-result]
|
||||
(let [{:keys [bioauth-success bioauth-notrequired bioauth-message]} biometric-auth-result]
|
||||
(if (and password
|
||||
(or bioauth-success bioauth-notrequired))
|
||||
(fx/merge cofx
|
||||
{:db (assoc-in db [:accounts/login :password] password)}
|
||||
(navigation/navigate-to-cofx :progress nil)
|
||||
(user-login false))
|
||||
(navigation/navigate-to-cofx cofx :login nil)))
|
||||
(fx/merge cofx
|
||||
(when bioauth-message
|
||||
{:utils/show-popup {:title (i18n/label :t/biometric-auth-login-error-title) :content bioauth-message}})
|
||||
(navigation/navigate-to-cofx :login nil)))))
|
||||
|
||||
(fx/defn do-biometric-auth
|
||||
[{:keys [db] :as cofx} password]
|
||||
(biometric-auth/authenticate-fx cofx
|
||||
#(re-frame/dispatch [:accounts.login.callback/biometric-auth-done password %])
|
||||
{:reason (i18n/label :t/biometric-auth-reason-login)
|
||||
:ios-fallback-label (i18n/label :t/biometric-auth-login-ios-fallback-label)}))
|
||||
|
||||
(re-frame/reg-fx
|
||||
:accounts.login/login
|
||||
|
93
src/status_im/biometric_auth/core.cljs
Normal file
93
src/status_im/biometric_auth/core.cljs
Normal file
@ -0,0 +1,93 @@
|
||||
(ns status-im.biometric-auth.core
|
||||
(:require [re-frame.core :as re-frame]
|
||||
[status-im.utils.platform :as platform]
|
||||
[status-im.i18n :as i18n]
|
||||
[status-im.utils.fx :as fx]
|
||||
[status-im.ui.components.colors :as colors]
|
||||
[status-im.native-module.core :as status]
|
||||
[status-im.react-native.js-dependencies :as rn]))
|
||||
|
||||
;; currently, for android, react-native-touch-id
|
||||
;; is not returning supported biometric type
|
||||
;; defaulting to :fingerprint
|
||||
(def android-default-support :fingerprint)
|
||||
|
||||
;;; android blacklist based on device info:
|
||||
|
||||
(def deviceinfo (status/get-device-model-info))
|
||||
|
||||
;; {:model ?
|
||||
;; :brand "Xiaomi"
|
||||
;; :build-id "13D15"
|
||||
;; :device-id "goldfish"
|
||||
;; more info on https://github.com/react-native-community/react-native-device-info
|
||||
|
||||
(def android-device-blacklisted?
|
||||
(cond
|
||||
(= (:brand deviceinfo) "bannedbrand") true
|
||||
:else false))
|
||||
|
||||
;; biometric auth config
|
||||
;; https://github.com/naoufal/react-native-touch-id#authenticatereason-config
|
||||
(defn- authenticate-options [ios-fallback-label]
|
||||
(clj->js (merge
|
||||
{:unifiedErrors true}
|
||||
(when platform/ios?
|
||||
{:passcodeFallback false
|
||||
:fallbackLabel (or ios-fallback-label "")})
|
||||
(when platform/android?
|
||||
{:title (i18n/label :t/biometric-auth-android-title)
|
||||
:imageColor colors/blue
|
||||
:imageErrorColor colors/red
|
||||
:sensorDescription (i18n/label :t/biometric-auth-android-sensor-desc)
|
||||
:sensorErrorDescription (i18n/label :t/biometric-auth-android-sensor-error-desc)
|
||||
:cancelText (i18n/label :cancel)}))))
|
||||
|
||||
(defn- get-error-message
|
||||
"must return an error message for the user"
|
||||
[touchid-error-code]
|
||||
(cond
|
||||
;; no message if user canceled or falled back to password
|
||||
(= touchid-error-code "USER_CANCELED") nil
|
||||
(= touchid-error-code "USER_FALLBACK") nil
|
||||
;; add here more specific errors if needed
|
||||
;; https://github.com/naoufal/react-native-touch-id#unified-errors
|
||||
:else (i18n/label :t/biometric-auth-error {:code touchid-error-code})))
|
||||
|
||||
(def success-result
|
||||
{:bioauth-success true})
|
||||
|
||||
(defn- generate-error-result [touchid-error-obj]
|
||||
(let [code (aget touchid-error-obj "code")]
|
||||
{:bioauth-success false
|
||||
:bioauth-code code
|
||||
:bioauth-message (get-error-message code)}))
|
||||
|
||||
(defn- do-get-supported [callback]
|
||||
(-> (.isSupported (rn/touchid))
|
||||
(.then #(callback (or (keyword %) android-default-support)))
|
||||
(.catch #(callback nil))))
|
||||
|
||||
(defn get-supported [callback]
|
||||
(cond platform/ios? (do-get-supported callback)
|
||||
platform/android? (if android-device-blacklisted?
|
||||
(callback false)
|
||||
(do-get-supported callback))
|
||||
:else (callback false)))
|
||||
|
||||
(defn authenticate
|
||||
([cb]
|
||||
(authenticate cb nil))
|
||||
([cb {:keys [reason ios-fallback-label]}]
|
||||
(-> (.authenticate (rn/touchid) reason (authenticate-options ios-fallback-label))
|
||||
(.then #(cb success-result))
|
||||
(.catch #(cb (generate-error-result %))))))
|
||||
|
||||
(fx/defn authenticate-fx
|
||||
[_ cb options]
|
||||
{:biometric-auth/authenticate [cb options]})
|
||||
|
||||
(re-frame/reg-fx
|
||||
:biometric-auth/authenticate
|
||||
(fn [[cb options]]
|
||||
(authenticate #(cb %) options)))
|
@ -5,6 +5,8 @@
|
||||
|
||||
(def ethereum-rpc-url "http://localhost:8545")
|
||||
|
||||
(def ms-in-bg-for-require-bioauth 5000)
|
||||
|
||||
(def content-type-text "text/plain")
|
||||
(def content-type-sticker "sticker")
|
||||
(def content-type-status "status")
|
||||
|
@ -60,6 +60,7 @@
|
||||
[status-im.wallet.core :as wallet]
|
||||
[status-im.wallet.db :as wallet.db]
|
||||
[status-im.web3.core :as web3]
|
||||
[status-im.biometric-auth.core :as biomentric-auth]
|
||||
[taoensso.timbre :as log]
|
||||
[status-im.wallet.custom-tokens.core :as custom-tokens]))
|
||||
|
||||
@ -202,6 +203,20 @@
|
||||
:on-accept open-chaos-unicorn-day-link}})
|
||||
(accounts/switch-chaos-mode chaos-mode?)))))
|
||||
|
||||
(handlers/register-handler-fx
|
||||
:accounts.ui/biometric-auth-switched
|
||||
(fn [cofx [_ biometric-auth?]]
|
||||
(if biometric-auth?
|
||||
(biomentric-auth/authenticate-fx
|
||||
cofx
|
||||
(fn [{:keys [bioauth-success bioauth-message]}]
|
||||
(when bioauth-success
|
||||
(re-frame/dispatch [:accounts.ui/switch-biometric-auth true]))
|
||||
(when bioauth-message
|
||||
(utils/show-popup (i18n/label :t/biometric-auth-reason-verify) bioauth-message)))
|
||||
{:reason (i18n/label :t/biometric-auth-reason-verify)})
|
||||
(accounts/switch-biometric-auth cofx false))))
|
||||
|
||||
(handlers/register-handler-fx
|
||||
:accounts.ui/notifications-enabled
|
||||
(fn [cofx [_ desktop-notifications?]]
|
||||
@ -325,8 +340,11 @@
|
||||
|
||||
(handlers/register-handler-fx
|
||||
:accounts.login.callback/get-user-password-success
|
||||
(fn [cofx [_ password]]
|
||||
(accounts.login/open-login-callback cofx password)))
|
||||
(fn [{:keys [db] :as cofx} [_ password address]]
|
||||
(let [biometric-auth? (get-in db [:accounts/accounts address :settings :biometric-auth?])]
|
||||
(if (and password biometric-auth?)
|
||||
(accounts.login/do-biometric-auth cofx password)
|
||||
(accounts.login/open-login-callback cofx password {:bioauth-notrequired true})))))
|
||||
|
||||
;; accounts logout module
|
||||
|
||||
|
@ -22,6 +22,7 @@
|
||||
[status-im.utils.fx :as fx]
|
||||
[status-im.utils.keychain.core :as keychain]
|
||||
[status-im.utils.platform :as platform]
|
||||
[status-im.biometric-auth.core :as biometric-auth]
|
||||
[taoensso.timbre :as log]))
|
||||
|
||||
(defn init-store!
|
||||
@ -66,6 +67,7 @@
|
||||
(fx/defn start-app [cofx]
|
||||
(fx/merge cofx
|
||||
{:init/get-device-UUID nil
|
||||
:init/get-supported-biometric-auth nil
|
||||
:init/restore-native-settings nil
|
||||
:ui/listen-to-window-dimensions-change nil
|
||||
:notifications/init nil
|
||||
@ -79,7 +81,7 @@
|
||||
[{{:keys [view-id hardwallet
|
||||
initial-props desktop/desktop
|
||||
network-status network peers-count peers-summary device-UUID
|
||||
push-notifications/stored network/type]
|
||||
supported-biometric-auth push-notifications/stored network/type]
|
||||
:node/keys [status]
|
||||
:or {network (get app-db :network)}} :db}]
|
||||
{:db (assoc app-db
|
||||
@ -94,6 +96,7 @@
|
||||
:network/type type
|
||||
:hardwallet hardwallet
|
||||
:device-UUID device-UUID
|
||||
:supported-biometric-auth supported-biometric-auth
|
||||
:view-id view-id
|
||||
:push-notifications/stored stored)})
|
||||
|
||||
@ -109,6 +112,11 @@
|
||||
[{:keys [db]} device-uuid]
|
||||
{:db (assoc db :device-UUID device-uuid)})
|
||||
|
||||
(fx/defn set-supported-biometric-auth
|
||||
{:events [:init.callback/get-supported-biometric-auth-success]}
|
||||
[{:keys [db]} supported-biometric-auth]
|
||||
{:db (assoc db :supported-biometric-auth supported-biometric-auth)})
|
||||
|
||||
(fx/defn handle-init-store-error
|
||||
[encryption-key cofx]
|
||||
{:ui/show-confirmation
|
||||
@ -159,7 +167,7 @@
|
||||
:keys [accounts/accounts accounts/create networks/networks network
|
||||
network-status peers-count peers-summary view-id navigation-stack
|
||||
mailserver/mailservers
|
||||
desktop/desktop hardwallet custom-fleets
|
||||
desktop/desktop hardwallet custom-fleets supported-biometric-auth
|
||||
device-UUID semaphores accounts/login]
|
||||
:node/keys [status on-ready]
|
||||
:or {network (get app-db :network)}} db
|
||||
@ -187,6 +195,7 @@
|
||||
:peers-summary peers-summary
|
||||
:peers-count peers-count
|
||||
:device-UUID device-UUID
|
||||
:supported-biometric-auth supported-biometric-auth
|
||||
:semaphores semaphores
|
||||
:hardwallet hardwallet
|
||||
:web3 web3)
|
||||
@ -254,6 +263,11 @@
|
||||
(fn []
|
||||
(status/get-device-UUID #(re-frame/dispatch [:init.callback/get-device-UUID-success %]))))
|
||||
|
||||
(re-frame/reg-fx
|
||||
:init/get-supported-biometric-auth
|
||||
(fn []
|
||||
(biometric-auth/get-supported #(re-frame/dispatch [:init.callback/get-supported-biometric-auth-success %]))))
|
||||
|
||||
(re-frame/reg-fx
|
||||
:init/reset-data
|
||||
reset-data!)
|
||||
|
@ -94,6 +94,9 @@
|
||||
(defn is24Hour []
|
||||
(native-module/is24Hour))
|
||||
|
||||
(defn get-device-model-info []
|
||||
(native-module/get-device-model-info))
|
||||
|
||||
(def extract-group-membership-signatures native-module/extract-group-membership-signatures)
|
||||
|
||||
(def sign-group-membership native-module/sign-group-membership)
|
||||
|
@ -156,6 +156,13 @@
|
||||
(when (status)
|
||||
(.-is24Hour (status))))
|
||||
|
||||
(defn get-device-model-info []
|
||||
(when status
|
||||
{:model (.-model status)
|
||||
:brand (.-brand status)
|
||||
:build-id (.-buildId status)
|
||||
:device-id (.-deviceId status)}))
|
||||
|
||||
(defn update-mailservers [enodes on-result]
|
||||
(when (status)
|
||||
(.updateMailservers (status) enodes on-result)))
|
||||
|
@ -89,6 +89,7 @@
|
||||
(reg-root-key-sub :get-pairing-installations :pairing/installations)
|
||||
(reg-root-key-sub :network/type :network/type)
|
||||
(reg-root-key-sub :tooltips :tooltips)
|
||||
(reg-root-key-sub :supported-biometric-auth :supported-biometric-auth)
|
||||
|
||||
;;profile
|
||||
(reg-root-key-sub :my-profile/seed :my-profile/seed)
|
||||
|
@ -93,6 +93,7 @@
|
||||
(spec/def ::network-status (spec/nilable keyword?))
|
||||
|
||||
(spec/def ::app-state string?)
|
||||
(spec/def ::app-in-background-since (spec/nilable number?))
|
||||
|
||||
;;;;NODE
|
||||
|
||||
@ -176,6 +177,10 @@
|
||||
|
||||
(spec/def ::device-UUID (spec/nilable string?))
|
||||
|
||||
;;;; Supported Biometric authentication types
|
||||
|
||||
(spec/def ::supported-biometric-auth (spec/nilable #{:FaceID :TouchID :fingerprint}))
|
||||
|
||||
;;;;UNIVERSAL LINKS
|
||||
|
||||
(spec/def :universal-links/url (spec/nilable string?))
|
||||
@ -295,6 +300,7 @@
|
||||
::network
|
||||
::chain
|
||||
::app-state
|
||||
::app-in-background-since
|
||||
::semaphores
|
||||
::hardwallet
|
||||
:navigation/view-id
|
||||
@ -332,6 +338,7 @@
|
||||
:prices/prices-loading?
|
||||
:notifications/notifications
|
||||
::device-UUID
|
||||
::supported-biometric-auth
|
||||
::collectible
|
||||
::collectibles
|
||||
::extensions-store
|
||||
|
@ -32,7 +32,10 @@
|
||||
[status-im.utils.handlers :as handlers]
|
||||
[status-im.utils.http :as http]
|
||||
[status-im.utils.utils :as utils]
|
||||
[status-im.wallet.core :as wallet]))
|
||||
[status-im.wallet.core :as wallet]
|
||||
[status-im.i18n :as i18n]
|
||||
[status-im.biometric-auth.core :as biometric-auth]
|
||||
[status-im.constants :as const]))
|
||||
|
||||
(defn- http-get [{:keys [url response-validator success-event-creator failure-event-creator timeout-ms]}]
|
||||
(let [on-success #(re-frame/dispatch (success-event-creator %))
|
||||
@ -136,18 +139,51 @@
|
||||
(fn [{:keys [db]} [_ path v]]
|
||||
{:db (assoc-in db path v)}))
|
||||
|
||||
(fx/defn on-return-from-background [cofx]
|
||||
(def authentication-options
|
||||
{:reason (i18n/label :t/biometric-auth-reason-login)})
|
||||
|
||||
(defn- on-biometric-auth-result [{:keys [bioauth-success bioauth-code bioauth-message]}]
|
||||
(when-not bioauth-success
|
||||
(if (= bioauth-code "USER_FALLBACK")
|
||||
(re-frame/dispatch [:accounts.logout.ui/logout-confirmed])
|
||||
(utils/show-confirmation {:title (i18n/label :t/biometric-auth-confirm-title)
|
||||
:content (or bioauth-message (i18n/label :t/biometric-auth-confirm-message))
|
||||
:confirm-button-text (i18n/label :t/biometric-auth-confirm-try-again)
|
||||
:cancel-button-text (i18n/label :t/biometric-auth-confirm-logout)
|
||||
:on-accept #(biometric-auth/authenticate on-biometric-auth-result authentication-options)
|
||||
:on-cancel #(re-frame/dispatch [:accounts.logout.ui/logout-confirmed])}))))
|
||||
|
||||
(fx/defn on-return-from-background [{:keys [db now] :as cofx}]
|
||||
(let [app-in-background-since (get db :app-in-background-since)
|
||||
signed-up? (get-in db [:account/account :signed-up?])
|
||||
biometric-auth? (get-in db [:account/account :settings :biometric-auth?])
|
||||
requires-bio-auth (and
|
||||
signed-up?
|
||||
biometric-auth?
|
||||
(some? app-in-background-since)
|
||||
(>= (- now app-in-background-since)
|
||||
const/ms-in-bg-for-require-bioauth))]
|
||||
(fx/merge cofx
|
||||
{:db (assoc db :app-in-background-since nil)}
|
||||
(mailserver/process-next-messages-request)
|
||||
(hardwallet/return-back-from-nfc-settings)))
|
||||
(hardwallet/return-back-from-nfc-settings)
|
||||
#(when requires-bio-auth
|
||||
(biometric-auth/authenticate-fx % on-biometric-auth-result authentication-options)))))
|
||||
|
||||
(fx/defn on-going-in-background [{:keys [db now] :as cofx}]
|
||||
(fx/merge cofx
|
||||
{:db (assoc db :app-in-background-since now)}))
|
||||
|
||||
(defn app-state-change [state {:keys [db] :as cofx}]
|
||||
(let [app-coming-from-background? (= state "active")]
|
||||
(let [app-coming-from-background? (= state "active")
|
||||
app-going-in-background? (= state "background")]
|
||||
(fx/merge cofx
|
||||
{::app-state-change-fx state
|
||||
:db (assoc db :app-state state)}
|
||||
#(when app-coming-from-background?
|
||||
(on-return-from-background %)))))
|
||||
(on-return-from-background %))
|
||||
#(when app-going-in-background?
|
||||
(on-going-in-background %)))))
|
||||
|
||||
(handlers/register-handler-fx
|
||||
:app-state-change
|
||||
|
@ -23,6 +23,7 @@
|
||||
[status-im.utils.identicon :as identicon]
|
||||
[status-im.utils.platform :as platform]
|
||||
[status-im.utils.universal-links.core :as universal-links]
|
||||
[status-im.biometric-auth.core :as biometric-auth]
|
||||
[status-im.utils.utils :as utils])
|
||||
(:require-macros [status-im.utils.views :refer [defview letsubs]]))
|
||||
|
||||
@ -180,7 +181,7 @@
|
||||
:active? logged-in?
|
||||
:action-fn #(re-frame/dispatch [:accounts.logout.ui/logout-pressed])}]]]]))
|
||||
|
||||
(defview advanced-settings [{:keys [network networks dev-mode? settings]} on-show]
|
||||
(defview advanced-settings [{:keys [network networks dev-mode? settings]} on-show supported-biometric-auth]
|
||||
{:component-did-mount on-show}
|
||||
[react/view
|
||||
(when (and config/extensions-enabled? dev-mode?)
|
||||
@ -239,10 +240,18 @@
|
||||
[profile.components/settings-switch-item
|
||||
{:label-kw :t/chaos-mode
|
||||
:value (:chaos-mode? settings)
|
||||
:action-fn #(re-frame/dispatch [:accounts.ui/chaos-mode-switched %])}]])
|
||||
:action-fn #(re-frame/dispatch [:accounts.ui/chaos-mode-switched %])}]
|
||||
(when dev-mode?
|
||||
[profile.components/settings-item-separator]
|
||||
[profile.components/settings-switch-item
|
||||
{:label-kw :t/biometric-auth-setting-label
|
||||
:value (:biometric-auth? settings)
|
||||
:active? (some? supported-biometric-auth)
|
||||
:action-fn #(re-frame/dispatch [:accounts.ui/biometric-auth-switched %])}])])
|
||||
|
||||
(defview advanced [params on-show]
|
||||
(letsubs [advanced? [:my-profile/advanced?]]
|
||||
(letsubs [advanced? [:my-profile/advanced?]
|
||||
supported-biometric-auth [:supported-biometric-auth]]
|
||||
{:component-will-unmount #(re-frame/dispatch [:set :my-profile/advanced? false])}
|
||||
[react/view {:padding-bottom 16}
|
||||
[react/touchable-highlight {:on-press #(re-frame/dispatch [:set :my-profile/advanced? (not advanced?)])
|
||||
@ -254,7 +263,7 @@
|
||||
(i18n/label :t/wallet-advanced)]
|
||||
[icons/icon (if advanced? :main-icons/dropdown-up :main-icons/dropdown) {:color colors/blue}]]]]]
|
||||
(when advanced?
|
||||
[advanced-settings params on-show])]))
|
||||
[advanced-settings params on-show supported-biometric-auth])]))
|
||||
|
||||
(defn share-profile-item
|
||||
[{:keys [public-key photo-path] :as current-account}]
|
||||
|
@ -4,6 +4,7 @@
|
||||
[status-im.react-native.js-dependencies :as rn]
|
||||
[status-im.utils.platform :as platform]
|
||||
[status-im.utils.security :as security]
|
||||
[status-im.biometric-auth.core :as biometric-auth]
|
||||
[status-im.native-module.core :as status]))
|
||||
|
||||
(def key-bytes 64)
|
||||
@ -84,6 +85,10 @@
|
||||
(enum-val "ACCESS_CONTROL" "BIOMETRY_ANY_OR_DEVICE_PASSCODE")}))
|
||||
(.then callback)))
|
||||
|
||||
;; Android and iOS
|
||||
(defn- biometric-auth-available? [callback]
|
||||
(biometric-auth/get-supported #(callback (some? %))))
|
||||
|
||||
;; Stores the password for the address to the Keychain
|
||||
(defn save-user-password [address password callback]
|
||||
(-> (.setInternetCredentials (rn/keychain) address address password keychain-secure-hardware (clj->js keychain-restricted-availability))
|
||||
@ -112,11 +117,14 @@
|
||||
;; Resolves to `false` if the device doesn't have neither a passcode nor a biometry auth.
|
||||
(defn can-save-user-password? [callback]
|
||||
(cond
|
||||
platform/ios? (device-encrypted? callback)
|
||||
platform/ios? (check-conditions callback
|
||||
device-encrypted?
|
||||
biometric-auth-available?)
|
||||
|
||||
platform/android? (check-conditions
|
||||
callback
|
||||
secure-hardware-available?
|
||||
biometric-auth-available?
|
||||
device-not-rooted?)
|
||||
|
||||
:else (callback false)))
|
||||
|
@ -25,6 +25,7 @@
|
||||
(def vector-icons (fn [] #js {:default #js {}}))
|
||||
(def webview-bridge (fn [] #js {:default #js {}}))
|
||||
(def webview (fn [] #js {:WebView #js {}}))
|
||||
(def touchid (fn [] #js {}))
|
||||
(def svg (fn [] #js {:default #js {}}))
|
||||
(def status-keycard (fn [] #js {:default #js {}}))
|
||||
|
||||
|
@ -1029,6 +1029,19 @@
|
||||
"load-messages-before": "before {{date}}",
|
||||
"open-dapp-store": "Discover ÐApps",
|
||||
"browsed-websites": "Browsed websites will appear here.",
|
||||
"biometric-auth-error": "Unable perform biometric authentication ({{code}})",
|
||||
"biometric-auth-reason-verify": "Verify authentication",
|
||||
"biometric-auth-reason-login": "Login in Status",
|
||||
"biometric-auth-confirm-try-again": "Try again",
|
||||
"biometric-auth-confirm-logout": "Relogin",
|
||||
"biometric-auth-confirm-message": "Biometric authentication is required to continue, if not possible please relogin using account password",
|
||||
"biometric-auth-confirm-title": "You must authenticate!",
|
||||
"biometric-auth-login-error-title": "Biometric authentication error",
|
||||
"biometric-auth-login-ios-fallback-label": "Enter Password",
|
||||
"biometric-auth-setting-label": "Use biometric authentication",
|
||||
"biometric-auth-android-title": "Authentication Required",
|
||||
"biometric-auth-android-sensor-desc": "Touch sensor",
|
||||
"biometric-auth-android-sensor-error-desc": "Failed",
|
||||
"dapps-can-access" : "ÐApps can access my wallet and contact code",
|
||||
"require-my-permission" : "Require my permission",
|
||||
"might-break" : "Might break some ÐApps",
|
||||
|
Loading…
x
Reference in New Issue
Block a user