A first stab on managing users
This commit is contained in:
parent
ec61b27129
commit
0d41958b5b
@ -38,6 +38,7 @@
|
|||||||
#include "connection/awsclient.h"
|
#include "connection/awsclient.h"
|
||||||
#include "system/systemcontroller.h"
|
#include "system/systemcontroller.h"
|
||||||
#include "configuration/networkmanager.h"
|
#include "configuration/networkmanager.h"
|
||||||
|
#include "usersmanager.h"
|
||||||
|
|
||||||
#include "connection/tcpsockettransport.h"
|
#include "connection/tcpsockettransport.h"
|
||||||
#include "connection/websockettransport.h"
|
#include "connection/websockettransport.h"
|
||||||
@ -54,7 +55,8 @@ Engine::Engine(QObject *parent) :
|
|||||||
m_logManager(new LogManager(m_jsonRpcClient, this)),
|
m_logManager(new LogManager(m_jsonRpcClient, this)),
|
||||||
m_tagsManager(new TagsManager(m_jsonRpcClient, this)),
|
m_tagsManager(new TagsManager(m_jsonRpcClient, this)),
|
||||||
m_nymeaConfiguration(new NymeaConfiguration(m_jsonRpcClient, this)),
|
m_nymeaConfiguration(new NymeaConfiguration(m_jsonRpcClient, this)),
|
||||||
m_systemController(new SystemController(m_jsonRpcClient, this))
|
m_systemController(new SystemController(m_jsonRpcClient, this)),
|
||||||
|
m_usersManager(new UsersManager(m_jsonRpcClient, this))
|
||||||
{
|
{
|
||||||
m_connection->registerTransport(new TcpSocketTransportFactory());
|
m_connection->registerTransport(new TcpSocketTransportFactory());
|
||||||
m_connection->registerTransport(new WebsocketTransportFactory());
|
m_connection->registerTransport(new WebsocketTransportFactory());
|
||||||
@ -122,6 +124,11 @@ SystemController *Engine::systemController() const
|
|||||||
return m_systemController;
|
return m_systemController;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
UsersManager *Engine::usersManager() const
|
||||||
|
{
|
||||||
|
return m_usersManager;
|
||||||
|
}
|
||||||
|
|
||||||
void Engine::deployCertificate()
|
void Engine::deployCertificate()
|
||||||
{
|
{
|
||||||
if (!m_jsonRpcClient->connected()) {
|
if (!m_jsonRpcClient->connected()) {
|
||||||
|
|||||||
@ -45,6 +45,7 @@ class TagsManager;
|
|||||||
class NymeaConfiguration;
|
class NymeaConfiguration;
|
||||||
class SystemController;
|
class SystemController;
|
||||||
class NetworkManager;
|
class NetworkManager;
|
||||||
|
class UsersManager;
|
||||||
|
|
||||||
class Engine : public QObject
|
class Engine : public QObject
|
||||||
{
|
{
|
||||||
@ -57,6 +58,7 @@ class Engine : public QObject
|
|||||||
Q_PROPERTY(JsonRpcClient* jsonRpcClient READ jsonRpcClient CONSTANT)
|
Q_PROPERTY(JsonRpcClient* jsonRpcClient READ jsonRpcClient CONSTANT)
|
||||||
Q_PROPERTY(NymeaConfiguration* nymeaConfiguration READ nymeaConfiguration CONSTANT)
|
Q_PROPERTY(NymeaConfiguration* nymeaConfiguration READ nymeaConfiguration CONSTANT)
|
||||||
Q_PROPERTY(SystemController* systemController READ systemController CONSTANT)
|
Q_PROPERTY(SystemController* systemController READ systemController CONSTANT)
|
||||||
|
Q_PROPERTY(UsersManager* usersManager READ usersManager CONSTANT)
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit Engine(QObject *parent = nullptr);
|
explicit Engine(QObject *parent = nullptr);
|
||||||
@ -73,6 +75,7 @@ public:
|
|||||||
LogManager *logManager() const;
|
LogManager *logManager() const;
|
||||||
NymeaConfiguration *nymeaConfiguration() const;
|
NymeaConfiguration *nymeaConfiguration() const;
|
||||||
SystemController *systemController() const;
|
SystemController *systemController() const;
|
||||||
|
UsersManager *usersManager() const;
|
||||||
|
|
||||||
Q_INVOKABLE void deployCertificate();
|
Q_INVOKABLE void deployCertificate();
|
||||||
|
|
||||||
@ -86,6 +89,7 @@ private:
|
|||||||
TagsManager *m_tagsManager;
|
TagsManager *m_tagsManager;
|
||||||
NymeaConfiguration *m_nymeaConfiguration;
|
NymeaConfiguration *m_nymeaConfiguration;
|
||||||
SystemController *m_systemController;
|
SystemController *m_systemController;
|
||||||
|
UsersManager *m_usersManager;
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void onConnectedChanged();
|
void onConnectedChanged();
|
||||||
|
|||||||
@ -90,6 +90,8 @@ SOURCES += \
|
|||||||
configuration/mqttpolicies.cpp \
|
configuration/mqttpolicies.cpp \
|
||||||
models/devicemodel.cpp \
|
models/devicemodel.cpp \
|
||||||
system/systemcontroller.cpp \
|
system/systemcontroller.cpp \
|
||||||
|
usersmanager.cpp \
|
||||||
|
|
||||||
|
|
||||||
HEADERS += \
|
HEADERS += \
|
||||||
configuration/networkmanager.h \
|
configuration/networkmanager.h \
|
||||||
@ -157,6 +159,7 @@ HEADERS += \
|
|||||||
configuration/mqttpolicies.h \
|
configuration/mqttpolicies.h \
|
||||||
models/devicemodel.h \
|
models/devicemodel.h \
|
||||||
system/systemcontroller.h \
|
system/systemcontroller.h \
|
||||||
|
usersmanager.h \
|
||||||
|
|
||||||
ubports: {
|
ubports: {
|
||||||
DEFINES += UBPORTS
|
DEFINES += UBPORTS
|
||||||
|
|||||||
20
libnymea-app-core/usersmanager.cpp
Normal file
20
libnymea-app-core/usersmanager.cpp
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
#include "usersmanager.h"
|
||||||
|
|
||||||
|
#include <QDebug>
|
||||||
|
|
||||||
|
UsersManager::UsersManager(JsonRpcClient *client, QObject *parent):
|
||||||
|
JsonHandler(parent),
|
||||||
|
m_jsonRpcClient(client)
|
||||||
|
{
|
||||||
|
m_jsonRpcClient->registerNotificationHandler(this, "notificationReceived");
|
||||||
|
}
|
||||||
|
|
||||||
|
QString UsersManager::nameSpace() const
|
||||||
|
{
|
||||||
|
return "Users";
|
||||||
|
}
|
||||||
|
|
||||||
|
void UsersManager::notificationReceived(const QVariantMap &data)
|
||||||
|
{
|
||||||
|
qDebug() << "Users notification" << data;
|
||||||
|
}
|
||||||
23
libnymea-app-core/usersmanager.h
Normal file
23
libnymea-app-core/usersmanager.h
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
#ifndef USERSMANAGER_H
|
||||||
|
#define USERSMANAGER_H
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
|
||||||
|
#include "jsonrpc/jsonrpcclient.h"
|
||||||
|
|
||||||
|
class UsersManager: public JsonHandler
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
explicit UsersManager(JsonRpcClient *client, QObject *parent = nullptr);
|
||||||
|
|
||||||
|
QString nameSpace() const override;
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void notificationReceived(const QVariantMap &data);
|
||||||
|
|
||||||
|
private:
|
||||||
|
JsonRpcClient *m_jsonRpcClient = nullptr;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // USERSMANAGER_H
|
||||||
@ -208,5 +208,6 @@
|
|||||||
<file>ui/magic/scripting/LineNumbers.qml</file>
|
<file>ui/magic/scripting/LineNumbers.qml</file>
|
||||||
<file>ui/magic/scripting/CompletionBox.qml</file>
|
<file>ui/magic/scripting/CompletionBox.qml</file>
|
||||||
<file>ui/magic/scripting/EditorPane.qml</file>
|
<file>ui/magic/scripting/EditorPane.qml</file>
|
||||||
|
<file>ui/system/UsersSettingsPage.qml</file>
|
||||||
</qresource>
|
</qresource>
|
||||||
</RCC>
|
</RCC>
|
||||||
|
|||||||
@ -70,6 +70,21 @@ Page {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Pane {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Material.elevation: layout.isGrid ? 1 : 0
|
||||||
|
padding: 0
|
||||||
|
NymeaListItemDelegate {
|
||||||
|
width: parent.width
|
||||||
|
iconName: "../images/lock-closed.svg"
|
||||||
|
text: qsTr("Authentication")
|
||||||
|
subText: qsTr("Configure who can log in")
|
||||||
|
prominentSubText: false
|
||||||
|
wrapTexts: false
|
||||||
|
onClicked: pageStack.push(Qt.resolvedUrl("system/UsersSettingsPage.qml"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Pane {
|
Pane {
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
Material.elevation: layout.isGrid ? 1 : 0
|
Material.elevation: layout.isGrid ? 1 : 0
|
||||||
|
|||||||
237
nymea-app/ui/system/UsersSettingsPage.qml
Normal file
237
nymea-app/ui/system/UsersSettingsPage.qml
Normal file
@ -0,0 +1,237 @@
|
|||||||
|
import QtQuick 2.5
|
||||||
|
import QtQuick.Controls 2.1
|
||||||
|
import QtQuick.Controls.Material 2.1
|
||||||
|
import QtQuick.Layouts 1.1
|
||||||
|
import Nymea 1.0
|
||||||
|
import "../components"
|
||||||
|
|
||||||
|
Page {
|
||||||
|
id: root
|
||||||
|
header: NymeaHeader {
|
||||||
|
text: qsTr("Authentication")
|
||||||
|
backButtonVisible: true
|
||||||
|
onBackPressed: pageStack.pop()
|
||||||
|
}
|
||||||
|
|
||||||
|
ColumnLayout {
|
||||||
|
id: settingsGrid
|
||||||
|
anchors { horizontalCenter: parent.horizontalCenter; top: parent.top; margins: app.margins }
|
||||||
|
width: Math.min(500, parent.width - app.margins * 2)
|
||||||
|
|
||||||
|
RowLayout {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
spacing: app.margins
|
||||||
|
Label {
|
||||||
|
text: qsTr("Name")
|
||||||
|
}
|
||||||
|
TextField {
|
||||||
|
id: nameTextField
|
||||||
|
Layout.fillWidth: true
|
||||||
|
text: engine.nymeaConfiguration.serverName
|
||||||
|
}
|
||||||
|
Button {
|
||||||
|
text: qsTr("OK")
|
||||||
|
visible: nameTextField.displayText !== engine.nymeaConfiguration.serverName
|
||||||
|
onClicked: engine.nymeaConfiguration.serverName = nameTextField.displayText
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
RowLayout {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
visible: engine.jsonRpcClient.ensureServerVersion("4.1") && engine.systemController.automaticTimeAvailable
|
||||||
|
Label {
|
||||||
|
text: qsTr("Set date and time automatically")
|
||||||
|
Layout.fillWidth: true
|
||||||
|
}
|
||||||
|
CheckBox {
|
||||||
|
checked: engine.systemController.automaticTime
|
||||||
|
onClicked: {
|
||||||
|
engine.systemController.automaticTime = checked
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
RowLayout {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
spacing: app.margins
|
||||||
|
Layout.preferredHeight: dateButton.implicitHeight
|
||||||
|
visible: engine.jsonRpcClient.ensureServerVersion("4.1")
|
||||||
|
Label {
|
||||||
|
text: qsTr("Date")
|
||||||
|
Layout.fillWidth: true
|
||||||
|
}
|
||||||
|
Label {
|
||||||
|
text: engine.systemController.serverTime.toLocaleDateString()
|
||||||
|
Layout.fillWidth: true
|
||||||
|
horizontalAlignment: Text.AlignRight
|
||||||
|
}
|
||||||
|
Button {
|
||||||
|
id: dateButton
|
||||||
|
visible: !engine.systemController.automaticTime && engine.systemController.timeManagementAvailable
|
||||||
|
contentItem: Item {
|
||||||
|
ColorIcon {
|
||||||
|
name: "../images/edit.svg"
|
||||||
|
color: app.foregroundColor
|
||||||
|
anchors.centerIn: parent
|
||||||
|
height: parent.height
|
||||||
|
width: height
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onClicked: {
|
||||||
|
var popup = datePickerComponent.createObject(root, {dateTime: engine.systemController.serverTime})
|
||||||
|
popup.accepted.connect(function() {
|
||||||
|
print("setting new date", popup.dateTime)
|
||||||
|
engine.systemController.serverTime = popup.dateTime
|
||||||
|
})
|
||||||
|
popup.open();
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
RowLayout {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
spacing: app.margins
|
||||||
|
Layout.preferredHeight: timeButton.implicitHeight
|
||||||
|
visible: engine.jsonRpcClient.ensureServerVersion("4.1")
|
||||||
|
Label {
|
||||||
|
text: qsTr("Time")
|
||||||
|
Layout.fillWidth: true
|
||||||
|
}
|
||||||
|
Label {
|
||||||
|
text: engine.systemController.serverTime.toLocaleTimeString(/*Locale.ShortTimeString*/)
|
||||||
|
Layout.fillWidth: true
|
||||||
|
horizontalAlignment: Text.AlignRight
|
||||||
|
}
|
||||||
|
Button {
|
||||||
|
id: timeButton
|
||||||
|
visible: !engine.systemController.automaticTime && engine.systemController.timeManagementAvailable
|
||||||
|
contentItem: Item {
|
||||||
|
ColorIcon {
|
||||||
|
name: "../images/edit.svg"
|
||||||
|
color: app.foregroundColor
|
||||||
|
anchors.centerIn: parent
|
||||||
|
height: parent.height
|
||||||
|
width: height
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onClicked: {
|
||||||
|
var popup = timePickerComponent.createObject(root, {hour: engine.systemController.serverTime.getHours(), minute: engine.systemController.serverTime.getMinutes()})
|
||||||
|
popup.accepted.connect(function() {
|
||||||
|
var date = new Date(engine.systemController.serverTime)
|
||||||
|
date.setHours(popup.hour);
|
||||||
|
date.setMinutes(popup.minute)
|
||||||
|
engine.systemController.serverTime = date;
|
||||||
|
})
|
||||||
|
popup.open();
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
RowLayout {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
spacing: app.margins
|
||||||
|
visible: engine.jsonRpcClient.ensureServerVersion("4.1")
|
||||||
|
Label {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
text: qsTr("Time zone")
|
||||||
|
}
|
||||||
|
ComboBox {
|
||||||
|
Layout.minimumWidth: 200
|
||||||
|
model: engine.systemController.timeZones
|
||||||
|
currentIndex: model.indexOf(engine.systemController.serverTimeZone)
|
||||||
|
onActivated: {
|
||||||
|
engine.systemController.serverTimeZone = currentText;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Button {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
text: qsTr("Reboot %1:core").arg(app.systemName)
|
||||||
|
visible: engine.systemController.powerManagementAvailable
|
||||||
|
onClicked: {
|
||||||
|
var dialog = Qt.createComponent(Qt.resolvedUrl("../components/MeaDialog.qml"));
|
||||||
|
var text = qsTr("Are you sure you want to reboot your %1:core sytem now?").arg(app.systemName)
|
||||||
|
var popup = dialog.createObject(app,
|
||||||
|
{
|
||||||
|
headerIcon: "../images/dialog-warning-symbolic.svg",
|
||||||
|
title: qsTr("Reboot %1:core").arg(app.systemName),
|
||||||
|
text: text,
|
||||||
|
standardButtons: Dialog.Ok | Dialog.Cancel
|
||||||
|
});
|
||||||
|
popup.open();
|
||||||
|
popup.accepted.connect(function() {
|
||||||
|
engine.systemController.reboot()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Button {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
text: qsTr("Shutdown %1:core").arg(app.systemName)
|
||||||
|
visible: engine.systemController.powerManagementAvailable
|
||||||
|
onClicked: {
|
||||||
|
var dialog = Qt.createComponent(Qt.resolvedUrl("../components/MeaDialog.qml"));
|
||||||
|
var text = qsTr("Are you sure you want to shut down your %1:core sytem now?").arg(app.systemName)
|
||||||
|
var popup = dialog.createObject(app,
|
||||||
|
{
|
||||||
|
headerIcon: "../images/dialog-warning-symbolic.svg",
|
||||||
|
title: qsTr("Shut down %1:core").arg(app.systemName),
|
||||||
|
text: text,
|
||||||
|
standardButtons: Dialog.Ok | Dialog.Cancel
|
||||||
|
});
|
||||||
|
popup.open();
|
||||||
|
popup.accepted.connect(function() {
|
||||||
|
engine.systemController.shutdown()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Component {
|
||||||
|
id: timePickerComponent
|
||||||
|
Dialog {
|
||||||
|
id: timePicker
|
||||||
|
property int maxSize: Math.min(parent.width, parent.height)
|
||||||
|
property int size: Math.min(maxSize, 500)
|
||||||
|
property alias hour: p.hour
|
||||||
|
property alias minute: p.minute
|
||||||
|
width: size - 80
|
||||||
|
height: size
|
||||||
|
x: (parent.width - width) / 2
|
||||||
|
y: (parent.height - height) / 2
|
||||||
|
|
||||||
|
TimePicker {
|
||||||
|
id: p
|
||||||
|
width: parent.width
|
||||||
|
height: parent.height
|
||||||
|
}
|
||||||
|
standardButtons: Dialog.Ok | Dialog.Cancel
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Component {
|
||||||
|
id: datePickerComponent
|
||||||
|
Dialog {
|
||||||
|
id: datePicker
|
||||||
|
property int maxSize: Math.min(parent.width, parent.height)
|
||||||
|
property int size: Math.min(maxSize, 500)
|
||||||
|
property alias dateTime: p.date
|
||||||
|
width: size - 80
|
||||||
|
height: size
|
||||||
|
x: (parent.width - width) / 2
|
||||||
|
y: (parent.height - height) / 2
|
||||||
|
|
||||||
|
DatePicker {
|
||||||
|
id: p
|
||||||
|
width: parent.width
|
||||||
|
height: parent.height
|
||||||
|
date: datePicker.dateTime
|
||||||
|
}
|
||||||
|
standardButtons: Dialog.Ok | Dialog.Cancel
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user