From 7ef3a5a5dab34500608ef30f3e2dd4b9ce95f55a Mon Sep 17 00:00:00 2001 From: Andrea Maria Piana Date: Fri, 1 Jun 2018 10:04:48 +0200 Subject: [PATCH] Delete mailservers Signed-off-by: Andrea Maria Piana --- src/status_im/data_store/mailservers.cljs | 9 +- src/status_im/models/mailserver.cljs | 86 ++++++++++++++++++ src/status_im/models/wnode.cljs | 22 ----- src/status_im/translations/en.cljs | 3 + .../edit_mailserver/events.cljs | 77 ++++------------ .../edit_mailserver/styles.cljs | 24 +++-- .../edit_mailserver/subs.cljs | 10 ++- .../edit_mailserver/views.cljs | 27 +++++- .../events.cljs => models/mailserver.cljs} | 90 +++++++++++++++---- test/cljs/status_im/test/runner.cljs | 4 +- 10 files changed, 233 insertions(+), 119 deletions(-) create mode 100644 src/status_im/models/mailserver.cljs delete mode 100644 src/status_im/models/wnode.cljs rename test/cljs/status_im/test/{offline_messaging_settings/events.cljs => models/mailserver.cljs} (58%) diff --git a/src/status_im/data_store/mailservers.cljs b/src/status_im/data_store/mailservers.cljs index 237620224c..abfa25ce96 100644 --- a/src/status_im/data_store/mailservers.cljs +++ b/src/status_im/data_store/mailservers.cljs @@ -9,7 +9,7 @@ (core/get-all :mailserver) (core/all-clj :mailserver))))) -(defn save-mailserver-tx +(defn save-tx "Returns tx function for saving a mailserver" [{:keys [id] :as mailserver}] (fn [realm] @@ -17,3 +17,10 @@ :mailserver mailserver (core/exists? realm :mailserver :id id)))) + +(defn delete-tx + "Returns tx function for deleting a mailserver" + [id] + (fn [realm] + (core/delete realm + (core/get-by-field realm :mailserver :id id)))) diff --git a/src/status_im/models/mailserver.cljs b/src/status_im/models/mailserver.cljs new file mode 100644 index 0000000000..7ce4e07489 --- /dev/null +++ b/src/status_im/models/mailserver.cljs @@ -0,0 +1,86 @@ +(ns status-im.models.mailserver + (:require + [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])) + +(defn- extract-address-components [address] + (rest (re-matches #"enode://(.*)@(.*)" address))) + +(defn- get-chain [db] + (let [network (get (:networks (:account/account db)) (:network db))] + (ethereum/network->chain-keyword network))) + +(defn- build [id mailserver-name address] + (assoc (utils.inbox/address->mailserver address) + :id (string/replace id "-" "") + :name mailserver-name)) + +(defn build-url [address password] + (let [[initial host] (extract-address-components address)] + (str "enode://" initial ":" password "@" host))) + +(defn set-input [input-key value {:keys [db]}] + {:db (update + db + :mailservers/manage + assoc + input-key + {:value value + :error (case input-key + :id false + :name (string/blank? value) + :url (not (utils.inbox/valid-enode-address? value)))})}) + +(defn connected? [id {:keys [db]}] + (let [current-id (get-in db [:account/account :settings :wnode (get-chain db)])] + (= current-id id))) + +(defn fetch [id {:keys [db]}] + (get-in db [:inbox/wnodes (get-chain db) id])) + +(def default? (comp not :user-defined fetch)) + +(defn delete [id {:keys [db] :as cofx}] + (when-not (or + (default? id cofx) + (connected? id cofx)) + {:db (update-in db [:inbox/wnodes (get-chain db)] dissoc id) + :data-store/tx [(data-store.mailservers/delete-tx id)]})) + +(defn edit [id {:keys [db] :as cofx}] + (let [{:keys [id + address + password + name]} (fetch id cofx) + url (when address (build-url address password)) + fxs (handlers-macro/merge-fx + cofx + (set-input :id id) + (set-input :url (str url)) + (set-input :name (str name)))] + (assoc fxs :dispatch [:navigate-to :edit-mailserver]))) + +(defn upsert [{{:mailservers/keys [manage] :account/keys [account] :as db} :db :as cofx}] + (let [{:keys [name url id]} manage + network (get (:networks (:account/account db)) (:network db)) + chain (ethereum/network->chain-keyword network) + mailserver (build + (or (:value id) + (string/replace (:random-id cofx) "-" "")) + (:value name) + (:value url)) + current (connected? (:id mailserver) cofx)] + {:db (-> db + (dissoc :mailservers/manage) + (assoc-in [:inbox/wnodes chain (:id mailserver)] mailserver)) + :data-store/tx [{:transaction + (data-store.mailservers/save-tx (assoc + mailserver + :chain + chain)) + ;; we naively logout if the user is connected to the edited mailserver + :success-event (when current [:logout])}] + :dispatch [:navigate-back]})) diff --git a/src/status_im/models/wnode.cljs b/src/status_im/models/wnode.cljs deleted file mode 100644 index 634c1a25ad..0000000000 --- a/src/status_im/models/wnode.cljs +++ /dev/null @@ -1,22 +0,0 @@ -(ns status-im.models.wnode - (:require - [clojure.string :as string] - [status-im.utils.ethereum.core :as ethereum])) - -(defn- extract-address-components [address] - (rest (re-matches #"enode://(.*)@(.*)" address))) - -(defn- get-chain [db] - (let [network (get (:networks (:account/account db)) (:network db))] - (ethereum/network->chain-keyword network))) - -(defn get-wnode [wnode-id {:keys [db]}] - (get-in db [:inbox/wnodes (get-chain db) wnode-id])) - -(defn current-wnode? [wnode-id {:keys [db]}] - (let [current-wnode-id (get-in db [:account/account :settings :wnode (get-chain db)])] - (= current-wnode-id wnode-id))) - -(defn build-url [address password] - (let [[initial host] (extract-address-components address)] - (str "enode://" initial ":" password "@" host))) diff --git a/src/status_im/translations/en.cljs b/src/status_im/translations/en.cljs index 0e3031bb6e..7da688e91e 100644 --- a/src/status_im/translations/en.cljs +++ b/src/status_im/translations/en.cljs @@ -597,6 +597,9 @@ ;; TODO(dmitryn): come up with better description/naming. Suggested namings: Mailbox and Master Node :existing-wnodes "Existing mailservers" :add-mailserver "Add Mailserver" + :delete-mailserver-title "Delete mailserver" + :delete-mailserver-are-you-sure "Are you sure you want to delete this mailserver?" + :delete-mailserver "Delete mailserver" :mailserver-address "Mailserver address" :specify-mailserver-address "Specify a mailserver address" :add-json-file "Add a JSON file" diff --git a/src/status_im/ui/screens/offline_messaging_settings/edit_mailserver/events.cljs b/src/status_im/ui/screens/offline_messaging_settings/edit_mailserver/events.cljs index f4f3c0f5ee..976c2b0d37 100644 --- a/src/status_im/ui/screens/offline_messaging_settings/edit_mailserver/events.cljs +++ b/src/status_im/ui/screens/offline_messaging_settings/edit_mailserver/events.cljs @@ -1,79 +1,32 @@ (ns status-im.ui.screens.offline-messaging-settings.edit-mailserver.events - (:require [clojure.string :as string] - [re-frame.core :as re-frame] - [status-im.models.wnode :as models.wnode] - [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] - [status-im.utils.inbox :as utils.inbox] - [status-im.data-store.mailservers :as data-store.mailservers])) - -(defn- build-mailserver [id mailserver-name address] - (assoc (utils.inbox/address->mailserver address) - :id (string/replace id "-" "") - :name mailserver-name)) - -(defn upsert-mailserver [{{:mailservers/keys [manage] :account/keys [account] :as db} :db :as cofx} _] - (let [{:keys [name url id]} manage - network (get (:networks (:account/account db)) (:network db)) - chain (ethereum/network->chain-keyword network) - mailserver (build-mailserver - (or (:value id) - (string/replace (:random-id cofx) "-" "")) - (:value name) - (:value url)) - connected-to-wnode? (models.wnode/current-wnode? (:id mailserver) cofx)] - {:db (-> db - (dissoc :mailservers/manage) - (assoc-in [:inbox/wnodes chain (:id mailserver)] mailserver)) - :data-store/tx [{:transaction - (data-store.mailservers/save-mailserver-tx (assoc - mailserver - :chain - chain)) - ;; we naively logout if the user is connected to the edited mailserver - :success-event (when connected-to-wnode? [:logout])}] - :dispatch [:navigate-back]})) - -(defn set-input [input-key value {:keys [db]}] - {:db (update db :mailservers/manage assoc input-key {:value value - :error (case input-key - :id false - :name (string/blank? value) - :url (not (utils.inbox/valid-enode-address? value)))})}) - -(defn edit-mailserver [wnode-id {:keys [db] :as cofx}] - (let [{:keys [id - address - password - name]} (models.wnode/get-wnode wnode-id cofx) - url (when address (models.wnode/build-url address password)) - fxs (handlers-macro/merge-fx - cofx - (set-input :id id) - (set-input :url (str url)) - (set-input :name (str name)))] - (assoc fxs :dispatch [:navigate-to :edit-mailserver]))) + (:require [re-frame.core :as re-frame] + [status-im.models.mailserver :as models.mailserver] + [status-im.utils.handlers :refer [register-handler] :as handlers])) (handlers/register-handler-fx :upsert-mailserver [(re-frame/inject-cofx :random-id)] - upsert-mailserver) + (fn [cofx _] + (models.mailserver/upsert cofx))) (handlers/register-handler-fx :mailserver-set-input (fn [cofx [_ input-key value]] - (set-input input-key value cofx))) + (models.mailserver/set-input input-key value cofx))) (handlers/register-handler-fx :edit-mailserver - (fn [cofx [_ wnode-id]] - (edit-mailserver wnode-id cofx))) + (fn [cofx [_ mailserver-id]] + (models.mailserver/edit mailserver-id cofx))) + +(handlers/register-handler-fx + :delete-mailserver + (fn [cofx [_ mailserver-id]] + (assoc (models.mailserver/delete mailserver-id cofx) + :dispatch [:navigate-back]))) (handlers/register-handler-fx :set-mailserver-from-qr (fn [cofx [_ _ contact-identity]] - (assoc (set-input :url contact-identity cofx) + (assoc (models.mailserver/set-input :url contact-identity cofx) :dispatch [:navigate-back]))) diff --git a/src/status_im/ui/screens/offline_messaging_settings/edit_mailserver/styles.cljs b/src/status_im/ui/screens/offline_messaging_settings/edit_mailserver/styles.cljs index c4c4248b46..843037b526 100644 --- a/src/status_im/ui/screens/offline_messaging_settings/edit_mailserver/styles.cljs +++ b/src/status_im/ui/screens/offline_messaging_settings/edit_mailserver/styles.cljs @@ -30,30 +30,28 @@ :margin-horizontal 12 :margin-vertical 15}) -(def connect-button-container +(def button-container {:margin-top 8 :margin-bottom 16 :margin-horizontal 16}) -(defstyle connect-button +(def button {:height 52 :align-items :center :justify-content :center - :background-color colors/blue :border-radius 8 :ios {:opacity 0.9}}) -(defstyle connect-button-label +(defstyle connect-button + (assoc button + :background-color colors/blue)) + +(defstyle delete-button + (assoc button + :background-color colors/red)) + +(defstyle button-label {:color colors/white :ios {:font-size 17 :letter-spacing -0.2} :android {:font-size 14}}) - -(defstyle connect-button-description - {:color colors/gray - :ios {:margin-top 8 - :height 20 - :font-size 14 - :letter-spacing -0.2} - :android {:margin-top 12 - :font-size 12}}) diff --git a/src/status_im/ui/screens/offline_messaging_settings/edit_mailserver/subs.cljs b/src/status_im/ui/screens/offline_messaging_settings/edit_mailserver/subs.cljs index 9b5bd2ab45..f9dfa42a4b 100644 --- a/src/status_im/ui/screens/offline_messaging_settings/edit_mailserver/subs.cljs +++ b/src/status_im/ui/screens/offline_messaging_settings/edit_mailserver/subs.cljs @@ -1,5 +1,7 @@ (ns status-im.ui.screens.offline-messaging-settings.edit-mailserver.subs - (:require [re-frame.core :refer [reg-sub]])) + (:require + [re-frame.core :refer [reg-sub]] + [status-im.models.mailserver :as models.mailserver])) (reg-sub :get-manage-mailserver @@ -7,6 +9,12 @@ (fn [manage] manage)) +(reg-sub + :get-connected-mailserver + (fn [db] + (models.mailserver/connected? (get-in db [:mailservers/manage :id :value]) + {:db db}))) + (reg-sub :manage-mailserver-valid? :<- [:get-manage-mailserver] diff --git a/src/status_im/ui/screens/offline_messaging_settings/edit_mailserver/views.cljs b/src/status_im/ui/screens/offline_messaging_settings/edit_mailserver/views.cljs index 891f59aa13..f45037c2fe 100644 --- a/src/status_im/ui/screens/offline_messaging_settings/edit_mailserver/views.cljs +++ b/src/status_im/ui/screens/offline_messaging_settings/edit_mailserver/views.cljs @@ -4,6 +4,7 @@ [re-frame.core :as re-frame] [status-im.ui.components.react :as react] [status-im.i18n :as i18n] + [status-im.utils.utils :as utils] [status-im.ui.components.colors :as colors] [status-im.ui.components.icons.vector-icons :as vector-icons] [status-im.ui.components.styles :as components.styles] @@ -14,15 +15,30 @@ [status-im.ui.components.text-input.view :as text-input] [status-im.ui.screens.offline-messaging-settings.edit-mailserver.styles :as styles])) +(defn handle-delete [id] + (utils/show-confirmation (i18n/label :t/delete-mailserver-title) + (i18n/label :t/delete-mailserver-are-you-sure) + (i18n/label :t/delete-mailserver) + #(re-frame/dispatch [:delete-mailserver id]))) + (defn connect-button [id] [react/touchable-highlight {:on-press #(re-frame/dispatch [:connect-wnode id])} - [react/view styles/connect-button-container + [react/view styles/button-container [react/view {:style styles/connect-button :accessibility-label :mailserver-connect-button} - [react/text {:style styles/connect-button-label + [react/text {:style styles/button-label :uppercase? true} (i18n/label :t/connect)]]]]) +(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 :mailserver-delete-button} + [react/text {:style styles/button-label + :uppercase? true} + (i18n/label :t/delete)]]]]) + (def qr-code [react/touchable-highlight {:on-press #(re-frame/dispatch [:scan-qr-code {:toolbar-title (i18n/label :t/add-mailserver)} @@ -33,6 +49,7 @@ (views/defview edit-mailserver [] (views/letsubs [manage-mailserver [:get-manage-mailserver] + connected? [:get-connected-mailserver] is-valid? [:manage-mailserver-valid?]] (let [url (get-in manage-mailserver [:url :value]) id (get-in manage-mailserver [:id :value]) @@ -59,7 +76,11 @@ :container styles/input-container :default-value url :on-change-text #(re-frame/dispatch [:mailserver-set-input :url %])}] - (when id [connect-button id])]] + (when (and id + (not connected?)) + [react/view + [connect-button id] + [delete-button id]])]] [react/view styles/bottom-container [react/view components.styles/flex] [components.common/bottom-button diff --git a/test/cljs/status_im/test/offline_messaging_settings/events.cljs b/test/cljs/status_im/test/models/mailserver.cljs similarity index 58% rename from test/cljs/status_im/test/offline_messaging_settings/events.cljs rename to test/cljs/status_im/test/models/mailserver.cljs index 7cb64a361b..9125d3d2c3 100644 --- a/test/cljs/status_im/test/offline_messaging_settings/events.cljs +++ b/test/cljs/status_im/test/models/mailserver.cljs @@ -1,6 +1,6 @@ -(ns status-im.test.offline-messaging-settings.events +(ns status-im.test.models.mailserver (:require [cljs.test :refer-macros [deftest is testing]] - [status-im.ui.screens.offline-messaging-settings.edit-mailserver.events :as events])) + [status-im.models.mailserver :as model])) (def enode-id "1da276e34126e93babf24ec88aac1a7602b4cbb2e11b0961d0ab5e989ca9c261aa7f7c1c85f15550a5f1e5a5ca2305b53b9280cf5894d5ecf7d257b173136d40") (def password "password") @@ -14,20 +14,20 @@ (testing "correct name" (is (= {:db {:mailservers/manage {:name {:value "value" :error false}}}} - (events/set-input :name "value" {})))) + (model/set-input :name "value" {})))) (testing "blank name" (is (= {:db {:mailservers/manage {:name {:value "" :error true}}}} - (events/set-input :name "" {}))))) + (model/set-input :name "" {}))))) (testing "it validates enodes url" (testing "correct url" (is (= {:db {:mailservers/manage {:url {:value valid-enode-url :error false}}}} - (events/set-input :url valid-enode-url {})))) + (model/set-input :url valid-enode-url {})))) (testing "broken url" (is (= {:db {:mailservers/manage {:url {:value "broken" :error true}}}} - (events/set-input :url "broken" {})))))) + (model/set-input :url "broken" {})))))) (deftest edit-mailserver (let [db {:network "mainnet_rpc" @@ -40,7 +40,7 @@ :name "name"}}}} cofx {:db db}] (testing "when no id is given" - (let [actual (events/edit-mailserver nil cofx)] + (let [actual (model/edit nil cofx)] (testing "it resets :mailserver/manage" (is (= {:id {:value nil :error false} @@ -54,7 +54,7 @@ (-> actual :dispatch)))))) (testing "when an id is given" (testing "when the wnode is in the list" - (let [actual (events/edit-mailserver "a" cofx)] + (let [actual (model/edit "a" cofx)] (testing "it populates the fields with the correct values" (is (= {:id {:value "a" :error false} @@ -67,7 +67,7 @@ (is (= [:navigate-to :edit-mailserver] (-> actual :dispatch)))))) (testing "when the wnode is not in the list" - (let [actual (events/edit-mailserver "not-existing" cofx)] + (let [actual (model/edit "not-existing" cofx)] (testing "it populates the fields with the correct values" (is (= {:id {:value nil :error false} @@ -80,6 +80,66 @@ (is (= [:navigate-to :edit-mailserver] (-> actual :dispatch))))))))) +(deftest connected-mailserver + (testing "it returns true when set in settings" + (let [cofx {:db {:network "mainnet_rpc" + :account/account {:settings {:wnode {:mainnet "a"}} + :networks {"mainnet_rpc" + {:config {:NetworkId 1}}}} + :inbox/wnodes {:mainnet {"a" {:id "a" + :name "old-name" + :address "enode://old-id:old-password@url:port"}}}}}] + (is (model/connected? "a" cofx))))) + +(deftest fetch-mailserver + (testing "it fetches the mailserver from the db" + (let [cofx {:db {:network "mainnet_rpc" + :account/account {:networks {"mainnet_rpc" + {:config {:NetworkId 1}}}} + :inbox/wnodes {:mainnet {"a" {:id "a" + :name "old-name" + :address "enode://old-id:old-password@url:port"}}}}}] + (is (model/fetch "a" cofx))))) + +(deftest delete-mailserver + (testing "the user is not connected to the mailserver" + (let [cofx {:random-id "random-id" + :db {:network "mainnet_rpc" + :account/account {:networks {"mainnet_rpc" + {:config {:NetworkId 1}}}} + :inbox/wnodes {:mainnet {"a" {:id "a" + :name "old-name" + :user-defined true + :address "enode://old-id:old-password@url:port"}}}}} + actual (model/delete "a" cofx)] + (testing "it removes the mailserver from the list" + (is (not (model/fetch "a" actual)))) + (testing "it stores it in the db" + (is (= 1 (count (:data-store/tx actual))))))) + (testing "the mailserver is not user-defined" + (let [cofx {:random-id "random-id" + :db {:network "mainnet_rpc" + :account/account {:networks {"mainnet_rpc" + {:config {:NetworkId 1}}}} + :inbox/wnodes {:mainnet {"a" {:id "a" + :name "old-name" + :address "enode://old-id:old-password@url:port"}}}}} + actual (model/delete "a" cofx)] + (testing "it does not delete the mailserver" + (is (nil? actual))))) + (testing "the user is connected to the mailserver" + (let [cofx {:random-id "random-id" + :db {:network "mainnet_rpc" + :account/account {:settings {:wnode {:mainnet "a"}} + :networks {"mainnet_rpc" + {:config {:NetworkId 1}}}} + :inbox/wnodes {:mainnet {"a" {:id "a" + :name "old-name" + :address "enode://old-id:old-password@url:port"}}}}} + actual (model/delete "a" cofx)] + (testing "it does not remove the mailserver from the list" + (is (nil? actual)))))) + (deftest upsert-mailserver (testing "new mailserver" (let [cofx {:random-id "random-id" @@ -90,7 +150,7 @@ :url {:value "enode://test-id:test-password@url:port"}} :inbox/wnodes {}}} - actual (events/upsert-mailserver cofx nil)] + actual (model/upsert cofx)] (testing "it adds the enode to inbox/wnodes" (is (= {:mainnet {"randomid" {:password "test-password" @@ -116,7 +176,7 @@ :inbox/wnodes {:mainnet {"a" {:id "a" :name "old-name" :address "enode://old-id:old-password@url:port"}}}}} - actual (events/upsert-mailserver cofx nil)] + actual (model/upsert cofx)] (testing "it navigates back" (is (= [:navigate-back] (:dispatch actual)))) @@ -130,9 +190,9 @@ (testing "it stores it in the db" (is (= 1 (count (:data-store/tx actual))))) (testing "it logs the user out if connected to the current mailserver" - (let [actual (events/upsert-mailserver (assoc-in cofx - [:db :account/account :settings] - {:wnode - {:mainnet "a"}}) nil)] + (let [actual (model/upsert (assoc-in cofx + [:db :account/account :settings] + {:wnode + {:mainnet "a"}}))] (is (= [:logout] (-> actual :data-store/tx first :success-event)))))))) diff --git a/test/cljs/status_im/test/runner.cljs b/test/cljs/status_im/test/runner.cljs index dad674a4fa..3e67939d76 100644 --- a/test/cljs/status_im/test/runner.cljs +++ b/test/cljs/status_im/test/runner.cljs @@ -10,7 +10,7 @@ [status-im.test.wallet.transactions.views] [status-im.test.profile.events] [status-im.test.bots.events] - [status-im.test.offline-messaging-settings.events] + [status-im.test.models.mailserver] [status-im.test.transport.core] [status-im.test.chat.models] [status-im.test.chat.models.input] @@ -57,7 +57,7 @@ 'status-im.test.contacts.subs 'status-im.test.profile.events 'status-im.test.data-store.realm.core - 'status-im.test.offline-messaging-settings.events + 'status-im.test.models.mailserver 'status-im.test.bots.events 'status-im.test.transport.core 'status-im.test.wallet.subs