Allow editing/deleting custom bootnodes

Signed-off-by: Andrea Maria Piana <andrea.maria.piana@gmail.com>
This commit is contained in:
Andrea Maria Piana 2018-06-01 14:32:37 +02:00
parent 19ff402b4b
commit 49592f3a50
No known key found for this signature in database
GPG Key ID: AA6CCA6DE0E06424
8 changed files with 161 additions and 25 deletions

View File

@ -43,21 +43,39 @@
(set-input :name (str name)))] (set-input :name (str name)))]
(assoc fxs :dispatch [:navigate-to :edit-bootnode]))) (assoc fxs :dispatch [:navigate-to :edit-bootnode])))
(defn save [{{:bootnodes/keys [manage] :account/keys [account] :as db} :db :as cofx}] (defn custom-bootnodes-in-use? [{:keys [db] :as cofx}]
(let [{:keys [name url]} manage (let [network (:network db)]
network (:network db) (get-in db [:account/account :settings :bootnodes network])))
bootnode (build
(:random-id cofx) (defn delete [id {{:account/keys [account] :as db} :db :as cofx}]
(:value name) (let [network (:network db)
(:value url) new-account (update-in account [:bootnodes network] dissoc id)]
network) (handlers-macro/merge-fx {:db (assoc db :account/account new-account)}
new-bootnodes (assoc-in (accounts.utils/account-update
(:bootnodes account) (select-keys new-account [:bootnodes])
[network (:id bootnode)] (when (custom-bootnodes-in-use? cofx)
bootnode)] [:logout])))))
(defn upsert [{{:bootnodes/keys [manage] :account/keys [account] :as db} :db :as cofx}]
(let [{:keys [name
id
url]} manage
network (:network db)
bootnode (build
(or (:value id) (:random-id cofx))
(:value name)
(:value url)
network)
new-bootnodes (assoc-in
(:bootnodes account)
[network (:id bootnode)]
bootnode)]
(handlers-macro/merge-fx (handlers-macro/merge-fx
cofx cofx
{:db (dissoc db :bootnodes/manage) {:db (dissoc db :bootnodes/manage)
:dispatch [:navigate-back]} :dispatch [:navigate-back]}
(accounts.utils/account-update {:bootnodes new-bootnodes})))) (accounts.utils/account-update
{:bootnodes new-bootnodes}
(when (custom-bootnodes-in-use? cofx)
[:logout])))))

View File

@ -597,6 +597,7 @@
;; TODO(dmitryn): come up with better description/naming. Suggested namings: Mailbox and Master Node ;; TODO(dmitryn): come up with better description/naming. Suggested namings: Mailbox and Master Node
:existing-wnodes "Existing mailservers" :existing-wnodes "Existing mailservers"
:add-mailserver "Add Mailserver" :add-mailserver "Add Mailserver"
:mailserver-details "Mailserver details"
:delete-mailserver-title "Delete mailserver" :delete-mailserver-title "Delete mailserver"
:delete-mailserver-are-you-sure "Are you sure you want to delete this mailserver?" :delete-mailserver-are-you-sure "Are you sure you want to delete this mailserver?"
:delete-mailserver "Delete mailserver" :delete-mailserver "Delete mailserver"
@ -632,7 +633,11 @@
:bootnodes-enabled "Bootnodes enabled" :bootnodes-enabled "Bootnodes enabled"
:bootnode-address "Bootnode address" :bootnode-address "Bootnode address"
:add-bootnode "Add bootnode" :add-bootnode "Add bootnode"
:bootnode-details "Bootnode details"
:specify-bootnode-address "Specify bootnode address" :specify-bootnode-address "Specify bootnode address"
:delete-bootnode-title "Delete bootnode"
:delete-bootnode-are-you-sure "Are you sure you want to delete this bootnode?"
:delete-bootnode "Delete bootnode"
:mainnet-warning-title "Warning!" :mainnet-warning-title "Warning!"
:mainnet-warning-text "While we highly appreciate your contribution as a tester of Status, wed like to point out the dangers. Youre switching to Mainnet mode which is still in Alpha. This means it is still in development and has not been audited yet. Some of the risks you may be exposed to include:\n\n- Accounts may be unrecoverable due to breaking changes\n- Loss of ETH and tokens\n- Failure to send or receive messages\n\nSwitching to Mainnet should be done for testing purposes only. By tapping \"I understand\", you confirm that you assume the full responsibility for all risks concerning your data and funds. " :mainnet-warning-text "While we highly appreciate your contribution as a tester of Status, wed like to point out the dangers. Youre switching to Mainnet mode which is still in Alpha. This means it is still in development and has not been audited yet. Some of the risks you may be exposed to include:\n\n- Accounts may be unrecoverable due to breaking changes\n- Loss of ETH and tokens\n- Failure to send or receive messages\n\nSwitching to Mainnet should be done for testing purposes only. By tapping \"I understand\", you confirm that you assume the full responsibility for all risks concerning your data and funds. "

View File

@ -8,7 +8,7 @@
:save-new-bootnode :save-new-bootnode
[(re-frame/inject-cofx :random-id)] [(re-frame/inject-cofx :random-id)]
(fn [cofx _] (fn [cofx _]
(models.bootnode/save cofx))) (models.bootnode/upsert cofx)))
(handlers/register-handler-fx (handlers/register-handler-fx
:bootnode-set-input :bootnode-set-input
@ -20,6 +20,12 @@
(fn [cofx [_ bootnode-id]] (fn [cofx [_ bootnode-id]]
(models.bootnode/edit bootnode-id cofx))) (models.bootnode/edit bootnode-id cofx)))
(handlers/register-handler-fx
:delete-bootnode
(fn [cofx [_ bootnode-id]]
(assoc (models.bootnode/delete bootnode-id cofx)
:dispatch [:navigate-back])))
(handlers/register-handler-fx (handlers/register-handler-fx
:set-bootnode-from-qr :set-bootnode-from-qr
(fn [cofx [_ _ url]] (fn [cofx [_ _ url]]

View File

@ -29,3 +29,25 @@
{:flex-direction :row {:flex-direction :row
:margin-horizontal 12 :margin-horizontal 12
:margin-vertical 15}) :margin-vertical 15})
(def button-container
{:margin-top 8
:margin-bottom 16
:margin-horizontal 16})
(def button
{:height 52
:align-items :center
:justify-content :center
:border-radius 8
:ios {:opacity 0.9}})
(defstyle button-label
{:color colors/white
:ios {:font-size 17
:letter-spacing -0.2}
:android {:font-size 14}})
(defstyle delete-button
(assoc button
:background-color colors/red))

View File

@ -4,6 +4,7 @@
[re-frame.core :as re-frame] [re-frame.core :as re-frame]
[status-im.ui.components.react :as react] [status-im.ui.components.react :as react]
[status-im.i18n :as i18n] [status-im.i18n :as i18n]
[status-im.utils.utils :as utils]
[status-im.ui.components.styles :as components.styles] [status-im.ui.components.styles :as components.styles]
[status-im.ui.components.common.common :as components.common] [status-im.ui.components.common.common :as components.common]
[status-im.ui.components.colors :as colors] [status-im.ui.components.colors :as colors]
@ -13,6 +14,21 @@
[status-im.ui.components.text-input.view :as text-input] [status-im.ui.components.text-input.view :as text-input]
[status-im.ui.screens.bootnodes-settings.edit-bootnode.styles :as styles])) [status-im.ui.screens.bootnodes-settings.edit-bootnode.styles :as styles]))
(defn handle-delete [id]
(utils/show-confirmation (i18n/label :t/delete-bootnode-title)
(i18n/label :t/delete-bootnode-are-you-sure)
(i18n/label :t/delete-bootnode)
#(re-frame/dispatch [:delete-bootnode id])))
(defn delete-button [id]
[react/touchable-highlight {:on-press #(handle-delete id)}
[react/view styles/button-container
[react/view {:style styles/delete-button
:accessibility-label :bootnode-delete-button}
[react/text {:style styles/button-label
:uppercase? true}
(i18n/label :t/delete)]]]])
(def qr-code (def qr-code
[react/touchable-highlight {:on-press #(re-frame/dispatch [:scan-qr-code [react/touchable-highlight {:on-press #(re-frame/dispatch [:scan-qr-code
{:toolbar-title (i18n/label :t/add-bootnode)} {:toolbar-title (i18n/label :t/add-bootnode)}
@ -25,12 +41,13 @@
(views/letsubs [manage-bootnode [:get-manage-bootnode] (views/letsubs [manage-bootnode [:get-manage-bootnode]
is-valid? [:manage-bootnode-valid?]] is-valid? [:manage-bootnode-valid?]]
(let [url (get-in manage-bootnode [:url :value]) (let [url (get-in manage-bootnode [:url :value])
id (get-in manage-bootnode [:id :value])
name (get-in manage-bootnode [:name :value])] name (get-in manage-bootnode [:name :value])]
[react/view components.styles/flex [react/view components.styles/flex
[status-bar/status-bar] [status-bar/status-bar]
[react/keyboard-avoiding-view components.styles/flex [react/keyboard-avoiding-view components.styles/flex
[toolbar/simple-toolbar (i18n/label :t/add-bootnode)] [toolbar/simple-toolbar (i18n/label (if id :t/bootnode-details :t/add-bootnode))]
[react/scroll-view [react/scroll-view
[react/view styles/edit-bootnode-view [react/view styles/edit-bootnode-view
[text-input/text-input-with-label [text-input/text-input-with-label
@ -48,7 +65,9 @@
:style styles/input :style styles/input
:container styles/input-container :container styles/input-container
:default-value url :default-value url
:on-change-text #(re-frame/dispatch [:bootnode-set-input :url %])}]]] :on-change-text #(re-frame/dispatch [:bootnode-set-input :url %])}]
(when id
[delete-button id])]]
[react/view styles/bottom-container [react/view styles/bottom-container
[react/view components.styles/flex] [react/view components.styles/flex]
[components.common/bottom-button [components.common/bottom-button

View File

@ -13,12 +13,13 @@
[status-im.ui.screens.profile.components.views :as profile.components] [status-im.ui.screens.profile.components.views :as profile.components]
[status-im.ui.screens.bootnodes-settings.styles :as styles])) [status-im.ui.screens.bootnodes-settings.styles :as styles]))
(defn navigate-to-add-bootnode [] (defn navigate-to-add-bootnode [id]
(re-frame/dispatch [:edit-bootnode])) (re-frame/dispatch [:edit-bootnode id]))
(defn render-row [{:keys [name id]}] (defn render-row [{:keys [name id]}]
[react/view [react/touchable-highlight
{:accessibility-label :bootnode-item} {:on-press #(navigate-to-add-bootnode id)
:accessibility-label :bootnode-item}
[react/view styles/bootnode-item [react/view styles/bootnode-item
[react/view styles/bootnode-item-inner [react/view styles/bootnode-item-inner
[react/text {:style styles/bootnode-item-name-text} [react/text {:style styles/bootnode-item-name-text}
@ -33,7 +34,7 @@
toolbar/default-nav-back toolbar/default-nav-back
[toolbar/content-title (i18n/label :t/bootnodes-settings)] [toolbar/content-title (i18n/label :t/bootnodes-settings)]
[toolbar/actions [toolbar/actions
[(toolbar.actions/add false navigate-to-add-bootnode)]]] [(toolbar.actions/add false #(navigate-to-add-bootnode nil))]]]
[react/view styles/switch-container [react/view styles/switch-container
[profile.components/settings-switch-item [profile.components/settings-switch-item
{:label-kw :t/bootnodes-enabled {:label-kw :t/bootnodes-enabled

View File

@ -57,7 +57,7 @@
[react/view components.styles/flex [react/view components.styles/flex
[status-bar/status-bar] [status-bar/status-bar]
[react/keyboard-avoiding-view components.styles/flex [react/keyboard-avoiding-view components.styles/flex
[toolbar/simple-toolbar (i18n/label :t/add-mailserver)] [toolbar/simple-toolbar (i18n/label (if id :t/mailserver-details :t/add-mailserver))]
[react/scroll-view [react/scroll-view
[react/view styles/edit-mailserver-view [react/view styles/edit-mailserver-view
[text-input/text-input-with-label [text-input/text-input-with-label

View File

@ -7,19 +7,38 @@
(def valid-bootnode-address (str "enode://" bootnode-id "@" host)) (def valid-bootnode-address (str "enode://" bootnode-id "@" host))
(deftest save-bootnode (deftest upsert-bootnode
(testing "adding a bootnode" (testing "adding a new bootnode"
(let [new-bootnode {:name {:value "name"} (let [new-bootnode {:name {:value "name"}
:url {:value "url"}} :url {:value "url"}}
expected {"mainnet_rpc" {"someid" {:name "name" expected {"mainnet_rpc" {"someid" {:name "name"
:address "url" :address "url"
:chain "mainnet_rpc" :chain "mainnet_rpc"
:id "someid"}}} :id "someid"}}}
actual (model/save actual (model/upsert
{:random-id "some-id" {:random-id "some-id"
:db {:bootnodes/manage new-bootnode :db {:bootnodes/manage new-bootnode
:network "mainnet_rpc" :network "mainnet_rpc"
:account/account {}}})] :account/account {}}})]
(is (= expected (get-in actual [:db :account/account :bootnodes])))))
(testing "adding an existing bootnode"
(let [new-bootnode {:id {:value "a"}
:name {:value "new-name"}
:url {:value "new-url"}}
expected {"mainnet_rpc" {"a" {:name "new-name"
:address "new-url"
:chain "mainnet_rpc"
:id "a"}}}
actual (model/upsert
{:random-id "some-id"
:db {:bootnodes/manage new-bootnode
:network "mainnet_rpc"
:account/account {:bootnodes
{"mainnet_rpc"
{"a" {:name "name"
:address "url"
:chain "mainnet_rpc"
:id "a"}}}}}})]
(is (= expected (get-in actual [:db :account/account :bootnodes])))))) (is (= expected (get-in actual [:db :account/account :bootnodes]))))))
(deftest set-input-bootnode (deftest set-input-bootnode
@ -100,3 +119,49 @@
:name "name" :name "name"
:address "enode://old-id:old-password@url:port"}}}}}}] :address "enode://old-id:old-password@url:port"}}}}}}]
(is (model/fetch "a" cofx))))) (is (model/fetch "a" cofx)))))
(deftest custom-bootnodes-in-use?
(testing "is on the same network"
(testing "it returns false when not enabled"
(is (not (model/custom-bootnodes-in-use? {:db {:network "mainnet_rpc"}}))))
(testing "it returns true when enabled"
(is (model/custom-bootnodes-in-use?
{:db {:network "mainnet_rpc"
:account/account {:settings
{:bootnodes
{"mainnet_rpc" true}}}}}))))
(testing "is on a different network"
(testing "it returns false when not enabled"
(is (not (model/custom-bootnodes-in-use? {:db {:network "testnet_rpc"}}))))
(testing "it returns true when enabled"
(is (not (model/custom-bootnodes-in-use?
{:db {:network "testnet_rpc"
:account/account {:settings
{:bootnodes
{"mainnnet_rpc" true}}}}}))))))
(deftest delete-bootnode
(testing "non existing bootnode"
(let [cofx {:db {:network "mainnet_rpc"
:account/account {:bootnodes {"mainnet_rpc"
{"a" {:id "a"
:name "name"
:address "enode://old-id:old-password@url:port"}}}
:settings {:bootnodes
{"mainnnet_rpc" true}}}}}
actual (model/delete "b" cofx)]
(testing "it does not removes the bootnode"
(is (model/fetch "a" actual)))))
(testing "existing bootnode"
(let [cofx {:db {:network "mainnet_rpc"
:account/account {:bootnodes {"mainnet_rpc"
{"a" {:id "a"
:name "name"
:address "enode://old-id:old-password@url:port"}}}
:settings {:bootnodes
{"mainnnet_rpc" true}}}}}
actual (model/delete "a" cofx)]
(testing "it removes the bootnode"
(is (not (model/fetch "a" actual))))
(testing "it updates the db"
(is (= 1 (count (:data-store/base-tx actual))))))))