Signed-off-by: Andrey Shovkoplyas <motor4ik@gmail.com>
This commit is contained in:
tbenr 2019-05-30 16:01:20 +02:00 committed by Andrey Shovkoplyas
parent daacccb512
commit 090a4e7c76
No known key found for this signature in database
GPG Key ID: EAAB7C8622D860A4
30 changed files with 335 additions and 24 deletions

View File

@ -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')

View File

@ -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) -->

View File

@ -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

View File

@ -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'

View File

@ -23,6 +23,7 @@
"react-native-webview-bridge"
"react-native-webview"
"react-native-firebase"
"react-native-touch-id"
"homoglyph-finder"
"web3"
"web3-utils"

View File

@ -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'

View File

@ -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

View File

@ -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>

View File

@ -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",

View File

@ -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"

View File

@ -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;
}

View File

@ -1,3 +1,4 @@
#import <sys/utsname.h>
#import <Foundation/Foundation.h>
#import <React/RCTBridgeModule.h>
#import "Statusgo/Statusgo.h"

View File

@ -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],
};
}

View File

@ -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 {}))

View File

@ -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)))

View File

@ -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?}

View File

@ -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
{: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))
(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]
(if password
(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)))
(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

View 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)))

View File

@ -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")

View File

@ -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

View File

@ -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!)

View File

@ -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)

View File

@ -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)))

View File

@ -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)

View File

@ -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

View File

@ -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)
#(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
(mailserver/process-next-messages-request)
(hardwallet/return-back-from-nfc-settings)))
{: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

View File

@ -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}]

View File

@ -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)))

View File

@ -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 {}}))

View File

@ -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",