diff --git a/src/status_im/constants.cljs b/src/status_im/constants.cljs index b6983df070..49b979f629 100644 --- a/src/status_im/constants.cljs +++ b/src/status_im/constants.cljs @@ -22,6 +22,8 @@ (def console-chat-id "console") +(def inbox-password "status-offline-inbox") + (def default-network config/default-network) (def system "system") @@ -80,21 +82,27 @@ (def default-wnodes {:testnet {"mailserver-a" {:id "mailserver-a" :name "Status mailserver A" + :password inbox-password :address "enode://1da276e34126e93babf24ec88aac1a7602b4cbb2e11b0961d0ab5e989ca9c261aa7f7c1c85f15550a5f1e5a5ca2305b53b9280cf5894d5ecf7d257b173136d40@167.99.209.61:30504"} "mailserver-b" {:id "mailserver-b" :name "Status mailserver B" + :password inbox-password :address "enode://07ac64fe0e9b2d4ecbfe0ccaeab3d8d95fa8858754f511104bb403b19255d7bf47a8416bdd0df01f6720ff82164451b7a028c93d15ddd37b7e8382d74e91ebc2@167.99.209.72:30504"}} :mainnet {"mailserver-a" {:id "mailserver-a" :name "Status mailserver A" + :password inbox-password :address "enode://1da276e34126e93babf24ec88aac1a7602b4cbb2e11b0961d0ab5e989ca9c261aa7f7c1c85f15550a5f1e5a5ca2305b53b9280cf5894d5ecf7d257b173136d40@167.99.209.61:30504"} "mailserver-b" {:id "mailserver-b" :name "Status mailserver B" + :password inbox-password :address "enode://07ac64fe0e9b2d4ecbfe0ccaeab3d8d95fa8858754f511104bb403b19255d7bf47a8416bdd0df01f6720ff82164451b7a028c93d15ddd37b7e8382d74e91ebc2@167.99.209.72:30504"}} :rinkeby {"mailserver-a" {:id "mailserver-a" :name "Status mailserver A" + :password inbox-password :address "enode://43829580446ad138386dadb7fa50b6bd4d99f7c28659a0bc08115f8c0380005922a340962496f6af756a42b94a1522baa38a694fa27de59c3a73d4e08d5dbb31@206.189.6.48:30504"} "mailserver-b" {:id "mailserver-b" :name "Status mailserver B" + :password inbox-password :address "enode://70a2004e78399075f566033c42e9a0b1d43c683d4742755bb5457d03191be66a1b48c2b4fb259696839f28646a5828a1958b900860e27897f984ad0fc8482404@206.189.56.154:30504"}}}) (defn default-account-settings [] @@ -199,8 +207,6 @@ :yer {:id :yer :code "YER" :display-name (i18n/label :t/currency-display-name-yer) :symbol "﷼"} :zar {:id :zar :code "ZAR" :display-name (i18n/label :t/currency-display-name-zar) :symbol "R"}}) -(def inbox-password "status-offline-inbox") - ;; Used to generate topic for contact discoveries (def contact-discovery "contact-discovery") diff --git a/src/status_im/models/mailserver.cljs b/src/status_im/models/mailserver.cljs index 7ce4e07489..967a1a6835 100644 --- a/src/status_im/models/mailserver.cljs +++ b/src/status_im/models/mailserver.cljs @@ -3,18 +3,37 @@ [clojure.string :as string] [status-im.utils.handlers-macro :as handlers-macro] [status-im.utils.ethereum.core :as ethereum] - [status-im.utils.inbox :as utils.inbox] [status-im.data-store.mailservers :as data-store.mailservers])) +(def enode-address-regex #"enode://[a-zA-Z0-9]+\@\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\b:(\d{1,5})") +(def enode-url-regex #"enode://[a-zA-Z0-9]+:(.+)\@\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\b:(\d{1,5})") + (defn- extract-address-components [address] (rest (re-matches #"enode://(.*)@(.*)" address))) +(defn- extract-url-components [address] + (rest (re-matches #"enode://(.*?):(.*)@(.*)" address))) + +(defn valid-enode-url? [address] + (re-matches enode-url-regex address)) + +(defn valid-enode-address? [address] + (re-matches enode-address-regex address)) + (defn- get-chain [db] (let [network (get (:networks (:account/account db)) (:network db))] (ethereum/network->chain-keyword network))) +(defn- address->mailserver [address] + (let [[enode password url :as response] (extract-url-components address)] + (cond-> {:address (if (seq response) + (str "enode://" enode "@" url) + address) + :user-defined true} + password (assoc :password password)))) + (defn- build [id mailserver-name address] - (assoc (utils.inbox/address->mailserver address) + (assoc (address->mailserver address) :id (string/replace id "-" "") :name mailserver-name)) @@ -32,7 +51,7 @@ :error (case input-key :id false :name (string/blank? value) - :url (not (utils.inbox/valid-enode-address? value)))})}) + :url (not (valid-enode-url? value)))})}) (defn connected? [id {:keys [db]}] (let [current-id (get-in db [:account/account :settings :wnode (get-chain db)])] diff --git a/src/status_im/transport/inbox.cljs b/src/status_im/transport/inbox.cljs index 94e53c7fef..49b901f14b 100644 --- a/src/status_im/transport/inbox.cljs +++ b/src/status_im/transport/inbox.cljs @@ -75,11 +75,18 @@ (error-fn error) (success-fn result))))) -(defn get-current-wnode-address [db] +(defn add-sym-key-id-to-wnode [{:keys [id]} sym-key-id {:keys [db]}] + (let [network (get (:networks (:account/account db)) (:network db)) + chain (ethereum/network->chain-keyword network)] + {:db (assoc-in db [:inbox/wnodes chain id :sym-key-id] sym-key-id)})) + +(defn get-current-wnode [db] (let [network (get (:networks (:account/account db)) (:network db)) chain (ethereum/network->chain-keyword network) wnode-id (get-in db [:account/account :settings :wnode chain])] - (get-in db [:inbox/wnodes chain wnode-id :address]))) + (get-in db [:inbox/wnodes chain wnode-id]))) + +(def get-current-wnode-address (comp :address get-current-wnode)) (defn registered-peer? [peers enode] (let [peer-ids (into #{} (map :id) peers) @@ -101,14 +108,14 @@ (def seven-days (* 7 one-day)) (defn request-inbox-messages - [web3 wnode topics from to sym-key-id success-fn error-fn] + [web3 wnode topics from to success-fn error-fn] (loop [from from current-to to] (let [current-to (if (> (- to from) one-day) (+ from one-day) to) - opts (merge {:mailServerPeer wnode - :symKeyID sym-key-id + opts (merge {:mailServerPeer (:address wnode) + :symKeyID (:sym-key-id wnode) :from from :to current-to})] (log/info "offline inbox: request-messages request for topics " topics " from " from " to " current-to) @@ -140,19 +147,18 @@ (re-frame/reg-fx ::request-messages - (fn [{:keys [wnode topics to from sym-key-id web3]}] + (fn [{:keys [wnode topics to from web3]}] (request-inbox-messages web3 wnode topics from to - sym-key-id #(log/info "offline inbox: request-messages response" %1 %2 from to) #(log/error "offline inbox: request-messages error" %1 %2 from to)))) (re-frame/reg-fx ::request-history - (fn [{:keys [wnode topics now-in-s sym-key-id web3]}] + (fn [{:keys [wnode topics now-in-s web3]}] (let [from (- now-in-s seven-days) to now-in-s] (request-inbox-messages web3 @@ -160,7 +166,6 @@ topics from to - sym-key-id #(log/info "offline inbox: request-messages response" %1 %2 from to) #(log/error "offline inbox: request-messages error" %1 %2 from to))))) @@ -170,13 +175,13 @@ :mailserver-status state :inbox/fetching? false)})) -(defn generate-mailserver-symkey [{:keys [db] :as cofx}] - (when-not (:inbox/sym-key-id db) +(defn generate-mailserver-symkey [wnode {:keys [db] :as cofx}] + (when-not (:sym-key-id wnode) {:shh/generate-sym-key-from-password - {:password (:inbox/password db) + {:password (:password wnode) :web3 (:web3 db) :on-success (fn [_ sym-key-id] - (re-frame/dispatch [:inbox/get-sym-key-success sym-key-id])) + (re-frame/dispatch [:inbox/get-sym-key-success wnode sym-key-id])) :on-error #(log/error "offline inbox: get-sym-key error" %)}})) (defn connect-to-mailserver @@ -187,21 +192,21 @@ A connection-check is made after `connection timeout` is reached and mailserver-status is changed to error if it is not connected by then" [{:keys [db] :as cofx}] - (let [web3 (:web3 db) - wnode (get-current-wnode-address db) - peers-summary (:peers-summary db) - connected? (registered-peer? peers-summary wnode)] + (let [web3 (:web3 db) + {:keys [address] :as wnode} (get-current-wnode db) + peers-summary (:peers-summary db) + connected? (registered-peer? peers-summary address)] (when config/offline-inbox-enabled? (if connected? (handlers-macro/merge-fx cofx (update-mailserver-status :connected) - (generate-mailserver-symkey)) + (generate-mailserver-symkey wnode)) (handlers-macro/merge-fx cofx - {::add-peer {:wnode wnode} + {::add-peer {:wnode address} :utils/dispatch-later [{:ms connection-timeout :dispatch [:inbox/check-connection]}]} (update-mailserver-status :connecting) - (generate-mailserver-symkey)))))) + (generate-mailserver-symkey wnode)))))) (defn peers-summary-change-fx "There is only 2 summary changes that require offline inboxing action: @@ -230,9 +235,8 @@ {::mark-trusted-peer {:web3 (:web3 db) :wnode wnode}})))) -(defn inbox-ready? [{:keys [db]}] - (let [mailserver-status (:mailserver-status db) - sym-key-id (:inbox/sym-key-id db)] +(defn inbox-ready? [{:keys [sym-key-id]} {:keys [db]}] + (let [mailserver-status (:mailserver-status db)] (and (= :connected mailserver-status) sym-key-id))) @@ -253,25 +257,22 @@ (defn request-messages ([{:keys [db now] :as cofx}] - (let [wnode (get-current-wnode-address db) + (let [wnode (get-current-wnode db) web3 (:web3 db) - sym-key-id (:inbox/sym-key-id db) now-in-s (quot now 1000) last-request (get-in db [:account/account :last-request] (- now-in-s seven-days)) request-messages-topics (get-request-messages-topics db) request-history-topics (get-request-history-topics db)] - (when (inbox-ready? cofx) + (when (inbox-ready? wnode cofx) {::request-messages {:wnode wnode :topics request-messages-topics :from last-request :to now-in-s - :sym-key-id sym-key-id :web3 web3} ::request-history {:wnode wnode :now-in-s now-in-s :topics request-history-topics - :sym-key-id sym-key-id :web3 web3} :db (assoc db :inbox/fetching? true) :dispatch-later [{:ms fetching-timeout @@ -281,16 +282,14 @@ (request-messages cofx)))) (defn request-chat-history [chat-id {:keys [db now] :as cofx}] - (let [wnode (get-current-wnode-address db) + (let [wnode (get-current-wnode db) web3 (:web3 db) - sym-key-id (:inbox/sym-key-id db) topic (get-in db [:transport/chats chat-id :topic]) now-in-s (quot now 1000)] - (when (inbox-ready? cofx) + (when (inbox-ready? wnode cofx) {::request-history {:wnode wnode :topics [topic] :now-in-s now-in-s - :sym-key-id sym-key-id :web3 web3} :db (assoc db :inbox/fetching? true) :dispatch-later [{:ms fetching-timeout @@ -316,9 +315,9 @@ (handlers/register-handler-fx :inbox/get-sym-key-success - (fn [{:keys [db] :as cofx} [_ sym-key-id]] + (fn [{:keys [db] :as cofx} [_ wnode sym-key-id]] (handlers-macro/merge-fx cofx - {:db (assoc db :inbox/sym-key-id sym-key-id)} + (add-sym-key-id-to-wnode wnode sym-key-id) (request-messages)))) (handlers/register-handler-fx diff --git a/src/status_im/ui/screens/db.cljs b/src/status_im/ui/screens/db.cljs index 772cfd46ad..b927188e80 100644 --- a/src/status_im/ui/screens/db.cljs +++ b/src/status_im/ui/screens/db.cljs @@ -43,7 +43,6 @@ :network constants/default-network :networks/networks constants/default-networks :inbox/wnodes constants/default-wnodes - :inbox/password constants/inbox-password :my-profile/editing? false :transport/chats {} :transport/message-envelopes {} @@ -174,8 +173,6 @@ :node/after-start :node/after-stop :inbox/wnodes - :inbox/password - :inbox/sym-key-id :inbox/last-received :inbox/fetching? :browser/browsers diff --git a/src/status_im/ui/screens/offline_messaging_settings/db.cljs b/src/status_im/ui/screens/offline_messaging_settings/db.cljs index f6af44a79a..201234e706 100644 --- a/src/status_im/ui/screens/offline_messaging_settings/db.cljs +++ b/src/status_im/ui/screens/offline_messaging_settings/db.cljs @@ -1,20 +1,21 @@ (ns status-im.ui.screens.offline-messaging-settings.db (:require-macros [status-im.utils.db :refer [allowed-keys]]) (:require - [cljs.spec.alpha :as spec] - [status-im.utils.inbox :as utils.inbox])) + [status-im.models.mailserver :as models.mailserver] + [cljs.spec.alpha :as spec])) (spec/def ::not-blank-string (spec/and string? seq)) -(spec/def :wnode/address (spec/and string? utils.inbox/valid-enode-address?)) +(spec/def :wnode/address (spec/and string? models.mailserver/valid-enode-address?)) (spec/def :wnode/name ::not-blank-string) (spec/def :wnode/id ::not-blank-string) (spec/def :wnode/user-defined boolean?) -(spec/def :wnode/password (spec/nilable string?)) +(spec/def :wnode/password ::not-blank-string) +(spec/def :wnode/sym-key-id string?) (spec/def :wnode/wnode (allowed-keys :req-un [:wnode/address :wnode/name :wnode/id] - :opt-un [:wnode/user-defined :wnode/password])) + :opt-un [:wnode/sym-key-id + :wnode/user-defined + :wnode/password])) -(spec/def :inbox/password ::not-blank-string) (spec/def :inbox/wnodes (spec/nilable (spec/map-of keyword? (spec/map-of :wnode/id :wnode/wnode)))) -(spec/def :inbox/sym-key-id string?) (spec/def :inbox/last-received integer?) diff --git a/src/status_im/utils/inbox.cljs b/src/status_im/utils/inbox.cljs deleted file mode 100644 index ab0bca5857..0000000000 --- a/src/status_im/utils/inbox.cljs +++ /dev/null @@ -1,17 +0,0 @@ -(ns status-im.utils.inbox) - -(def enode-address-regex #"enode://[a-zA-Z0-9]+:?(.*)\@\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\b:(\d{1,5})") - -(defn- extract-url-components [address] - (rest (re-matches #"enode://(.*?):(.*)@(.*)" address))) - -(defn address->mailserver [address] - (let [[enode password url :as response] (extract-url-components address)] - (cond-> {:address (if (seq response) - (str "enode://" enode "@" url) - address) - :user-defined true} - password (assoc :password password)))) - -(defn valid-enode-address? [address] - (re-matches enode-address-regex address)) diff --git a/test/cljs/status_im/test/models/mailserver.cljs b/test/cljs/status_im/test/models/mailserver.cljs index 9125d3d2c3..a0eb4c8a0c 100644 --- a/test/cljs/status_im/test/models/mailserver.cljs +++ b/test/cljs/status_im/test/models/mailserver.cljs @@ -9,6 +9,39 @@ (def valid-enode-address (str "enode://" enode-id "@" host)) (def valid-enode-url (str "enode://" enode-id ":" password "@" host)) +(deftest valid-enode-address-test + (testing "url without password" + (let [address "enode://1da276e34126e93babf24ec88aac1a7602b4cbb2e11b0961d0ab5e989ca9c261aa7f7c1c85f15550a5f1e5a5ca2305b53b9280cf5894d5ecf7d257b173136d40@167.99.209.61:30504"] + (is (model/valid-enode-address? address)))) + (testing "url with password" + (let [address "enode://1da276e34126e93babf24ec88aac1a7602b4cbb2e11b0961d0ab5e989ca9c261aa7f7c1c85f15550a5f1e5a5ca2305b53b9280cf5894d5ecf7d257b173136d40:somepasswordwith@and:@@167.99.209.61:30504"] + (is (not (model/valid-enode-address? address))))) + (testing "invalid url" + (is (not (model/valid-enode-address? "something not valid"))))) + +(deftest valid-enode-url-test + (testing "url without password" + (let [address "enode://1da276e34126e93babf24ec88aac1a7602b4cbb2e11b0961d0ab5e989ca9c261aa7f7c1c85f15550a5f1e5a5ca2305b53b9280cf5894d5ecf7d257b173136d40@167.99.209.61:30504"] + (is (not (model/valid-enode-url? address))))) + (testing "url with password" + (let [address "enode://1da276e34126e93babf24ec88aac1a7602b4cbb2e11b0961d0ab5e989ca9c261aa7f7c1c85f15550a5f1e5a5ca2305b53b9280cf5894d5ecf7d257b173136d40:somepasswordwith@and:@@167.99.209.61:30504"] + (is (model/valid-enode-url? address)))) + (testing "invalid url" + (is (not (model/valid-enode-url? "something not valid"))))) + +(deftest address->mailserver + (testing "with password" + (let [address "enode://some-id:the-password@206.189.56.154:30504"] + (is (= {:address "enode://some-id@206.189.56.154:30504" + :password "the-password" + :user-defined true} + (model/address->mailserver address))))) + (testing "without password" + (let [address "enode://some-id@206.189.56.154:30504"] + (is (= {:address "enode://some-id@206.189.56.154:30504" + :user-defined true} + (model/address->mailserver address)))))) + (deftest set-input (testing "it validates names" (testing "correct name" diff --git a/test/cljs/status_im/test/runner.cljs b/test/cljs/status_im/test/runner.cljs index 2bfd684f2b..e481f63829 100644 --- a/test/cljs/status_im/test/runner.cljs +++ b/test/cljs/status_im/test/runner.cljs @@ -25,7 +25,6 @@ [status-im.test.utils.money] [status-im.test.utils.handlers-macro] [status-im.test.utils.clocks] - [status-im.test.utils.inbox] [status-im.test.utils.ethereum.eip681] [status-im.test.utils.ethereum.core] [status-im.test.utils.random] @@ -74,7 +73,6 @@ 'status-im.test.utils.handlers-macro 'status-im.test.utils.money 'status-im.test.utils.clocks - 'status-im.test.utils.inbox 'status-im.test.utils.ethereum.eip681 'status-im.test.utils.ethereum.core 'status-im.test.utils.random diff --git a/test/cljs/status_im/test/transport/inbox.cljs b/test/cljs/status_im/test/transport/inbox.cljs index 0778c97dfa..03d7265da2 100644 --- a/test/cljs/status_im/test/transport/inbox.cljs +++ b/test/cljs/status_im/test/transport/inbox.cljs @@ -5,14 +5,14 @@ (defn cofx-fixtures [sym-key registered-peer?] {:db {:mailserver-status :connected - :inbox/sym-key-id sym-key :network "mainnet_rpc" :peers-summary (if registered-peer? [{:id "wnode-id"}] []) :account/account {:networks constants/default-networks :settings {:wnode {:mainnet "mailserver-a"}}} - :inbox/wnodes {:mainnet {"mailserver-a" {:address "enode://wnode-id@ip"}}}}}) + :inbox/wnodes {:mainnet {"mailserver-a" {:sym-key-id sym-key + :address "enode://wnode-id@ip"}}}}}) (defn peers-summary-change-fx-result [sym-key registered-peer? registered-peer-before?] (inbox/peers-summary-change-fx (if registered-peer-before? @@ -43,3 +43,26 @@ #{})) (is (= (into #{} (keys (peers-summary-change-fx-result true false false))) #{})))) + +(deftest connect-to-mailserver + (let [db {:network "mainnet" + :inbox/wnodes + {:mainnet {"wnodeid" {:address "wnode-address" + :password "wnode-password"}}} + :account/account + {:settings {:wnode {:mainnet "wnodeid"}} + :networks {"mainnet" {:config {:NetworkId 1}}}}}] + (testing "it adds the peer" + (is (= {:wnode "wnode-address"} + (::inbox/add-peer (inbox/connect-to-mailserver {:db db}))))) + (testing "it generates a sym key if hasn't been generated before" + (is (= "wnode-password" + (-> (inbox/connect-to-mailserver {:db db}) + :shh/generate-sym-key-from-password + :password)))) + (let [wnode-with-sym-key-db (assoc-in db + [:inbox/wnodes :mainnet "wnodeid" :sym-key-id] + "somesymkeyid")] + (testing "it does not generate a sym key if already present" + (is (not (-> (inbox/connect-to-mailserver {:db wnode-with-sym-key-db}) + :shh/generate-sym-key-from-password))))))) diff --git a/test/cljs/status_im/test/utils/inbox.cljs b/test/cljs/status_im/test/utils/inbox.cljs deleted file mode 100644 index 45907d4f68..0000000000 --- a/test/cljs/status_im/test/utils/inbox.cljs +++ /dev/null @@ -1,26 +0,0 @@ -(ns status-im.test.utils.inbox - (:require [cljs.test :refer-macros [deftest is testing]] - [status-im.utils.inbox :as inbox])) - -(deftest address->mailserver - (testing "with password" - (let [address "enode://some-id:the-password@206.189.56.154:30504"] - (is (= {:address "enode://some-id@206.189.56.154:30504" - :password "the-password" - :user-defined true} - (inbox/address->mailserver address))))) - (testing "without password" - (let [address "enode://some-id@206.189.56.154:30504"] - (is (= {:address "enode://some-id@206.189.56.154:30504" - :user-defined true} - (inbox/address->mailserver address)))))) - -(deftest valid-enode-address - (testing "a valid url without password" - (let [address "enode://1da276e34126e93babf24ec88aac1a7602b4cbb2e11b0961d0ab5e989ca9c261aa7f7c1c85f15550a5f1e5a5ca2305b53b9280cf5894d5ecf7d257b173136d40@167.99.209.61:30504"] - (is (inbox/valid-enode-address? address)))) - (testing "a valid url with password" - (let [address "enode://1da276e34126e93babf24ec88aac1a7602b4cbb2e11b0961d0ab5e989ca9c261aa7f7c1c85f15550a5f1e5a5ca2305b53b9280cf5894d5ecf7d257b173136d40:somepasswordwith@and:@@167.99.209.61:30504"] - (is (inbox/valid-enode-address? address))) - (testing "invalid url" - (is (not (inbox/valid-enode-address? "something not valid"))))))