From 61374add534ccb7c45184ccc5c96956b71797055 Mon Sep 17 00:00:00 2001 From: Andrey Shovkoplyas Date: Wed, 18 Jul 2018 16:48:08 +0300 Subject: [PATCH] Introduce extended DApp API [#5042] Signed-off-by: Andrey Shovkoplyas --- resources/js/webview.js | 34 ++++++-- src/status_im/constants.cljs | 5 ++ .../data_store/dapp_permissions.cljs | 16 ++++ .../realm/schemas/account/core.cljs | 8 +- .../realm/schemas/account/v9/core.cljs | 26 ++++++ .../schemas/account/v9/dapp_permissions.cljs | 7 ++ src/status_im/models/browser.cljs | 44 +++++++++- src/status_im/translations/en.cljs | 6 +- src/status_im/ui/screens/browser/db.cljs | 13 ++- src/status_im/ui/screens/browser/events.cljs | 61 +++++++++++++- src/status_im/ui/screens/browser/views.cljs | 14 ++-- src/status_im/ui/screens/db.cljs | 3 +- src/status_im/ui/screens/events.cljs | 1 + src/status_im/ui/screens/profile/events.cljs | 5 +- src/status_im/utils/utils.cljs | 7 +- test/cljs/status_im/test/browser/events.cljs | 84 ++++++++++++++++++- 16 files changed, 296 insertions(+), 38 deletions(-) create mode 100644 src/status_im/data_store/dapp_permissions.cljs create mode 100644 src/status_im/data_store/realm/schemas/account/v9/core.cljs create mode 100644 src/status_im/data_store/realm/schemas/account/v9/dapp_permissions.cljs diff --git a/resources/js/webview.js b/resources/js/webview.js index 9aa513f041..1dfdeb464c 100644 --- a/resources/js/webview.js +++ b/resources/js/webview.js @@ -1,20 +1,40 @@ (function () { + function bridgeSend(data){ + WebViewBridge.send(JSON.stringify(data)); + } + var history = window.history; var pushState = history.pushState; history.pushState = function(state) { setTimeout(function () { - WebViewBridge.send(JSON.stringify({ - type: 'navStateChange', - navState: { url: location.href, title: document.title } - })) + bridgeSend({ + type: 'history-state-changed', + navState: { url: location.href, title: document.title } + }); }, 100); return pushState.apply(history, arguments); }; - WebViewBridge.onMessage = function (messageString) { - console.log("received from react-native: " + messageString); + window.addEventListener('message', function (event) { + if (!event.data || !event.data.type) { return; } + if (event.data.type === 'STATUS_API_REQUEST') { + bridgeSend({ + type: 'status-api-request', + permissions: event.data.permissions, + host: window.location.hostname + }); + } + }); - if (messageString === "navigate-to-blank") + WebViewBridge.onMessage = function (message) { + + data = JSON.parse(message); + + if (data.type === "navigate-to-blank") window.location.href = "about:blank"; + + else if (data.type === "status-api-success") + window.STATUS_API = data.data; + window.postMessage({ type: 'STATUS_API_SUCCESS', permissions: data.keys }, "*"); }; }()); diff --git a/src/status_im/constants.cljs b/src/status_im/constants.cljs index 1946adc4d9..111c0fa5f2 100644 --- a/src/status_im/constants.cljs +++ b/src/status_im/constants.cljs @@ -247,3 +247,8 @@ (ethereum/sha3 "Transfer(address,address,uint256)")) (def regx-emoji #"^((?:[\u261D\u26F9\u270A-\u270D]|\uD83C[\uDF85\uDFC2-\uDFC4\uDFC7\uDFCA-\uDFCC]|\uD83D[\uDC42\uDC43\uDC46-\uDC50\uDC66-\uDC69\uDC6E\uDC70-\uDC78\uDC7C\uDC81-\uDC83\uDC85-\uDC87\uDCAA\uDD74\uDD75\uDD7A\uDD90\uDD95\uDD96\uDE45-\uDE47\uDE4B-\uDE4F\uDEA3\uDEB4-\uDEB6\uDEC0\uDECC]|\uD83E[\uDD18-\uDD1C\uDD1E\uDD1F\uDD26\uDD30-\uDD39\uDD3D\uDD3E\uDDD1-\uDDDD])(?:\uD83C[\uDFFB-\uDFFF])?|(?:[\u231A\u231B\u23E9-\u23EC\u23F0\u23F3\u25FD\u25FE\u2614\u2615\u2648-\u2653\u267F\u2693\u26A1\u26AA\u26AB\u26BD\u26BE\u26C4\u26C5\u26CE\u26D4\u26EA\u26F2\u26F3\u26F5\u26FA\u26FD\u2705\u270A\u270B\u2728\u274C\u274E\u2753-\u2755\u2757\u2795-\u2797\u27B0\u27BF\u2B1B\u2B1C\u2B50\u2B55]|\uD83C[\uDC04\uDCCF\uDD8E\uDD91-\uDD9A\uDDE6-\uDDFF\uDE01\uDE1A\uDE2F\uDE32-\uDE36\uDE38-\uDE3A\uDE50\uDE51\uDF00-\uDF20\uDF2D-\uDF35\uDF37-\uDF7C\uDF7E-\uDF93\uDFA0-\uDFCA\uDFCF-\uDFD3\uDFE0-\uDFF0\uDFF4\uDFF8-\uDFFF]|\uD83D[\uDC00-\uDC3E\uDC40\uDC42-\uDCFC\uDCFF-\uDD3D\uDD4B-\uDD4E\uDD50-\uDD67\uDD7A\uDD95\uDD96\uDDA4\uDDFB-\uDE4F\uDE80-\uDEC5\uDECC\uDED0-\uDED2\uDEEB\uDEEC\uDEF4-\uDEF8]|\uD83E[\uDD10-\uDD3A\uDD3C-\uDD3E\uDD40-\uDD45\uDD47-\uDD4C\uDD50-\uDD6B\uDD80-\uDD97\uDDC0\uDDD0-\uDDE6])|(?:[#\*0-9\xA9\xAE\u203C\u2049\u2122\u2139\u2194-\u2199\u21A9\u21AA\u231A\u231B\u2328\u23CF\u23E9-\u23F3\u23F8-\u23FA\u24C2\u25AA\u25AB\u25B6\u25C0\u25FB-\u25FE\u2600-\u2604\u260E\u2611\u2614\u2615\u2618\u261D\u2620\u2622\u2623\u2626\u262A\u262E\u262F\u2638-\u263A\u2640\u2642\u2648-\u2653\u2660\u2663\u2665\u2666\u2668\u267B\u267F\u2692-\u2697\u2699\u269B\u269C\u26A0\u26A1\u26AA\u26AB\u26B0\u26B1\u26BD\u26BE\u26C4\u26C5\u26C8\u26CE\u26CF\u26D1\u26D3\u26D4\u26E9\u26EA\u26F0-\u26F5\u26F7-\u26FA\u26FD\u2702\u2705\u2708-\u270D\u270F\u2712\u2714\u2716\u271D\u2721\u2728\u2733\u2734\u2744\u2747\u274C\u274E\u2753-\u2755\u2757\u2763\u2764\u2795-\u2797\u27A1\u27B0\u27BF\u2934\u2935\u2B05-\u2B07\u2B1B\u2B1C\u2B50\u2B55\u3030\u303D\u3297\u3299]|\uD83C[\uDC04\uDCCF\uDD70\uDD71\uDD7E\uDD7F\uDD8E\uDD91-\uDD9A\uDDE6-\uDDFF\uDE01\uDE02\uDE1A\uDE2F\uDE32-\uDE3A\uDE50\uDE51\uDF00-\uDF21\uDF24-\uDF93\uDF96\uDF97\uDF99-\uDF9B\uDF9E-\uDFF0\uDFF3-\uDFF5\uDFF7-\uDFFF]|\uD83D[\uDC00-\uDCFD\uDCFF-\uDD3D\uDD49-\uDD4E\uDD50-\uDD67\uDD6F\uDD70\uDD73-\uDD7A\uDD87\uDD8A-\uDD8D\uDD90\uDD95\uDD96\uDDA4\uDDA5\uDDA8\uDDB1\uDDB2\uDDBC\uDDC2-\uDDC4\uDDD1-\uDDD3\uDDDC-\uDDDE\uDDE1\uDDE3\uDDE8\uDDEF\uDDF3\uDDFA-\uDE4F\uDE80-\uDEC5\uDECB-\uDED2\uDEE0-\uDEE5\uDEE9\uDEEB\uDEEC\uDEF0\uDEF3-\uDEF8]|\uD83E[\uDD10-\uDD3A\uDD3C-\uDD3E\uDD40-\uDD45\uDD47-\uDD4C\uDD50-\uDD6B\uDD80-\uDD97\uDDC0\uDDD0-\uDDE6])\uFE0F|[\t-\r \xA0\u1680\u2000-\u200A\u2028\u2029\u202F\u205F\u3000\uFEFF])+$") + +(def ^:const dapp-permission-contact-code "CONTACT_CODE") +(def ^:const status-api-success "status-api-success") +(def ^:const status-api-request "status-api-request") +(def ^:const history-state-changed "history-state-changed") \ No newline at end of file diff --git a/src/status_im/data_store/dapp_permissions.cljs b/src/status_im/data_store/dapp_permissions.cljs new file mode 100644 index 0000000000..2bb5270d95 --- /dev/null +++ b/src/status_im/data_store/dapp_permissions.cljs @@ -0,0 +1,16 @@ +(ns status-im.data-store.dapp-permissions + (:require [re-frame.core :as re-frame] + [status-im.data-store.realm.core :as core])) + +(re-frame/reg-cofx + :data-store/all-dapp-permissions + (fn [cofx _] + (assoc cofx :all-dapp-permissions (-> @core/account-realm + (core/get-all :dapp-permissions) + (core/all-clj :dapp-permissions))))) + +(defn save-dapp-permissions + "Returns tx function for saving dapp permissions" + [permissions] + (fn [realm] + (core/create realm :dapp-permissions permissions true))) \ No newline at end of file diff --git a/src/status_im/data_store/realm/schemas/account/core.cljs b/src/status_im/data_store/realm/schemas/account/core.cljs index f1100ee90a..45fedfbfa4 100644 --- a/src/status_im/data_store/realm/schemas/account/core.cljs +++ b/src/status_im/data_store/realm/schemas/account/core.cljs @@ -7,7 +7,8 @@ [status-im.data-store.realm.schemas.account.v5.core :as v5] [status-im.data-store.realm.schemas.account.v6.core :as v6] [status-im.data-store.realm.schemas.account.v7.core :as v7] - [status-im.data-store.realm.schemas.account.v8.core :as v8])) + [status-im.data-store.realm.schemas.account.v8.core :as v8] + [status-im.data-store.realm.schemas.account.v9.core :as v9])) ;; TODO(oskarth): Add failing test if directory vXX exists but isn't in schemas. @@ -35,4 +36,7 @@ :migration v7/migration} {:schema v8/schema :schemaVersion 8 - :migration v8/migration}]) + :migration v8/migration} + {:schema v9/schema + :schemaVersion 9 + :migration v9/migration}]) diff --git a/src/status_im/data_store/realm/schemas/account/v9/core.cljs b/src/status_im/data_store/realm/schemas/account/v9/core.cljs new file mode 100644 index 0000000000..46f08a4331 --- /dev/null +++ b/src/status_im/data_store/realm/schemas/account/v9/core.cljs @@ -0,0 +1,26 @@ +(ns status-im.data-store.realm.schemas.account.v9.core + (:require [status-im.data-store.realm.schemas.account.v5.chat :as chat] + [status-im.data-store.realm.schemas.account.v6.transport :as transport] + [status-im.data-store.realm.schemas.account.v1.contact :as contact] + [status-im.data-store.realm.schemas.account.v7.message :as message] + [status-im.data-store.realm.schemas.account.v1.request :as request] + [status-im.data-store.realm.schemas.account.v1.user-status :as user-status] + [status-im.data-store.realm.schemas.account.v1.local-storage :as local-storage] + [status-im.data-store.realm.schemas.account.v2.mailserver :as mailserver] + [status-im.data-store.realm.schemas.account.v8.browser :as browser] + [status-im.data-store.realm.schemas.account.v9.dapp-permissions :as dapp-permissions] + [taoensso.timbre :as log])) + +(def schema [chat/schema + transport/schema + contact/schema + message/schema + request/schema + mailserver/schema + user-status/schema + local-storage/schema + browser/schema + dapp-permissions/schema]) + +(defn migration [old-realm new-realm] + (log/debug "migrating v9 account database: " old-realm new-realm)) \ No newline at end of file diff --git a/src/status_im/data_store/realm/schemas/account/v9/dapp_permissions.cljs b/src/status_im/data_store/realm/schemas/account/v9/dapp_permissions.cljs new file mode 100644 index 0000000000..9b3cf5c52f --- /dev/null +++ b/src/status_im/data_store/realm/schemas/account/v9/dapp_permissions.cljs @@ -0,0 +1,7 @@ +(ns status-im.data-store.realm.schemas.account.v9.dapp-permissions) + +(def schema {:name :dapp-permissions + :primaryKey :dapp + :properties {:dapp :string + :permissions {:type "string[]" + :optional true}}}) \ No newline at end of file diff --git a/src/status_im/models/browser.cljs b/src/status_im/models/browser.cljs index 249ddadabe..96cc56e684 100644 --- a/src/status_im/models/browser.cljs +++ b/src/status_im/models/browser.cljs @@ -1,5 +1,8 @@ (ns status-im.models.browser - (:require [status-im.data-store.browser :as browser-store])) + (:require [status-im.data-store.browser :as browser-store] + [status-im.data-store.dapp-permissions :as dapp-permissions] + [status-im.i18n :as i18n] + [status-im.constants :as constants])) (defn get-current-url [{:keys [history history-index]}] (when (and history-index history) @@ -23,7 +26,7 @@ history (:history browser) history-url (try (nth history history-index) (catch js/Error _))] (when (not= history-url url) - (let [slash? (= url (str history-url "/")) + (let [slash? (= url (str history-url "/")) new-history (if slash? (assoc history history-index url) (conj (subvec history 0 (inc history-index)) url)) @@ -35,4 +38,39 @@ (defn update-browser-and-navigate [cofx browser] (merge (update-browser-fx cofx browser) - {:dispatch [:navigate-to :browser (:browser-id browser)]})) \ No newline at end of file + {:dispatch [:navigate-to :browser (:browser-id browser)]})) + +(def permissions {constants/dapp-permission-contact-code {:label (i18n/label :t/your-contact-code)}}) + +(defn update-dapp-permissions-fx [{:keys [db]} permissions] + {:db (assoc-in db [:dapps/permissions (:dapp permissions)] permissions) + :data-store/tx [(dapp-permissions/save-dapp-permissions permissions)]}) + +(defn request-permission [cofx + {:keys [dapp-name index requested-permissions permissions-allowed user-permissions + permissions-data webview] + :as params}] + ;; iterate all requested permissions + (if (< index (count requested-permissions)) + (let [requested-permission (get requested-permissions index)] + ;; if requested permission exists and valid continue if not decline permission + (if (and requested-permission (get permissions requested-permission)) + ;; if permission already allowed go to next, if not, show confirmation dialog + (if ((set user-permissions) requested-permission) + {:dispatch [:next-dapp-permission params requested-permission permissions-data]} + {:show-dapp-permission-confirmation-fx [requested-permission params]}) + {:dispatch [:next-dapp-permission params]})) + (assoc (update-dapp-permissions-fx cofx {:dapp dapp-name + :permissions (vec (set (concat (keys permissions-allowed) + user-permissions)))}) + :send-to-bridge-fx [permissions-allowed webview]))) + +(defn next-permission [cofx params & [permission permissions-data]] + (request-permission + cofx + (cond-> params + true + (update :index inc) + + (and permission permissions-data) + (assoc-in [:permissions-allowed permission] (get permissions-data permission))))) \ No newline at end of file diff --git a/src/status_im/translations/en.cljs b/src/status_im/translations/en.cljs index 00e3f68fb5..4c2d8d1e41 100644 --- a/src/status_im/translations/en.cljs +++ b/src/status_im/translations/en.cljs @@ -30,6 +30,7 @@ :on "On" :off "Off" :mailserver-connection-error "Could not connect to mailserver" + :dont-allow "Don't Allow" :custom "Custom" :camera-access-error "To grant the required camera permission, please go to your system settings and make sure that Status > Camera is selected." @@ -693,4 +694,7 @@ :dapp "ÐApp" :selected "Selected" :selected-dapps "Selected ÐApps" - :browser-warning "Connection is not proven secure. Make sure you trust this site before signing transactions or entering personal data."}) + :browser-warning "Connection is not proven secure. Make sure you trust this site before signing transactions or entering personal data." + :make-sure-you-trust-dapp "Make sure that you trust this DApp" + :would-like-to-access "Would like to Access" + :your-contact-code "Your Contact Code"}) \ No newline at end of file diff --git a/src/status_im/ui/screens/browser/db.cljs b/src/status_im/ui/screens/browser/db.cljs index 5967eb3409..1fcba17f1b 100644 --- a/src/status_im/ui/screens/browser/db.cljs +++ b/src/status_im/ui/screens/browser/db.cljs @@ -3,10 +3,7 @@ (:require [cljs.spec.alpha :as spec])) (spec/def :browser/browser-id (spec/nilable string?)) -(spec/def :browser/contact (spec/nilable string?)) (spec/def :browser/timestamp (spec/nilable int?)) -(spec/def :browser/url (spec/nilable string?)) -(spec/def :browser/photo-path (spec/nilable string?)) (spec/def :browser/name (spec/nilable string?)) (spec/def :browser/dapp? (spec/nilable boolean?)) (spec/def :browser/error? (spec/nilable boolean?)) @@ -28,3 +25,13 @@ :browser/history-index])) (spec/def :browser/browsers (spec/nilable (spec/map-of :global/not-empty-string :browser/browser))) + +(spec/def :dapp/dapp (spec/nilable string?)) +(spec/def :dapp/permissions (spec/nilable vector?)) + +(spec/def :dapp/permission-map + (allowed-keys + :req-un [:dapp/dapp] + :opt-un [:dapp/permissions])) + +(spec/def :dapps/permissions (spec/nilable (spec/map-of :global/not-empty-string :dapp/permission-map))) \ No newline at end of file diff --git a/src/status_im/ui/screens/browser/events.cljs b/src/status_im/ui/screens/browser/events.cljs index 6808272728..494782453f 100644 --- a/src/status_im/ui/screens/browser/events.cljs +++ b/src/status_im/ui/screens/browser/events.cljs @@ -8,7 +8,10 @@ [status-im.utils.universal-links.core :as utils.universal-links] [status-im.data-store.browser :as browser-store] [status-im.utils.http :as http] - [status-im.models.browser :as model])) + [status-im.models.browser :as model] + [status-im.utils.platform :as platform] + [status-im.utils.utils :as utils] + [status-im.constants :as constants])) (re-frame/reg-fx :browse @@ -17,6 +20,25 @@ (utils.universal-links/open! link) (list-selection/browse link)))) +(re-frame/reg-fx + :send-to-bridge-fx + (fn [[permissions-allowed webview]] + (.sendToBridge @webview (.stringify js/JSON (clj->js {:type constants/status-api-success + :data permissions-allowed + :keys (keys permissions-allowed)}))))) + +(re-frame/reg-fx + :show-dapp-permission-confirmation-fx + (fn [[permission {:keys [dapp-name permissions-data] :as params}]] + (utils/show-confirmation + {:ios-confirm-style "default"} + (str "\"" dapp-name "\" " (i18n/label :t/would-like-to-access) " " (:label (get model/permissions permission))) + (i18n/label :t/make-sure-you-trust-dapp) + nil + #(re-frame/dispatch [:next-dapp-permission params permission permissions-data]) + #(re-frame/dispatch [:next-dapp-permission params]) + (i18n/label :t/dont-allow)))) + (handlers/register-handler-fx :initialize-browsers [(re-frame/inject-cofx :data-store/all-browsers)] @@ -24,6 +46,13 @@ (let [browsers (into {} (map #(vector (:browser-id %) %) all-stored-browsers))] {:db (assoc db :browser/browsers browsers)}))) +(handlers/register-handler-fx + :initialize-dapp-permissions + [(re-frame/inject-cofx :data-store/all-dapp-permissions)] + (fn [{:keys [db all-dapp-permissions]} _] + (let [dapp-permissions (into {} (map #(vector (:dapp %) %) all-dapp-permissions))] + {:db (assoc db :dapps/permissions dapp-permissions)}))) + (handlers/register-handler-fx :browse-link-from-message (fn [_ [_ link]] @@ -90,4 +119,32 @@ [re-frame/trim-v] (fn [cofx [{:keys [history-index] :as browser}]] (when (< history-index (dec (count (:history browser)))) - (nav-update-browser cofx browser (inc history-index))))) \ No newline at end of file + (nav-update-browser cofx browser (inc history-index))))) + +(handlers/register-handler-fx + :on-bridge-message + [re-frame/trim-v] + (fn [{:keys [db] :as cofx} [{{:keys [url]} :navState :keys [type host permissions]} browser webview]] + (cond + + (and (= type constants/history-state-changed) platform/ios? (not= "about:blank" url)) + (model/update-browser-history-fx cofx browser url false) + + (= type constants/status-api-request) + (let [{:account/keys [account]} db + {:keys [dapp? name]} browser + dapp-name (if dapp? name host)] + (model/request-permission + cofx + {:dapp-name dapp-name + :webview webview + :index 0 + :user-permissions (get-in db [:dapps/permissions dapp-name :permissions]) + :requested-permissions permissions + :permissions-data {constants/dapp-permission-contact-code (:public-key account)}}))))) + +(handlers/register-handler-fx + :next-dapp-permission + [re-frame/trim-v] + (fn [cofx [params permission permissions-data]] + (model/next-permission cofx params permission permissions-data))) \ No newline at end of file diff --git a/src/status_im/ui/screens/browser/views.cljs b/src/status_im/ui/screens/browser/views.cljs index 2c66764bf9..cfb0a01086 100644 --- a/src/status_im/ui/screens/browser/views.cljs +++ b/src/status_im/ui/screens/browser/views.cljs @@ -18,7 +18,6 @@ [status-im.ui.components.toolbar.actions :as actions] [status-im.ui.components.tooltip.views :as tooltip] [status-im.models.browser :as model] - [status-im.utils.platform :as platform] [status-im.utils.http :as http])) (views/defview toolbar-content-dapp [name] @@ -67,13 +66,6 @@ [react/view styles/web-view-loading [components/activity-indicator {:animating true}]])) -(defn on-bridge-message [message browser] - (let [{:strs [type navState]} (js->clj (.parse js/JSON message)) - {:strs [url]} navState] - (when (and platform/ios? (= type "navStateChange")) - (when (not= "about:blank" url) - (re-frame/dispatch [:update-browser-on-nav-change browser url false]))))) - (defn on-navigation-change [event browser] (let [{:strs [url loading]} (js->clj event)] (when (not= "about:blank" url) @@ -116,7 +108,11 @@ :render-error web-view-error :render-loading web-view-loading :on-navigation-state-change #(on-navigation-change % browser) - :on-bridge-message #(on-bridge-message % browser) + :on-bridge-message #(re-frame/dispatch [:on-bridge-message + (js->clj (.parse js/JSON %) + :keywordize-keys true) + browser + webview]) :on-load #(re-frame/dispatch [:update-browser-options {:error? false}]) :on-error #(re-frame/dispatch [:update-browser-options {:error? true}]) :injected-on-start-loading-java-script (str js-res/web3 diff --git a/src/status_im/ui/screens/db.cljs b/src/status_im/ui/screens/db.cljs index 2e092617f4..780b6eb955 100644 --- a/src/status_im/ui/screens/db.cljs +++ b/src/status_im/ui/screens/db.cljs @@ -207,7 +207,8 @@ :transport/chats :transport/discovery-filter :desktop/desktop - :dimensions/window] + :dimensions/window + :dapps/permissions] :opt-un [::current-public-key ::modal diff --git a/src/status_im/ui/screens/events.cljs b/src/status_im/ui/screens/events.cljs index fb7db77fdd..7ac1e389ea 100644 --- a/src/status_im/ui/screens/events.cljs +++ b/src/status_im/ui/screens/events.cljs @@ -372,6 +372,7 @@ [:load-contacts] [:initialize-chats] [:initialize-browsers] + [:initialize-dapp-permissions] [:send-account-update-if-needed] [:process-pending-messages] [:update-wallet] diff --git a/src/status_im/ui/screens/profile/events.cljs b/src/status_im/ui/screens/profile/events.cljs index 476af29f3a..56c81908b0 100644 --- a/src/status_im/ui/screens/profile/events.cljs +++ b/src/status_im/ui/screens/profile/events.cljs @@ -35,9 +35,6 @@ (chat-events/start-chat chat-id {:navigation-replace? true}) (input-events/select-chat-input-command send-command nil true))))) -(defn get-current-account [db] - (:account/account db)) - (defn valid-name? [name] (spec/valid? :profile/name name)) @@ -101,7 +98,7 @@ (handlers/register-handler-fx :my-profile/enter-two-random-words (fn [{:keys [db]} []] - (let [{:keys [mnemonic]} (get-current-account db) + (let [{:keys [mnemonic]} (:account/account db) shuffled-mnemonic (shuffle (map-indexed vector (clojure.string/split mnemonic #" ")))] {:db (assoc db :my-profile/seed {:step :first-word :first-word (first shuffled-mnemonic) diff --git a/src/status_im/utils/utils.cljs b/src/status_im/utils/utils.cljs index a62ccf7421..115fc8a1f9 100644 --- a/src/status_im/utils/utils.cljs +++ b/src/status_im/utils/utils.cljs @@ -25,13 +25,16 @@ (show-confirmation title content confirm-button-text on-accept nil)) ([title content confirm-button-text on-accept on-cancel] (show-confirmation nil title content confirm-button-text on-accept on-cancel)) - ([{:keys [ios-confirm-style] :or {ios-confirm-style "destructive"}} title content confirm-button-text on-accept on-cancel] + ([ios-style title content confirm-button-text on-accept on-cancel] + (show-confirmation ios-style title content confirm-button-text on-accept on-cancel nil)) + ([{:keys [ios-confirm-style] :or {ios-confirm-style "destructive"}} + title content confirm-button-text on-accept on-cancel cancel-button-text] (.alert (.-Alert rn-dependencies/react-native) title content ;; Styles are only relevant on iOS. On Android first button is 'neutral' and second is 'positive' (clj->js - (vector (merge {:text (i18n/label :t/cancel) + (vector (merge {:text (or cancel-button-text (i18n/label :t/cancel)) :style "cancel" :accessibility-label :cancel-button} (when on-cancel {:onPress on-cancel})) diff --git a/test/cljs/status_im/test/browser/events.cljs b/test/cljs/status_im/test/browser/events.cljs index a360815b67..a04f1e6a90 100644 --- a/test/cljs/status_im/test/browser/events.cljs +++ b/test/cljs/status_im/test/browser/events.cljs @@ -17,7 +17,21 @@ (re-frame/reg-cofx :data-store/all-browsers (fn [coeffects _] - (assoc coeffects :all-stored-browsers [])))) + (assoc coeffects :all-stored-browsers []))) + + (re-frame/reg-cofx + :data-store/all-dapp-permissions + (fn [coeffects _] + (assoc coeffects :all-dapp-permissions []))) + + (re-frame/reg-fx :send-to-bridge-fx #()) + + (re-frame/reg-fx + :show-dapp-permission-confirmation-fx + (fn [[permission {:keys [dapp-name permissions-data index] :as params}]] + (if (and (= dapp-name "test.com") (#{0 1} index)) + (re-frame/dispatch [:next-dapp-permission params permission permissions-data]) + (re-frame/dispatch [:next-dapp-permission params]))))) (deftest browser-events @@ -63,8 +77,7 @@ (re-frame/dispatch [:open-browser (first (vals @browsers))]) - (let [browser (re-frame/subscribe [:get-current-browser]) - options (re-frame/subscribe [:get :browser/options]) + (let [browser (re-frame/subscribe [:get-current-browser]) dapp2-url2 (str dapp2-url "/nav2") dapp2-url3 (str dapp2-url "/nav3")] @@ -106,4 +119,67 @@ (re-frame/dispatch [:browser-nav-forward @browser]) (is (= 1 (:history-index @browser))) - (is (= [dapp2-url dapp2-url3] (:history @browser)))))))) \ No newline at end of file + (is (= [dapp2-url dapp2-url3] (:history @browser)))))) + + (re-frame/dispatch [:initialize-dapp-permissions]) + + (let [dapps-permissions (re-frame/subscribe [:get :dapps/permissions]) + dapp-name "test.com" + dapp-name2 "test2.org"] + + (testing "dapps permissions" + + (is (zero? (count @dapps-permissions))) + + (re-frame/dispatch [:on-bridge-message {:type "status-api-request" + :host dapp-name + :permissions ["FAKE_PERMISSION"]} + nil nil]) + + (is (= {:dapp dapp-name + :permissions []} + (get @dapps-permissions dapp-name))) + + (re-frame/dispatch [:on-bridge-message {:type "status-api-request" + :host dapp-name + :permissions ["CONTACT_CODE"]} + nil nil]) + + (is (= 1 (count @dapps-permissions))) + + (is (= {:dapp dapp-name + :permissions ["CONTACT_CODE"]} + (get @dapps-permissions dapp-name))) + + (re-frame/dispatch [:on-bridge-message {:type "status-api-request" + :host dapp-name + :permissions ["CONTACT_CODE" "FAKE_PERMISSION"]} + nil nil]) + + (is (= 1 (count @dapps-permissions))) + + (is (= {:dapp dapp-name + :permissions ["CONTACT_CODE"]} + (get @dapps-permissions dapp-name))) + + (re-frame/dispatch [:on-bridge-message {:type "status-api-request" + :host dapp-name + :permissions ["FAKE_PERMISSION"]} + nil nil]) + + (is (= 1 (count @dapps-permissions))) + + (is (= {:dapp dapp-name + :permissions ["CONTACT_CODE"]} + (get @dapps-permissions dapp-name))) + + (re-frame/dispatch [:on-bridge-message {:type "status-api-request" + :host dapp-name2 + :permissions ["CONTACT_CODE"]} + nil nil]) + + (is (= 2 (count @dapps-permissions))) + + (is (= {:dapp dapp-name2 + :permissions []} + (get @dapps-permissions dapp-name2)))))))