Enabled password reset UI

Fix function typo that caused android version to fail
Fix Issue 1 pointed out by Tetiana. Implement new UI to accomodate slow progress on Android
Fix QA Issue 3 - Hide reset password option for keycard accounts
Add steps to password reset
Align the checkbox on terms of use
Make modal rext align center because it wrapped abruptly
Logout user after password reset
Disable next button to curb recklessness
Remove reset password feature flag

Signed-off-by: Shivek Khurana <shivek@status.im>
This commit is contained in:
Shivek Khurana 2021-06-24 13:50:52 +05:30
parent ab01093a6e
commit dea7227c29
No known key found for this signature in database
GPG Key ID: 9BEB56E6E62968C7
13 changed files with 107 additions and 57 deletions

1
.env
View File

@ -29,4 +29,3 @@ 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

@ -29,4 +29,4 @@ VERIFY_TRANSACTION_CHAIN_ID=3
DATABASE_MANAGEMENT_ENABLED=1 DATABASE_MANAGEMENT_ENABLED=1
COMMUNITIES_ENABLED=1 COMMUNITIES_ENABLED=1
COMMUNITIES_MANAGEMENT_ENABLED=1 COMMUNITIES_MANAGEMENT_ENABLED=1
METRICS_ENABLED=0 METRICS_ENABLED=0

View File

@ -29,4 +29,4 @@ GOOGLE_FREE=0
DATABASE_MANAGEMENT_ENABLED=1 DATABASE_MANAGEMENT_ENABLED=1
COMMUNITIES_ENABLED=1 COMMUNITIES_ENABLED=1
COMMUNITIES_MANAGEMENT_ENABLED=1 COMMUNITIES_MANAGEMENT_ENABLED=1
METRICS_ENABLED=0 METRICS_ENABLED=0

View File

@ -18,4 +18,4 @@ PARTITIONED_TOPIC=0
ENABLE_ROOT_ALERT=1 ENABLE_ROOT_ALERT=1
MAX_IMAGES_BATCH=1 MAX_IMAGES_BATCH=1
ENABLE_REFERRAL_INVITE=0 ENABLE_REFERRAL_INVITE=0
METRICS_ENABLED=0 METRICS_ENABLED=0

View File

@ -1504,7 +1504,7 @@ class StatusModule extends ReactContextBaseJavaModule implements LifecycleEventL
} }
@ReactMethod @ReactMethod
public void reEncryptDbAndKeyStore(final String keyUID, final String password, final String newPassword, final Callback callback) { public void reEncryptDbAndKeystore(final String keyUID, final String password, final String newPassword, final Callback callback) {
Log.d(TAG, "reEncryptDbAndKeyStore"); Log.d(TAG, "reEncryptDbAndKeyStore");
Runnable r = new Runnable() { Runnable r = new Runnable() {

View File

@ -4,6 +4,7 @@
[status-im.utils.types :as types] [status-im.utils.types :as types]
[clojure.string :as string] [clojure.string :as string]
[status-im.utils.security :as security] [status-im.utils.security :as security]
[status-im.utils.keychain.core :as keychain]
[status-im.popover.core :as popover] [status-im.popover.core :as popover]
[status-im.native-module.core :as status] [status-im.native-module.core :as status]
[status-im.ethereum.core :as ethereum])) [status-im.ethereum.core :as ethereum]))
@ -34,13 +35,19 @@
(fx/defn password-reset-success (fx/defn password-reset-success
{:events [::password-reset-success]} {:events [::password-reset-success]}
[{:keys [db] :as cofx}] [{:keys [db] :as cofx}]
(fx/merge cofx (let [{:keys [key-uid]} (:multiaccount db)
{:db (dissoc auth-method (get db :auth-method keychain/auth-method-none)
db new-password (get-in db [:multiaccount/reset-password-form-vals :new-password])]
:multiaccount/reset-password-form-vals (fx/merge cofx
:multiaccount/reset-password-errors {:db (dissoc
:multiaccount/reset-password-next-enabled?)} db
(popover/show-popover {:view :password-reset-success}))) :multiaccount/reset-password-form-vals
:multiaccount/reset-password-errors
:multiaccount/reset-password-next-enabled?
:multiaccount/resetting-password?)}
;; update password in keychain if biometrics are enabled
(when (= auth-method keychain/auth-method-biometric)
(keychain/save-user-password key-uid new-password)))))
(defn change-db-password-cb [res] (defn change-db-password-cb [res]
(let [{:keys [error]} (types/json->clj res)] (let [{:keys [error]} (types/json->clj res)]
@ -59,9 +66,14 @@
(fx/defn handle-verification-success (fx/defn handle-verification-success
{:events [::handle-verification-success]} {:events [::handle-verification-success]}
[{:keys [db]} form-vals] [{:keys [db] :as cofx} form-vals]
(let [{:keys [key-uid name]} (:multiaccount db)] (let [{:keys [key-uid name]} (:multiaccount db)]
{::change-db-password [key-uid form-vals]})) (fx/merge cofx
{::change-db-password [key-uid form-vals]
:db (assoc db
:multiaccount/resetting-password? true)}
(popover/show-popover {:view :password-reset-popover
:prevent-closing? true}))))
(defn handle-verification [form-vals result] (defn handle-verification [form-vals result]
(let [{:keys [error]} (types/json->clj result)] (let [{:keys [error]} (types/json->clj result)]

View File

@ -100,6 +100,7 @@
(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-form-vals :multiaccount/reset-password-form-vals)
(reg-root-key-sub :multiaccount/reset-password-errors :multiaccount/reset-password-errors) (reg-root-key-sub :multiaccount/reset-password-errors :multiaccount/reset-password-errors)
(reg-root-key-sub :multiaccount/resetting-password? :multiaccount/resetting-password?)
;;chat ;;chat
(reg-root-key-sub ::cooldown-enabled? :chat/cooldown-enabled?) (reg-root-key-sub ::cooldown-enabled? :chat/cooldown-enabled?)
@ -2707,10 +2708,12 @@
:multiaccount/reset-password-form-vals-and-errors :multiaccount/reset-password-form-vals-and-errors
:<- [:multiaccount/reset-password-form-vals] :<- [:multiaccount/reset-password-form-vals]
:<- [:multiaccount/reset-password-errors] :<- [:multiaccount/reset-password-errors]
(fn [[form-vals errors]] :<- [:multiaccount/resetting-password?]
(fn [[form-vals errors resetting?]]
(let [{:keys [current-password new-password confirm-new-password]} form-vals] (let [{:keys [current-password new-password confirm-new-password]} form-vals]
{:form-vals form-vals {:form-vals form-vals
:errors errors :errors errors
:resetting? resetting?
:next-enabled? :next-enabled?
(and (pos? (count current-password)) (and (pos? (count current-password))
(pos? (count new-password)) (pos? (count new-password))

View File

@ -152,6 +152,7 @@
[react/view {:style {:align-items :center}} [react/view {:style {:align-items :center}}
[react/view {:flex-direction :row [react/view {:flex-direction :row
:justify-content :space-between :justify-content :space-between
:align-items :center
:margin-top 36 :margin-top 36
:margin-bottom 24} :margin-bottom 24}
[quo/checkbox {:value @tos-accepted [quo/checkbox {:value @tos-accepted
@ -159,9 +160,9 @@
[rn/touchable-opacity {:on-press #(swap! tos-accepted not)} [rn/touchable-opacity {:on-press #(swap! tos-accepted not)}
[react/nested-text {:style {:margin-left 12}} [react/nested-text {:style {:margin-left 12}}
(i18n/label :t/accept-status-tos-prefix) (i18n/label :t/accept-status-tos-prefix)
[{:style (merge {:color colors/blue} [{:style (merge {:color colors/blue}
typography/font-medium) typography/font-medium)
:on-press #(re-frame/dispatch [:open-modal :terms-of-service]) :on-press #(re-frame/dispatch [:open-modal :terms-of-service])
:accessibility-label :terms-of-service-link} :accessibility-label :terms-of-service-link}
" " " "
(i18n/label :t/terms-of-service)]]]] (i18n/label :t/terms-of-service)]]]]
@ -173,7 +174,7 @@
(re-frame/dispatch [:hide-terms-of-services-opt-in-screen]))} (re-frame/dispatch [:hide-terms-of-services-opt-in-screen]))}
(i18n/label :t/get-started)]] (i18n/label :t/get-started)]]
[react/text [react/text
{:style {:color colors/blue} {:style {:color colors/blue}
:on-press #(re-frame/dispatch [:open-modal :privacy-policy]) :on-press #(re-frame/dispatch [:open-modal :privacy-policy])
:accessibility-label :privacy-policy-link} :accessibility-label :privacy-policy-link}
(i18n/label :t/privacy-policy)]]]) (i18n/label :t/privacy-policy)]]])

View File

@ -171,8 +171,8 @@
(= :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) (= :password-reset-popover view)
[reset-password.views/reset-success-popover] [reset-password.views/reset-password-popover]
(= :pin-limit view) (= :pin-limit view)
[pinned-message/pin-limit-popover] [pinned-message/pin-limit-popover]

View File

@ -19,6 +19,7 @@
messages-from-contacts-only messages-from-contacts-only
webview-allow-permission-requests?]} [:multiaccount] webview-allow-permission-requests?]} [:multiaccount]
supported-biometric-auth [:supported-biometric-auth] supported-biometric-auth [:supported-biometric-auth]
keycard? [:keycard-multiaccount?]
auth-method [:auth-method]] auth-method [:auth-method]]
[react/scroll-view {:padding-vertical 8} [react/scroll-view {:padding-vertical 8}
[quo/list-header (i18n/label :t/security)] [quo/list-header (i18n/label :t/security)]
@ -69,7 +70,7 @@
: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? (when (not keycard?)
[quo/list-item {:size :small [quo/list-item {:size :small
:title (i18n/label :t/reset-password) :title (i18n/label :t/reset-password)
:chevron true :chevron true

View File

@ -11,12 +11,14 @@
(:require-macros [status-im.utils.views :refer [defview letsubs]])) (:require-macros [status-im.utils.views :refer [defview letsubs]]))
(defn input-field (defn input-field
([id errors on-submit] (input-field id errors on-submit false)) [{:keys [id errors on-submit disabled? focus?]
([id errors on-submit focus?] :or {disabled? false focus? false}}]
[react/view {:style {:opacity (if disabled? 0.33 1)}}
[quo/text-input [quo/text-input
{:placeholder (i18n/label id) {:placeholder (i18n/label id)
:default-value "" :default-value ""
:auto-focus focus? :auto-focus focus?
:editable (not disabled?)
:accessibility-label id :accessibility-label id
:show-cancel false :show-cancel false
:style {:margin-bottom 32} :style {:margin-bottom 32}
@ -28,20 +30,33 @@
:error (when-let [error (get errors id)] :error (when-let [error (get errors id)]
(if (keyword? error) (if (keyword? error)
(i18n/label error) (i18n/label error)
error))}])) error))}]])
(defview reset-password [] (defview reset-password []
(letsubs [{:keys [form-vals errors next-enabled?]} (letsubs [{:keys [form-vals errors next-enabled? resetting?]}
[:multiaccount/reset-password-form-vals-and-errors]] [:multiaccount/reset-password-form-vals-and-errors]]
(let [on-submit #(re-frame/dispatch [::reset-password/reset form-vals])] (let [{:keys [current-password
new-password]} form-vals
on-submit #(re-frame/dispatch [::reset-password/reset form-vals])]
[react/keyboard-avoiding-view {:flex 1} [react/keyboard-avoiding-view {:flex 1}
[react/view {:style {:flex 1 [react/view {:style {:flex 1
:justify-content :space-between}} :justify-content :space-between}}
[react/view {:style {:padding-horizontal 16 [react/view {:style {:margin-top 32
:padding-horizontal 16
:padding-vertical 16}} :padding-vertical 16}}
[input-field :current-password errors on-submit true] [input-field {:id :current-password
[input-field :new-password errors on-submit] :errors errors
[input-field :confirm-new-password errors on-submit]] :on-sumbit on-submit
:disabled? false
:focus? true}]
[input-field {:id :new-password
:errors errors
:on-sumbit on-submit
:disabled? (zero? (count current-password))}]
[input-field {:id :confirm-new-password
:errors errors
:on-sumbit on-submit
:disabled? (zero? (count new-password))}]]
[quo/text {:color :secondary :align :center :size :small [quo/text {:color :secondary :align :center :size :small
:style {:padding-horizontal 16}} :style {:padding-horizontal 16}}
(i18n/label :t/password-description)] (i18n/label :t/password-description)]
@ -51,28 +66,46 @@
[quo/button [quo/button
{:on-press on-submit {:on-press on-submit
:accessibility-label :next-button :accessibility-label :next-button
:disabled (not next-enabled?) :disabled (or (not next-enabled?)
;; disable on resetting? so the user cannot press the next button recklessly
;; https://github.com/status-im/status-react/pull/12245#issuecomment-874827573
resetting?)
:type :secondary :type :secondary
:after :main-icons/next} :after :main-icons/next}
(i18n/label :t/next)]}]]]))) (i18n/label :t/next)]}]]])))
(defview reset-success-popover [] (defview reset-password-popover []
[react/view {:padding-vertical 24 (letsubs [{:keys [resetting?]} [:multiaccount/reset-password-form-vals-and-errors]]
:padding-horizontal 48 [react/view {:padding-vertical 24
:align-items :center} :padding-horizontal 48
[react/view {:width 32 :align-items :center}
:height 32 [react/view {:width 32
:background-color colors/green-transparent-10 :height 32
:border-radius 32 :background-color (if resetting?
:align-items :center colors/gray-lighter
:justify-content :center} colors/green-transparent-10)
[icons/icon :main-icons/check {:color colors/green}]] :border-radius 32
[quo/text {:size :x-large :align-items :center
:weight :bold :justify-content :center}
:style {:typography :title-bold (if resetting?
:margin-top 16 [react/activity-indicator {:size :small
:margin-bottom 24}} :animating true}]
(i18n/label :t/password-reset-success)] [icons/icon :main-icons/check {:color colors/green}])]
[react/view {:align-items :center} [quo/text {:size :x-large
[quo/button {:on-press #(re-frame/dispatch [:hide-popover])} :weight :bold
(i18n/label :t/ok-got-it)]]]) :align :center
:style {:typography :title-bold
:margin-top 16
:margin-bottom 24}}
(i18n/label (if resetting?
:t/password-reset-in-progress
:t/password-reset-success))]
(when-not resetting?
[quo/text {:align :center
:color :secondary
:style {:margin-bottom 24}}
(i18n/label :t/password-reset-success-message)])
[react/view {:align-items :center}
[quo/button {:on-press #(re-frame/dispatch [:logout])
:disabled resetting?}
(i18n/label :t/okay)]]]))

View File

@ -49,7 +49,6 @@
(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

@ -1577,7 +1577,9 @@
"bip39-password-placeholder": "BIP39 password", "bip39-password-placeholder": "BIP39 password",
"current-password": "Current password", "current-password": "Current password",
"reset-password": "Reset password", "reset-password": "Reset password",
"password-reset-success": "Password reset", "password-reset-success": "Password changed",
"password-reset-success-message": "You will need to sign in again",
"password-reset-in-progress": "Changing password...",
"new-password": "New password", "new-password": "New password",
"confirm-new-password": "Confirm new password", "confirm-new-password": "Confirm new password",
"password-mismatch": "New password and confirmation does not match", "password-mismatch": "New password and confirmation does not match",