diff --git a/modules/react-native-status/android/src/main/java/im/status/ethereum/module/StatusModule.java b/modules/react-native-status/android/src/main/java/im/status/ethereum/module/StatusModule.java index bed410cc62..86a63c1228 100644 --- a/modules/react-native-status/android/src/main/java/im/status/ethereum/module/StatusModule.java +++ b/modules/react-native-status/android/src/main/java/im/status/ethereum/module/StatusModule.java @@ -391,6 +391,31 @@ class StatusModule extends ReactContextBaseJavaModule implements LifecycleEventL StatusThreadPoolExecutor.getInstance().execute(r); } + @ReactMethod + public void verify(final String address, final String password, final Callback callback) { + Log.d(TAG, "verify"); + if (!checkAvailability()) { + callback.invoke(false); + return; + } + + Activity currentActivity = getCurrentActivity(); + + final String absRootDirPath = currentActivity.getApplicationInfo().dataDir; + final String newKeystoreDir = pathCombine(absRootDirPath, "keystore"); + + Runnable r = new Runnable() { + @Override + public void run() { + String result = Statusgo.VerifyAccountPassword(newKeystoreDir, address, password); + + callback.invoke(result); + } + }; + + StatusThreadPoolExecutor.getInstance().execute(r); + } + @ReactMethod public void createAccount(final String password, final Callback callback) { Log.d(TAG, "createAccount"); diff --git a/modules/react-native-status/ios/RCTStatus/RCTStatus.m b/modules/react-native-status/ios/RCTStatus/RCTStatus.m index 7de89880f2..c24d93e110 100644 --- a/modules/react-native-status/ios/RCTStatus/RCTStatus.m +++ b/modules/react-native-status/ios/RCTStatus/RCTStatus.m @@ -228,6 +228,25 @@ RCT_EXPORT_METHOD(login:(NSString *)address callback(@[[NSString stringWithUTF8String: result]]); } +//////////////////////////////////////////////////////////////////// login +RCT_EXPORT_METHOD(verify:(NSString *)address + password:(NSString *)password + callback:(RCTResponseSenderBlock)callback) { +#if DEBUG + NSLog(@"VerifyAccountPassword() method called"); +#endif + NSFileManager *fileManager = [NSFileManager defaultManager]; + NSURL *rootUrl =[[fileManager + URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] + lastObject]; + NSURL *absKeystoreUrl = [rootUrl URLByAppendingPathComponent:@"keystore"]; + + char * result = VerifyAccountPassword((char *) [absKeystoreUrl.path UTF8String], + (char *) [address UTF8String], + (char *) [password UTF8String]); + callback(@[[NSString stringWithUTF8String: result]]); +} + //////////////////////////////////////////////////////////////////// #pragma mark - SendTransaction //////////////////////////////////////////////////////////////////// sendTransaction diff --git a/src/status_im/accounts/login/core.cljs b/src/status_im/accounts/login/core.cljs index d2e5eb35fc..d5612aaa0e 100644 --- a/src/status_im/accounts/login/core.cljs +++ b/src/status_im/accounts/login/core.cljs @@ -3,13 +3,17 @@ [status-im.accounts.db :as accounts.db] [status-im.data-store.core :as data-store] [status-im.native-module.core :as status] - [status-im.node.core :as node] [status-im.ui.screens.navigation :as navigation] [status-im.utils.fx :as fx] [status-im.utils.keychain.core :as keychain] [status-im.utils.types :as types] [taoensso.timbre :as log] - [status-im.utils.security :as security])) + [status-im.utils.security :as security] + [status-im.utils.platform :as platform] + [status-im.protocol.core :as protocol] + [status-im.models.wallet :as models.wallet] + [status-im.models.transactions :as transactions] + [status-im.i18n :as i18n])) ;; login flow: ;; @@ -22,13 +26,18 @@ (defn login! [address password save-password?] (status/login address password #(re-frame/dispatch [:accounts.login.callback/login-success %]))) +(defn verify! [address password realm-error] + (status/verify address password + #(re-frame/dispatch + [:accounts.login.callback/verify-success % realm-error]))) + (defn clear-web-data! [] (status/clear-web-data)) -(defn change-account! [address password] +(defn change-account! [address password create-database-if-not-exist?] ;; No matter what is the keychain we use, as checks are done on decrypting base (.. (keychain/safe-get-encryption-key) - (then #(data-store/change-account address password %)) + (then #(data-store/change-account address password % create-database-if-not-exist?)) (then (fn [] (re-frame/dispatch [:init.callback/account-change-success address]))) (catch (fn [error] (log/warn "Could not change account" error) @@ -40,26 +49,137 @@ (let [{:keys [address password save-password?]} (accounts.db/credentials cofx)] {:accounts.login/login [address password save-password?]})) -(fx/defn user-login [{:keys [db] :as cofx}] +(fx/defn initialize-wallet [cofx] (fx/merge cofx - {:db (assoc-in db [:accounts/login :processing] true)} - (node/initialize (get-in db [:accounts/login :address])))) + (models.wallet/initialize-tokens) + (models.wallet/update-wallet) + (transactions/start-sync))) + +(fx/defn user-login [{:keys [db] :as cofx}] + (let [{:keys [address password save-password?]} (accounts.db/credentials cofx)] + (fx/merge + cofx + (merge + {:db (assoc-in db [:accounts/login :processing] true) + :accounts.login/clear-web-data nil + :data-store/change-account [address password false]} + (when save-password? + {:keychain/save-user-password [address password]}))))) + +(fx/defn account-and-db-password-do-not-match + [{:keys [db] :as cofx} error] + (fx/merge + cofx + {:db + (update db :accounts/login assoc + :error error + :processing false) + + :utils/show-popup + {:title (i18n/label :account-and-db-password-mismatch-title) + :content (i18n/label :account-and-db-password-mismatch-content)} + + :dispatch [:accounts.logout.ui/logout-confirmed]})) (fx/defn user-login-callback - [{db :db :as cofx} login-result] + [{:keys [db web3] :as cofx} login-result] (let [data (types/json->clj login-result) + error (:error data) + success (empty? error) + address (get-in db [:account/account :address])] + ;; check if logged into account + (when address + (if success + (fx/merge + cofx + {:db (dissoc db :accounts/login) + :web3/set-default-account [web3 address] + :web3/fetch-node-version [web3 + #(re-frame/dispatch + [:web3/fetch-node-version-callback %])]} + (protocol/initialize-protocol address) + #(when-not platform/desktop? + (initialize-wallet %))) + (account-and-db-password-do-not-match cofx error))))) + +(fx/defn show-migration-error-dialog + [{:keys [db]} realm-error] + (let [{:keys [message]} realm-error + address (get-in db [:accounts/login :address]) + erase-button (i18n/label :migrations-erase-accounts-data-button)] + {:ui/show-confirmation + {:title (i18n/label :invalid-key-title) + :content (i18n/label + :invalid-key-content + {:message message + :erase-accounts-data-button-text erase-button}) + :confirm-button-text (i18n/label :invalid-key-confirm) + :on-cancel #(re-frame/dispatch + [:init.ui/data-reset-cancelled ""]) + :on-accept #(re-frame/dispatch + [:init.ui/account-data-reset-accepted address])}})) +(fx/defn verify-callback + [{:keys [db] :as cofx} verify-result realm-error] + (let [data (types/json->clj verify-result) error (:error data) success (empty? error)] (if success - (let [{:keys [address password save-password?]} (accounts.db/credentials cofx)] - (merge {:accounts.login/clear-web-data nil - :data-store/change-account [address password]} - (when save-password? - {:keychain/save-user-password [address password]}))) + (case (:error realm-error) + :decryption-failed + (show-migration-error-dialog cofx realm-error) + + :database-does-not-exist + (let [{:keys [address password]} (accounts.db/credentials cofx)] + {:data-store/change-account [address password true]})) {:db (update db :accounts/login assoc :error error :processing false)}))) +(fx/defn handle-change-account-error + [{:keys [db] :as cofx} error] + (let [{:keys [error message details] :as realm-error} + (if (map? error) + error + {:message (str error)}) + {:keys [address password]} (accounts.db/credentials cofx) + erase-button (i18n/label :migrations-erase-accounts-data-button)] + (case error + :migrations-failed + (let [{:keys [message]} realm-error + address (get-in db [:accounts/login :address])] + {:ui/show-confirmation + {:title (i18n/label :migrations-failed-title) + :content (i18n/label + :migrations-failed-content + (merge + {:message message + :erase-accounts-data-button-text erase-button} + details)) + :confirm-button-text erase-button + :on-cancel #(re-frame/dispatch + [:init.ui/data-reset-cancelled ""]) + :on-accept #(re-frame/dispatch + [:init.ui/account-data-reset-accepted address])}}) + + :database-does-not-exist + {:accounts.login/verify [address password realm-error]} + + :decryption-failed + ;; check if decryption failed because of wrong password + {:accounts.login/verify [address password realm-error]} + + {:ui/show-confirmation + {:title (i18n/label :unknown-realm-error) + :content (i18n/label + :unknown-realm-error-content + {:message message + :erase-accounts-data-button-text erase-button}) + :confirm-button-text (i18n/label :invalid-key-confirm) + :on-cancel #(re-frame/dispatch + [:init.ui/data-reset-cancelled ""]) + :on-accept #(re-frame/dispatch + [:init.ui/account-data-reset-accepted address])}}))) + (fx/defn open-login [{:keys [db]} address photo-path name] {:db (-> db (update :accounts/login assoc @@ -87,11 +207,17 @@ (fn [[address password save-password?]] (login! address (security/safe-unmask-data password) save-password?))) +(re-frame/reg-fx + :accounts.login/verify + (fn [[address password realm-error]] + (verify! address (security/safe-unmask-data password) realm-error))) + (re-frame/reg-fx :accounts.login/clear-web-data clear-web-data!) (re-frame/reg-fx :data-store/change-account - (fn [[address password]] - (change-account! address (security/safe-unmask-data password)))) + (fn [[address password create-database-if-not-exist?]] + (change-account! address (security/safe-unmask-data password) + create-database-if-not-exist?))) diff --git a/src/status_im/accounts/logout/core.cljs b/src/status_im/accounts/logout/core.cljs index d9efafd849..93babfdb1c 100644 --- a/src/status_im/accounts/logout/core.cljs +++ b/src/status_im/accounts/logout/core.cljs @@ -1,7 +1,6 @@ (ns status-im.accounts.logout.core (:require [re-frame.core :as re-frame] [status-im.i18n :as i18n] - [status-im.init.core :as init] [status-im.transport.core :as transport] [status-im.ui.screens.navigation :as navigation] [status-im.utils.fx :as fx] @@ -12,11 +11,11 @@ (let [{:transport/keys [chats]} db] (fx/merge cofx {:keychain/clear-user-password (get-in db [:account/account :address]) - :dev-server/stop nil} + :dev-server/stop nil + :keychain/get-encryption-key [:init.callback/get-encryption-key-success]} (transactions/stop-sync) (navigation/navigate-to-clean :login {}) - (transport/stop-whisper) - (init/initialize-keychain)))) + (transport/stop-whisper)))) (fx/defn show-logout-confirmation [_] {:ui/show-confirmation diff --git a/src/status_im/data_store/core.cljs b/src/status_im/data_store/core.cljs index 819921b8a5..325e0c3f2b 100644 --- a/src/status_im/data_store/core.cljs +++ b/src/status_im/data_store/core.cljs @@ -25,7 +25,8 @@ (log/error "Could not move realms" error))) (then #(data-source/open-base-realm encryption-key))))) -(defn change-account [address password encryption-key] +(defn change-account + [address password encryption-key create-database-if-not-exist?] (log/debug "changing account to: " address) (.. (js/Promise. @@ -36,6 +37,10 @@ (catch :default e (on-error {:message (str e) :error :closing-account-failed}))))) + (then + (if create-database-if-not-exist? + #(js/Promise. (fn [on-success] (on-success))) + #(data-source/db-exists? address))) (then #(data-source/check-db-encryption address password encryption-key)) (then diff --git a/src/status_im/data_store/realm/core.cljs b/src/status_im/data_store/realm/core.cljs index faf7f0d5ab..a9ddb57aa3 100644 --- a/src/status_im/data_store/realm/core.cljs +++ b/src/status_im/data_store/realm/core.cljs @@ -255,6 +255,16 @@ #(re-encrypt-realm file-name old-key new-key on-success on-error)) (catch on-error))))))))) +(defn db-exists? [address] + (js/Promise. + (fn [on-success on-error] + (.. (fs/file-exists? (get-account-db-path address)) + (then (fn [db-exists?] + (if db-exists? + (on-success) + (on-error {:message "Account's database doesn't exist." + :error :database-does-not-exist})))))))) + (defn open-account [address password encryption-key] (let [path (get-account-db-path address) account-db-key (db-encryption-key password encryption-key)] diff --git a/src/status_im/events.cljs b/src/status_im/events.cljs index 9c7c254d23..41c0085fda 100644 --- a/src/status_im/events.cljs +++ b/src/status_im/events.cljs @@ -45,7 +45,8 @@ [taoensso.timbre :as log] [status-im.utils.datetime :as time] [status-im.chat.commands.core :as commands] - [status-im.chat.models.loading :as chat-loading])) + [status-im.chat.models.loading :as chat-loading] + [status-im.node.core :as node])) ;; init module @@ -102,15 +103,11 @@ :init-chats [(re-frame/inject-cofx :web3/get-web3) (re-frame/inject-cofx :get-default-dapps) - (re-frame/inject-cofx :data-store/all-chats) - (re-frame/inject-cofx :data-store/get-all-mailservers) - (re-frame/inject-cofx :data-store/transport) - (re-frame/inject-cofx :data-store/mailserver-topics)] + (re-frame/inject-cofx :data-store/all-chats)] (fn [{:keys [db] :as cofx} [_ address]] (fx/merge cofx {:db (assoc db :chats/loading? false)} (chat-loading/initialize-chats) - (protocol/initialize-protocol address) (chat-loading/initialize-pending-messages)))) (handlers/register-handler-fx @@ -120,13 +117,11 @@ (re-frame/inject-cofx :data-store/get-all-installations) (re-frame/inject-cofx :data-store/all-browsers) (re-frame/inject-cofx :data-store/all-dapp-permissions)] - (fn [cofx [_ address]] - (init/initialize-account cofx address))) - -(handlers/register-handler-fx - :init.callback/account-change-error - (fn [cofx [_ error]] - (init/handle-change-account-error cofx error))) + (fn [{:keys [db] :as cofx} [_ address]] + (fx/merge + cofx + (node/initialize (get-in db [:accounts/login :address])) + (init/initialize-account address)))) (handlers/register-handler-fx :init.callback/keychain-reset @@ -261,9 +256,24 @@ (handlers/register-handler-fx :accounts.login.callback/login-success + [(re-frame/inject-cofx :web3/get-web3) + (re-frame/inject-cofx :data-store/all-chats) + (re-frame/inject-cofx :data-store/get-all-mailservers) + (re-frame/inject-cofx :data-store/transport) + (re-frame/inject-cofx :data-store/mailserver-topics)] (fn [cofx [_ login-result]] (accounts.login/user-login-callback cofx login-result))) +(handlers/register-handler-fx + :accounts.login.callback/verify-success + (fn [cofx [_ verify-result realm-error]] + (accounts.login/verify-callback cofx verify-result realm-error))) + +(handlers/register-handler-fx + :init.callback/account-change-error + (fn [cofx [_ error]] + (accounts.login/handle-change-account-error cofx error))) + (handlers/register-handler-fx :accounts.login.ui/account-selected (fn [cofx [_ address photo-path name]] diff --git a/src/status_im/init/core.cljs b/src/status_im/init/core.cljs index 5515224b47..e1ab7bb575 100644 --- a/src/status_im/init/core.cljs +++ b/src/status_im/init/core.cljs @@ -106,41 +106,6 @@ [{:keys [db]} device-uuid] {:db (assoc db :device-UUID device-uuid)}) -(fx/defn handle-change-account-error - [{:keys [db]} error] - (let [{:keys [error message details]} - (if (map? error) - error - {:message (str error)}) - address (get-in db [:accounts/login :address]) - erase-button-text (i18n/label :migrations-erase-accounts-data-button)] - (case error - :migrations-failed - {:ui/show-confirmation - {:title (i18n/label :migrations-failed-title) - :content (i18n/label - :migrations-failed-content - (merge - {:message message - :erase-accounts-data-button-text erase-button-text} - details)) - :confirm-button-text erase-button-text - :on-cancel #(re-frame/dispatch [:init.ui/data-reset-cancelled ""]) - :on-accept #(re-frame/dispatch [:init.ui/account-data-reset-accepted address])}} - - ;; TODO(rasom): handle different errors as separate cases - ;; Right now it might be corrupted db file, wrong password, - ;; problem with permissions, etc. - {:ui/show-confirmation - {:title (i18n/label :invalid-key-title) - :content (i18n/label - :invalid-key-content - {:message message - :erase-accounts-data-button-text erase-button-text}) - :confirm-button-text (i18n/label :invalid-key-confirm) - :on-cancel #(re-frame/dispatch [:init.ui/data-reset-cancelled ""]) - :on-accept #(re-frame/dispatch [:init.ui/account-data-reset-accepted address])}}))) - (fx/defn handle-init-store-error [encryption-key cofx] {:ui/show-confirmation @@ -183,9 +148,9 @@ (fx/defn initialize-account-db [{:keys [db web3]} address] (let [{:universal-links/keys [url] - :keys [accounts/accounts accounts/create contacts/contacts networks/networks - network network-status peers-count peers-summary view-id navigation-stack - pairing/installations status-module-initialized? device-UUID semaphores] + :keys [accounts/accounts accounts/create networks/networks network + network-status peers-count peers-summary view-id navigation-stack + status-module-initialized? device-UUID semaphores accounts/login] :node/keys [status] :or {network (get app-db :network)}} db current-account (get accounts address) @@ -199,6 +164,8 @@ :accounts/create create :networks/networks networks :account/account current-account + :accounts/login login + :accounts/accounts accounts :network-status network-status :network network :chain (ethereum/network->chain-name account-network) @@ -211,12 +178,6 @@ (= view-id :create-account) (assoc-in [:accounts/create :step] :enter-name))})) -(defn initialize-wallet [cofx] - (fx/merge cofx - (models.wallet/initialize-tokens) - (models.wallet/update-wallet) - (transactions/start-sync))) - (defn login-only-events [cofx address] (fx/merge cofx {:notifications/request-notifications-permissions nil} @@ -234,23 +195,18 @@ (= (get-in cofx [:db :view-id]) :create-account)) -(fx/defn initialize-account [{:keys [db web3] :as cofx} address] +(fx/defn initialize-account [cofx address] (fx/merge cofx - {:web3/set-default-account [web3 address] - :web3/fetch-node-version [web3 - #(re-frame/dispatch - [:web3/fetch-node-version-callback %])] - :notifications/get-fcm-token nil} + {:notifications/get-fcm-token nil} (initialize-account-db address) (contact/load-contacts) (pairing/load-installations) #(when (dev-mode? %) (models.dev-server/start)) (browser/initialize-browsers) + (browser/initialize-dapp-permissions) (extensions.registry/initialize) - #(when-not platform/desktop? - (initialize-wallet %)) (accounts.update/update-sign-in-time) #(when-not (creating-account? %) (login-only-events % address)))) diff --git a/src/status_im/mailserver/core.cljs b/src/status_im/mailserver/core.cljs index 2d50e76824..b7d175290e 100644 --- a/src/status_im/mailserver/core.cljs +++ b/src/status_im/mailserver/core.cljs @@ -365,12 +365,13 @@ [{:keys [db] :as cofx}] ;; check if logged into account (when (contains? db :account/account) - (if (zero? (dec (:mailserver/connection-checks db))) - (fx/merge cofx - {:db (dissoc db :mailserver/connection-checks)} - (when (= :connecting (:mailserver/state db)) - (change-mailserver cofx))) - {:db (update db :mailserver/connection-checks dec)}))) + (let [connection-checks (dec (:mailserver/connection-checks db))] + (if (>= 0 connection-checks) + (fx/merge cofx + {:db (dissoc db :mailserver/connection-checks)} + (when (= :connecting (:mailserver/state db)) + (change-mailserver cofx))) + {:db (update db :mailserver/connection-checks dec)})))) (fx/defn reset-request-to [{:keys [db]}] diff --git a/src/status_im/native_module/core.cljs b/src/status_im/native_module/core.cljs index 48bda83730..5d6656035d 100644 --- a/src/status_im/native_module/core.cljs +++ b/src/status_im/native_module/core.cljs @@ -6,6 +6,9 @@ (defn start-node [config] (native-module/start-node config)) +(defn node-ready [] + (native-module/node-ready)) + (defn stop-node [] (native-module/stop-node)) @@ -18,6 +21,9 @@ (defn login [address password callback] (native-module/login address password callback)) +(defn verify [address password callback] + (native-module/verify address password callback)) + (defn set-soft-input-mode [mode] (native-module/set-soft-input-mode mode)) diff --git a/src/status_im/native_module/impl/module.cljs b/src/status_im/native_module/impl/module.cljs index 7237908224..10a0279c2a 100644 --- a/src/status_im/native_module/impl/module.cljs +++ b/src/status_im/native_module/impl/module.cljs @@ -54,10 +54,16 @@ (.addListener r/device-event-emitter "gethEvent" #(re-frame/dispatch [:signals/signal-received (.-jsonEvent %)]))) +(defonce node-started (atom false)) + (defn stop-node [] + (reset! node-started false) (when status (call-module #(.stopNode status)))) +(defn node-ready [] + (reset! node-started true)) + (defn start-node [config] (when status (call-module #(.startNode status config)))) @@ -82,17 +88,21 @@ (call-module #(.notifyUsers status message payload tokens on-result)))) (defn add-peer [enode on-result] - (when status + (when (and @node-started status) (call-module #(.addPeer status enode on-result)))) (defn recover-account [passphrase password on-result] - (when status + (when (and @node-started status) (call-module #(.recoverAccount status passphrase password on-result)))) (defn login [address password on-result] - (when status + (when (and @node-started status) (call-module #(.login status address password on-result)))) +(defn verify [address password on-result] + (when (and @node-started status) + (call-module #(.verify status address password on-result)))) + (defn set-soft-input-mode [mode] (when status (call-module #(.setSoftInputMode status mode)))) @@ -103,19 +113,19 @@ (call-module #(.clearStorageAPIs status)))) (defn call-rpc [payload callback] - (when status + (when (and @node-started status) (call-module #(.callRPC status payload callback)))) (defn call-private-rpc [payload callback] - (when status + (when (and @node-started status) (call-module #(.callPrivateRPC status payload callback)))) (defn sign-message [rpcParams callback] - (when status + (when (and @node-started status) (call-module #(.signMessage status rpcParams callback)))) (defn send-transaction [rpcParams password callback] - (when status + (when (and @node-started status) (call-module #(.sendTransaction status rpcParams password callback)))) (defn close-application [] diff --git a/src/status_im/node/core.cljs b/src/status_im/node/core.cljs index a85a88be95..47f270495f 100644 --- a/src/status_im/node/core.cljs +++ b/src/status_im/node/core.cljs @@ -177,6 +177,11 @@ (fn [config] (status/start-node config))) +(re-frame/reg-fx + :node/ready + (fn [config] + (status/node-ready))) + (re-frame/reg-fx :node/stop (fn [] diff --git a/src/status_im/notifications/core.cljs b/src/status_im/notifications/core.cljs index c08f4f6e80..29f3b51d2e 100644 --- a/src/status_im/notifications/core.cljs +++ b/src/status_im/notifications/core.cljs @@ -4,7 +4,6 @@ [status-im.react-native.js-dependencies :as rn] [taoensso.timbre :as log] [status-im.accounts.db :as accounts.db] - [status-im.accounts.login.core :as accounts.login] [status-im.chat.models :as chat-model] [status-im.utils.platform :as platform] [status-im.utils.fx :as fx])) diff --git a/src/status_im/signals/core.cljs b/src/status_im/signals/core.cljs index 59b003b09e..87b10519d4 100644 --- a/src/status_im/signals/core.cljs +++ b/src/status_im/signals/core.cljs @@ -16,9 +16,10 @@ can-login? (and (not restart?) (:password (accounts.db/credentials cofx)))] (fx/merge cofx - {:db (-> db - (assoc :node/status :started) - (dissoc :node/restart? :node/address))} + {:db (-> db + (assoc :node/status :started) + (dissoc :node/restart? :node/address)) + :node/ready nil} (when restart? (node/initialize address)) diff --git a/src/status_im/ui/screens/accounts/login/views.cljs b/src/status_im/ui/screens/accounts/login/views.cljs index 6f02620acd..5ba1c29f0d 100644 --- a/src/status_im/ui/screens/accounts/login/views.cljs +++ b/src/status_im/ui/screens/accounts/login/views.cljs @@ -38,7 +38,9 @@ (string/starts-with? error "there is no running node") :t/node-unavailable - (string/starts-with? error "cannot retrieve a valid key") + (or + (string/starts-with? error "cannot retrieve a valid key") + (string/starts-with? error "could not decrypt key")) :t/wrong-password :else diff --git a/src/status_im/ui/screens/chat/input/send_button.cljs b/src/status_im/ui/screens/chat/input/send_button.cljs index 801769078d..8eccbb7db8 100644 --- a/src/status_im/ui/screens/chat/input/send_button.cljs +++ b/src/status_im/ui/screens/chat/input/send_button.cljs @@ -14,20 +14,22 @@ (animation/timing spin-value {:toValue to-spin-value :duration 300}))))) -(defn sendable? [input-text offline?] +(defn sendable? [input-text offline? login-processing?] (let [trimmed (string/trim input-text)] (not (or (string/blank? trimmed) (= trimmed "/") - offline?)))) + offline? + login-processing?)))) (defview send-button-view [] - (letsubs [{:keys [command-completion]} [:chats/selected-chat-command] - {:keys [input-text seq-arg-input-text]} [:chats/current-chat] - offline? [:offline?] - spin-value (animation/create-value 1)] + (letsubs [{:keys [command-completion]} [:chats/selected-chat-command] + {:keys [input-text]} [:chats/current-chat] + offline? [:offline?] + spin-value (animation/create-value 1) + login-processing? [:get-in [:accounts/login :processing]]] {:component-did-update (send-button-view-on-update {:spin-value spin-value :command-completion command-completion})} - (when (and (sendable? input-text offline?) + (when (and (sendable? input-text offline? login-processing?) (or (not command-completion) (#{:complete :less-than-needed} command-completion))) [react/touchable-highlight {:on-press #(re-frame/dispatch [:chat.ui/send-current-message])} diff --git a/src/status_im/ui/screens/profile/components/styles.cljs b/src/status_im/ui/screens/profile/components/styles.cljs index 0ffbb6949c..4018551145 100644 --- a/src/status_im/ui/screens/profile/components/styles.cljs +++ b/src/status_im/ui/screens/profile/components/styles.cljs @@ -72,6 +72,9 @@ (def settings-item-destructive {:color colors/red}) +(def settings-item-disabled + {:color colors/gray}) + (def settings-item-value {:flex 1 :flex-wrap :nowrap diff --git a/src/status_im/ui/screens/profile/components/views.cljs b/src/status_im/ui/screens/profile/components/views.cljs index 530047fd2a..d731597cdf 100644 --- a/src/status_im/ui/screens/profile/components/views.cljs +++ b/src/status_im/ui/screens/profile/components/views.cljs @@ -84,7 +84,8 @@ [react/view styles/settings-item [react/view styles/settings-item-text-wrapper [react/text {:style (merge styles/settings-item-text - (when destructive? styles/settings-item-destructive)) + (when destructive? styles/settings-item-destructive) + (when-not active? styles/settings-item-disabled)) :number-of-lines 1} (or item-text (i18n/label label-kw))] (when-not (string/blank? value) diff --git a/src/status_im/ui/screens/profile/user/views.cljs b/src/status_im/ui/screens/profile/user/views.cljs index 9d9db22342..7cddc4d979 100644 --- a/src/status_im/ui/screens/profile/user/views.cljs +++ b/src/status_im/ui/screens/profile/user/views.cljs @@ -98,7 +98,7 @@ :source source :value value}])) -(defn- my-profile-settings [{:keys [seed-backed-up? mnemonic]} {:keys [settings]} currency] +(defn- my-profile-settings [{:keys [seed-backed-up? mnemonic]} {:keys [settings]} currency logged-in?] (let [show-backup-seed? (and (not seed-backed-up?) (not (string/blank? mnemonic)))] [react/view [profile.components/settings-title (i18n/label :t/settings)] @@ -143,6 +143,7 @@ :accessibility-label :log-out-button :destructive? true :hide-arrow? true + :active? logged-in? :action-fn #(re-frame/dispatch [:accounts.logout.ui/logout-pressed])}]]]])) (defview advanced-settings [{:keys [network networks dev-mode? settings]} on-show] @@ -214,6 +215,7 @@ editing? [:get :my-profile/editing?] changed-account [:get :my-profile/profile] currency [:wallet/currency] + login-data [:get :accounts/login] scroll (reagent/atom nil)] (let [shown-account (merge current-account changed-account) ;; We scroll on the component once rendered. setTimeout is necessary, @@ -252,5 +254,5 @@ :accessibility-label :share-my-profile-button} (i18n/label :t/share-my-profile)]] [react/view styles/my-profile-info-container - [my-profile-settings current-account shown-account currency]] + [my-profile-settings current-account shown-account currency (nil? login-data)]] [advanced shown-account on-show-advanced]]]))) diff --git a/src/status_im/utils/fs.cljs b/src/status_im/utils/fs.cljs index 10e17a57ec..8052e9712c 100644 --- a/src/status_im/utils/fs.cljs +++ b/src/status_im/utils/fs.cljs @@ -17,3 +17,6 @@ (defn unlink [path] (.unlink rn-dependencies/fs path)) + +(defn file-exists? [path] + (.exists rn-dependencies/fs path)) diff --git a/translations/en.json b/translations/en.json index 9e2d7cb0c1..ebf581e342 100644 --- a/translations/en.json +++ b/translations/en.json @@ -385,6 +385,7 @@ "currency-display-name-ron": "Romania Leu", "log-level-settings": "Log level settings", "invalid-key-content": "{{message}}\n\nAccount's database can't be encrypted because file is corrupted. There is no way to restore it. If you press \"Cancel\" button, nothing will happen. If you press \"{{erase-accounts-data-button-text}}\" button, account's db will be removed and you will be able to unlock account. All account's data will be lost.", + "unknown-realm-error-content": "{{message}}\n\nAccount's database can't be opened. Please let us know about this problem at #status public chat. If you press \"Cancel\" button, nothing will happen. If you press \"{{erase-accounts-data-button-text}}\" button, account's db will be removed and you will be able to unlock account. All account's data will be lost.", "advanced-settings": "Advanced settings", "group-info": "Group info", "currency-display-name-nio": "Nicaragua Cordoba", @@ -420,6 +421,7 @@ "wallet-send": "Send", "wallet-deposit": "Deposit", "invalid-key-title": "We detected a problem with the encryption key", + "unknown-realm-error": "Something went wrong", "notifications": "Notifications", "currency-display-name-czk": "Czech Koruna", "extension-installed": "You installed an extension", @@ -791,5 +793,7 @@ "install-the-extension": "install the extension", "migrations-failed-title": "Migration failed", "migrations-failed-content": "{{message}}\nschema version: initial {{initial-version}}, current {{current-version}}, last {{last-version}}\n\nPlease let us know about this problem at #status public chat. If you press \"Cancel\" button, nothing will happen. If you press \"{{erase-accounts-data-button-text}}\" button, account's db will be removed and you will be able to unlock account. All account's data will be lost.", - "migrations-erase-accounts-data-button": "Erase account's db" + "migrations-erase-accounts-data-button": "Erase account's db", + "account-and-db-password-mismatch-title": "The problem occurred!", + "account-and-db-password-mismatch-content": "Account's and realm db passwords do not match." }