feat: ask for user approval for API requests

This commit is contained in:
Richard Ramos 2020-09-25 15:05:07 -04:00 committed by Iuri Matias
parent 02a7abf864
commit 3326c8b5f5
4 changed files with 140 additions and 45 deletions

View File

@ -41,8 +41,10 @@ type
request: string
APIRequest = ref object
isAllowed: bool
messageId: JsonNode
permission: Permissions
hostname: string
proc requestType(message: string): RequestTypes =
let data = message.parseJson
@ -74,7 +76,9 @@ proc toAPIRequest(message: string): APIRequest =
result = APIRequest(
messageId: data["messageId"],
permission: permission
isAllowed: data{"isAllowed"}.getBool(),
permission: permission,
hostname: data{"hostname"}.getStr()
)
QtObject:
@ -133,30 +137,28 @@ QtObject:
"result": rpcResult.parseJson
}
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
of Permissions.Web3: %* [status_settings.getSetting[string](Setting.DappsAddress, "0x0000000000000000000000000000000000000000")]
of Permissions.ContactCode: %* status_settings.getSetting[string](Setting.PublicKey, "0x0")
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 $ %* {
"type": $ResponseTypes.APIResponse,
"isAllowed": true, # TODO isAllowed or permission is unknown
"type": ResponseTypes.APIResponse,
"isAllowed": isAllowed,
"permission": data.permission,
"messageId": data.messageId,
"data": value
}
proc postMessage*(self: Web3ProviderView, message: string): string {.slot.} =
let requestType = message.requestType()
info "Provider request received", value=requestType
case requestType:
case message.requestType():
of RequestTypes.Web3SendAsyncReadOnly: message.toWeb3SendAsyncReadOnly().process()
of RequestTypes.HistoryStateChanged: """{"type":"TODO-IMPLEMENT-THIS"}""" ############# TODO:
of RequestTypes.APIRequest: message.toAPIRequest().process()

View File

@ -2,12 +2,16 @@ import QtQuick 2.13
import QtQuick.Layouts 1.13
import QtWebEngine 1.10
import QtWebChannel 1.13
import "../../../shared"
import "../../../imports"
Item {
id: browserView
Layout.fillHeight: true
Layout.fillWidth: true
property var request: {"hostname": "", "permission": ""}
// TODO: example qml webbrowser available here:
// 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 {
id: provider
WebChannel.id: "backend"
@ -31,8 +104,15 @@ Item {
signal web3Response(string data);
function 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
}

View File

@ -795,12 +795,12 @@ You may add additional accurate notices of copyright ownership.
(function(){
// Based on
// https://github.com/status-im/status-react/blob/f9fb4d6974138a276b0cdcc6e4ea1611063e70ca/resources/js/provider.js
if(typeof EthereumProvider === "undefined"){
let callbackId = 0;
let callbacks = {};
const onMessage = function(message){
try {
const data = JSON.parse(message);
const id = data.messageId;
const callback = callbacks[id];
@ -837,6 +837,9 @@ You may add additional accurate notices of copyright ownership.
}
}
}
} catch(e) {
console.error(e)
}
}
let backend;
@ -845,7 +848,10 @@ You may add additional accurate notices of copyright ownership.
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 pushState = history.pushState;

View File

@ -57,4 +57,11 @@ QtObject {
"#887af9",
"#8B3131"
]
readonly property string api_request: "api-request"
readonly property string permission_web3: "web3"
readonly property string permission_contactCode: "contact-code"
}