Validate rpc-url when creating a custom network

Signed-off-by: Andrea Maria Piana <andrea.maria.piana@gmail.com>
This commit is contained in:
Andrea Maria Piana 2018-06-08 13:50:58 +02:00
parent c66c457bbb
commit 34174cd539
No known key found for this signature in database
GPG Key ID: AA6CCA6DE0E06424
5 changed files with 162 additions and 52 deletions

View File

@ -0,0 +1,66 @@
(ns status-im.models.network
(:require [clojure.string :as string]
[status-im.utils.ethereum.core :as ethereum]
[status-im.utils.handlers-macro :as handlers-macro]
[status-im.ui.screens.accounts.utils :as accounts.utils]))
(def url-regex
#"https?://(www\.)?[-a-zA-Z0-9@:%._\+~#=]{2,256}(\.[a-z]{2,6})?\b([-a-zA-Z0-9@:%_\+.~#?&//=]*)")
(defn valid-rpc-url? [url]
(boolean (re-matches url-regex (str url))))
(def default-manage
{:name {:value ""}
:url {:value ""}
:chain {:value :mainnet}})
(defn validate-string [{:keys [value]}]
{:value value
:error (string/blank? value)})
(defn validate-url [{:keys [value]}]
{:value value
:error (not (valid-rpc-url? value))})
(defn validate-manage [manage]
(-> manage
(update :url validate-url)
(update :name validate-string)
(update :chain validate-string)))
(defn valid-manage? [manage]
(->> (validate-manage manage)
vals
(map :error)
(not-any? identity)))
(defn- new-network [{:keys [random-id] :as cofx} network-name upstream-url type]
(let [data-dir (str "/ethereum/" (name type) "_rpc")
config {:NetworkId (ethereum/chain-keyword->chain-id type)
:DataDir data-dir
:UpstreamConfig {:Enabled true
:URL upstream-url}}]
{:id (string/replace random-id "-" "")
:name network-name
:config config}))
(defn set-input [input-key value {:keys [db]}]
{:db (-> db
(update-in [:networks/manage input-key] assoc :value value)
(update-in [:networks/manage] validate-manage))})
(defn save [{{:networks/keys [manage] :account/keys [account] :as db} :db :as cofx}]
(when (valid-manage? manage)
(let [{:keys [name url chain]} manage
network (new-network cofx (:value name) (:value url) (:value chain))
new-networks (merge {(:id network) network} (:networks account))]
(handlers-macro/merge-fx cofx
{:db (dissoc db :networks/manage)
:dispatch [:navigate-back]}
(accounts.utils/account-update {:networks new-networks})))))
;; No edit functionality actually implemented
(defn edit [{db :db}]
{:db (assoc db :networks/manage (validate-manage default-manage))
:dispatch [:navigate-to :edit-network]})

View File

@ -1,46 +1,20 @@
(ns status-im.ui.screens.network-settings.edit-network.events
(:require [re-frame.core :as re-frame]
[status-im.utils.handlers :refer [register-handler] :as handlers]
[status-im.utils.handlers-macro :as handlers-macro]
[status-im.ui.screens.accounts.utils :as accounts.utils]
[status-im.utils.ethereum.core :as ethereum]
[status-im.utils.types :as types]
[clojure.string :as string]))
(defn- new-network [{:keys [random-id] :as cofx} network-name upstream-url type]
(let [data-dir (str "/ethereum/" (name type) "_rpc")
config {:NetworkId (ethereum/chain-keyword->chain-id type)
:DataDir data-dir
:UpstreamConfig {:Enabled true
:URL upstream-url}}]
{:id (string/replace random-id "-" "")
:name network-name
:config config}))
[status-im.models.network :as models.network]
[status-im.utils.handlers :refer [register-handler] :as handlers]))
(handlers/register-handler-fx
:save-new-network
[(re-frame/inject-cofx :random-id)]
(fn [{{:networks/keys [manage] :account/keys [account] :as db} :db :as cofx} _]
(let [{:keys [name url chain]} manage
network (new-network cofx (:value name) (:value url) (:value chain))
new-networks (merge {(:id network) network} (:networks account))]
(handlers-macro/merge-fx cofx
{:db (dissoc db :networks/manage)
:dispatch [:navigate-back]}
(accounts.utils/account-update {:networks new-networks})))))
(fn [cofx _]
(models.network/save cofx)))
(handlers/register-handler-fx
:network-set-input
(fn [{db :db} [_ input-key value]]
{:db (update db :networks/manage merge {input-key {:value value
:error (and (string? value) (empty? value))}})}))
(fn [cofx [_ input-key value]]
(models.network/set-input input-key value cofx)))
(handlers/register-handler-fx
:edit-network
(fn [{db :db} _]
{:db (update-in db [:networks/manage] assoc
:name {:error true}
:url {:error true}
:chain {:value :mainnet})
:dispatch [:navigate-to :edit-network]}))
(fn [cofx _]
(models.network/edit cofx)))

View File

@ -0,0 +1,86 @@
(ns status-im.test.models.network
(:require [cljs.test :refer-macros [deftest is testing]]
[status-im.models.network :as model]))
(deftest valid-rpc-url-test
(testing "nil?"
(is (not (model/valid-rpc-url? nil))))
(testing "a blank url"
(is (not (model/valid-rpc-url? ""))))
(testing "a url without a protocol"
(is (not (model/valid-rpc-url? "something"))))
(testing "a url without a protocol"
(is (not (model/valid-rpc-url? "http://something with space"))))
(testing "a url without a hostname"
(is (not (model/valid-rpc-url? "https://"))))
(testing "an http url"
(is (model/valid-rpc-url? "http://valid.com")))
(testing "an https url"
(is (model/valid-rpc-url? "https://valid.something.else")))
(testing "a fully qualified url"
(is (model/valid-rpc-url? "https://mainnet.infura.io:6523/z6GCTmjdP3FETEJmMBI4")))
(testing "an ip address"
(is (model/valid-rpc-url? "https://192.168.1.1")))
(testing "localhost"
(is (model/valid-rpc-url? "https://localhost")))
(testing "a fully qualified url, ip address"
(is (model/valid-rpc-url? "https://192.168.1.1:6523/z6GCTmjdP3FETEJmMBI4")))
(testing "an https url not on the default port"
(is (model/valid-rpc-url? "https://valid.something.else:65323"))))
(deftest new-network-test
(let [actual (model/new-network {:random-id "random-id"}
"network-name"
"upstream-url"
:mainnet)]
(is (= {:id "randomid"
:name "network-name"
:config {:NetworkId 1
:DataDir "/ethereum/mainnet_rpc"
:UpstreamConfig {:Enabled true
:URL "upstream-url"}}}
actual))))
(deftest valid-manage-test
(testing "a valid manage"
(is (model/valid-manage? {:url {:value "http://valid.com"}
:name {:value "valid"}
:chain {:value "valid"}})))
(testing "invalid url"
(is (not (model/valid-manage? {:url {:value "invalid"}
:name {:value "valid"}
:chain {:value "valid"}}))))
(testing "invalid name"
(is (not (model/valid-manage? {:url {:value "http://valid.com"}
:name {:value ""}
:chain {:value "valid"}}))))
(testing "invalid chain"
(is (not (model/valid-manage? {:url {:value "http://valid.com"}
:name {:value "valid"}
:chain {:value ""}})))))
(deftest set-input-test
(testing "it updates and validate a field"
(is (= {:db {:networks/manage {:url {:value "http://valid.com"
:error false}
:name {:value ""
:error true}
:chain {:value "mainnet"
:error false}}}}
(model/set-input :url "http://valid.com"
{:db {:networks/manage {:url {:value "something"
:error true}
:name {:value ""
:error false}
:chain {:value "mainnet"
:error false}}}})))))
(deftest save
(testing "it does not save a network with an invalid url"
(is (nil? (model/save {:random-id "random"
:db {:networks/manage {:url {:value "wrong"}
:chain {:value "1"}
:name {:value "empty"}}
:account/account {}}})))))

View File

@ -14,6 +14,7 @@
[status-im.test.models.bootnode]
[status-im.test.models.account]
[status-im.test.models.contact]
[status-im.test.models.network]
[status-im.test.transport.core]
[status-im.test.transport.inbox]
[status-im.test.transport.handlers]
@ -39,7 +40,6 @@
[status-im.test.utils.datetime]
[status-im.test.utils.mixpanel]
[status-im.test.utils.prices]
[status-im.test.ui.screens.network-settings.edit-network.events]
[status-im.test.ui.screens.accounts.login.events]))
(enable-console-print!)
@ -64,6 +64,7 @@
'status-im.test.models.bootnode
'status-im.test.models.account
'status-im.test.models.contact
'status-im.test.models.network
'status-im.test.bots.events
'status-im.test.wallet.subs
'status-im.test.wallet.transactions.subs
@ -90,5 +91,4 @@
'status-im.test.utils.datetime
'status-im.test.utils.mixpanel
'status-im.test.utils.prices
'status-im.test.ui.screens.network-settings.edit-network.events
'status-im.test.ui.screens.accounts.login.events)

View File

@ -1,16 +0,0 @@
(ns status-im.test.ui.screens.network-settings.edit-network.events
(:require [cljs.test :refer-macros [deftest is testing]]
[status-im.ui.screens.network-settings.edit-network.events :as events]))
(deftest new-network
(let [actual (events/new-network {:random-id "random-id"}
"network-name"
"upstream-url"
:mainnet)]
(is (= {:id "randomid"
:name "network-name"
:config {:NetworkId 1
:DataDir "/ethereum/mainnet_rpc"
:UpstreamConfig {:Enabled true
:URL "upstream-url"}}}
actual))))