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:
parent
ab01093a6e
commit
dea7227c29
1
.env
1
.env
|
@ -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
|
|
2
.env.e2e
2
.env.e2e
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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() {
|
||||||
|
|
|
@ -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)]
|
||||||
|
|
|
@ -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))
|
||||||
|
|
|
@ -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)]]])
|
||||||
|
|
|
@ -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]
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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)]]]))
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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",
|
||||||
|
|
Loading…
Reference in New Issue