feat: dapps permissions

This commit is contained in:
Richard Ramos 2020-10-04 19:03:37 -04:00 committed by Iuri Matias
parent 1ec6dee429
commit 37e213e89b
11 changed files with 454 additions and 10 deletions

View File

@ -1,5 +1,5 @@
import NimQml, sequtils, strutils, sugar, os
import views/[mailservers_list, ens_manager, contact_list, profile_info, device_list]
import views/[mailservers_list, ens_manager, contact_list, profile_info, device_list, dapp_list]
import ../../status/profile/[mailserver, profile, devices]
import ../../status/profile as status_profile
import ../../status/contacts as status_contacts
@ -22,6 +22,7 @@ QtObject:
addedContacts*: ContactList
blockedContacts*: ContactList
deviceList*: DeviceList
dappList*: DappList
network: string
status*: Status
isDeviceSetup: bool
@ -40,6 +41,7 @@ QtObject:
if not self.deviceList.isNil: self.deviceList.delete
if not self.ens.isNil: self.ens.delete
if not self.profile.isNil: self.profile.delete
if not self.dappList.isNil: self.dappList.delete
self.QObject.delete
proc newProfileView*(status: Status, changeLanguage: proc(locale: string)): ProfileView =
@ -51,6 +53,7 @@ QtObject:
result.addedContacts = newContactList()
result.blockedContacts = newContactList()
result.deviceList = newDeviceList()
result.dappList = newDappList(status)
result.ens = newEnsManager(status)
result.network = ""
result.status = status
@ -241,6 +244,12 @@ QtObject:
QtProperty[QVariant] deviceList:
read = getDeviceList
proc getDappList(self: ProfileView): QVariant {.slot.} =
return newQVariant(self.dappList)
QtProperty[QVariant] dappList:
read = getDappList
proc getEnsManager(self: ProfileView): QVariant {.slot.} =
return newQVariant(self.ens)

View File

@ -0,0 +1,63 @@
import NimQml
import Tables
import ../../../status/status
import permission_list
type
DappsRoles {.pure.} = enum
Name = UserRole + 1,
QtObject:
type DappList* = ref object of QAbstractListModel
status: Status
dapps: seq[Dapp]
permissionList: PermissionList
proc setup(self: DappList) = self.QAbstractListModel.setup
proc delete(self: DappList) =
self.dapps = @[]
self.permissionList.delete
self.QAbstractListModel.delete
proc newDappList*(status: Status): DappList =
new(result, delete)
result.status = status
result.permissionList = newPermissionList(status)
result.dapps = @[]
result.setup
proc init*(self: DappList) {.slot.} =
self.beginResetModel()
self.dapps = self.status.permissions.getDapps()
self.endResetModel()
method rowCount(self: DappList, index: QModelIndex = nil): int =
return self.dapps.len
method data(self: DappList, index: QModelIndex, role: int): QVariant =
if not index.isValid:
return
if index.row < 0 or index.row >= self.dapps.len:
return
result = newQVariant(self.dapps[index.row].name)
method roleNames(self: DappList): Table[int, string] =
{
DappsRoles.Name.int:"name",
}.toTable
proc clearData(self: DappList) {.slot.} =
self.beginResetModel()
self.dapps = @[]
self.endResetModel()
proc revokeAllPermissions(self: DappList) {.slot.} =
self.status.permissions.clearPermissions()
self.clearData()
proc getPermissionList(self: DappList): QVariant {.slot.} =
return newQVariant(self.permissionList)
QtProperty[QVariant] permissionList:
read = getPermissionList

View File

@ -0,0 +1,70 @@
import NimQml
import Tables
import ../../../status/status
import sets
import sequtils
type
PermissionRoles {.pure.} = enum
Name = UserRole + 1,
QtObject:
type PermissionList* = ref object of QAbstractListModel
status: Status
dapp: string
permissions: HashSet[Permission]
proc setup(self: PermissionList) = self.QAbstractListModel.setup
proc delete(self: PermissionList) =
self.dapp = ""
self.permissions = initHashSet[Permission]()
self.QAbstractListModel.delete
proc newPermissionList*(status: Status): PermissionList =
new(result, delete)
result.status = status
result.dapp = ""
result.permissions = initHashSet[Permission]()
result.setup
proc init*(self: PermissionList, dapp: string) {.slot.} =
self.beginResetModel()
self.dapp = dapp
self.permissions = self.status.permissions.getPermissions(dapp)
self.endResetModel()
proc getDapp(self: PermissionList): string {.slot.} = self.dapp
QtProperty[QVariant] dapp:
read = getDapp
proc revokePermission(self: PermissionList, permission: string) {.slot.} =
self.status.permissions.revokePermission(self.dapp, permission.toPermission())
proc revokeAccess(self: PermissionList) {.slot.} =
self.status.permissions.clearPermissions(self.dapp)
method rowCount(self: PermissionList, index: QModelIndex = nil): int = self.permissions.len
method data(self: PermissionList, index: QModelIndex, role: int): QVariant =
if not index.isValid:
return
if index.row < 0 or index.row >= self.permissions.len:
return
result = newQVariant($self.permissions.toSeq[index.row])
method roleNames(self: PermissionList): Table[int, string] =
{
PermissionRoles.Name.int:"name",
}.toTable
proc clearData(self: PermissionList) {.slot.} =
self.beginResetModel()
self.dapp = ""
self.permissions = initHashSet[Permission]()
self.endResetModel()
proc revokeAllPermissions(self: PermissionList) {.slot.} =
self.status.permissions.clearPermissions(self.dapp)
self.clearData()

View File

@ -34,11 +34,29 @@ proc newPermissionsModel*(events: EventEmitter): PermissionsModel =
proc init*(self: PermissionsModel) =
discard
type Dapp* = object
name*: string
permissions*: HashSet[Permission]
proc getDapps*(self: PermissionsModel): seq[Dapp] =
let response = callPrivateRPC("permissions_getDappPermissions")
result = @[]
for dapps in response.parseJson["result"].getElems():
var dapp = Dapp(
name: dapps["dapp"].getStr(),
permissions: initHashSet[Permission]()
)
for permission in dapps["permissions"].getElems():
dapp.permissions.incl(permission.getStr().toPermission())
result.add(dapp)
proc getPermissions*(self: PermissionsModel, dapp: string): HashSet[Permission] =
let response = callPrivateRPC("permissions_getDappPermissions")
result = initHashSet[Permission]()
for dappPermission in response.parseJson["result"].getElems():
if dappPermission["dapp"].getStr() == dapp:
if not dappPermission.hasKey("permissions"): return
for permission in dappPermission["permissions"].getElems():
result.incl(permission.getStr().toPermission())
@ -54,12 +72,19 @@ proc addPermission*(self: PermissionsModel, dapp: string, permission: Permission
}])
proc revokePermission*(self: PermissionsModel, dapp: string, permission: Permission) =
# TODO: implement
discard
var permissions = self.getPermissions(dapp)
permissions.excl(permission)
if permissions.len == 0:
discard callPrivateRPC("permissions_deleteDappPermissions", %*[dapp])
else:
discard callPrivateRPC("permissions_addDappPermissions", %*[{
"dapp": dapp,
"permissions": permissions.toSeq()
}])
proc clearPermissions*(self: PermissionsModel, dapp: string) =
# TODO implement
discard
discard callPrivateRPC("permissions_deleteDappPermissions", %*[dapp])
proc clearPermissions*(self: PermissionsModel) =
let response = callPrivateRPC("permissions_getDappPermissions")

View File

@ -26,11 +26,6 @@ Rectangle {
onClosing: destroy()
}
property Item currentWebView: tabs.currentIndex < tabs.count ? tabs.getTab(tabs.currentIndex).item : null
property Component browserDialogComponent: BrowserDialog {
onClosing: destroy()
}
Layout.fillHeight: true
Layout.fillWidth: true

View File

@ -5,12 +5,17 @@ import QtGraphicalEffects 1.13
import "../../../../imports"
import "../../../../shared"
import "../../../../shared/status"
import "Privileges/"
Item {
id: privacyContainer
Layout.fillHeight: true
Layout.fillWidth: true
property Component dappListPopup: DappList {
onClosed: destroy()
}
Item {
id: profileImgNameContainer
anchors.top: parent.top
@ -74,6 +79,51 @@ Item {
anchors.top: backupSeedPhrase.bottom
anchors.topMargin: Style.current.bigPadding
}
Item {
id: dappPermissions
anchors.top: backupSeedPhrase.bottom
anchors.topMargin: Style.current.padding
height: dappPermissionsText.height
width: parent.width
StyledText {
id: dappPermissionsText
text: qsTr("Set DApp access permissions")
font.pixelSize: 15
}
SVGImage {
id: caret2
anchors.right: parent.right
anchors.rightMargin: 0
anchors.verticalCenter: dappPermissionsText.verticalCenter
source: "../../../img/caret.svg"
width: 13
height: 7
rotation: -90
}
ColorOverlay {
anchors.fill: caret2
source: caret
color: Style.current.darkGrey
rotation: -90
}
MouseArea {
anchors.fill: parent
onClicked: dappListPopup.createObject(privacyContainer).open()
cursorShape: Qt.PointingHandCursor
}
}
Separator {
id: separator2
anchors.top: dappPermissions.bottom
anchors.topMargin: Style.current.bigPadding
}
StatusSectionHeadline {
id: labelPrivacy
//% "Privacy"

View File

@ -0,0 +1,58 @@
import QtQuick 2.3
import QtQuick.Controls 2.3
import QtQuick.Layouts 1.3
import Qt.labs.platform 1.1
import "../../../../../imports"
import "../../../../../shared"
Item {
property string name: "Status.im"
height: 50
anchors.right: parent.right
anchors.left: parent.left
signal dappClicked(string dapp)
SVGImage {
id: image
height: 40
width: 40
anchors.top: parent.top
anchors.topMargin: 4
anchors.left: parent.left
fillMode: Image.PreserveAspectFit
source: "../../../../img/generalDappIcon.svg"
}
StyledText {
id: dappText
text: name
elide: Text.ElideRight
anchors.right: parent.right
anchors.rightMargin: Style.current.padding
font.pixelSize: 17
anchors.top: parent.top
anchors.topMargin: 10
anchors.left: image.right
anchors.leftMargin: Style.current.padding
}
SVGImage {
id: arrow
height: 24
width: 24
anchors.top: parent.top
anchors.topMargin: 10
anchors.right: parent.right
anchors.rightMargin: Style.current.padding
fillMode: Image.PreserveAspectFit
source: "../../../../img/list-next.svg"
}
MouseArea {
cursorShape: Qt.PointingHandCursor
anchors.fill: parent
onClicked: dappClicked(name)
}
}

View File

@ -0,0 +1,50 @@
import QtQuick 2.13
import QtQuick.Controls 2.13
import QtQuick.Layouts 1.13
import "../../../../../imports"
import "../../../../../shared"
import "./"
ModalPopup {
id: popup
title: qsTr("Dapp permissions")
Component.onCompleted: profileModel.dappList.init()
Component.onDestruction: profileModel.dappList.clearData()
property Component permissionListPopup: PermissionList {
onClosed: destroy()
onAccessRevoked: profileModel.dappList.init()
}
Item {
anchors.fill: parent
ScrollView {
anchors.fill: parent
Layout.fillWidth: true
Layout.fillHeight: true
ScrollBar.horizontal.policy: ScrollBar.AlwaysOff
ScrollBar.vertical.policy: dappListView.contentHeight > dappListView.height ? ScrollBar.AlwaysOn : ScrollBar.AlwaysOff
ListView {
anchors.fill: parent
spacing: 0
clip: true
id: dappListView
model: profileModel.dappList
delegate: Dapp {
name: model.name
onDappClicked: permissionListPopup.createObject(privacyContainer, {dapp: dapp}).open()
}
}
}
}
}
/*##^##
Designer {
D{i:0;height:300;width:300}
}
##^##*/

View File

@ -0,0 +1,46 @@
import QtQuick 2.3
import QtQuick.Controls 2.3
import QtQuick.Layouts 1.3
import Qt.labs.platform 1.1
import "../../../../../imports"
import "../../../../../shared"
Item {
property string name: "permission-name-here"
height: 50
anchors.right: parent.right
anchors.left: parent.left
signal removeBtnClicked(string permission)
StyledText {
id: dappText
text: name
elide: Text.ElideRight
anchors.right: parent.right
anchors.rightMargin: Style.current.padding
font.pixelSize: 17
anchors.top: parent.top
anchors.topMargin: Style.current.smallPadding
anchors.left: parent.left
anchors.leftMargin: Style.current.padding
}
StyledText {
text: qsTr("Revoke access")
color: Style.current.red
anchors.top: parent.top
anchors.topMargin: Style.current.smallPadding
anchors.right: parent.right
anchors.rightMargin: Style.current.padding
MouseArea {
cursorShape: Qt.PointingHandCursor
anchors.fill: parent
onClicked: removeBtnClicked(name)
}
}
}

View File

@ -0,0 +1,73 @@
import QtQuick 2.13
import QtQuick.Controls 2.13
import QtQuick.Layouts 1.13
import "../../../../../imports"
import "../../../../../shared"
import "./"
ModalPopup {
property string dapp: ""
id: popup
title: dapp
width: 400
height: 400
Component.onCompleted: profileModel.dappList.permissionList.init(dapp)
Component.onDestruction: profileModel.dappList.permissionList.clearData()
signal accessRevoked(string dapp)
Item {
anchors.fill: parent
ScrollView {
anchors.fill: parent
Layout.fillWidth: true
Layout.fillHeight: true
ScrollBar.horizontal.policy: ScrollBar.AlwaysOff
ScrollBar.vertical.policy: permissionListView.contentHeight > permissionListView.height ? ScrollBar.AlwaysOn : ScrollBar.AlwaysOff
ListView {
anchors.fill: parent
spacing: 0
clip: true
id: permissionListView
model: profileModel.dappList.permissionList
delegate: Permission {
name: model.name
onRemoveBtnClicked: {
profileModel.dappList.permissionList.revokePermission(model.name);
if(permissionListView.count === 1){
accessRevoked(dapp);
close();
}
profileModel.dappList.permissionList.init(dapp)
}
}
}
}
}
footer: StyledButton {
anchors.horizontalCenter: parent.horizontalCenter
btnColor: Style.current.lightRed
btnBorderWidth: 1
btnBorderColor: Style.current.border
textColor: Style.current.red
label: qsTr("Revoke all access")
onClicked: {
profileModel.dappList.permissionList.revokeAccess();
accessRevoked(dapp);
close();
}
}
}
/*##^##
Designer {
D{i:0;height:300;width:300}
}
##^##*/

View File

@ -0,0 +1,5 @@
<svg width="40" height="40" viewBox="0 0 40 40" fill="none" xmlns="http://www.w3.org/2000/svg">
<rect width="40" height="40" rx="20" fill="#EEF2F5"/>
<path d="M19 12.5H15.6923C14.9828 12.5 14.8299 12.5062 14.7296 12.5246C14.1166 12.6369 13.6369 13.1166 13.5246 13.7296C13.5062 13.8299 13.5 13.9828 13.5 14.6923V16.25C13.5 16.6642 13.1642 17 12.75 17C12.3358 17 12 16.6642 12 16.25V14.6923C12 14.049 12 13.7274 12.0491 13.4592C12.2738 12.2332 13.2332 11.2738 14.4592 11.0491C14.7274 11 15.049 11 15.6923 11H19C23.9706 11 28 15.0294 28 20C28 24.9706 23.9706 29 19 29H15.6923C15.049 29 14.7274 29 14.4592 28.9509C13.2332 28.7262 12.2738 27.7668 12.0491 26.5408C12 26.2726 12 25.951 12 25.3077V23.75C12 23.3358 12.3358 23 12.75 23C13.1642 23 13.5 23.3358 13.5 23.75V25.3077C13.5 26.0172 13.5062 26.1701 13.5246 26.2704C13.6369 26.8834 14.1166 27.3631 14.7296 27.4754C14.8299 27.4938 14.9828 27.5 15.6923 27.5H19C23.1421 27.5 26.5 24.1421 26.5 20C26.5 15.8579 23.1421 12.5 19 12.5Z" fill="#939BA1"/>
<path d="M11 19.25C10.5858 19.25 10.25 19.5858 10.25 20C10.25 20.4142 10.5858 20.75 11 20.75H19C19.4142 20.75 19.75 20.4142 19.75 20C19.75 19.5858 19.4142 19.25 19 19.25H11Z" fill="#939BA1"/>
</svg>

After

Width:  |  Height:  |  Size: 1.2 KiB