add creation of backup keycards

Signed-off-by: Michele Balistreri <michele@bitgamma.com>
This commit is contained in:
Michele Balistreri 2021-03-25 16:39:13 +03:00
parent be0ad943ea
commit f0827ff624
No known key found for this signature in database
GPG Key ID: E9567DA33A4F791A
8 changed files with 113 additions and 24 deletions

View File

@ -0,0 +1,40 @@
(ns status-im.keycard.backup-key
(:require [status-im.utils.fx :as fx]
[status-im.ethereum.mnemonic :as mnemonic]
[status-im.multiaccounts.recover.core :as multiaccounts.recover]
[status-im.navigation :as navigation]
[taoensso.timbre :as log]))
(fx/defn backup-card-pressed
{:events [:keycard-settings.ui/backup-card-pressed]}
[{:keys [db] :as cofx}]
(log/debug "[keycard] start backup")
(fx/merge cofx
{:db (-> db
(assoc-in [:keycard :creating-backup?] true))}
(navigation/navigate-to-cofx :seed-phrase nil)))
(fx/defn start-keycard-backup
{:events [::start-keycard-backup]}
[{:keys [db] :as cofx}]
{::multiaccounts.recover/import-multiaccount {:passphrase (-> db
:multiaccounts/key-storage
:seed-phrase
mnemonic/sanitize-passphrase)
:password nil
:success-event ::create-backup-card}})
(fx/defn create-backup-card
{:events [::create-backup-card]}
[{:keys [db] :as cofx} root-data derived-data]
(fx/merge cofx
{:db (-> db
(update :intro-wizard
assoc
:root-key root-data
:derived derived-data
:recovering? true
:selected-storage-type :advanced)
(assoc-in [:keycard :flow] :recovery)
(update :multiaccounts/key-storage dissoc :seed-phrase))
:dismiss-keyboard nil}
(navigation/navigate-to-cofx :keycard-onboarding-intro nil)))

View File

@ -5,6 +5,7 @@
status-im.keycard.delete-key status-im.keycard.delete-key
status-im.keycard.export-key status-im.keycard.export-key
status-im.keycard.unpair status-im.keycard.unpair
status-im.keycard.backup-key
[status-im.keycard.login :as login] [status-im.keycard.login :as login]
[status-im.keycard.mnemonic :as mnemonic] [status-im.keycard.mnemonic :as mnemonic]
[status-im.keycard.onboarding :as onboarding] [status-im.keycard.onboarding :as onboarding]
@ -65,8 +66,9 @@
"instance-uid" instance-uid) "instance-uid" instance-uid)
(if (= flow :import) (if (= flow :import)
(navigation/navigate-to-cofx cofx :keycard-recovery-no-key nil) (navigation/navigate-to-cofx cofx :keycard-recovery-no-key nil)
(let [pairing-data (get-in db [:keycard :pairings instance-uid])] (let [pairing-data (get-in db [:keycard :pairings (keyword instance-uid)])
(if pairing-data paired? (get-in db [:keycard :application-info :paired?])]
(if paired?
(fx/merge cofx (fx/merge cofx
{:db (update-in db [:keycard :secrets] merge pairing-data)} {:db (update-in db [:keycard :secrets] merge pairing-data)}
(common/listen-to-hardware-back-button) (common/listen-to-hardware-back-button)

View File

@ -197,12 +197,20 @@
(navigation/navigate-to-cofx (if platform/android? (navigation/navigate-to-cofx (if platform/android?
:notifications-settings :welcome) nil)))))) :notifications-settings :welcome) nil))))))
(fx/defn on-backup-success
[{:keys [db] :as cofx}]
(fx/merge cofx
{:utils/show-popup {:title (i18n/label :t/keycard-backup-success-title)
:content (i18n/label :t/keycard-backup-success-body)}}
(navigation/navigate-to-cofx :keycard-settings nil)))
(fx/defn on-generate-and-load-key-success (fx/defn on-generate-and-load-key-success
{:events [:keycard.callback/on-generate-and-load-key-success] {:events [:keycard.callback/on-generate-and-load-key-success]
:interceptors [(re-frame/inject-cofx :random-guid-generator) :interceptors [(re-frame/inject-cofx :random-guid-generator)
(re-frame/inject-cofx ::multiaccounts.create/get-signing-phrase)]} (re-frame/inject-cofx ::multiaccounts.create/get-signing-phrase)]}
[{:keys [db random-guid-generator] :as cofx} data] [{:keys [db random-guid-generator] :as cofx} data]
(let [account-data (js->clj data :keywordize-keys true)] (let [account-data (js->clj data :keywordize-keys true)
backup? (get-in db [:keycard :creating-backup?])]
(fx/merge cofx (fx/merge cofx
{:db (-> db {:db (-> db
(assoc-in [:keycard :multiaccount] (assoc-in [:keycard :multiaccount]
@ -222,12 +230,13 @@
(assoc-in [:keycard :application-info :key-uid] (assoc-in [:keycard :application-info :key-uid]
(ethereum/normalized-hex (:key-uid account-data))) (ethereum/normalized-hex (:key-uid account-data)))
(update :keycard dissoc :recovery-phrase) (update :keycard dissoc :recovery-phrase)
(update :keycard dissoc :creating-backup?)
(update-in [:keycard :secrets] dissoc :pin :puk :password) (update-in [:keycard :secrets] dissoc :pin :puk :password)
(assoc :multiaccounts/new-installation-id (random-guid-generator)) (assoc :multiaccounts/new-installation-id (random-guid-generator))
(update-in [:keycard :secrets] dissoc :mnemonic))} (update-in [:keycard :secrets] dissoc :mnemonic))}
(common/remove-listener-to-hardware-back-button) (common/remove-listener-to-hardware-back-button)
(common/hide-connection-sheet) (common/hide-connection-sheet)
(create-keycard-multiaccount)))) (if backup? (on-backup-success) (create-keycard-multiaccount)))))
(fx/defn on-generate-and-load-key-error (fx/defn on-generate-and-load-key-error
{:events [:keycard.callback/on-generate-and-load-key-error]} {:events [:keycard.callback/on-generate-and-load-key-error]}

View File

@ -10,7 +10,8 @@
[status-im.popover.core :as popover] [status-im.popover.core :as popover]
[status-im.utils.fx :as fx] [status-im.utils.fx :as fx]
[status-im.utils.security :as security] [status-im.utils.security :as security]
[status-im.utils.types :as types])) [status-im.utils.types :as types]
[status-im.keycard.backup-key :as keycard.backup]))
(fx/defn key-and-storage-management-pressed (fx/defn key-and-storage-management-pressed
"This event can be dispatched before login and from profile and needs to redirect accordingly" "This event can be dispatched before login and from profile and needs to redirect accordingly"
@ -53,6 +54,14 @@
[cofx _] [cofx _]
(popover/show-popover cofx {:view :seed-key-uid-mismatch})) (popover/show-popover cofx {:view :seed-key-uid-mismatch}))
(fx/defn key-uid-matches
{:events [::key-uid-matches]}
[{:keys [db] :as cofx} _]
(let [backup? (get-in db [:keycard :creating-backup?])]
(if backup?
(keycard.backup/start-keycard-backup cofx)
(navigation/navigate-to-cofx cofx :storage nil))))
(defn validate-seed-against-key-uid (defn validate-seed-against-key-uid
"Check if the key-uid was generated with the given seed-phrase" "Check if the key-uid was generated with the given seed-phrase"
[{:keys [import-mnemonic-fn on-success on-error]} {:keys [seed-phrase key-uid]}] [{:keys [import-mnemonic-fn on-success on-error]} {:keys [seed-phrase key-uid]}]
@ -70,7 +79,7 @@
::validate-seed-against-key-uid ::validate-seed-against-key-uid
(partial validate-seed-against-key-uid (partial validate-seed-against-key-uid
{:import-mnemonic-fn native-module/multiaccount-import-mnemonic {:import-mnemonic-fn native-module/multiaccount-import-mnemonic
:on-success #(re-frame/dispatch [:navigate-to :storage]) :on-success #(re-frame/dispatch [::key-uid-matches])
:on-error #(re-frame/dispatch [::show-seed-key-uid-mismatch-error-popup])})) :on-error #(re-frame/dispatch [::show-seed-key-uid-mismatch-error-popup])}))
(fx/defn seed-phrase-validated (fx/defn seed-phrase-validated
@ -85,7 +94,7 @@
(popover/show-popover cofx {:view :custom-seed-phrase}) (popover/show-popover cofx {:view :custom-seed-phrase})
{::validate-seed-against-key-uid {:seed-phrase (-> db :multiaccounts/key-storage :seed-phrase) {::validate-seed-against-key-uid {:seed-phrase (-> db :multiaccounts/key-storage :seed-phrase)
;; Unique key-uid of the account for which we are going to move keys ;; Unique key-uid of the account for which we are going to move keys
:key-uid (-> db :multiaccounts/login :key-uid)}}))) :key-uid (or (-> db :multiaccounts/login :key-uid) (-> db :multiaccount :key-uid))}})))
(fx/defn choose-storage-pressed (fx/defn choose-storage-pressed
{:events [::choose-storage-pressed]} {:events [::choose-storage-pressed]}

View File

@ -95,19 +95,15 @@
:on-press #(re-frame/dispatch [:keycard-settings.ui/change-pin-pressed])}] :on-press #(re-frame/dispatch [:keycard-settings.ui/change-pin-pressed])}]
;; TODO(rasom): uncomment this when unpairing will be enabled ;; TODO(rasom): uncomment this when unpairing will be enabled
;; https://github.com/status-im/status-react/issues/9227 ;; https://github.com/status-im/status-react/issues/9227
[quo/list-item {:icon :main-icons/keycard
:size :small
:title (i18n/label :t/keycard-backup)
:accessibility-label "create-backup-keycard"
:on-press #(re-frame/dispatch [:keycard-settings.ui/backup-card-pressed])}]
#_[quo/list-item {:icon :main-icons/close #_[quo/list-item {:icon :main-icons/close
:size :small :size :small
:title (i18n/label :t/unpair-card) :title (i18n/label :t/unpair-card)
:on-press #(re-frame/dispatch [:keycard-settings.ui/unpair-card-pressed])}]])])] :on-press #(re-frame/dispatch [:keycard-settings.ui/unpair-card-pressed])}]])])]]]))
; NOTE: Reset card is hidden until multiaccount removal will be implemented
#_(when pairing
[react/view {:margin-bottom 35
:margin-left 16}
[quo/list-item {:icon :main-icons/warning
:theme :negative
:size :small
:title (i18n/label :t/reset-card)
:on-press #(re-frame/dispatch [:keycard-settings.ui/reset-card-pressed])}]])]]))
(defn reset-pin [] (defn reset-pin []
[keycard.views/login-pin [keycard.views/login-pin

View File

@ -103,7 +103,8 @@
(defview seed-phrase [] (defview seed-phrase []
(letsubs (letsubs
[{:keys [seed-word-count seed-shape-invalid?]} [:multiaccounts/key-storage]] [{:keys [seed-word-count seed-shape-invalid?]} [:multiaccounts/key-storage]
{:keys [creating-backup?]} [:keycard]]
[react/keyboard-avoiding-view {:flex 1} [react/keyboard-avoiding-view {:flex 1}
[local-topbar (i18n/label :t/enter-seed-phrase)] [local-topbar (i18n/label :t/enter-seed-phrase)]
[multiaccounts.views/seed-phrase-input [multiaccounts.views/seed-phrase-input
@ -122,7 +123,7 @@
(nil? seed-shape-invalid?)) (nil? seed-shape-invalid?))
:on-press #(re-frame/dispatch [::multiaccounts.key-storage/choose-storage-pressed]) :on-press #(re-frame/dispatch [::multiaccounts.key-storage/choose-storage-pressed])
:after :main-icons/next} :after :main-icons/next}
(i18n/label :t/choose-storage)]}]])) (i18n/label (if creating-backup? :t/next :t/choose-storage))]}]]))
(defn keycard-subtitle [] (defn keycard-subtitle []
[react/view [react/view
@ -197,7 +198,8 @@
(i18n/label :t/confirm)]}]]])) (i18n/label :t/confirm)]}]]]))
(defview seed-key-uid-mismatch-popover [] (defview seed-key-uid-mismatch-popover []
(letsubs [{:keys [name]} [:multiaccounts/login]] (letsubs [{:keys [name]} [:multiaccounts/login]
{logged-in-name :name} [:multiaccount]]
[react/view {:margin-top 24 [react/view {:margin-top 24
:margin-horizontal 24 :margin-horizontal 24
:align-items :center} :align-items :center}
@ -215,7 +217,7 @@
[react/view [react/view
[react/text {:style (into styles/popover-text [react/text {:style (into styles/popover-text
{:margin-bottom 16})} {:margin-bottom 16})}
(i18n/label :t/seed-key-uid-mismatch-desc-1 {:multiaccount-name name})] (i18n/label :t/seed-key-uid-mismatch-desc-1 {:multiaccount-name (or name logged-in-name)})]
[react/text {:style styles/popover-text} [react/text {:style styles/popover-text}
(i18n/label :t/seed-key-uid-mismatch-desc-2)]]] (i18n/label :t/seed-key-uid-mismatch-desc-2)]]]
[react/view {:margin-vertical 24 [react/view {:margin-vertical 24

View File

@ -27,7 +27,12 @@
[status-im.ui.screens.status.new.views :as status.new] [status-im.ui.screens.status.new.views :as status.new]
[status-im.ui.screens.browser.bookmarks.views :as bookmarks] [status-im.ui.screens.browser.bookmarks.views :as bookmarks]
[status-im.ui.screens.routing.status-stack :as status-stack] [status-im.ui.screens.routing.status-stack :as status-stack]
[status-im.ui.screens.communities.invite :as communities.invite])) [status-im.ui.screens.communities.invite :as communities.invite]
[status-im.ui.screens.keycard.onboarding.views :as keycard.onboarding]
[status-im.ui.screens.keycard.recovery.views :as keycard.recovery]
[status-im.keycard.core :as keycard.core]
[status-im.ui.screens.keycard.views :as keycard]
[status-im.ui.screens.multiaccounts.key-storage.views :as key-storage.views]))
(defonce main-stack (navigation/create-stack)) (defonce main-stack (navigation/create-stack))
(defonce bottom-tabs (navigation/create-bottom-tabs)) (defonce bottom-tabs (navigation/create-bottom-tabs))
@ -55,7 +60,8 @@
:component profile-stack/profile-stack}]]) :component profile-stack/profile-stack}]])
(views/defview get-main-component [_] (views/defview get-main-component [_]
(views/letsubs [logged-in? [:multiaccount/logged-in?]] (views/letsubs [logged-in? [:multiaccount/logged-in?]
keycard-account? [:multiaccounts/keycard-account?]]
[main-stack (merge {:header-mode :none} [main-stack (merge {:header-mode :none}
;; https://github.com/react-navigation/react-navigation/issues/6520 ;; https://github.com/react-navigation/react-navigation/issues/6520
(when platform/ios? (when platform/ios?
@ -170,4 +176,26 @@
(when config/quo-preview-enabled? (when config/quo-preview-enabled?
[{:name :quo-preview [{:name :quo-preview
:insets {:top false :bottom false} :insets {:top false :bottom false}
:component quo.preview/preview-stack}]))])) :component quo.preview/preview-stack}])
(when keycard-account?
[{:name :keycard-onboarding-intro
:back-handler keycard.core/onboarding-intro-back-handler
:component keycard.onboarding/intro}
{:name :keycard-onboarding-puk-code
:back-handler :noop
:component keycard.onboarding/puk-code}
{:name :keycard-onboarding-pin
:back-handler :noop
:component keycard.onboarding/pin}
{:name :keycard-recovery-pair
:back-handler :noop
:component keycard.recovery/pair}
{:name :seed-phrase
:component key-storage.views/seed-phrase}
{:name :keycard-recovery-pin
:component keycard.recovery/pin}
{:name :keycard-wrong
:component keycard/wrong}
{:name :not-keycard
:component keycard/not-keycard}]))]))

View File

@ -1211,6 +1211,9 @@
"keycard-error-description": "Connect the card again to continue", "keycard-error-description": "Connect the card again to continue",
"keycard-success-title": "Success", "keycard-success-title": "Success",
"keycard-success-description": "You may remove the card now", "keycard-success-description": "You may remove the card now",
"keycard-backup": "Create a backup Keycard",
"keycard-backup-success-title": "Backup successful",
"keycard-backup-success-body": "Backup card created successfully. You can now use it with your account just like the primary card.",
"type-a-message": "Message", "type-a-message": "Message",
"ulc-enabled": "ULC enabled", "ulc-enabled": "ULC enabled",
"unable-to-read-this-code": "Unable to read this code", "unable-to-read-this-code": "Unable to read this code",