Hide user settings if permission is missing
This commit is contained in:
parent
0c574dff84
commit
3ba0c0405e
@ -372,7 +372,7 @@ void registerQmlTypes() {
|
|||||||
qmlRegisterType<ScriptAutoSaver>(uri, 1, 0, "ScriptAutoSaver");
|
qmlRegisterType<ScriptAutoSaver>(uri, 1, 0, "ScriptAutoSaver");
|
||||||
|
|
||||||
qmlRegisterType<UserManager>(uri, 1, 0, "UserManager");
|
qmlRegisterType<UserManager>(uri, 1, 0, "UserManager");
|
||||||
qmlRegisterUncreatableType<UserInfo>(uri, 1, 0, "UserInfo", "Get it from UserManager");
|
qmlRegisterType<UserInfo>(uri, 1, 0, "UserInfo");
|
||||||
qmlRegisterUncreatableType<TokenInfo>(uri, 1, 0, "TokenInfo", "Get it from TokenInfos");
|
qmlRegisterUncreatableType<TokenInfo>(uri, 1, 0, "TokenInfo", "Get it from TokenInfos");
|
||||||
qmlRegisterUncreatableType<TokenInfos>(uri, 1, 0, "TokenInfos", "Get it from UserManager");
|
qmlRegisterUncreatableType<TokenInfos>(uri, 1, 0, "TokenInfos", "Get it from UserManager");
|
||||||
qmlRegisterUncreatableType<Users>(uri, 1, 0, "Users", "Get it from UserManager");
|
qmlRegisterUncreatableType<Users>(uri, 1, 0, "Users", "Get it from UserManager");
|
||||||
|
|||||||
@ -31,18 +31,18 @@
|
|||||||
class UserInfo : public QObject
|
class UserInfo : public QObject
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
Q_PROPERTY(QString username READ username NOTIFY usernameChanged)
|
Q_PROPERTY(QString username READ username WRITE setUsername NOTIFY usernameChanged)
|
||||||
Q_PROPERTY(QString email READ email NOTIFY emailChanged)
|
Q_PROPERTY(QString email READ email WRITE setEmail NOTIFY emailChanged)
|
||||||
Q_PROPERTY(QString displayName READ displayName NOTIFY displayNameChanged)
|
Q_PROPERTY(QString displayName READ displayName WRITE setDisplayName NOTIFY displayNameChanged)
|
||||||
Q_PROPERTY(PermissionScopes scopes READ scopes NOTIFY scopesChanged)
|
Q_PROPERTY(PermissionScopes scopes READ scopes WRITE setScopes NOTIFY scopesChanged)
|
||||||
Q_PROPERTY(QList<QUuid> allowedThingIds READ allowedThingIds NOTIFY allowedThingIdsChanged)
|
Q_PROPERTY(QList<QUuid> allowedThingIds READ allowedThingIds WRITE setAllowedThingIds NOTIFY allowedThingIdsChanged)
|
||||||
|
|
||||||
public:
|
public:
|
||||||
enum PermissionScope {
|
enum PermissionScope {
|
||||||
PermissionScopeNone = 0x0000,
|
PermissionScopeNone = 0x0000,
|
||||||
PermissionScopeControlThings = 0x0001,
|
PermissionScopeControlThings = 0x0001,
|
||||||
PermissionScopeConfigureThings = 0x0003,
|
PermissionScopeConfigureThings = 0x0003,
|
||||||
PermissionScopeAccessAllThings = 0x0004,
|
PermissionScopeAccessAllThings = 0x0004, // Since 8.4
|
||||||
PermissionScopeExecuteRules = 0x0010,
|
PermissionScopeExecuteRules = 0x0010,
|
||||||
PermissionScopeConfigureRules = 0x0030,
|
PermissionScopeConfigureRules = 0x0030,
|
||||||
PermissionScopeAdmin = 0xFFFF,
|
PermissionScopeAdmin = 0xFFFF,
|
||||||
|
|||||||
@ -103,7 +103,14 @@ int UserManager::createUser(const QString &username, const QString &password, co
|
|||||||
if (m_engine->jsonRpcClient()->ensureServerVersion("6.0")) {
|
if (m_engine->jsonRpcClient()->ensureServerVersion("6.0")) {
|
||||||
params.insert("displayName", displayName);
|
params.insert("displayName", displayName);
|
||||||
params.insert("email", email);
|
params.insert("email", email);
|
||||||
params.insert("scopes", UserInfo::scopesToList((UserInfo::PermissionScopes)permissionScopes));
|
|
||||||
|
// Backports compatibility for pre 8.4
|
||||||
|
UserInfo::PermissionScopes scopes = static_cast<UserInfo::PermissionScopes>(permissionScopes);
|
||||||
|
if (!m_engine->jsonRpcClient()->ensureServerVersion("8.4"))
|
||||||
|
scopes.setFlag(UserInfo::PermissionScopeAccessAllThings, false);
|
||||||
|
|
||||||
|
|
||||||
|
params.insert("scopes", UserInfo::scopesToList(scopes));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_engine->jsonRpcClient()->ensureServerVersion("8.4") && !allowedThingIds.isEmpty()) {
|
if (m_engine->jsonRpcClient()->ensureServerVersion("8.4") && !allowedThingIds.isEmpty()) {
|
||||||
@ -145,7 +152,14 @@ int UserManager::setUserScopes(const QString &username, int scopes, const QList<
|
|||||||
{
|
{
|
||||||
QVariantMap params;
|
QVariantMap params;
|
||||||
params.insert("username", username);
|
params.insert("username", username);
|
||||||
params.insert("scopes", UserInfo::scopesToList((UserInfo::PermissionScopes)scopes));
|
|
||||||
|
// Backports compatibility for pre 8.4
|
||||||
|
UserInfo::PermissionScopes finalScopes = static_cast<UserInfo::PermissionScopes>(scopes);
|
||||||
|
if (!m_engine->jsonRpcClient()->ensureServerVersion("8.4"))
|
||||||
|
finalScopes.setFlag(UserInfo::PermissionScopeAccessAllThings, false);
|
||||||
|
|
||||||
|
params.insert("scopes", UserInfo::scopesToList(finalScopes));
|
||||||
|
|
||||||
if (m_engine->jsonRpcClient()->ensureServerVersion("8.4") && !allowedThingIds.isEmpty()) {
|
if (m_engine->jsonRpcClient()->ensureServerVersion("8.4") && !allowedThingIds.isEmpty()) {
|
||||||
QVariantList thingIds;
|
QVariantList thingIds;
|
||||||
foreach (const QUuid &thingId, allowedThingIds)
|
foreach (const QUuid &thingId, allowedThingIds)
|
||||||
|
|||||||
@ -98,7 +98,7 @@ SettingsPageBase {
|
|||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
text: qsTr("Change password")
|
text: qsTr("Change password")
|
||||||
iconName: "qrc:/icons/key.svg"
|
iconName: "qrc:/icons/key.svg"
|
||||||
visible: !engine.jsonRpcClient.pushButtonAuthAvailable
|
visible: NymeaUtils.hasPermissionScope(engine.jsonRpcClient.permissions, UserInfo.PermissionScopeAdmin) && !engine.jsonRpcClient.pushButtonAuthAvailable
|
||||||
onClicked: {
|
onClicked: {
|
||||||
var page = pageStack.push(changePasswordComponent)
|
var page = pageStack.push(changePasswordComponent)
|
||||||
page.confirmed.connect(function(newPassword) {
|
page.confirmed.connect(function(newPassword) {
|
||||||
@ -112,16 +112,15 @@ SettingsPageBase {
|
|||||||
text: qsTr("Edit user information")
|
text: qsTr("Edit user information")
|
||||||
iconName: "qrc:/icons/edit.svg"
|
iconName: "qrc:/icons/edit.svg"
|
||||||
onClicked: pageStack.push(editUserInfoComponent)
|
onClicked: pageStack.push(editUserInfoComponent)
|
||||||
visible: !engine.jsonRpcClient.pushButtonAuthAvailable
|
visible: NymeaUtils.hasPermissionScope(engine.jsonRpcClient.permissions, UserInfo.PermissionScopeAdmin) && !engine.jsonRpcClient.pushButtonAuthAvailable
|
||||||
}
|
}
|
||||||
|
|
||||||
NymeaItemDelegate {
|
NymeaItemDelegate {
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
text: qsTr("Manage authorized devices")
|
text: qsTr("Manage authorized devices")
|
||||||
iconName: "qrc:/icons/smartphone.svg"
|
iconName: "qrc:/icons/smartphone.svg"
|
||||||
onClicked: {
|
visible: NymeaUtils.hasPermissionScope(engine.jsonRpcClient.permissions, UserInfo.PermissionScopeAdmin)
|
||||||
pageStack.push(manageTokensComponent)
|
onClicked: pageStack.push(manageTokensComponent)
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SettingsPageSectionHeader {
|
SettingsPageSectionHeader {
|
||||||
@ -134,12 +133,9 @@ SettingsPageBase {
|
|||||||
text: qsTr("Manage users")
|
text: qsTr("Manage users")
|
||||||
visible: NymeaUtils.hasPermissionScope(engine.jsonRpcClient.permissions, UserInfo.PermissionScopeAdmin) && !engine.jsonRpcClient.pushButtonAuthAvailable
|
visible: NymeaUtils.hasPermissionScope(engine.jsonRpcClient.permissions, UserInfo.PermissionScopeAdmin) && !engine.jsonRpcClient.pushButtonAuthAvailable
|
||||||
iconName: "qrc:/icons/contact-group.svg"
|
iconName: "qrc:/icons/contact-group.svg"
|
||||||
onClicked: {
|
onClicked: pageStack.push(manageUsersComponent)
|
||||||
pageStack.push(manageUsersComponent)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Component {
|
Component {
|
||||||
id: editUserInfoComponent
|
id: editUserInfoComponent
|
||||||
SettingsPageBase {
|
SettingsPageBase {
|
||||||
@ -199,14 +195,16 @@ SettingsPageBase {
|
|||||||
id: configureAllowedThingsPage
|
id: configureAllowedThingsPage
|
||||||
|
|
||||||
property UserInfo userInfo: null
|
property UserInfo userInfo: null
|
||||||
|
property bool existingUser: true
|
||||||
|
|
||||||
|
title: qsTr("Accessable things for") + " \"" + userInfo.username + "\""
|
||||||
|
|
||||||
header: NymeaHeader {
|
header: NymeaHeader {
|
||||||
text: root.title
|
text: configureAllowedThingsPage.title
|
||||||
backButtonVisible: true
|
backButtonVisible: true
|
||||||
onBackPressed: pageStack.pop()
|
onBackPressed: pageStack.pop()
|
||||||
}
|
}
|
||||||
|
|
||||||
title: qsTr("Allowed things for") + " \"" + userInfo.username + "\""
|
|
||||||
ColumnLayout {
|
ColumnLayout {
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
|
|
||||||
@ -236,7 +234,10 @@ SettingsPageBase {
|
|||||||
checked: configureAllowedThingsPage.userInfo.thingAllowed(thingDelegate.thing.id)
|
checked: configureAllowedThingsPage.userInfo.thingAllowed(thingDelegate.thing.id)
|
||||||
onCheckedChanged: {
|
onCheckedChanged: {
|
||||||
configureAllowedThingsPage.userInfo.allowThingId(thingDelegate.thing.id, checked)
|
configureAllowedThingsPage.userInfo.allowThingId(thingDelegate.thing.id, checked)
|
||||||
userManager.setUserScopes(configureAllowedThingsPage.userInfo.username, configureAllowedThingsPage.userInfo.scopes, configureAllowedThingsPage.userInfo.allowedThingIds)
|
if (configureAllowedThingsPage.existingUser) {
|
||||||
|
// Only update if this user already exists
|
||||||
|
userManager.setUserScopes(configureAllowedThingsPage.userInfo.username, configureAllowedThingsPage.userInfo.scopes, configureAllowedThingsPage.userInfo.allowedThingIds)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -438,7 +439,7 @@ SettingsPageBase {
|
|||||||
Repeater {
|
Repeater {
|
||||||
id: permissionRepeater
|
id: permissionRepeater
|
||||||
|
|
||||||
model: NymeaUtils.scopesModel
|
model: engine.jsonRpcClient.ensureServerVersion("8.4") ? NymeaUtils.scopesModel : NymeaUtils.scopesModelPre8dot4
|
||||||
delegate: NymeaSwipeDelegate {
|
delegate: NymeaSwipeDelegate {
|
||||||
|
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
@ -478,24 +479,22 @@ SettingsPageBase {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
SettingsPageSectionHeader {
|
SettingsPageSectionHeader {
|
||||||
text: qsTr("Acessable things")
|
text: qsTr("Acessable things")
|
||||||
visible: (userDetailsPage.userInfo.scopes & UserInfo.PermissionScopeAccessAllThings) !== UserInfo.PermissionScopeAccessAllThings
|
visible: engine.jsonRpcClient.ensureServerVersion("8.4") &&
|
||||||
|
(userDetailsPage.userInfo.scopes & UserInfo.PermissionScopeAccessAllThings) !== UserInfo.PermissionScopeAccessAllThings
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
NymeaSwipeDelegate {
|
NymeaSwipeDelegate {
|
||||||
id: allowedThingsEntry
|
id: allowedThingsEntry
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
text: qsTr("Allowed things for this user")
|
text: qsTr("Allowed things for this user")
|
||||||
subText: userDetailsPage.userInfo.allowedThingIds.length + " " + qsTr("things accessable")
|
subText: userDetailsPage.userInfo.allowedThingIds.length + " " + qsTr("things accessable")
|
||||||
visible: (userDetailsPage.userInfo.scopes & UserInfo.PermissionScopeAccessAllThings) !== UserInfo.PermissionScopeAccessAllThings
|
visible: engine.jsonRpcClient.ensureServerVersion("8.4") &&
|
||||||
|
(userDetailsPage.userInfo.scopes & UserInfo.PermissionScopeAccessAllThings) !== UserInfo.PermissionScopeAccessAllThings
|
||||||
progressive: true
|
progressive: true
|
||||||
onClicked: {
|
onClicked: pageStack.push(configureAllowedThingsComponent, {userInfo: userDetailsPage.userInfo})
|
||||||
pageStack.push(configureAllowedThingsComponent, {userInfo: userDetailsPage.userInfo})
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SettingsPageSectionHeader {
|
SettingsPageSectionHeader {
|
||||||
@ -537,7 +536,13 @@ SettingsPageBase {
|
|||||||
id: createUserPage
|
id: createUserPage
|
||||||
title: qsTr("Add a user")
|
title: qsTr("Add a user")
|
||||||
|
|
||||||
property var permissionScopes: UserInfo.PermissionScopeNone
|
UserInfo {
|
||||||
|
id: newUserInfo
|
||||||
|
username: usernameTextField.text
|
||||||
|
email: emailTextField.text
|
||||||
|
displayName: displayNameTextField.text
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
SettingsPageSectionHeader {
|
SettingsPageSectionHeader {
|
||||||
text: qsTr("User information")
|
text: qsTr("User information")
|
||||||
@ -588,30 +593,59 @@ SettingsPageBase {
|
|||||||
text: qsTr("Permissions")
|
text: qsTr("Permissions")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Repeater {
|
Repeater {
|
||||||
id: scopesRepeater
|
id: scopesRepeater
|
||||||
model: NymeaUtils.scopesModel
|
|
||||||
|
|
||||||
delegate: CheckDelegate {
|
model: engine.jsonRpcClient.ensureServerVersion("8.4") ? NymeaUtils.scopesModel : NymeaUtils.scopesModelPre8dot4
|
||||||
|
|
||||||
|
delegate: NymeaSwipeDelegate {
|
||||||
|
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
text: model.text
|
|
||||||
checked: (createUserPage.permissionScopes & model.scope) === model.scope
|
|
||||||
onClicked: {
|
|
||||||
var scopes = createUserPage.permissionScopes
|
|
||||||
if (checked) {
|
|
||||||
scopes |= model.scope
|
|
||||||
} else {
|
|
||||||
scopes &= ~model.scope
|
|
||||||
}
|
|
||||||
|
|
||||||
// make sure the new permissions are consistant before sending them to the core
|
text: model.text
|
||||||
scopes = NymeaUtils.getPermissionScopeAdjustments(model.scope, checked, scopes)
|
subText: model.description
|
||||||
createUserPage.permissionScopes = scopes
|
progressive: false
|
||||||
|
|
||||||
|
CheckBox {
|
||||||
|
anchors.right: parent.right
|
||||||
|
anchors.rightMargin: app.margins
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
enabled: model.scope === UserInfo.PermissionScopeAdmin || ((newUserInfo.scopes & UserInfo.PermissionScopeAdmin) !== UserInfo.PermissionScopeAdmin)
|
||||||
|
checked: (newUserInfo.scopes & model.scope) === model.scope
|
||||||
|
onClicked: {
|
||||||
|
var scopes = newUserInfo.scopes
|
||||||
|
if (checked) {
|
||||||
|
scopes |= model.scope
|
||||||
|
} else {
|
||||||
|
scopes &= ~model.scope
|
||||||
|
}
|
||||||
|
|
||||||
|
// make sure the new permissions are consistant before sending them to the core
|
||||||
|
scopes = NymeaUtils.getPermissionScopeAdjustments(model.scope, checked, scopes)
|
||||||
|
newUserInfo.scopes = scopes
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SettingsPageSectionHeader {
|
||||||
|
text: qsTr("Acessable things")
|
||||||
|
visible: engine.jsonRpcClient.ensureServerVersion("8.4") &&
|
||||||
|
(newUserInfo.scopes & UserInfo.PermissionScopeAccessAllThings) !== UserInfo.PermissionScopeAccessAllThings
|
||||||
|
Layout.fillWidth: true
|
||||||
|
}
|
||||||
|
|
||||||
|
NymeaSwipeDelegate {
|
||||||
|
id: allowedThingsEntry
|
||||||
|
Layout.fillWidth: true
|
||||||
|
text: qsTr("Allowed things for this user")
|
||||||
|
subText: newUserInfo.allowedThingIds.length + " " + qsTr("things accessable")
|
||||||
|
visible: engine.jsonRpcClient.ensureServerVersion("8.4") &&
|
||||||
|
(newUserInfo.scopes & UserInfo.PermissionScopeAccessAllThings) !== UserInfo.PermissionScopeAccessAllThings
|
||||||
|
progressive: true
|
||||||
|
onClicked: pageStack.push(configureAllowedThingsComponent, {userInfo: newUserInfo, existingUser: false})
|
||||||
|
}
|
||||||
|
|
||||||
Button {
|
Button {
|
||||||
text: qsTr("Create new user")
|
text: qsTr("Create new user")
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
@ -620,7 +654,7 @@ SettingsPageBase {
|
|||||||
enabled: usernameTextField.displayText.length >= 3 && passwordTextField.isValid
|
enabled: usernameTextField.displayText.length >= 3 && passwordTextField.isValid
|
||||||
onClicked: {
|
onClicked: {
|
||||||
createUserPage.busy = true
|
createUserPage.busy = true
|
||||||
userManager.createUser(usernameTextField.displayText, passwordTextField.password, displayNameTextField.text, emailTextField.text, createUserPage.permissionScopes)
|
userManager.createUser(usernameTextField.displayText, passwordTextField.password, displayNameTextField.text, emailTextField.text, newUserInfo.scopes, newUserInfo.allowedThingIds)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Connections {
|
Connections {
|
||||||
|
|||||||
@ -166,6 +166,35 @@ Item {
|
|||||||
return namedIcons[name]
|
return namedIcons[name]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
property ListModel scopesModelPre8dot4: ListModel {
|
||||||
|
ListElement {
|
||||||
|
text: qsTr("Admin")
|
||||||
|
description: qsTr("Full access to the system.")
|
||||||
|
scope: UserInfo.PermissionScopeAdmin
|
||||||
|
}
|
||||||
|
ListElement {
|
||||||
|
text: qsTr("Control things")
|
||||||
|
description: qsTr("Execute actions and use things and services.")
|
||||||
|
scope: UserInfo.PermissionScopeControlThings
|
||||||
|
}
|
||||||
|
ListElement {
|
||||||
|
text: qsTr("Configure things")
|
||||||
|
description: qsTr("Add new things and change settings.")
|
||||||
|
scope: UserInfo.PermissionScopeConfigureThings
|
||||||
|
}
|
||||||
|
ListElement {
|
||||||
|
text: qsTr("Execute magic")
|
||||||
|
description: qsTr("Execute rules, scenes and scripts.")
|
||||||
|
scope: UserInfo.PermissionScopeExecuteRules
|
||||||
|
}
|
||||||
|
ListElement {
|
||||||
|
text: qsTr("Configure magic")
|
||||||
|
description: qsTr("Create new rules and scripts in the system.")
|
||||||
|
scope: UserInfo.PermissionScopeConfigureRules
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
property ListModel scopesModel: ListModel {
|
property ListModel scopesModel: ListModel {
|
||||||
ListElement {
|
ListElement {
|
||||||
text: qsTr("Admin")
|
text: qsTr("Admin")
|
||||||
|
|||||||
Reference in New Issue
Block a user