[#21446] Keycard - Current profile key pair migrate (#21558)

[#21470] Keycard - Keycard initialized but has no keys
This commit is contained in:
flexsurfer 2024-11-05 14:48:45 +01:00 committed by GitHub
parent e43a328c6f
commit 03ec410862
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
8 changed files with 113 additions and 46 deletions

View File

@ -1,6 +1,5 @@
(ns status-im.contexts.keycard.migrate.events
(:require [clojure.string :as string]
[status-im.contexts.keycard.pin.view :as keycard.pin]
[utils.re-frame :as rf]
[utils.security.core :as security]))
@ -11,12 +10,8 @@
{:key-uid (get-in db [:profile/profile :key-uid])
:on-success
(fn []
;;TODO keys already on the keycard, new flow needs to be implemented
;; https://github.com/status-im/status-mobile/issues/21446
(rf/dispatch [:keycard/disconnect])
(rf/dispatch [:open-modal :screen/keycard.authorise
{:on-success
#(rf/dispatch [:keycard/migration.authorisation-success %])}]))
(rf/dispatch [:open-modal :screen/keycard.profile-keys]))
:on-error
(fn [error]
(if (= error :keycard/error.keycard-blank)
@ -40,31 +35,27 @@
(fn [{:keys [db]}]
(let [key-uid (get-in db [:profile/profile :key-uid])
{:keys [initialized? has-master-key?]} (get-in db [:keycard :application-info])
{:keys [masked-phrase pin]} (get-in db [:keycard :migration])
on-failure (fn []
(rf/dispatch [:keycard/disconnect])
(rf/dispatch [:navigate-to
:screen/keycard.migrate.fail]))]
{:keys [masked-phrase pin]} (get-in db [:keycard :migration])]
(cond
(not initialized?)
{:fx [[:keycard/init-card
{:pin pin
:on-success #(get-application-info-and-continue key-uid)
:on-failure on-failure}]]}
:on-success #(get-application-info-and-continue key-uid)}]]}
(not has-master-key?)
{:fx [[:effects.keycard/generate-and-load-key
{:mnemonic (security/safe-unmask-data masked-phrase)
:pin pin
:on-success #(get-application-info-and-continue key-uid)
:on-failure on-failure}]]}
:on-failure #(rf/dispatch [:keycard/on-action-with-pin-error %])}]]}
:else
{:fx [[:effects.keycard/get-keys
{:pin pin
:on-success #(rf/dispatch [:keycard/migration.convert-to-keycard-profile %])
:on-failure on-failure}]]}))))
:on-failure #(rf/dispatch [:keycard/on-action-with-pin-error %])}]]}))))
(rf/reg-event-fx :keycard/migration.start
(fn [{:keys [db]}]
@ -115,11 +106,7 @@
{:db (assoc-in db [:keycard :migration :masked-password] masked-password)
:fx [[:dispatch [:navigate-back]]
(if initialized?
[:dispatch
[:show-bottom-sheet
{:content (fn []
[keycard.pin/auth
{:on-complete #(rf/dispatch [:keycard/migration.pin-created %])}])}]]
[:dispatch [:open-modal :screen/keycard.migrate]]
[:dispatch
[:open-modal :screen/keycard.pin.create
{:on-complete (fn [new-pin]
@ -130,3 +117,8 @@
(fn [{:keys [db]} [pin]]
{:db (assoc-in db [:keycard :migration :pin] pin)
:fx [[:dispatch [:open-modal :screen/keycard.migrate]]]}))
(rf/reg-event-fx :keycard/migration.pin-entered
(fn [{:keys [db]} [pin]]
{:db (assoc-in db [:keycard :migration :pin] pin)
:fx [[:dispatch [:keycard/migration.start]]]}))

View File

@ -0,0 +1,34 @@
(ns status-im.contexts.keycard.migrate.profile-keys.view
(:require [quo.core :as quo]
[react-native.core :as rn]
[status-im.common.events-helper :as events-helper]
[utils.i18n :as i18n]
[utils.re-frame :as rf]))
(defn view
[]
[:<>
[quo/page-nav
{:icon-name :i/close
:on-press events-helper/navigate-back}]
[quo/page-top
{:title (i18n/label :t/keycard-contains-key-pair)
:description :text
:description-text (i18n/label :t/finalise-migration-instructions)}]
[rn/view {:style {:margin-horizontal 20}}
[rn/view {:style {:padding-top 8 :padding-bottom 20}}
[quo/keycard {:holder-name ""}]]
[quo/section-label {:section (i18n/label :t/what-you-can-do) :container-style {:padding-vertical 8}}]
[quo/settings-item
{:title (i18n/label :t/finalise-migration)
:image :icon
:image-props :i/profile
:action :arrow
:description :text
:description-props {:text (i18n/label :t/use-keycard-instead-password)}
:on-press (fn []
(rf/dispatch [:navigate-back])
(rf/dispatch [:open-modal :screen/keycard.authorise
{:on-success
#(rf/dispatch [:keycard/migration.authorisation-success
%])}]))}]]])

View File

@ -10,7 +10,8 @@
[]
(let [profile-name (rf/sub [:profile/name])
profile-picture (rf/sub [:profile/image])
customization-color (rf/sub [:profile/customization-color])]
customization-color (rf/sub [:profile/customization-color])
initialized? (rf/sub [:keycard/initialized?])]
[:<>
[quo/page-nav
{:icon-name :i/close
@ -30,5 +31,13 @@
[quo/markdown-list {:description (i18n/label :t/keep-card-steady)}]
[quo/bottom-actions
{:actions :one-action
:button-one-label (i18n/label :t/scan-keycard)
:button-one-props {:on-press #(rf/dispatch [:keycard/migration.start])}}]]))
:button-one-label (if initialized? (i18n/label :t/enter-keycard-pin) (i18n/label :t/scan-keycard))
:button-one-props {:on-press
(fn []
(if initialized?
(do
(rf/dispatch [:navigate-back])
(rf/dispatch [:open-modal :screen/keycard.pin.enter
{:on-complete #(rf/dispatch
[:keycard/migration.pin-entered %])}]))
(rf/dispatch [:keycard/migration.start])))}}]]))

View File

@ -49,7 +49,7 @@
(i18n/label :t/create-keycard-pin)
(i18n/label :t/repeat-keycard-pin))
:description :text
:description-text "Youll need this PIN to login and sign transactions"}]
:description-text (i18n/label :t/pin-needed-login-sign)}]
[rn/view {:style {:flex 1 :justify-content :center :align-items :center :padding-vertical 34}}
[quo/pin-input
{:blur? false

View File

@ -0,0 +1,18 @@
(ns status-im.contexts.keycard.pin.enter.view
(:require [quo.core :as quo]
[react-native.core :as rn]
[status-im.common.events-helper :as events-helper]
[status-im.contexts.keycard.pin.view :as keycard.pin]
[utils.i18n :as i18n]
[utils.re-frame :as rf]))
(defn view
[]
(let [{:keys [on-complete]} (rf/sub [:get-screen-params])]
[rn/view {:style {:padding-bottom 12 :flex 1}}
[quo/page-nav
{:icon-name :i/close
:on-press events-helper/navigate-back}]
[quo/page-top {:title (i18n/label :t/enter-keycard-pin)}]
[rn/view {:style {:flex 1}}]
[keycard.pin/auth {:on-complete on-complete}]]))

View File

@ -33,11 +33,13 @@
[status-im.contexts.keycard.empty.view :as keycard.empty]
[status-im.contexts.keycard.error.view :as keycard.error]
[status-im.contexts.keycard.migrate.fail.view :as keycard.migrate.fail]
[status-im.contexts.keycard.migrate.profile-keys.view :as keycard.migrate.profile-keys]
[status-im.contexts.keycard.migrate.re-encrypting.view :as keycard.re-encrypting]
[status-im.contexts.keycard.migrate.success.view :as keycard.migrate.success]
[status-im.contexts.keycard.migrate.view :as keycard.migrate]
[status-im.contexts.keycard.not-keycard.view :as keycard.not-keycard]
[status-im.contexts.keycard.pin.create.view :as pin.create]
[status-im.contexts.keycard.pin.create.view :as keycard.pin.create]
[status-im.contexts.keycard.pin.enter.view :as keycard.pin.enter]
[status-im.contexts.onboarding.create-or-sync-profile.view :as create-or-sync-profile]
[status-im.contexts.onboarding.create-password.view :as create-password]
[status-im.contexts.onboarding.create-profile.view :as create-profile]
@ -883,44 +885,37 @@
(def keycard-screens
[{:name :screen/keycard.check
:metrics {:track? :true
:alias-id :keycard.check}
:metrics {:track? :true}
:options {:insets {:top? true :bottom? true}}
:component keycard.check/view}
{:name :screen/keycard.empty
:metrics {:track? :true
:alias-id :keycard.empty}
:metrics {:track? :true}
:options {:insets {:top? true :bottom? true}}
:component keycard.empty/view}
{:name :screen/keycard.error
:metrics {:track? :true
:alias-id :keycard.error}
:metrics {:track? :true}
:options {:insets {:top? true :bottom? true}}
:component keycard.error/view}
{:name :screen/keycard.not-keycard
:metrics {:track? :true
:alias-id :keycard.not-keycard}
:metrics {:track? :true}
:options {:insets {:top? true :bottom? true}}
:component keycard.not-keycard/view}
{:name :screen/keycard.authorise
:metrics {:track? :true
:alias-id :keycard.authorise}
:metrics {:track? :true}
:options {:insets {:top? true :bottom? true}}
:component keycard.authorise/view}
{:name :screen/keycard.migrate
:metrics {:track? :true
:alias-id :keycard.migrate}
:metrics {:track? :true}
:options {:insets {:top? true :bottom? true}}
:component keycard.migrate/view}
{:name :screen/keycard.re-encrypting
:metrics {:track? :true
:alias-id :keycard.re-encrypting}
:metrics {:track? :true}
:options {:insets {:top? true :bottom? true}
:popGesture false
:hardwareBackButton {:dismissModalOnPress false
@ -928,8 +923,7 @@
:component keycard.re-encrypting/view}
{:name :screen/keycard.migrate.success
:metrics {:track? :true
:alias-id :keycard.migrate.success}
:metrics {:track? :true}
:options {:insets {:top? true :bottom? true}
:popGesture false
:hardwareBackButton {:dismissModalOnPress false
@ -937,8 +931,7 @@
:component keycard.migrate.success/view}
{:name :screen/keycard.migrate.fail
:metrics {:track? :true
:alias-id :keycard.migrate.fail}
:metrics {:track? :true}
:options {:insets {:top? true :bottom? true}
:popGesture false
:hardwareBackButton {:dismissModalOnPress false
@ -946,10 +939,19 @@
:component keycard.migrate.fail/view}
{:name :screen/keycard.pin.create
:metrics {:track? :true
:alias-id :keycard.pin.create}
:metrics {:track? :true}
:options {:insets {:top? true :bottom? true}}
:component pin.create/view}])
:component keycard.pin.create/view}
{:name :screen/keycard.pin.enter
:metrics {:track? :true}
:options {:insets {:top? true :bottom? true}}
:component keycard.pin.enter/view}
{:name :screen/keycard.profile-keys
:metrics {:track? :true}
:options {:insets {:top? true :bottom? true}}
:component keycard.migrate.profile-keys/view}])
(defn screens
[]

View File

@ -41,3 +41,9 @@
:<- [:keycard]
(fn [keycard]
(:application-info-error keycard)))
(rf/reg-sub
:keycard/initialized?
:<- [:keycard]
(fn [keycard]
(get-in keycard [:application-info :initialized?])))

View File

@ -965,6 +965,7 @@
"enter-chat-key": "Enter chat key or scan a QR",
"enter-contact-code": "ENS (vitalik94) or chat key (0x04…)",
"enter-eth": "Enter any ETH address or ENS name.",
"enter-keycard-pin": "Enter Keycard PIN",
"enter-pair-code": "Enter your pairing code",
"enter-pair-code-description": "Pairing code can be set from an already paired Status client",
"enter-password": "Enter password",
@ -1033,6 +1034,8 @@
"fetch-timeline": "↓ Fetch",
"fetching-community": "Fetching community...",
"fetching-the-price-took-longer-than-expected": "Fetching the price took longer than expected.\nPlease, try again later.",
"finalise-migration": "Finalise migration",
"finalise-migration-instructions": "Finalise migration to use this Keycard for logging in and signing transactions on this device",
"finalized-on": "Finalized on",
"find": "Find",
"find-it-in-setting": "Find it in Settings on your other synced device",
@ -1339,6 +1342,7 @@
"keycard-cancel-setup-title": "Dangerous operation",
"keycard-connected-description": "Try keeping the card still",
"keycard-connected-title": "Connected",
"keycard-contains-key-pair": "Keycard contains your profile key pair",
"keycard-desc": "Own a Keycard? Store your keys on it; youll need it for transactions",
"keycard-dont-ask-card": "Don't ask for card to sign in",
"keycard-empty": "Keycard is empty",
@ -1945,6 +1949,7 @@
"pin-code": "6-digit passcode",
"pin-limit-reached": "Pin limit reached. Unpin a previous message first.",
"pin-mismatch": "Wrong passcode",
"pin-needed-login-sign": "Youll need this PIN to login and sign transactions",
"pin-not-match": "PIN do not match",
"pin-one-attempt": " one attempt ",
"pin-one-attempt-blocked-after": "before your Keycard gets blocked",
@ -2678,6 +2683,7 @@
"use-biometrics": "Use biometrics to fill in your password",
"use-keycard": "Use Keycard",
"use-keycard-for-status": "From now on, use this Keycard to login to Status and transact with derived accounts on all synced devices. To start using it, logout and log back in with this Keycard.",
"use-keycard-instead-password": "To use Keycard instead of password",
"use-keycard-login-sign": "Use this Keycard to login and sign transactions",
"use-keycard-subtitle": "Keys will be stored on your Keycard",
"use-photo": "Use Photo",