mirror of
https://github.com/status-im/status-mobile.git
synced 2025-01-26 16:39:24 +00:00
introduced new status js api according latest web3 opt-in api
This commit is contained in:
parent
81b2afebc1
commit
a1d0dcc0ec
@ -6,70 +6,77 @@ function bridgeSend(data){
|
||||
WebViewBridge.send(JSON.stringify(data));
|
||||
}
|
||||
|
||||
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
|
||||
});
|
||||
}
|
||||
});
|
||||
function sendAPIrequest(permission) {
|
||||
var messageId = callbackId++;
|
||||
|
||||
bridgeSend({
|
||||
type: 'api-request',
|
||||
permission: permission,
|
||||
messageId: messageId,
|
||||
host: window.location.hostname
|
||||
});
|
||||
|
||||
return new Promise(function (resolve, reject) { callbacks[messageId] = {resolve: resolve, reject: reject};});
|
||||
}
|
||||
|
||||
WebViewBridge.onMessage = function (message) {
|
||||
data = JSON.parse(message);
|
||||
var id = data.messageId;
|
||||
var callback = callbacks[id];
|
||||
|
||||
if (data.type === "status-api-success")
|
||||
{
|
||||
window.dispatchEvent(new CustomEvent('statusapi', { detail: { permissions: data.keys,
|
||||
data: data.data
|
||||
} }));
|
||||
}
|
||||
if (callback) {
|
||||
|
||||
else if (data.type === "web3-send-async-callback")
|
||||
{
|
||||
var id = data.messageId;
|
||||
var callback = callbacks[id];
|
||||
if (callback) {
|
||||
if (callback.results)
|
||||
{
|
||||
callback.results.push(data.error || data.result);
|
||||
if (callback.results.length == callback.num)
|
||||
callback.callback(undefined, callback.results);
|
||||
}
|
||||
else
|
||||
{
|
||||
callback.callback(data.error, data.result);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
else if (data.type === "scan-qr-code-callback")
|
||||
{
|
||||
var id = data.data.messageId;
|
||||
var callback = callbacks[id];
|
||||
if (callback) {
|
||||
var result = data.result;
|
||||
var regex = new RegExp(callback.regex);
|
||||
if (regex.test(result)) {
|
||||
if (callback.resolve) {
|
||||
callback.resolve(result);
|
||||
}
|
||||
if (data.type === "api-response") {
|
||||
if (data.isAllowed) {
|
||||
callback.resolve(data.data);
|
||||
} else {
|
||||
if (callback.reject) {
|
||||
callback.reject(result);
|
||||
callback.reject(new Error("Denied"));
|
||||
}
|
||||
} else if (data.type === "web3-send-async-callback") {
|
||||
var id = data.messageId;
|
||||
var callback = callbacks[id];
|
||||
if (callback) {
|
||||
if (callback.results) {
|
||||
callback.results.push(data.error || data.result);
|
||||
if (callback.results.length == callback.num)
|
||||
callback.callback(undefined, callback.results);
|
||||
} else {
|
||||
callback.callback(data.error, data.result);
|
||||
}
|
||||
}
|
||||
} else if (data.type === "scan-qr-code-callback") {
|
||||
var id = data.data.messageId;
|
||||
var callback = callbacks[id];
|
||||
if (callback) {
|
||||
var result = data.result;
|
||||
var regex = new RegExp(callback.regex);
|
||||
if (regex.test(result)) {
|
||||
if (callback.resolve) {
|
||||
callback.resolve(result);
|
||||
}
|
||||
} else {
|
||||
if (callback.reject) {
|
||||
callback.reject(result);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
var StatusAPI = function () {};
|
||||
|
||||
StatusAPI.prototype.getContactCode = function () {
|
||||
return sendAPIrequest('contact-code');
|
||||
};
|
||||
|
||||
var StatusHttpProvider = function () {};
|
||||
|
||||
StatusHttpProvider.prototype.isStatus = true;
|
||||
StatusHttpProvider.prototype.isConnected = function () { return true; };
|
||||
|
||||
StatusHttpProvider.prototype.status = new StatusAPI();
|
||||
|
||||
function web3Response (payload, result){
|
||||
return {id: payload.id,
|
||||
jsonrpc: "2.0",
|
||||
|
@ -1,52 +1,52 @@
|
||||
if(typeof ReadOnlyProvider === "undefined"){
|
||||
var callbackId = 0;
|
||||
var callbacks = {};
|
||||
var ethereumPromise = {};
|
||||
|
||||
function bridgeSend(data){
|
||||
WebViewBridge.send(JSON.stringify(data));
|
||||
}
|
||||
|
||||
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
|
||||
});
|
||||
}
|
||||
});
|
||||
function sendAPIrequest(permission) {
|
||||
var messageId = callbackId++;
|
||||
|
||||
bridgeSend({
|
||||
type: 'api-request',
|
||||
permission: permission,
|
||||
messageId: messageId,
|
||||
host: window.location.hostname
|
||||
});
|
||||
|
||||
return new Promise(function (resolve, reject) { callbacks[messageId] = {resolve: resolve, reject: reject};});
|
||||
}
|
||||
|
||||
WebViewBridge.onMessage = function (message) {
|
||||
data = JSON.parse(message);
|
||||
var id = data.messageId;
|
||||
var callback = callbacks[id];
|
||||
|
||||
if (data.type === "status-api-success")
|
||||
if (callback)
|
||||
{
|
||||
if (data.keys == 'WEB3')
|
||||
if (data.type === "api-response")
|
||||
{
|
||||
ethereumPromise.allowed = true;
|
||||
window.currentAccountAddress = data.data["WEB3"];
|
||||
ethereumPromise.resolve();
|
||||
if (data.isAllowed)
|
||||
{
|
||||
if (data.permission == 'web3')
|
||||
{
|
||||
window.currentAccountAddress = data.data;
|
||||
callback.resolve();
|
||||
}
|
||||
else
|
||||
{
|
||||
callback.resolve(data.data);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
callback.reject(new Error("Denied"));
|
||||
}
|
||||
}
|
||||
else
|
||||
else if (data.type === "web3-send-async-callback")
|
||||
{
|
||||
window.dispatchEvent(new CustomEvent('statusapi', { detail: { permissions: data.keys,
|
||||
data: data.data
|
||||
} }));
|
||||
}
|
||||
}
|
||||
|
||||
else if (data.type === "web3-permission-request-denied")
|
||||
{
|
||||
ethereumPromise.reject(new Error("Denied"));
|
||||
}
|
||||
|
||||
else if (data.type === "web3-send-async-callback")
|
||||
{
|
||||
var id = data.messageId;
|
||||
var callback = callbacks[id];
|
||||
if (callback) {
|
||||
if (callback.results)
|
||||
{
|
||||
callback.results.push(data.error || data.result);
|
||||
@ -82,11 +82,19 @@ function getSyncResponse (payload) {
|
||||
}
|
||||
}
|
||||
|
||||
var StatusAPI = function () {};
|
||||
|
||||
StatusAPI.prototype.getContactCode = function () {
|
||||
return sendAPIrequest('contact-code');
|
||||
};
|
||||
|
||||
var ReadOnlyProvider = function () {};
|
||||
|
||||
ReadOnlyProvider.prototype.isStatus = true;
|
||||
ReadOnlyProvider.prototype.isConnected = function () { return true; };
|
||||
|
||||
ReadOnlyProvider.prototype.status = new StatusAPI();
|
||||
|
||||
ReadOnlyProvider.prototype.send = function (payload) {
|
||||
if (payload.method == "eth_uninstallFilter"){
|
||||
this.sendAsync(payload, function (res, err) {})
|
||||
@ -100,15 +108,7 @@ ReadOnlyProvider.prototype.send = function (payload) {
|
||||
};
|
||||
|
||||
ReadOnlyProvider.prototype.enable = function () {
|
||||
bridgeSend({
|
||||
type: 'status-api-request',
|
||||
permissions: ['WEB3'],
|
||||
host: window.location.hostname
|
||||
});
|
||||
return new Promise(function (resolve, reject) {
|
||||
ethereumPromise.resolve = resolve;
|
||||
ethereumPromise.reject = reject;
|
||||
});
|
||||
return sendAPIrequest('web3');
|
||||
};
|
||||
|
||||
ReadOnlyProvider.prototype.sendAsync = function (payload, callback) {
|
||||
|
@ -268,7 +268,7 @@
|
||||
{:keys [browser-id]} options
|
||||
browser (get browsers browser-id)
|
||||
data (types/json->clj message)
|
||||
{{:keys [url]} :navState :keys [type host permissions payload messageId]} data
|
||||
{{:keys [url]} :navState :keys [type host permission payload messageId]} data
|
||||
{:keys [dapp? name]} browser
|
||||
dapp-name (if dapp? name host)]
|
||||
(cond
|
||||
@ -290,8 +290,8 @@
|
||||
{:type constants/scan-qr-code-callback
|
||||
:data data}))
|
||||
|
||||
(= type constants/status-api-request)
|
||||
(browser.permissions/process-permissions cofx dapp-name permissions))))
|
||||
(= type constants/api-request)
|
||||
(browser.permissions/process-permission cofx dapp-name permission messageId))))
|
||||
|
||||
(fx/defn handle-message-link
|
||||
[cofx link]
|
||||
|
@ -15,10 +15,7 @@
|
||||
(spec/def :browser/url-editing? (spec/nilable boolean?))
|
||||
(spec/def :browser/show-tooltip (spec/nilable keyword?))
|
||||
(spec/def :browser/show-permission (spec/nilable map?))
|
||||
|
||||
(spec/def :browser/pending-permissions set?)
|
||||
(spec/def :browser/allowed-permissions set?)
|
||||
(spec/def :browser/requested-permissions set?)
|
||||
(spec/def :browser/pending-permissions (spec/nilable list?))
|
||||
|
||||
(spec/def :browser/options
|
||||
(spec/nilable
|
||||
@ -30,8 +27,6 @@
|
||||
:browser/show-tooltip
|
||||
:browser/show-permission
|
||||
:browser/pending-permissions
|
||||
:browser/allowed-permissions
|
||||
:browser/requested-permissions
|
||||
:browser/error?])))
|
||||
|
||||
(spec/def :browser/browser
|
||||
|
@ -1,6 +1,5 @@
|
||||
(ns status-im.browser.permissions
|
||||
(:require [clojure.set :as set]
|
||||
[status-im.constants :as constants]
|
||||
(:require [status-im.constants :as constants]
|
||||
[status-im.data-store.dapp-permissions :as dapp-permissions]
|
||||
[status-im.i18n :as i18n]
|
||||
[status-im.utils.ethereum.core :as ethereum]
|
||||
@ -14,112 +13,77 @@
|
||||
:description (i18n/label :t/allowing-authorizes-this-dapp)
|
||||
:icon :icons/wallet-active}})
|
||||
|
||||
(defn get-pending-permissions [db]
|
||||
(get-in db [:browser/options :pending-permissions]))
|
||||
|
||||
(defn remove-pending-permission [db pending-permission]
|
||||
(update-in db [:browser/options :pending-permissions] disj pending-permission))
|
||||
|
||||
(defn get-allowed-permissions [db]
|
||||
(get-in db [:browser/options :allowed-permissions]))
|
||||
|
||||
(defn get-requested-permissions [db]
|
||||
(get-in db [:browser/options :requested-permissions]))
|
||||
|
||||
(defn add-allowed-permission [db allowed-permission]
|
||||
(update-in db [:browser/options :allowed-permissions] conj allowed-permission))
|
||||
|
||||
(defn get-permissions-data [allowed-permissions cofx]
|
||||
(defn get-permission-data [cofx allowed-permission]
|
||||
(let [account (get-in cofx [:db :account/account])]
|
||||
(select-keys {constants/dapp-permission-contact-code (:public-key account)
|
||||
constants/dapp-permission-web3 (ethereum/normalized-address
|
||||
(:address account))}
|
||||
(vec allowed-permissions))))
|
||||
(get {constants/dapp-permission-contact-code (:public-key account)
|
||||
constants/dapp-permission-web3 (ethereum/normalized-address (:address account))}
|
||||
allowed-permission)))
|
||||
|
||||
(fx/defn send-permissions-data-to-bridge
|
||||
"If there is granted permissions, return the data to the bridge
|
||||
If no permission were granted and dapp requested web3 permission,
|
||||
return `web3-permission-request-denied` message type
|
||||
Otherwise do nothing"
|
||||
;;TODO(yenda): this was the behavior of the code prior to refactoring
|
||||
;;if this is not the intended behavior please create an issue for that
|
||||
[{:keys [db] :as cofx}]
|
||||
(let [allowed-permissions (get-allowed-permissions db)
|
||||
requested-permissions (get-requested-permissions db)
|
||||
new-db (update db :browser/options dissoc
|
||||
:pending-permissions
|
||||
:allowed-permissions
|
||||
:requested-permissions)]
|
||||
(cond
|
||||
(not-empty allowed-permissions)
|
||||
{:db new-db
|
||||
:browser/send-to-bridge {:message {:type constants/status-api-success
|
||||
:data (get-permissions-data allowed-permissions cofx)
|
||||
:keys (vec allowed-permissions)}
|
||||
:webview (:webview-bridge db)}}
|
||||
(and (empty? allowed-permissions)
|
||||
(requested-permissions constants/dapp-permission-web3))
|
||||
{:db new-db
|
||||
:browser/send-to-bridge {:message {:type constants/web3-permission-request-denied}
|
||||
:webview (:webview-bridge db)}}
|
||||
|
||||
:else
|
||||
{:db new-db})))
|
||||
(fx/defn send-permission-data-to-bridge
|
||||
"If there is granted permission, return the data to the bridge"
|
||||
[{:keys [db] :as cofx} permission message-id allowed?]
|
||||
{:browser/send-to-bridge {:message (cond-> {:type constants/api-response
|
||||
:isAllowed allowed?
|
||||
:permission permission
|
||||
:messageId message-id}
|
||||
allowed?
|
||||
(assoc :data (get-permission-data cofx permission)))
|
||||
:webview (:webview-bridge db)}})
|
||||
|
||||
(fx/defn update-dapp-permissions
|
||||
[{:keys [db]} dapp-name]
|
||||
(let [allowed-permissions-set (get-allowed-permissions db)
|
||||
allowed-permissions {:dapp dapp-name
|
||||
[{:keys [db]} dapp-name permission allowed?]
|
||||
(let [dapp-permissions-set (set (get-in db [:dapps/permissions dapp-name :permissions]))
|
||||
allowed-permissions-set (if allowed?
|
||||
(conj dapp-permissions-set permission)
|
||||
(disj dapp-permissions-set permission))
|
||||
allowed-permissions {:dapp dapp-name
|
||||
:permissions (vec allowed-permissions-set)}]
|
||||
(when (not-empty allowed-permissions-set)
|
||||
{:db (assoc-in db [:dapps/permissions dapp-name] allowed-permissions)
|
||||
:data-store/tx [(dapp-permissions/save-dapp-permissions allowed-permissions)]})))
|
||||
{:db (assoc-in db [:dapps/permissions dapp-name] allowed-permissions)
|
||||
:data-store/tx [(dapp-permissions/save-dapp-permissions allowed-permissions)]}))
|
||||
|
||||
(fx/defn process-next-permission
|
||||
"Process next permission by removing it from pending permissions
|
||||
and prompting user
|
||||
"Process next permission by removing it from pending permissions and prompting user
|
||||
if there is no pending permissions left, save all granted permissions
|
||||
and return the result to the bridge"
|
||||
[{:keys [db] :as cofx} dapp-name]
|
||||
(let [pending-permissions (get-pending-permissions db)
|
||||
next-permission (first pending-permissions)]
|
||||
(if next-permission
|
||||
{:db (-> db
|
||||
(remove-pending-permission next-permission)
|
||||
(assoc-in [:browser/options :show-permission]
|
||||
{:requested-permission next-permission
|
||||
:dapp-name dapp-name}))}
|
||||
(fx/merge cofx
|
||||
{:db (assoc-in db [:browser/options :show-permission] nil)}
|
||||
(update-dapp-permissions dapp-name)
|
||||
(send-permissions-data-to-bridge)))))
|
||||
(if (get-in db [:browser/options :show-permission])
|
||||
{:db db}
|
||||
(let [pending-permissions (get-in db [:browser/options :pending-permissions])
|
||||
next-permission (last pending-permissions)]
|
||||
(when next-permission
|
||||
{:db (-> db
|
||||
(update-in [:browser/options :pending-permissions] butlast)
|
||||
(assoc-in [:browser/options :show-permission]
|
||||
{:requested-permission (:permission next-permission)
|
||||
:message-id (:message-id next-permission)
|
||||
:dapp-name dapp-name}))}))))
|
||||
|
||||
(fx/defn allow-permission
|
||||
"Add permission to set of allowed permission and process next permission"
|
||||
[{:keys [db] :as cofx} dapp-name permission]
|
||||
(fx/merge cofx
|
||||
{:db (add-allowed-permission db permission)}
|
||||
(process-next-permission dapp-name)))
|
||||
[{:keys [db] :as cofx}]
|
||||
(let [{:keys [requested-permission message-id dapp-name]} (get-in db [:browser/options :show-permission])]
|
||||
(fx/merge (assoc-in cofx [:db :browser/options :show-permission] nil)
|
||||
(update-dapp-permissions dapp-name requested-permission true)
|
||||
(send-permission-data-to-bridge requested-permission message-id true))))
|
||||
|
||||
(fx/defn process-permissions
|
||||
"Process the permissions requested by a dapp
|
||||
If all supported permissions are already granted, return the result immediatly
|
||||
to the bridge
|
||||
(fx/defn deny-permission
|
||||
"Add permission to set of allowed permission and process next permission"
|
||||
[{:keys [db] :as cofx}]
|
||||
(let [{:keys [requested-permission message-id dapp-name]} (get-in db [:browser/options :show-permission])]
|
||||
(fx/merge (assoc-in cofx [:db :browser/options :show-permission] nil)
|
||||
(send-permission-data-to-bridge requested-permission message-id false))))
|
||||
|
||||
(fx/defn process-permission
|
||||
"Process the permission requested by a dapp
|
||||
If supported permission is already granted, return the result immediatly to the bridge
|
||||
Otherwise process the first permission which will prompt user"
|
||||
[cofx dapp-name requested-permissions]
|
||||
(let [requested-permissions-set (set requested-permissions)
|
||||
current-dapp-permissions (get-in cofx [:db :dapps/permissions dapp-name :permissions])
|
||||
current-dapp-permissions-set (set current-dapp-permissions)
|
||||
supported-permissions-set (set (keys supported-permissions))
|
||||
allowed-permissions (set/intersection requested-permissions-set
|
||||
current-dapp-permissions-set)
|
||||
pending-permissions (-> requested-permissions-set
|
||||
(set/intersection supported-permissions-set)
|
||||
(set/difference current-dapp-permissions-set))
|
||||
new-cofx (update-in cofx [:db :browser/options] merge
|
||||
{:pending-permissions pending-permissions
|
||||
:allowed-permissions allowed-permissions
|
||||
:requested-permissions requested-permissions-set})]
|
||||
(if (empty? pending-permissions)
|
||||
(send-permissions-data-to-bridge new-cofx)
|
||||
(process-next-permission new-cofx dapp-name))))
|
||||
[cofx dapp-name permission message-id]
|
||||
(let [allowed-permissions (set (get-in cofx [:db :dapps/permissions dapp-name :permissions]))
|
||||
permission-allowed? (boolean (allowed-permissions permission))
|
||||
permission-supported? ((set (keys supported-permissions)) permission)]
|
||||
(if (or permission-allowed? (not permission-supported?))
|
||||
(send-permission-data-to-bridge cofx permission message-id permission-allowed?)
|
||||
(process-next-permission (update-in cofx [:db :browser/options :pending-permissions]
|
||||
conj {:permission permission
|
||||
:message-id message-id})
|
||||
dapp-name))))
|
@ -189,11 +189,10 @@
|
||||
|
||||
(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 dapp-permission-web3 "WEB3")
|
||||
(def ^:const status-api-success "status-api-success")
|
||||
(def ^:const status-api-request "status-api-request")
|
||||
(def ^:const web3-permission-request-denied "web3-permission-request-denied")
|
||||
(def ^:const dapp-permission-contact-code "contact-code")
|
||||
(def ^:const dapp-permission-web3 "web3")
|
||||
(def ^:const api-response "api-response")
|
||||
(def ^:const api-request "api-request")
|
||||
(def ^:const history-state-changed "history-state-changed")
|
||||
(def ^:const web3-send-async "web3-send-async")
|
||||
(def ^:const web3-send-async-read-only "web3-send-async-read-only")
|
||||
|
@ -837,11 +837,16 @@
|
||||
|
||||
(handlers/register-handler-fx
|
||||
:browser.permissions.ui/dapp-permission-allowed
|
||||
(fn [cofx [_ dapp-name permission]]
|
||||
(browser.permissions/allow-permission cofx dapp-name permission)))
|
||||
(fn [cofx _]
|
||||
(browser.permissions/allow-permission cofx)))
|
||||
|
||||
(handlers/register-handler-fx
|
||||
:browser.permissions.ui/dapp-permission-denied
|
||||
(fn [cofx _]
|
||||
(browser.permissions/deny-permission cofx)))
|
||||
|
||||
(handlers/register-handler-fx
|
||||
:browser.permissions.ui/permission-animation-finished
|
||||
(fn [cofx [_ dapp-name]]
|
||||
(browser.permissions/process-next-permission cofx dapp-name)))
|
||||
|
||||
|
@ -11,14 +11,19 @@
|
||||
[status-im.ui.screens.browser.styles :as styles])
|
||||
(:require-macros [status-im.utils.views :as views]))
|
||||
|
||||
(views/defview permissions-panel [{:keys [dapp? name dapp] :as browser} {:keys [requested-permission dapp-name]}]
|
||||
(views/defview permissions-panel [{:keys [dapp? dapp]} {:keys [requested-permission dapp-name]}]
|
||||
(views/letsubs [bottom-anim-value (anim/create-value -354)
|
||||
alpha-value (anim/create-value 0)
|
||||
hide-panel #(anim/start
|
||||
(anim/parallel
|
||||
[(anim/spring bottom-anim-value {:toValue -354})
|
||||
(anim/timing alpha-value {:toValue 0
|
||||
:duration 500})]))]
|
||||
hide-panel (fn []
|
||||
(js/setTimeout #(re-frame/dispatch
|
||||
[:browser.permissions.ui/permission-animation-finished
|
||||
dapp-name])
|
||||
600)
|
||||
(anim/start
|
||||
(anim/parallel
|
||||
[(anim/spring bottom-anim-value {:toValue -354})
|
||||
(anim/timing alpha-value {:toValue 0
|
||||
:duration 500})])))]
|
||||
{:component-did-mount #(anim/start
|
||||
(anim/parallel
|
||||
[(anim/spring bottom-anim-value {:toValue -20})
|
||||
@ -52,16 +57,13 @@
|
||||
[react/text {:style styles/permissions-panel-description-label}
|
||||
description]
|
||||
[react/view {:flex-direction :row :margin-top 14}
|
||||
[components.common/button {:on-press #(re-frame/dispatch [:browser.permissions.ui/dapp-permission-denied dapp-name])
|
||||
:label (i18n/label :t/deny)}]
|
||||
[components.common/button
|
||||
{:on-press #(re-frame/dispatch [:browser.permissions.ui/dapp-permission-denied])
|
||||
:label (i18n/label :t/deny)}]
|
||||
[react/view {:width 16}]
|
||||
[components.common/button {:on-press #(re-frame/dispatch [:browser.permissions.ui/dapp-permission-allowed dapp-name requested-permission])
|
||||
:label (i18n/label :t/allow)}]]
|
||||
;; TODO (andrey) will be in next PR
|
||||
#_[react/view {:flex-direction :row :margin-top 19}
|
||||
[icons/icon :icons/settings {:color colors/blue}]
|
||||
[react/text {:style styles/permissions-panel-permissions-label}
|
||||
(i18n/label :t/manage-permissions)]]]])))
|
||||
[components.common/button
|
||||
{:on-press #(re-frame/dispatch [:browser.permissions.ui/dapp-permission-allowed])
|
||||
:label (i18n/label :t/allow)}]]]])))
|
||||
|
||||
;; NOTE (andrey) we need this complex function, to show animation before component will be unmounted
|
||||
(defn permissions-anim-panel [browser show-permission]
|
||||
|
@ -5,82 +5,85 @@
|
||||
[status-im.browser.core :as browser]))
|
||||
|
||||
(deftest permissions-test
|
||||
(let [dapp-name "test.com"
|
||||
dapp-name2 "test2.org"
|
||||
cofx {:db (assoc-in (:db (browser/open-url {:db {}} dapp-name))
|
||||
[:account/account :public-key] "public-key")}]
|
||||
(let [dapp-name "test.com"
|
||||
dapp-name2 "test2.org"
|
||||
cofx {:db (assoc-in (:db (browser/open-url {:db {}} dapp-name))
|
||||
[:account/account :public-key] "public-key")}]
|
||||
(testing "dapps permissions are initialized"
|
||||
(is (zero? (count (get-in cofx [:db :dapps/permissions]))))
|
||||
(is (= dapp-name (get-in cofx [:db :browser/options :browser-id]))))
|
||||
|
||||
(testing "receiving an unsupported permission"
|
||||
(is (nil? (:browser/send-to-bridge (browser/process-bridge-message cofx
|
||||
(types/clj->json {:type "status-api-request"
|
||||
:host dapp-name
|
||||
:permissions ["FAKE_PERMISSION"]}))))
|
||||
"nothing should happen"))
|
||||
|
||||
(testing "receiving a supported permission and an unsupported one"
|
||||
(let [result-ask (browser/process-bridge-message cofx
|
||||
(types/clj->json {:type "status-api-request"
|
||||
:host dapp-name
|
||||
:permissions ["CONTACT_CODE" "FAKE_PERMISSION"]}))]
|
||||
(types/clj->json {:type "api-request"
|
||||
:host dapp-name
|
||||
:messageId 0
|
||||
:permission "FAKE_PERMISSION"}))]
|
||||
(is (not (get-in result-ask [:browser/send-to-bridge :message :isAllowed])))))
|
||||
|
||||
(testing "receiving a supported permission"
|
||||
(let [result-ask (browser/process-bridge-message cofx
|
||||
(types/clj->json {:type "api-request"
|
||||
:host dapp-name
|
||||
:messageId 1
|
||||
:permission "contact-code"}))]
|
||||
(is (= (get-in result-ask [:db :browser/options :show-permission])
|
||||
{:requested-permission "CONTACT_CODE", :dapp-name "test.com"}))
|
||||
{:requested-permission "contact-code" :dapp-name "test.com" :message-id 1}))
|
||||
(is (zero? (count (get-in result-ask [:db :dapps/permissions]))))
|
||||
|
||||
(testing "then user accepts the supported permission"
|
||||
(let [accept-result (permissions/allow-permission {:db (:db result-ask)} dapp-name "CONTACT_CODE")]
|
||||
(let [accept-result (permissions/allow-permission {:db (:db result-ask)})]
|
||||
(is (= (get-in accept-result [:browser/send-to-bridge :message])
|
||||
{:type "status-api-success"
|
||||
:data {"CONTACT_CODE" "public-key"}
|
||||
:keys ["CONTACT_CODE"]})
|
||||
{:type "api-response"
|
||||
:messageId 1
|
||||
:isAllowed true
|
||||
:data "public-key"
|
||||
:permission "contact-code"})
|
||||
"the data should have been sent to the bridge")
|
||||
(is (= (get-in accept-result [:db :dapps/permissions])
|
||||
{"test.com" {:dapp "test.com", :permissions ["CONTACT_CODE"]}})
|
||||
{"test.com" {:dapp "test.com", :permissions ["contact-code"]}})
|
||||
"the dapp should now have CONTACT_CODE permission")
|
||||
|
||||
(testing "then dapps asks for permission again"
|
||||
(testing "then dapp asks for permission again"
|
||||
(let [result-ask-again (browser/process-bridge-message {:db (:db accept-result)}
|
||||
(types/clj->json {:type "status-api-request"
|
||||
:host dapp-name
|
||||
:permissions ["CONTACT_CODE"]}))]
|
||||
(types/clj->json {:type "api-request"
|
||||
:host dapp-name
|
||||
:messageId 2
|
||||
:permission "contact-code"}))]
|
||||
(is (= (get-in result-ask-again
|
||||
[:browser/send-to-bridge :message])
|
||||
{:type "status-api-success"
|
||||
:data {"CONTACT_CODE" "public-key"}
|
||||
:keys ["CONTACT_CODE"]})
|
||||
{:type "api-response"
|
||||
:isAllowed true
|
||||
:messageId 2
|
||||
:data "public-key"
|
||||
:permission "contact-code"})
|
||||
"the response should be immediatly sent to the bridge")))
|
||||
|
||||
(testing "then user switch to another dapp that asks for permissions"
|
||||
(let [new-dapp (browser/open-url {:db (:db accept-result)} dapp-name2)
|
||||
(let [new-dapp (browser/open-url {:db (:db accept-result)} dapp-name2)
|
||||
result-ask2 (browser/process-bridge-message {:db (:db new-dapp)}
|
||||
(types/clj->json {:type "status-api-request"
|
||||
:host dapp-name2
|
||||
:permissions ["CONTACT_CODE" "FAKE_PERMISSION"]}))]
|
||||
(types/clj->json {:type "api-request"
|
||||
:host dapp-name2
|
||||
:messageId 3
|
||||
:permission "contact-code"}))]
|
||||
(is (= (get-in result-ask2 [:db :dapps/permissions])
|
||||
{"test.com" {:dapp "test.com", :permissions ["CONTACT_CODE"]}})
|
||||
{"test.com" {:dapp "test.com", :permissions ["contact-code"]}})
|
||||
"there should only be permissions for dapp-name at that point")
|
||||
(is (nil? (get-in result-ask2
|
||||
[:browser/send-to-bridge :message]))
|
||||
"no message should be sent to the bridge")
|
||||
|
||||
(testing "then user accepts permission for dapp-name2"
|
||||
(let [accept-result2 (permissions/allow-permission {:db (:db result-ask2)} dapp-name2 "CONTACT_CODE")]
|
||||
(let [accept-result2 (permissions/allow-permission {:db (:db result-ask2)})]
|
||||
(is (= (get-in accept-result2 [:db :dapps/permissions])
|
||||
{"test.com" {:dapp "test.com" :permissions ["CONTACT_CODE"]}
|
||||
"test2.org" {:dapp "test2.org" :permissions ["CONTACT_CODE"]}})
|
||||
{"test.com" {:dapp "test.com" :permissions ["contact-code"]}
|
||||
"test2.org" {:dapp "test2.org" :permissions ["contact-code"]}})
|
||||
"there should be permissions for both dapps now")
|
||||
(is (= (get-in accept-result2
|
||||
[:browser/send-to-bridge :message])
|
||||
{:type "status-api-success"
|
||||
:data {"CONTACT_CODE" "public-key"}
|
||||
:keys ["CONTACT_CODE"]})
|
||||
"the response should be sent to the bridge")))))
|
||||
|
||||
(testing "then user refuses the permission"
|
||||
(let [result-refuse (permissions/process-next-permission {:db (:db result-ask)} dapp-name)]
|
||||
(is (zero? (count (get-in result-refuse [:db :dapps/permissions])))
|
||||
"no permissions should be granted")
|
||||
(is (nil? (get-in result-refuse [:browser/send-to-bridge :message]))
|
||||
"no message should be sent to bridge")))))))))
|
||||
{:type "api-response"
|
||||
:isAllowed true
|
||||
:messageId 3
|
||||
:data "public-key"
|
||||
:permission "contact-code"})
|
||||
"the response should be sent to the bridge")))))))))))
|
Loading…
x
Reference in New Issue
Block a user