UI in place

Do not need account-info for password reset
Update status go version
Java API
PR Fixes and hide behind a feature flag
Reset status go version to HEAD
Disable reset password in DEV
Enable reset password in DEV

Signed-off-by: Shivek Khurana <shivek@status.im>
This commit is contained in:
Shivek Khurana 2021-05-26 14:25:01 +05:30
parent e7887d4fca
commit a1204d0c80
No known key found for this signature in database
GPG Key ID: 9BEB56E6E62968C7
16 changed files with 336 additions and 96 deletions

1
.env
View File

@ -29,3 +29,4 @@ APN_TOPIC=im.status.ethereum.pr
COMMUNITIES_ENABLED=1 COMMUNITIES_ENABLED=1
DATABASE_MANAGEMENT_ENABLED=1 DATABASE_MANAGEMENT_ENABLED=1
METRICS_ENABLED=0 METRICS_ENABLED=0
RESET_PASSWORD_ENABLED=1

View File

@ -596,7 +596,7 @@ SPEC CHECKSUMS:
FBLazyVector: 3bb422f41b18121b71783a905c10e58606f7dc3e FBLazyVector: 3bb422f41b18121b71783a905c10e58606f7dc3e
FBReactNativeSpec: f2c97f2529dd79c083355182cc158c9f98f4bd6e FBReactNativeSpec: f2c97f2529dd79c083355182cc158c9f98f4bd6e
Folly: b73c3869541e86821df3c387eb0af5f65addfab4 Folly: b73c3869541e86821df3c387eb0af5f65addfab4
glog: 40a13f7840415b9a77023fbcae0f1e6f43192af3 glog: 060ff9f5bfc2e5fc0ef1a3961cdf58307ce2086d
Keycard: dd96182888da0aacf4de821b641103143bbb26cc Keycard: dd96182888da0aacf4de821b641103143bbb26cc
Permission-Camera: afad27bf90337684d4a86f3825112d648c8c4d3b Permission-Camera: afad27bf90337684d4a86f3825112d648c8c4d3b
Permission-Microphone: 0ffabc3fe1c75cfb260525ee3f529383c9f4368c Permission-Microphone: 0ffabc3fe1c75cfb260525ee3f529383c9f4368c
@ -660,4 +660,4 @@ SPEC CHECKSUMS:
PODFILE CHECKSUM: 27b3929c4d7f0b5afd76276d0bd4ae289ec11f18 PODFILE CHECKSUM: 27b3929c4d7f0b5afd76276d0bd4ae289ec11f18
COCOAPODS: 1.10.0 COCOAPODS: 1.10.1

View File

@ -1481,5 +1481,23 @@ class StatusModule extends ReactContextBaseJavaModule implements LifecycleEventL
} }
}); });
} }
@ReactMethod
public void reEncryptDbAndKeyStore(final String keyUID, final String password, final String newPassword, final Callback callback) {
Log.d(TAG, "reEncryptDbAndKeyStore");
Runnable r = new Runnable() {
@Override
public void run() {
// changes db password and re-encrypts keystore
String result = Statusgo.changeDatabasePassword(keyUID, password, newPassword);
callback.invoke(result);
}
};
StatusThreadPoolExecutor.getInstance().execute(r);
}
} }

View File

@ -591,6 +591,19 @@ RCT_EXPORT_METHOD(verify:(NSString *)address
callback(@[result]); callback(@[result]);
} }
//////////////////////////////////////////////////////////////////// changeDatabasePassword
RCT_EXPORT_METHOD(reEncryptDbAndKeystore:(NSString *)keyUID
currentPassword:(NSString *)currentPassword
newPassword:(NSString *)newPassword
callback:(RCTResponseSenderBlock)callback) {
#if DEBUG
NSLog(@"reEncryptDbAndKeystore() method called");
#endif
// changes password and re-encrypts keystore
NSString *result = StatusgoChangeDatabasePassword(keyUID, currentPassword, newPassword);
callback(@[result]);
}
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
#pragma mark - SendTransaction #pragma mark - SendTransaction
//////////////////////////////////////////////////////////////////// sendTransaction //////////////////////////////////////////////////////////////////// sendTransaction

View File

@ -0,0 +1,85 @@
(ns status-im.multiaccounts.reset-password.core
(:require [re-frame.core :as re-frame]
[status-im.utils.fx :as fx]
[status-im.utils.types :as types]
[clojure.string :as string]
[status-im.utils.security :as security]
[status-im.popover.core :as popover]
[status-im.native-module.core :as status]
[status-im.ethereum.core :as ethereum]))
(fx/defn on-input-change
{:events [::handle-input-change]}
[{:keys [db]} input-id value]
(let [new-password (get-in db [:multiaccount/reset-password-form-vals :new-password])
error (when (and (= input-id :confirm-new-password)
(pos? (count new-password))
(pos? (count value))
(not= value new-password))
:t/password-mismatch)]
{:db (-> db
(assoc-in [:multiaccount/reset-password-form-vals input-id] value)
(assoc-in [:multiaccount/reset-password-errors input-id] error))}))
(fx/defn clear-form-vals
{:events [::clear-form-vals]}
[{:keys [db]}]
{:db (dissoc db :multiaccount/reset-password-form-vals :multiaccount/reset-password-errors)})
(fx/defn set-current-password-error
{:events [::handle-verification-error ::password-reset-error]}
[{:keys [db]} error]
{:db (assoc-in db [:multiaccount/reset-password-errors :current-password] error)})
(fx/defn password-reset-success
{:events [::password-reset-success]}
[{:keys [db] :as cofx}]
(fx/merge cofx
{:db (dissoc
db
:multiaccount/reset-password-form-vals
:multiaccount/reset-password-errors
:multiaccount/reset-password-next-enabled?)}
(popover/show-popover {:view :password-reset-success})))
(defn change-db-password-cb [res]
(let [{:keys [error]} (types/json->clj res)]
(if (not (string/blank? error))
(re-frame/dispatch [::password-reset-error error])
(re-frame/dispatch [::password-reset-success]))))
(re-frame/reg-fx
::change-db-password
(fn [[key-uid {:keys [current-password new-password]}]]
(status/reset-password
key-uid
(ethereum/sha3 (security/safe-unmask-data current-password))
(ethereum/sha3 (security/safe-unmask-data new-password))
change-db-password-cb)))
(fx/defn handle-verification-success
{:events [::handle-verification-success]}
[{:keys [db]} form-vals]
(let [{:keys [key-uid name]} (:multiaccount db)]
{::change-db-password [key-uid form-vals]}))
(defn handle-verification [form-vals result]
(let [{:keys [error]} (types/json->clj result)]
(if (not (string/blank? error))
(re-frame/dispatch [::handle-verification-error :t/wrong-password])
(re-frame/dispatch [::handle-verification-success form-vals]))))
(re-frame/reg-fx
::validate-current-password-and-reset
(fn [{:keys [address current-password] :as form-vals}]
(let [hashed-pass (ethereum/sha3 (security/safe-unmask-data current-password))]
(status/verify address hashed-pass
(partial handle-verification form-vals)))))
(fx/defn reset
{:events [::reset]}
[{:keys [db]} form-vals]
{::validate-current-password-and-reset
(assoc form-vals
:address
(get-in db [:multiaccount :wallet-root-address]))})

View File

@ -407,3 +407,11 @@
(log/debug "[native-module] resetKeyboardInput") (log/debug "[native-module] resetKeyboardInput")
(when platform/android? (when platform/android?
(.resetKeyboardInputCursor ^js (status) input selection))) (.resetKeyboardInputCursor ^js (status) input selection)))
;; passwords are hashed
(defn reset-password
[key-uid current-password# new-password# callback]
(log/debug "[native-module] change-database-password")
(init-keystore
key-uid
#(.reEncryptDbAndKeystore ^js (status) key-uid current-password# new-password# callback)))

View File

@ -98,6 +98,8 @@
(reg-root-key-sub :multiaccount/accounts :multiaccount/accounts) (reg-root-key-sub :multiaccount/accounts :multiaccount/accounts)
(reg-root-key-sub :get-recover-multiaccount :multiaccounts/recover) (reg-root-key-sub :get-recover-multiaccount :multiaccounts/recover)
(reg-root-key-sub :multiaccounts/key-storage :multiaccounts/key-storage) (reg-root-key-sub :multiaccounts/key-storage :multiaccounts/key-storage)
(reg-root-key-sub :multiaccount/reset-password-form-vals :multiaccount/reset-password-form-vals)
(reg-root-key-sub :multiaccount/reset-password-errors :multiaccount/reset-password-errors)
;;chat ;;chat
(reg-root-key-sub ::cooldown-enabled? :chat/cooldown-enabled?) (reg-root-key-sub ::cooldown-enabled? :chat/cooldown-enabled?)
@ -2614,3 +2616,20 @@
(and (and
(= network-type "cellular") (= network-type "cellular")
syncing-on-mobile-network?)))) syncing-on-mobile-network?))))
;; RESET PASSWORD
(re-frame/reg-sub
:multiaccount/reset-password-form-vals-and-errors
:<- [:multiaccount/reset-password-form-vals]
:<- [:multiaccount/reset-password-errors]
(fn [[form-vals errors]]
(let [{:keys [current-password new-password confirm-new-password]} form-vals]
{:form-vals form-vals
:errors errors
:next-enabled?
(and (pos? (count current-password))
(pos? (count new-password))
(pos? (count confirm-new-password))
(>= (count new-password) 6)
(>= (count current-password) 6)
(= new-password confirm-new-password))})))

View File

@ -11,6 +11,7 @@
[status-im.ui.screens.profile.user.views :as profile.user] [status-im.ui.screens.profile.user.views :as profile.user]
["react-native" :refer (BackHandler)] ["react-native" :refer (BackHandler)]
[status-im.ui.components.invite.advertiser :as advertiser.invite] [status-im.ui.components.invite.advertiser :as advertiser.invite]
[status-im.ui.screens.reset-password.views :as reset-password.views]
[status-im.ui.components.invite.dapp :as dapp.invite] [status-im.ui.components.invite.dapp :as dapp.invite]
[status-im.ui.screens.multiaccounts.recover.views :as multiaccounts.recover] [status-im.ui.screens.multiaccounts.recover.views :as multiaccounts.recover]
[status-im.ui.screens.multiaccounts.key-storage.views :as multiaccounts.key-storage] [status-im.ui.screens.multiaccounts.key-storage.views :as multiaccounts.key-storage]
@ -169,6 +170,9 @@
(= :transfer-multiaccount-unknown-error view) (= :transfer-multiaccount-unknown-error view)
[multiaccounts.key-storage/unknown-error-popover] [multiaccounts.key-storage/unknown-error-popover]
(= :password-reset-success view)
[reset-password.views/reset-success-popover]
:else :else
[view])]]]]])))}))) [view])]]]]])))})))

View File

@ -2,6 +2,7 @@
(:require [re-frame.core :as re-frame] (:require [re-frame.core :as re-frame]
[status-im.i18n.i18n :as i18n] [status-im.i18n.i18n :as i18n]
[quo.core :as quo] [quo.core :as quo]
[status-im.multiaccounts.reset-password.core :as reset-password]
[status-im.ui.components.common.common :as components.common] [status-im.ui.components.common.common :as components.common]
[status-im.ui.components.react :as react] [status-im.ui.components.react :as react]
[status-im.utils.config :as config] [status-im.utils.config :as config]
@ -38,14 +39,6 @@
:on-press #(re-frame/dispatch [:multiaccounts.ui/biometric-auth-switched :on-press #(re-frame/dispatch [:multiaccounts.ui/biometric-auth-switched
((complement boolean) (= auth-method "biometric"))])}]) ((complement boolean) (= auth-method "biometric"))])}])
[separator] [separator]
;; TODO - uncomment when implemented
;; {:size :small
;; :title (i18n/label :t/change-password)
;; :chevron true}
;; {:size :small
;; :title (i18n/label :t/change-passcode)
;; :chevron true}
[quo/list-header (i18n/label :t/privacy)] [quo/list-header (i18n/label :t/privacy)]
[quo/list-item {:size :small [quo/list-item {:size :small
:title (i18n/label :t/set-dapp-access-permissions) :title (i18n/label :t/set-dapp-access-permissions)
@ -76,6 +69,15 @@
:t/anyone)) :t/anyone))
:on-press #(re-frame/dispatch [:navigate-to :messages-from-contacts-only]) :on-press #(re-frame/dispatch [:navigate-to :messages-from-contacts-only])
:accessibility-label :accept-new-chats-from}] :accessibility-label :accept-new-chats-from}]
(when config/reset-password-enabled?
[quo/list-item {:size :small
:title (i18n/label :t/reset-password)
:chevron true
:accessory :text
:on-press #(do
(re-frame/dispatch [::reset-password/clear-form-vals])
(re-frame/dispatch [:navigate-to :reset-password]))
:accessibility-label :reset-password}])
(when config/metrics-enabled? (when config/metrics-enabled?
[quo/list-item {:size :small [quo/list-item {:size :small
:title (i18n/label :t/anonymous-usage-data) :title (i18n/label :t/anonymous-usage-data)

View File

@ -0,0 +1,78 @@
(ns status-im.ui.screens.reset-password.views
(:require [re-frame.core :as re-frame]
[status-im.i18n.i18n :as i18n]
[quo.core :as quo]
[status-im.ui.components.react :as react]
[status-im.ui.components.colors :as colors]
[status-im.ui.components.icons.icons :as icons]
[status-im.multiaccounts.reset-password.core :as reset-password]
[status-im.utils.security :as security]
[status-im.ui.components.toolbar :as toolbar])
(:require-macros [status-im.utils.views :refer [defview letsubs]]))
(defn input-field
([id errors on-submit] (input-field id errors on-submit false))
([id errors on-submit focus?]
[quo/text-input
{:placeholder (i18n/label id)
:default-value ""
:auto-focus focus?
:accessibility-label id
:show-cancel false
:style {:margin-bottom 32}
:on-submit-editing on-submit
:on-change-text #(re-frame/dispatch [::reset-password/handle-input-change
id
(security/mask-data %)])
:secure-text-entry true
:error (when-let [error (get errors id)]
(if (keyword? error)
(i18n/label error)
error))}]))
(defview reset-password []
(letsubs [{:keys [form-vals errors next-enabled?]}
[:multiaccount/reset-password-form-vals-and-errors]]
(let [on-submit #(re-frame/dispatch [::reset-password/reset form-vals])]
[react/keyboard-avoiding-view {:flex 1}
[react/view {:style {:flex 1
:justify-content :space-between}}
[react/view {:style {:padding-horizontal 16
:padding-vertical 16}}
[input-field :current-password errors on-submit true]
[input-field :new-password errors on-submit]
[input-field :confirm-new-password errors on-submit]]
[quo/text {:color :secondary :align :center :size :small
:style {:padding-horizontal 16}}
(i18n/label :t/password-description)]
[toolbar/toolbar
{:show-border? true
:right
[quo/button
{:on-press on-submit
:accessibility-label :next-button
:disabled (not next-enabled?)
:type :secondary
:after :main-icons/next}
(i18n/label :t/next)]}]]])))
(defview reset-success-popover []
[react/view {:padding-vertical 24
:padding-horizontal 48
:align-items :center}
[react/view {:width 32
:height 32
:background-color colors/green-transparent-10
:border-radius 32
:align-items :center
:justify-content :center}
[icons/icon :main-icons/check {:color colors/green}]]
[quo/text {:size :x-large
:weight :bold
:style {:typography :title-bold
:margin-top 16
:margin-bottom 24}}
(i18n/label :t/password-reset-success)]
[react/view {:align-items :center}
[quo/button {:on-press #(re-frame/dispatch [:hide-popover])}
(i18n/label :t/ok-got-it)]]])

View File

@ -85,6 +85,7 @@
[status-im.ui.screens.mobile-network-settings.view [status-im.ui.screens.mobile-network-settings.view
:as :as
mobile-network-settings] mobile-network-settings]
[status-im.ui.screens.reset-password.views :as reset-password]
[status-im.ui.screens.network.edit-network.views :as edit-network] [status-im.ui.screens.network.edit-network.views :as edit-network]
[status-im.ui.screens.network.views :as network] [status-im.ui.screens.network.views :as network]
[status-im.ui.screens.network.network-details.views :as network-details] [status-im.ui.screens.network.network-details.views :as network-details]
@ -233,40 +234,40 @@
:component notifications-center/center} :component notifications-center/center}
;; Community ;; Community
{:name :community {:name :community
;TODO custom ;;TODO custom
:options {:topBar {:visible false}} :options {:topBar {:visible false}}
:component community/community} :component community/community}
{:name :community-management {:name :community-management
:insets {:top false} :insets {:top false}
;TODO animated-header ;;TODO animated-header
:options {:topBar {:visible false}} :options {:topBar {:visible false}}
:component community.profile/management-container} :component community.profile/management-container}
{:name :community-members {:name :community-members
;TODO custom subtitle ;;TODO custom subtitle
:options {:topBar {:visible false}} :options {:topBar {:visible false}}
:component members/members-container} :component members/members-container}
{:name :community-requests-to-join {:name :community-requests-to-join
;TODO custom subtitle ;;TODO custom subtitle
:options {:topBar {:visible false}} :options {:topBar {:visible false}}
:component requests-to-join/requests-to-join-container} :component requests-to-join/requests-to-join-container}
{:name :create-community-channel {:name :create-community-channel
;TODO custom ;;TODO custom
:options {:topBar {:visible false}} :options {:topBar {:visible false}}
:component create-channel/view} :component create-channel/view}
{:name :community-channel-details {:name :community-channel-details
;TODO custom ;;TODO custom
:options {:topBar {:visible false}} :options {:topBar {:visible false}}
:component communities.channel-details/view} :component communities.channel-details/view}
{:name :edit-community-channel {:name :edit-community-channel
:insets {:bottom true} :insets {:bottom true}
:component edit-channel/view} :component edit-channel/view}
{:name :contact-toggle-list {:name :contact-toggle-list
;TODO custom subtitle ;;TODO custom subtitle
:options {:topBar {:visible false}} :options {:topBar {:visible false}}
:component group-chat/contact-toggle-list} :component group-chat/contact-toggle-list}
{:name :new-group {:name :new-group
:options {:topBar {:visible false}} :options {:topBar {:visible false}}
;TODO custom subtitle ;;TODO custom subtitle
:component group-chat/new-group} :component group-chat/new-group}
{:name :referral-enclav {:name :referral-enclav
;;TODO custom content ;;TODO custom content
@ -478,6 +479,9 @@
;;TODO dynamic navigation ;;TODO dynamic navigation
:options {:topBar {:visible false}} :options {:topBar {:visible false}}
:component profile.seed/backup-seed} :component profile.seed/backup-seed}
{:name :reset-password
:options {:topBar {:title {:text (i18n/label :t/reset-password)}}}
:component reset-password/reset-password}
{:name :delete-profile {:name :delete-profile
:insets {:bottom true} :insets {:bottom true}
:component delete-profile/delete-profile} :component delete-profile/delete-profile}

View File

@ -49,6 +49,7 @@
(def database-management-enabled? (enabled? (get-config :DATABASE_MANAGEMENT_ENABLED "0"))) (def database-management-enabled? (enabled? (get-config :DATABASE_MANAGEMENT_ENABLED "0")))
(def debug-webview? (enabled? (get-config :DEBUG_WEBVIEW "0"))) (def debug-webview? (enabled? (get-config :DEBUG_WEBVIEW "0")))
(def metrics-enabled? (enabled? (get-config :METRICS_ENABLED "0"))) (def metrics-enabled? (enabled? (get-config :METRICS_ENABLED "0")))
(def reset-password-enabled? (enabled? (get-config :RESET_PASSWORD_ENABLED "0")))
;; CONFIG VALUES ;; CONFIG VALUES
(def log-level (def log-level

View File

@ -2,7 +2,7 @@
"_comment": "DO NOT EDIT THIS FILE BY HAND. USE 'scripts/update-status-go.sh <tag>' instead", "_comment": "DO NOT EDIT THIS FILE BY HAND. USE 'scripts/update-status-go.sh <tag>' instead",
"owner": "status-im", "owner": "status-im",
"repo": "status-go", "repo": "status-go",
"version": "v0.79.11", "version": "v0.80.00",
"commit-sha1": "b395144704f29c9e1f4fd11714d1031a10160ad1", "commit-sha1": "659ca28974d9fca08091c20c1aa4cac34e5e5f81",
"src-sha256": "13yzac5n7w7hzispphm6g5xhw6r62qxg2hvzcrcl9jpwy0frvzi2" "src-sha256": "10xjfzdyayq8iw99wpr488r1l6la4zxdnmljv6pkrkkyghhf6wba"
} }

View File

@ -1570,5 +1570,12 @@
"no-thanks": "No thanks", "no-thanks": "No thanks",
"help-improve-status": "Help improve Status", "help-improve-status": "Help improve Status",
"thank-you": "Thank you", "thank-you": "Thank you",
"count-metrics-collected": "{{count}} metrics collected" "count-metrics-collected": "{{count}} metrics collected",
"bip39-password-placeholder": "BIP39 password",
"current-password": "Current password",
"reset-password": "Reset password",
"password-reset-success": "Password reset",
"new-password": "New password",
"confirm-new-password": "Confirm new password",
"password-mismatch": "New password and confirmation does not match"
} }