Show popup when device is not targeted.
When someone is sending a pfs message to us but did not include our own device, a pop up is shown propmting the user to connect with the user. The reason for receiving messages that are not targeting our devices are various: 1) The account was just recovered (which means it is a new installation id) 2) More than 3 devices are in use (we only keep max 3 devices in sync) 3) The sender has used an old bundle which does not include the current device Eventually we will reduce the likelihood of this scenario happening, but we can't dismiss it completely. It's only enabled when PFS is enabled. Signed-off-by: Andrea Maria Piana <andrea.maria.piana@gmail.com>
This commit is contained in:
parent
ad99ed2a28
commit
b56fd2e29f
|
@ -0,0 +1,63 @@
|
|||
(ns status-im.contact-recovery.core
|
||||
(:require
|
||||
[status-im.i18n :as i18n]
|
||||
[re-frame.core :as re-frame]
|
||||
[status-im.data-store.contact-recovery :as data-store.contact-recovery]
|
||||
[status-im.utils.fx :as fx]
|
||||
[status-im.accounts.db :as accounts.db]
|
||||
[status-im.contact.core :as models.contact]))
|
||||
|
||||
(defn prompt-dismissed! [public-key]
|
||||
(re-frame/dispatch [:contact-recovery.ui/prompt-dismissed public-key]))
|
||||
|
||||
(defn prompt-accepted! [public-key]
|
||||
(re-frame/dispatch [:contact-recovery.ui/prompt-accepted public-key]))
|
||||
|
||||
(defn show-contact-recovery-fx
|
||||
"Check that a pop up for that given user is not already shown, if not proceed fetching from the db whether we should be showing it"
|
||||
[{:keys [db] :as cofx} public-key]
|
||||
(let [my-public-key (accounts.db/current-public-key cofx)
|
||||
pfs? (get-in db [:account/account :settings :pfs?])]
|
||||
(when (and (not= public-key my-public-key)
|
||||
pfs?
|
||||
(not (get-in db [:contact-recovery/pop-up public-key])))
|
||||
{:db (update db :contact-recovery/pop-up conj public-key)
|
||||
:contact-recovery/show-contact-recovery-message public-key})))
|
||||
|
||||
(fx/defn prompt-dismissed [{:keys [db]} public-key]
|
||||
{:db (update db :contact-recovery/pop-up disj public-key)})
|
||||
|
||||
(defn show-contact-recovery-message? [public-key]
|
||||
(not (data-store.contact-recovery/get-contact-recovery-by-id public-key)))
|
||||
|
||||
(defn show-contact-recovery-message-fx [public-key]
|
||||
(when (show-contact-recovery-message? public-key)
|
||||
(re-frame/dispatch [:contact-recovery.callback/show-contact-recovery-message public-key])))
|
||||
|
||||
(re-frame/reg-fx
|
||||
:contact-recovery/show-contact-recovery-message
|
||||
show-contact-recovery-message-fx)
|
||||
|
||||
(fx/defn save-contact-recovery [{:keys [now]} public-key]
|
||||
{:data-store/tx [(data-store.contact-recovery/save-contact-recovery-tx {:timestamp now
|
||||
:id public-key})]})
|
||||
|
||||
(fx/defn prompt-accepted [cofx public-key]
|
||||
(fx/merge
|
||||
cofx
|
||||
(prompt-dismissed public-key)
|
||||
(save-contact-recovery public-key)))
|
||||
|
||||
(fx/defn show-contact-recovery-message [{:keys [db] :as cofx} public-key]
|
||||
(let [pfs? (get-in db [:account/account :settings :pfs?])
|
||||
contact (models.contact/build-contact cofx public-key)
|
||||
popup {:ui/show-confirmation {:title (i18n/label :t/contact-recovery-title {:name (:name contact)})
|
||||
:content (i18n/label :t/contact-recovery-content {:name (:name contact)})
|
||||
:confirm-button-text (i18n/label :t/add-to-contacts)
|
||||
:cancel-button-text (i18n/label :t/cancel)
|
||||
:on-cancel #(prompt-dismissed! public-key)
|
||||
:on-accept #(prompt-accepted! public-key)}}]
|
||||
|
||||
(when pfs?
|
||||
(fx/merge cofx
|
||||
popup))))
|
|
@ -0,0 +1,14 @@
|
|||
(ns status-im.data-store.contact-recovery
|
||||
(:require [status-im.data-store.realm.core :as core]))
|
||||
|
||||
(defn get-contact-recovery-by-id [public-key]
|
||||
(core/single (core/get-by-field @core/account-realm :contact-recovery :id public-key)))
|
||||
|
||||
(defn save-contact-recovery-tx
|
||||
"Returns tx function for saving a contact-recovery"
|
||||
[contact-recovery]
|
||||
(fn [realm]
|
||||
(core/create realm
|
||||
:contact-recovery
|
||||
contact-recovery
|
||||
true)))
|
|
@ -0,0 +1,7 @@
|
|||
(ns status-im.data-store.realm.schemas.account.contact-recovery)
|
||||
|
||||
(def v1 {:name :contact-recovery
|
||||
:primaryKey :id
|
||||
:properties {:id :string
|
||||
:timestamp {:type :int
|
||||
:optional true}}})
|
|
@ -13,6 +13,7 @@
|
|||
[status-im.data-store.realm.schemas.account.request :as request]
|
||||
[status-im.data-store.realm.schemas.account.membership-update :as membership-update]
|
||||
[status-im.data-store.realm.schemas.account.installation :as installation]
|
||||
[status-im.data-store.realm.schemas.account.contact-recovery :as contact-recovery]
|
||||
[status-im.data-store.realm.schemas.account.migrations :as migrations]
|
||||
[taoensso.timbre :as log]))
|
||||
|
||||
|
@ -343,6 +344,20 @@
|
|||
browser/v8
|
||||
dapp-permissions/v9])
|
||||
|
||||
(def v32 [chat/v13
|
||||
transport/v7
|
||||
contact/v3
|
||||
message/v9
|
||||
mailserver/v11
|
||||
mailserver-topic/v1
|
||||
user-status/v2
|
||||
membership-update/v1
|
||||
installation/v2
|
||||
local-storage/v1
|
||||
browser/v8
|
||||
dapp-permissions/v9
|
||||
contact-recovery/v1])
|
||||
|
||||
;; put schemas ordered by version
|
||||
(def schemas [{:schema v1
|
||||
:schemaVersion 1
|
||||
|
@ -436,4 +451,7 @@
|
|||
:migration migrations/v30}
|
||||
{:schema v31
|
||||
:schemaVersion 31
|
||||
:migration (constantly nil)}
|
||||
{:schema v32
|
||||
:schemaVersion 32
|
||||
:migration (constantly nil)}])
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
[status-im.chat.models.loading :as chat.loading]
|
||||
[status-im.chat.models.message :as chat.message]
|
||||
[status-im.contact.core :as contact]
|
||||
[status-im.contact-recovery.core :as contact-recovery]
|
||||
[status-im.data-store.core :as data-store]
|
||||
[status-im.extensions.core :as extensions]
|
||||
[status-im.extensions.registry :as extensions.registry]
|
||||
|
@ -1404,3 +1405,25 @@
|
|||
:pairing.callback/disable-installation-success
|
||||
(fn [cofx [_ installation-id]]
|
||||
(pairing/disable cofx installation-id)))
|
||||
|
||||
;; Contact recovery module
|
||||
|
||||
(handlers/register-handler-fx
|
||||
:contact-recovery.ui/prompt-accepted
|
||||
[(re-frame/inject-cofx :random-id-generator)]
|
||||
(fn [cofx [_ public-key]]
|
||||
(fx/merge
|
||||
cofx
|
||||
(contact/add-contact public-key)
|
||||
(contact-recovery/prompt-accepted public-key))))
|
||||
|
||||
(handlers/register-handler-fx
|
||||
:contact-recovery.ui/prompt-dismissed
|
||||
(fn [cofx [_ public-key]]
|
||||
(contact-recovery/prompt-dismissed cofx public-key)))
|
||||
|
||||
(handlers/register-handler-fx
|
||||
:contact-recovery.callback/show-contact-recovery-message
|
||||
[(re-frame/inject-cofx :random-id-generator)]
|
||||
(fn [cofx [_ public-key]]
|
||||
(contact-recovery/show-contact-recovery-message cofx public-key)))
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
[status-im.init.core :as init]
|
||||
[status-im.node.core :as node]
|
||||
[status-im.pairing.core :as pairing]
|
||||
[status-im.contact-recovery.core :as contact-recovery]
|
||||
[status-im.mailserver.core :as mailserver]
|
||||
[status-im.transport.message.core :as transport.message]
|
||||
[status-im.utils.fx :as fx]
|
||||
|
@ -75,5 +76,6 @@
|
|||
"mailserver.request.completed" (mailserver/handle-request-completed cofx event)
|
||||
"mailserver.request.expired" (when (accounts.db/logged-in? cofx)
|
||||
(mailserver/resend-request cofx {:request-id (:hash event)}))
|
||||
"messages.decrypt.failed" (contact-recovery/show-contact-recovery-fx cofx (:sender event))
|
||||
"discovery.summary" (summary cofx event)
|
||||
(log/debug "Event " type " not handled"))))
|
||||
|
|
|
@ -35,19 +35,36 @@
|
|||
:resend? resend?
|
||||
:now now}))})
|
||||
|
||||
(defn send-public-message
|
||||
"Sends the payload to topic"
|
||||
[{:keys [db] :as cofx} chat-id success-event payload]
|
||||
(let [{:keys [web3]} db]
|
||||
{:shh/send-public-message [{:web3 web3
|
||||
:success-event success-event
|
||||
:src (accounts.db/current-public-key cofx)
|
||||
:chat chat-id
|
||||
:payload payload}]}))
|
||||
|
||||
(fx/defn send-with-sym-key
|
||||
"Sends the payload using symetric key and topic from db (looked up by `chat-id`)"
|
||||
[{:keys [db] :as cofx} {:keys [payload chat-id success-event]}]
|
||||
;; we assume that the chat contains the contact public-key
|
||||
(let [{:keys [web3]} db
|
||||
{:keys [sym-key-id topic]} (get-in db [:transport/chats chat-id])]
|
||||
{:keys [sym-key-id topic]} (get-in db [:transport/chats chat-id])
|
||||
pfs? (get-in db [:account/account :settings :pfs?])]
|
||||
(if pfs?
|
||||
(send-public-message
|
||||
cofx
|
||||
chat-id
|
||||
success-event
|
||||
payload)
|
||||
{:shh/post [{:web3 web3
|
||||
:success-event success-event
|
||||
:message (merge {:sig (accounts.db/current-public-key cofx)
|
||||
:symKeyID sym-key-id
|
||||
:payload payload
|
||||
:topic topic}
|
||||
whisper-opts)}]}))
|
||||
whisper-opts)}]})))
|
||||
|
||||
(fx/defn send-direct-message
|
||||
"Sends the payload using to dst"
|
||||
|
@ -59,33 +76,28 @@
|
|||
:dst dst
|
||||
:payload payload}]}))
|
||||
|
||||
(defn send-public-message
|
||||
"Sends the payload to topic"
|
||||
[{:keys [db] :as cofx} chat-id success-event payload]
|
||||
(let [{:keys [web3]} db]
|
||||
{:shh/send-public-message [{:web3 web3
|
||||
:success-event success-event
|
||||
:src (accounts.db/current-public-key cofx)
|
||||
:chat chat-id
|
||||
:payload payload}]}))
|
||||
|
||||
(fx/defn send-with-pubkey
|
||||
"Sends the payload using asymetric key (account `:public-key` in db) and fixed discovery topic"
|
||||
[{:keys [db] :as cofx} {:keys [payload chat-id success-event]}]
|
||||
(let [{:keys [web3]} db]
|
||||
(let [pfs? (get-in db [:account/account :settings :pfs?])]
|
||||
(if pfs?
|
||||
(send-direct-message cofx
|
||||
chat-id
|
||||
success-event
|
||||
payload)
|
||||
{:shh/post [{:web3 web3
|
||||
:success-event success-event
|
||||
:message (merge {:sig (accounts.db/current-public-key cofx)
|
||||
:pubKey chat-id
|
||||
:payload payload
|
||||
:topic (transport.utils/get-topic constants/contact-discovery)}
|
||||
whisper-opts)}]}))
|
||||
whisper-opts)}]}))))
|
||||
|
||||
(defrecord Message [content content-type message-type clock-value timestamp]
|
||||
StatusMessage
|
||||
(send [this chat-id {:keys [message-id] :as cofx}]
|
||||
(let [dev-mode? (get-in cofx [:db :account/account :dev-mode?])
|
||||
pfs? (get-in cofx [:db :account/account :settings :pfs?])
|
||||
current-public-key (accounts.db/current-public-key cofx)
|
||||
params {:chat-id chat-id
|
||||
:payload this
|
||||
|
@ -95,25 +107,13 @@
|
|||
message-type]}]
|
||||
(case message-type
|
||||
:public-group-user-message
|
||||
(if pfs?
|
||||
(send-public-message
|
||||
cofx
|
||||
chat-id
|
||||
(:success-event params)
|
||||
this)
|
||||
(send-with-sym-key cofx params))
|
||||
(send-with-sym-key cofx params)
|
||||
|
||||
:user-message
|
||||
(if pfs?
|
||||
(send-direct-message
|
||||
cofx
|
||||
chat-id
|
||||
(:success-event params)
|
||||
this)
|
||||
(fx/merge cofx
|
||||
#(when (config/pairing-enabled? dev-mode?)
|
||||
(send-direct-message % current-public-key nil this))
|
||||
(send-with-pubkey params))))))
|
||||
(send-with-pubkey params)))))
|
||||
(receive [this chat-id signature _ cofx]
|
||||
{:chat-received-message/add-fx
|
||||
[(assoc (into {} this)
|
||||
|
@ -134,14 +134,8 @@
|
|||
(defrecord MessagesSeen [message-ids]
|
||||
StatusMessage
|
||||
(send [this chat-id cofx]
|
||||
(let [pfs? (get-in cofx [:db :account/account :settings :pfs?])]
|
||||
(if pfs?
|
||||
(send-direct-message cofx
|
||||
chat-id
|
||||
nil
|
||||
this)
|
||||
(send-with-pubkey cofx {:chat-id chat-id
|
||||
:payload this}))))
|
||||
:payload this}))
|
||||
(receive [this chat-id signature _ cofx]
|
||||
(chat/receive-seen cofx chat-id signature this))
|
||||
(validate [this]
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
:navigation-stack '()
|
||||
:contacts/contacts {}
|
||||
:pairing/installations {}
|
||||
:contact-recovery/pop-up #{}
|
||||
:qr-codes {}
|
||||
:group/selected-contacts #{}
|
||||
:chats {}
|
||||
|
|
|
@ -0,0 +1,38 @@
|
|||
(ns status-im.test.contact-recovery.core
|
||||
(:require [cljs.test :refer-macros [deftest is testing]]
|
||||
[status-im.contact-recovery.core :as contact-recovery]))
|
||||
|
||||
(deftest show-contact-recovery-fx
|
||||
(let [public-key "pk"]
|
||||
(testing "pfs is not enabled"
|
||||
(testing "no pop up is displayed"
|
||||
(let [actual (contact-recovery/show-contact-recovery-fx {:db {:contact-recovery/pop-up #{}}} public-key)]
|
||||
(testing "it does nothing"
|
||||
(is (not (:db actual)))
|
||||
(is (not (:contact-recovery/show-contact-recovery-message actual)))))))
|
||||
(testing "no pop up is displayed"
|
||||
(let [cofx {:db {:contact-recovery/pop-up #{}
|
||||
:account/account {:settings {:pfs? true}}}}
|
||||
actual (contact-recovery/show-contact-recovery-fx cofx public-key)]
|
||||
(testing "it sets the pop up as displayed"
|
||||
(is (get-in actual [:db :contact-recovery/pop-up public-key])))
|
||||
(testing "it adds an fx for fetching the contact"
|
||||
(is (= public-key (:contact-recovery/show-contact-recovery-message actual))))))
|
||||
(testing "pop up is already displayed"
|
||||
(let [actual (contact-recovery/show-contact-recovery-fx {:db {:contact-recovery/pop-up #{public-key}}} public-key)]
|
||||
(testing "it does nothing"
|
||||
(is (not (:db actual)))
|
||||
(is (not (:contact-recovery/show-contact-recovery-message actual))))))))
|
||||
|
||||
(deftest show-contact-recovery-message
|
||||
(let [public-key "pk"]
|
||||
(testing "pfs is enabled"
|
||||
(let [cofx {:db {:account/account {:settings {:pfs? true}}}}
|
||||
actual (contact-recovery/show-contact-recovery-message cofx public-key)]
|
||||
(testing "it shows a pop up"
|
||||
(is (:ui/show-confirmation actual)))))
|
||||
(testing "pfs is not enabled"
|
||||
(let [cofx {:db {:account/account {:settings {}}}}
|
||||
actual (contact-recovery/show-contact-recovery-message cofx public-key)]
|
||||
(testing "it shows a pop up"
|
||||
(is (not (:ui/show-confirmation actual))))))))
|
|
@ -56,6 +56,7 @@
|
|||
[status-im.test.utils.fx]
|
||||
[status-im.test.accounts.recover.core]
|
||||
[status-im.test.hardwallet.core]
|
||||
[status-im.test.contact-recovery.core]
|
||||
[status-im.test.ui.screens.currency-settings.models]
|
||||
[status-im.test.ui.screens.wallet.db]))
|
||||
|
||||
|
@ -124,5 +125,6 @@
|
|||
'status-im.test.ui.screens.currency-settings.models
|
||||
'status-im.test.ui.screens.wallet.db
|
||||
'status-im.test.browser.core
|
||||
'status-im.test.contact-recovery.core
|
||||
'status-im.test.extensions.ethereum
|
||||
'status-im.test.browser.permissions)
|
||||
|
|
|
@ -15,6 +15,8 @@
|
|||
"sync-all-devices": "Sync all devices",
|
||||
"syncing-devices": "Syncing...",
|
||||
"paired-devices": "Paired devices",
|
||||
"contact-recovery-title": "{{name}} has sent you a message",
|
||||
"contact-recovery-content": "{{name}} has sent you a message but did not include this device.\nThis might happen if you have more than 3 devices, you haven't paired your devices correctly or you just recovered your account.\nPlease make sure your devices are paired correctly and click Add to contacts to notify the user of this device.",
|
||||
"pairing-maximum-number-reached-title": "Max number of devices reached",
|
||||
"pairing-maximum-number-reached-content": "Please disable one of your devices before enabling a new one.",
|
||||
"pairing-new-installation-detected-title": "New device detected",
|
||||
|
|
Loading…
Reference in New Issue