mirror of
https://github.com/status-im/status-desktop.git
synced 2025-01-09 05:52:41 +00:00
feat: ask for user approval for API requests
This commit is contained in:
parent
02a7abf864
commit
3326c8b5f5
@ -41,8 +41,10 @@ type
|
|||||||
request: string
|
request: string
|
||||||
|
|
||||||
APIRequest = ref object
|
APIRequest = ref object
|
||||||
|
isAllowed: bool
|
||||||
messageId: JsonNode
|
messageId: JsonNode
|
||||||
permission: Permissions
|
permission: Permissions
|
||||||
|
hostname: string
|
||||||
|
|
||||||
proc requestType(message: string): RequestTypes =
|
proc requestType(message: string): RequestTypes =
|
||||||
let data = message.parseJson
|
let data = message.parseJson
|
||||||
@ -74,7 +76,9 @@ proc toAPIRequest(message: string): APIRequest =
|
|||||||
|
|
||||||
result = APIRequest(
|
result = APIRequest(
|
||||||
messageId: data["messageId"],
|
messageId: data["messageId"],
|
||||||
permission: permission
|
isAllowed: data{"isAllowed"}.getBool(),
|
||||||
|
permission: permission,
|
||||||
|
hostname: data{"hostname"}.getStr()
|
||||||
)
|
)
|
||||||
|
|
||||||
QtObject:
|
QtObject:
|
||||||
@ -133,30 +137,28 @@ QtObject:
|
|||||||
"result": rpcResult.parseJson
|
"result": rpcResult.parseJson
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
proc process*(data: APIRequest): string =
|
proc process*(data: APIRequest): string =
|
||||||
# TODO: Do a proper implementation. Must ask for approval from the user.
|
|
||||||
# Probably this should happen in BrowserLayout.qml
|
|
||||||
|
|
||||||
var value:JsonNode = case data.permission
|
var value:JsonNode = case data.permission
|
||||||
of Permissions.Web3: %* [status_settings.getSetting[string](Setting.DappsAddress, "0x0000000000000000000000000000000000000000")]
|
of Permissions.Web3: %* [status_settings.getSetting[string](Setting.DappsAddress, "0x0000000000000000000000000000000000000000")]
|
||||||
of Permissions.ContactCode: %* status_settings.getSetting[string](Setting.PublicKey, "0x0")
|
of Permissions.ContactCode: %* status_settings.getSetting[string](Setting.PublicKey, "0x0")
|
||||||
of Permissions.Unknown: newJNull()
|
of Permissions.Unknown: newJNull()
|
||||||
|
|
||||||
|
let isAllowed = data.isAllowed and data.permission != Permissions.Unknown
|
||||||
|
|
||||||
|
info "API request received", host=data.hostname, value=data.permission, isAllowed
|
||||||
|
|
||||||
|
# TODO: if isAllowed, store permission grant
|
||||||
|
|
||||||
return $ %* {
|
return $ %* {
|
||||||
"type": $ResponseTypes.APIResponse,
|
"type": ResponseTypes.APIResponse,
|
||||||
"isAllowed": true, # TODO isAllowed or permission is unknown
|
"isAllowed": isAllowed,
|
||||||
"permission": data.permission,
|
"permission": data.permission,
|
||||||
"messageId": data.messageId,
|
"messageId": data.messageId,
|
||||||
"data": value
|
"data": value
|
||||||
}
|
}
|
||||||
|
|
||||||
proc postMessage*(self: Web3ProviderView, message: string): string {.slot.} =
|
proc postMessage*(self: Web3ProviderView, message: string): string {.slot.} =
|
||||||
let requestType = message.requestType()
|
case message.requestType():
|
||||||
|
|
||||||
info "Provider request received", value=requestType
|
|
||||||
|
|
||||||
case requestType:
|
|
||||||
of RequestTypes.Web3SendAsyncReadOnly: message.toWeb3SendAsyncReadOnly().process()
|
of RequestTypes.Web3SendAsyncReadOnly: message.toWeb3SendAsyncReadOnly().process()
|
||||||
of RequestTypes.HistoryStateChanged: """{"type":"TODO-IMPLEMENT-THIS"}""" ############# TODO:
|
of RequestTypes.HistoryStateChanged: """{"type":"TODO-IMPLEMENT-THIS"}""" ############# TODO:
|
||||||
of RequestTypes.APIRequest: message.toAPIRequest().process()
|
of RequestTypes.APIRequest: message.toAPIRequest().process()
|
||||||
|
@ -2,12 +2,16 @@ import QtQuick 2.13
|
|||||||
import QtQuick.Layouts 1.13
|
import QtQuick.Layouts 1.13
|
||||||
import QtWebEngine 1.10
|
import QtWebEngine 1.10
|
||||||
import QtWebChannel 1.13
|
import QtWebChannel 1.13
|
||||||
|
import "../../../shared"
|
||||||
|
import "../../../imports"
|
||||||
|
|
||||||
Item {
|
Item {
|
||||||
id: browserView
|
id: browserView
|
||||||
Layout.fillHeight: true
|
Layout.fillHeight: true
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
|
|
||||||
|
property var request: {"hostname": "", "permission": ""}
|
||||||
|
|
||||||
// TODO: example qml webbrowser available here:
|
// TODO: example qml webbrowser available here:
|
||||||
// https://doc.qt.io/qt-5/qtwebengine-webengine-quicknanobrowser-example.html
|
// https://doc.qt.io/qt-5/qtwebengine-webengine-quicknanobrowser-example.html
|
||||||
|
|
||||||
@ -24,6 +28,75 @@ Item {
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function postMessage(isAllowed){
|
||||||
|
request.isAllowed = isAllowed;
|
||||||
|
provider.web3Response(web3Provider.postMessage(JSON.stringify(request)));
|
||||||
|
}
|
||||||
|
|
||||||
|
ModalPopup {
|
||||||
|
id: accessDialog
|
||||||
|
|
||||||
|
// TODO: design required
|
||||||
|
|
||||||
|
StyledText {
|
||||||
|
id: siteName
|
||||||
|
text: request.hostname
|
||||||
|
anchors.top: parent.top
|
||||||
|
anchors.topMargin: Style.current.padding
|
||||||
|
width: parent.width
|
||||||
|
wrapMode: Text.WordWrap
|
||||||
|
}
|
||||||
|
|
||||||
|
StyledText {
|
||||||
|
id: permission
|
||||||
|
text: qsTr("Permission requested: %1").arg(request.permission)
|
||||||
|
anchors.top: siteName.bottom
|
||||||
|
anchors.topMargin: Style.current.padding
|
||||||
|
width: parent.width
|
||||||
|
wrapMode: Text.WordWrap
|
||||||
|
}
|
||||||
|
|
||||||
|
StyledText {
|
||||||
|
id: description
|
||||||
|
anchors.top: permission.bottom
|
||||||
|
anchors.topMargin: Style.current.padding
|
||||||
|
width: parent.width
|
||||||
|
wrapMode: Text.WordWrap
|
||||||
|
text: {
|
||||||
|
switch(request.permission){
|
||||||
|
case Constants.permission_web3: return qsTr("Allowing authorizes this DApp to retrieve your wallet address and enable Web3");
|
||||||
|
case Constants.permission_contactCode: return qsTr("Granting access authorizes this DApp to retrieve your chat key");
|
||||||
|
default: return qsTr("Unknown permission");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
StyledButton {
|
||||||
|
anchors.bottom: parent.bottom
|
||||||
|
anchors.bottomMargin: Style.current.padding
|
||||||
|
anchors.left: parent.left
|
||||||
|
anchors.leftMargin: Style.current.padding
|
||||||
|
label: qsTr("Allow")
|
||||||
|
onClicked: {
|
||||||
|
postMessage(true);
|
||||||
|
accessDialog.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
StyledButton {
|
||||||
|
anchors.bottom: parent.bottom
|
||||||
|
anchors.bottomMargin: Style.current.padding
|
||||||
|
anchors.right: parent.right
|
||||||
|
anchors.rightMargin: Style.current.padding
|
||||||
|
label: qsTr("Deny")
|
||||||
|
onClicked: {
|
||||||
|
postMessage(false);
|
||||||
|
accessDialog.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
QtObject {
|
QtObject {
|
||||||
id: provider
|
id: provider
|
||||||
WebChannel.id: "backend"
|
WebChannel.id: "backend"
|
||||||
@ -31,7 +104,14 @@ Item {
|
|||||||
signal web3Response(string data);
|
signal web3Response(string data);
|
||||||
|
|
||||||
function postMessage(data){
|
function postMessage(data){
|
||||||
web3Response(web3Provider.postMessage(data));
|
request = JSON.parse(data)
|
||||||
|
if(request.type === Constants.api_request){
|
||||||
|
// TODO: check if permission has been granted before,
|
||||||
|
// to not show the dialog
|
||||||
|
accessDialog.open()
|
||||||
|
} else {
|
||||||
|
web3Response(web3Provider.postMessage(data));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
property int networkId: web3Provider.networkId
|
property int networkId: web3Provider.networkId
|
||||||
|
@ -795,47 +795,50 @@ You may add additional accurate notices of copyright ownership.
|
|||||||
(function(){
|
(function(){
|
||||||
// Based on
|
// Based on
|
||||||
// https://github.com/status-im/status-react/blob/f9fb4d6974138a276b0cdcc6e4ea1611063e70ca/resources/js/provider.js
|
// https://github.com/status-im/status-react/blob/f9fb4d6974138a276b0cdcc6e4ea1611063e70ca/resources/js/provider.js
|
||||||
|
|
||||||
if(typeof EthereumProvider === "undefined"){
|
if(typeof EthereumProvider === "undefined"){
|
||||||
let callbackId = 0;
|
let callbackId = 0;
|
||||||
let callbacks = {};
|
let callbacks = {};
|
||||||
|
|
||||||
const onMessage = function(message){
|
const onMessage = function(message){
|
||||||
const data = JSON.parse(message);
|
try {
|
||||||
const id = data.messageId;
|
const data = JSON.parse(message);
|
||||||
const callback = callbacks[id];
|
const id = data.messageId;
|
||||||
|
const callback = callbacks[id];
|
||||||
|
|
||||||
if (callback) {
|
if (callback) {
|
||||||
if (data.type === "api-response") {
|
if (data.type === "api-response") {
|
||||||
if (data.permission == "qr-code") {
|
if (data.permission == "qr-code") {
|
||||||
qrCodeResponse(data, callback); // TODO: are we going to support the qr-code permission?
|
qrCodeResponse(data, callback); // TODO: are we going to support the qr-code permission?
|
||||||
} else if (data.isAllowed) {
|
} else if (data.isAllowed) {
|
||||||
if (data.permission == "web3") {
|
if (data.permission == "web3") {
|
||||||
window.statusAppcurrentAccountAddress = data.data[0];
|
window.statusAppcurrentAccountAddress = data.data[0];
|
||||||
}
|
|
||||||
callback.resolve(data.data);
|
|
||||||
} else {
|
|
||||||
callback.reject(new UserRejectedRequest());
|
|
||||||
}
|
|
||||||
} else if (data.type === "web3-send-async-callback") {
|
|
||||||
if (callback.beta) {
|
|
||||||
if (data.error) {
|
|
||||||
if (data.error.code == 4100) {
|
|
||||||
callback.reject(new Unauthorized());
|
|
||||||
} else {
|
|
||||||
callback.reject(data.error);
|
|
||||||
}
|
}
|
||||||
|
callback.resolve(data.data);
|
||||||
} else {
|
} else {
|
||||||
callback.resolve(data.result.result);
|
callback.reject(new UserRejectedRequest());
|
||||||
|
}
|
||||||
|
} else if (data.type === "web3-send-async-callback") {
|
||||||
|
if (callback.beta) {
|
||||||
|
if (data.error) {
|
||||||
|
if (data.error.code == 4100) {
|
||||||
|
callback.reject(new Unauthorized());
|
||||||
|
} else {
|
||||||
|
callback.reject(data.error);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
callback.resolve(data.result.result);
|
||||||
|
}
|
||||||
|
} else 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 (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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} catch(e) {
|
||||||
|
console.error(e)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -845,7 +848,10 @@ You may add additional accurate notices of copyright ownership.
|
|||||||
backend.web3Response.connect(onMessage);
|
backend.web3Response.connect(onMessage);
|
||||||
});
|
});
|
||||||
|
|
||||||
const bridgeSend = data => backend.postMessage(JSON.stringify(data));
|
const bridgeSend = data => {
|
||||||
|
data.hostname = new URL(document.location).host
|
||||||
|
backend.postMessage(JSON.stringify(data));
|
||||||
|
}
|
||||||
|
|
||||||
let history = window.history;
|
let history = window.history;
|
||||||
let pushState = history.pushState;
|
let pushState = history.pushState;
|
||||||
|
@ -57,4 +57,11 @@ QtObject {
|
|||||||
"#887af9",
|
"#887af9",
|
||||||
"#8B3131"
|
"#8B3131"
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
readonly property string api_request: "api-request"
|
||||||
|
|
||||||
|
readonly property string permission_web3: "web3"
|
||||||
|
readonly property string permission_contactCode: "contact-code"
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user