diff --git a/libnymea-app-core/engine.cpp b/libnymea-app-core/engine.cpp index 68dcdd24..f3d07012 100644 --- a/libnymea-app-core/engine.cpp +++ b/libnymea-app-core/engine.cpp @@ -38,7 +38,6 @@ #include "connection/awsclient.h" #include "system/systemcontroller.h" #include "configuration/networkmanager.h" -#include "usersmanager.h" #include "connection/tcpsockettransport.h" #include "connection/websockettransport.h" @@ -55,8 +54,7 @@ Engine::Engine(QObject *parent) : m_logManager(new LogManager(m_jsonRpcClient, this)), m_tagsManager(new TagsManager(m_jsonRpcClient, this)), m_nymeaConfiguration(new NymeaConfiguration(m_jsonRpcClient, this)), - m_systemController(new SystemController(m_jsonRpcClient, this)), - m_usersManager(new UsersManager(m_jsonRpcClient, this)) + m_systemController(new SystemController(m_jsonRpcClient, this)) { m_connection->registerTransport(new TcpSocketTransportFactory()); m_connection->registerTransport(new WebsocketTransportFactory()); @@ -124,11 +122,6 @@ SystemController *Engine::systemController() const return m_systemController; } -UsersManager *Engine::usersManager() const -{ - return m_usersManager; -} - void Engine::deployCertificate() { if (!m_jsonRpcClient->connected()) { diff --git a/libnymea-app-core/engine.h b/libnymea-app-core/engine.h index b077678e..70e87dd0 100644 --- a/libnymea-app-core/engine.h +++ b/libnymea-app-core/engine.h @@ -45,7 +45,6 @@ class TagsManager; class NymeaConfiguration; class SystemController; class NetworkManager; -class UsersManager; class Engine : public QObject { @@ -58,7 +57,6 @@ class Engine : public QObject Q_PROPERTY(JsonRpcClient* jsonRpcClient READ jsonRpcClient CONSTANT) Q_PROPERTY(NymeaConfiguration* nymeaConfiguration READ nymeaConfiguration CONSTANT) Q_PROPERTY(SystemController* systemController READ systemController CONSTANT) - Q_PROPERTY(UsersManager* usersManager READ usersManager CONSTANT) public: explicit Engine(QObject *parent = nullptr); @@ -75,7 +73,6 @@ public: LogManager *logManager() const; NymeaConfiguration *nymeaConfiguration() const; SystemController *systemController() const; - UsersManager *usersManager() const; Q_INVOKABLE void deployCertificate(); @@ -89,7 +86,6 @@ private: TagsManager *m_tagsManager; NymeaConfiguration *m_nymeaConfiguration; SystemController *m_systemController; - UsersManager *m_usersManager; private slots: void onConnectedChanged(); diff --git a/libnymea-app-core/libnymea-app-core.h b/libnymea-app-core/libnymea-app-core.h index a4d8a699..fc65b699 100644 --- a/libnymea-app-core/libnymea-app-core.h +++ b/libnymea-app-core/libnymea-app-core.h @@ -105,6 +105,9 @@ #include "types/script.h" #include "types/scripts.h" #include "types/types.h" +#include "usermanager.h" +#include "types/tokeninfos.h" +#include "types/tokeninfo.h" #include @@ -281,6 +284,10 @@ void registerQmlTypes() { qmlRegisterType(uri, 1, 0, "ScriptSyntaxHighlighter"); qmlRegisterType(uri, 1, 0, "CodeCompletion"); qmlRegisterUncreatableType(uri, 1, 0, "CompletionModel", "Get it from ScriptSyntaxHighlighter"); + + qmlRegisterType(uri, 1, 0, "UserManager"); + qmlRegisterUncreatableType(uri, 1, 0, "TokenInfos", "Get it from UserManager"); + qmlRegisterUncreatableType(uri, 1, 0, "TokenInfo", "Get it from TokenInfos"); } #endif // LIBNYMEAAPPCORE_H diff --git a/libnymea-app-core/libnymea-app-core.pro b/libnymea-app-core/libnymea-app-core.pro index ebf067f5..663b8bd1 100644 --- a/libnymea-app-core/libnymea-app-core.pro +++ b/libnymea-app-core/libnymea-app-core.pro @@ -55,6 +55,7 @@ SOURCES += \ scripting/completionmodel.cpp \ scriptmanager.cpp \ scriptsyntaxhighlighter.cpp \ + usermanager.cpp \ vendorsproxy.cpp \ pluginsproxy.cpp \ interfacesmodel.cpp \ @@ -90,7 +91,6 @@ SOURCES += \ configuration/mqttpolicies.cpp \ models/devicemodel.cpp \ system/systemcontroller.cpp \ - usersmanager.cpp \ HEADERS += \ @@ -124,6 +124,7 @@ HEADERS += \ scripting/completionmodel.h \ scriptmanager.h \ scriptsyntaxhighlighter.h \ + usermanager.h \ vendorsproxy.h \ pluginsproxy.h \ interfacesmodel.h \ @@ -159,7 +160,6 @@ HEADERS += \ configuration/mqttpolicies.h \ models/devicemodel.h \ system/systemcontroller.h \ - usersmanager.h \ ubports: { DEFINES += UBPORTS diff --git a/libnymea-app-core/usermanager.cpp b/libnymea-app-core/usermanager.cpp new file mode 100644 index 00000000..e4355e2c --- /dev/null +++ b/libnymea-app-core/usermanager.cpp @@ -0,0 +1,64 @@ +#include "usermanager.h" +#include "types/tokeninfo.h" + +#include + +UserManager::UserManager(QObject *parent): + JsonHandler(parent) +{ + m_tokenInfos = new TokenInfos(this); +} + +Engine *UserManager::engine() const +{ + return m_engine; +} + +void UserManager::setEngine(Engine *engine) +{ + if (m_engine != engine) { + m_engine = engine; + m_engine->jsonRpcClient()->registerNotificationHandler(this, "notificationReceived"); + emit engineChanged(); + + m_loading = true; + emit loadingChanged(); + + m_engine->jsonRpcClient()->sendCommand("Users.GetTokens", QVariantMap(), this, "getTokensReply"); + } +} + +bool UserManager::loading() const +{ + return m_loading; +} + +TokenInfos *UserManager::tokenInfos() const +{ + return m_tokenInfos; +} + +QString UserManager::nameSpace() const +{ + return "Users"; +} + +void UserManager::notificationReceived(const QVariantMap &data) +{ + qDebug() << "Users notification" << data; +} + +void UserManager::getTokensReply(const QVariantMap ¶ms) +{ + + foreach (const QVariant &tokenVariant, params.value("params").toMap().value("tokenInfoList").toList()) { + qDebug() << "Token received" << tokenVariant.toMap(); + QVariantMap token = tokenVariant.toMap(); + QUuid id = token.value("id").toString(); + QString username = token.value("username").toString(); + QString deviceName = token.value("deviceName").toString(); + QDateTime creationTime = QDateTime::fromSecsSinceEpoch(token.value("creationTime").toInt()); + TokenInfo *tokenInfo = new TokenInfo(id, username, deviceName, creationTime); + m_tokenInfos->addToken(tokenInfo); + } +} diff --git a/libnymea-app-core/usermanager.h b/libnymea-app-core/usermanager.h new file mode 100644 index 00000000..3850963f --- /dev/null +++ b/libnymea-app-core/usermanager.h @@ -0,0 +1,47 @@ +#ifndef USERMANAGER_H +#define USERMANAGER_H + +#include + +#include "jsonrpc/jsonrpcclient.h" +#include "engine.h" + +#include "types/tokeninfos.h" + +class UserManager: public JsonHandler +{ + Q_OBJECT + Q_PROPERTY(Engine* engine READ engine WRITE setEngine NOTIFY engineChanged) + Q_PROPERTY(bool loading READ loading NOTIFY loadingChanged) + + Q_PROPERTY(TokenInfos* tokenInfos READ tokenInfos CONSTANT) + +public: + explicit UserManager(QObject *parent = nullptr); + + Engine* engine() const; + void setEngine(Engine* engine); + + bool loading() const; + + TokenInfos* tokenInfos() const; + + QString nameSpace() const override; + +signals: + void engineChanged(); + void loadingChanged(); + +private slots: + void notificationReceived(const QVariantMap &data); + + void getTokensReply(const QVariantMap ¶ms); + +private: + Engine *m_engine = nullptr; + bool m_loading = false; + + TokenInfos *m_tokenInfos = nullptr; +}; + +#endif // USERMANAGER_H diff --git a/libnymea-app-core/usersmanager.cpp b/libnymea-app-core/usersmanager.cpp deleted file mode 100644 index da931238..00000000 --- a/libnymea-app-core/usersmanager.cpp +++ /dev/null @@ -1,20 +0,0 @@ -#include "usersmanager.h" - -#include - -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; -} diff --git a/libnymea-app-core/usersmanager.h b/libnymea-app-core/usersmanager.h deleted file mode 100644 index 5b3684cc..00000000 --- a/libnymea-app-core/usersmanager.h +++ /dev/null @@ -1,23 +0,0 @@ -#ifndef USERSMANAGER_H -#define USERSMANAGER_H - -#include - -#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 diff --git a/libnymea-common/libnymea-common.pro b/libnymea-common/libnymea-common.pro index 26206534..407e6d01 100644 --- a/libnymea-common/libnymea-common.pro +++ b/libnymea-common/libnymea-common.pro @@ -64,6 +64,9 @@ HEADERS += \ types/tags.h \ types/wirelessaccesspoint.h \ types/wirelessaccesspoints.h \ + types/tokeninfo.h \ + types/tokeninfos.h \ + SOURCES += \ types/browseritem.cpp \ @@ -122,3 +125,7 @@ SOURCES += \ types/tags.cpp \ types/wirelessaccesspoint.cpp \ types/wirelessaccesspoints.cpp \ + types/tokeninfo.cpp \ + types/tokeninfos.cpp \ + + diff --git a/libnymea-common/types/tokeninfo.cpp b/libnymea-common/types/tokeninfo.cpp new file mode 100644 index 00000000..b7206cfc --- /dev/null +++ b/libnymea-common/types/tokeninfo.cpp @@ -0,0 +1,31 @@ +#include "tokeninfo.h" + +TokenInfo::TokenInfo(const QUuid &id, const QString &username, const QString &deviceName, const QDateTime &creationTime, QObject *parent): + QObject(parent), + m_id(id), + m_username(username), + m_deviceName(deviceName), + m_creationTime(creationTime) +{ + +} + +QUuid TokenInfo::id() const +{ + return m_id; +} + +QString TokenInfo::username() const +{ + return m_username; +} + +QString TokenInfo::deviceName() const +{ + return m_deviceName; +} + +QDateTime TokenInfo::creationTime() const +{ + return m_creationTime; +} diff --git a/libnymea-common/types/tokeninfo.h b/libnymea-common/types/tokeninfo.h new file mode 100644 index 00000000..c27f10f3 --- /dev/null +++ b/libnymea-common/types/tokeninfo.h @@ -0,0 +1,26 @@ +#ifndef TOKENINFO_H +#define TOKENINFO_H + +#include +#include +#include + +class TokenInfo : public QObject +{ + Q_OBJECT +public: + explicit TokenInfo(const QUuid &id, const QString &username, const QString &deviceName, const QDateTime &creationTime, QObject *parent = nullptr); + + QUuid id() const; + QString username() const; + QString deviceName() const; + QDateTime creationTime() const; + +private: + QUuid m_id; + QString m_username; + QString m_deviceName; + QDateTime m_creationTime; +}; + +#endif // TOKENINFO_H diff --git a/libnymea-common/types/tokeninfos.cpp b/libnymea-common/types/tokeninfos.cpp new file mode 100644 index 00000000..f9430435 --- /dev/null +++ b/libnymea-common/types/tokeninfos.cpp @@ -0,0 +1,47 @@ +#include "tokeninfos.h" +#include "tokeninfo.h" + +TokenInfos::TokenInfos(QObject *parent) : QAbstractListModel(parent) +{ + +} + +int TokenInfos::rowCount(const QModelIndex &parent) const +{ + Q_UNUSED(parent) + return m_list.count(); +} + +QVariant TokenInfos::data(const QModelIndex &index, int role) const +{ + switch (role) { + case RoleId: + return m_list.at(index.row())->id(); + case RoleUsername: + return m_list.at(index.row())->username(); + case RoleDeviceName: + return m_list.at(index.row())->deviceName(); + case RoleCreationTime: + return m_list.at(index.row())->creationTime(); + } + return QVariant(); +} + +QHash TokenInfos::roleNames() const +{ + QHash roles; + roles.insert(RoleId, "id"); + roles.insert(RoleUsername, "username"); + roles.insert(RoleDeviceName, "deviceName"); + roles.insert(RoleCreationTime, "creationTime"); + return roles; +} + +void TokenInfos::addToken(TokenInfo *tokenInfo) +{ + tokenInfo->setParent(this); + beginInsertRows(QModelIndex(), m_list.count(), m_list.count()); + m_list.append(tokenInfo); + endInsertRows(); + emit countChanged(); +} diff --git a/libnymea-common/types/tokeninfos.h b/libnymea-common/types/tokeninfos.h new file mode 100644 index 00000000..a1c332ba --- /dev/null +++ b/libnymea-common/types/tokeninfos.h @@ -0,0 +1,34 @@ +#ifndef TOKENINFOS_H +#define TOKENINFOS_H + +#include + +class TokenInfo; + +class TokenInfos : public QAbstractListModel +{ + Q_OBJECT + Q_PROPERTY(int count READ rowCount NOTIFY countChanged) +public: + enum Roles { + RoleId, + RoleUsername, + RoleDeviceName, + RoleCreationTime + }; + + explicit TokenInfos(QObject *parent = nullptr); + + int rowCount(const QModelIndex &parent = QModelIndex()) const override; + QVariant data(const QModelIndex &index, int role) const override; + QHash roleNames() const override; + + void addToken(TokenInfo *tokenInfo); +signals: + void countChanged(); + +private: + QList m_list; +}; + +#endif // TOKENINFOS_H diff --git a/nymea-app/ui/system/UsersSettingsPage.qml b/nymea-app/ui/system/UsersSettingsPage.qml index 97aecc29..717a7e11 100644 --- a/nymea-app/ui/system/UsersSettingsPage.qml +++ b/nymea-app/ui/system/UsersSettingsPage.qml @@ -8,230 +8,33 @@ import "../components" Page { id: root header: NymeaHeader { - text: qsTr("Authentication") + text: qsTr("Authentication") + userManager.tokenInfos.count backButtonVisible: true onBackPressed: pageStack.pop() } + UserManager { + id: userManager + engine: _engine + } + ColumnLayout { id: settingsGrid - anchors { horizontalCenter: parent.horizontalCenter; top: parent.top; margins: app.margins } - width: Math.min(500, parent.width - app.margins * 2) + anchors.fill: parent +// width: Math.min(500, parent.width - app.margins * 2) - RowLayout { + ListView { 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 - } - } + Layout.fillHeight: true + model: userManager.tokenInfos - 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 + delegate: NymeaListItemDelegate { width: parent.width - height: parent.height + text: model.deviceName + subText: qsTr("Created on %1").arg(Qt.formatDateTime(model.creationTime, Qt.DefaultLocaleShortDate)) + prominentSubText: false + progressive: false } - 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 } } }