Merge PR #261: Add Users API

pull/271/head
Jenkins nymea 2020-02-23 23:38:28 +01:00
commit f4cbf5c47c
8 changed files with 55 additions and 8 deletions

2
debian/rules vendored
View File

@ -47,7 +47,7 @@ override_dh_install: $(PREPROCESS_FILES:.in=)
cp -a $(CURDIR)/doc/html $(CURDIR)/debian/nymea-doc/usr/share/doc/nymea/ || true
override_dh_auto_test:
dh_auto_test -- -k TESTARGS="-m 120 -p -o -p -,txt -p -o -p test-results.xml,xunitxml" TESTRUNNER="dbus-test-runner --bus-type=system --task"
dh_auto_test -- -k TESTARGS="-m 120 -p -o -p -,txt -p -o -p test-results.xml,xunitxml" TESTRUNNER="dbus-test-runner --bus-type=both --task"
override_dh_strip:
dh_strip --dbg-package=nymea-dbg

View File

@ -71,7 +71,7 @@ INSTALLS += translations
QMAKE_EXTRA_TARGETS += lupdate lrelease
test.depends += lrelease
test.commands = LD_LIBRARY_PATH=$$top_builddir/libnymea-core:$$top_builddir/libnymea:$$top_builddir/tests/testlib make check TESTRUNNER=\"dbus-test-runner --bus-type=system --task\"
test.commands = LD_LIBRARY_PATH=$$top_builddir/libnymea-core:$$top_builddir/libnymea:$$top_builddir/tests/testlib make check TESTRUNNER=\"dbus-test-runner --bus-type=both --task\"
QMAKE_EXTRA_TARGETS += test
# Show doc files in project tree

View File

@ -854,6 +854,7 @@
}
},
"JSONRPC.Authenticate": {
"deprecated": "Use Users.Authenticate instead.",
"description": "Authenticate a client to the api via user & password challenge. Provide a device name which allows the user to identify the client and revoke the token in case the device is lost or stolen. This will return a new token to be used to authorize a client at the API.",
"params": {
"deviceName": "String",
@ -866,6 +867,7 @@
}
},
"JSONRPC.CreateUser": {
"deprecated": "Use Users.CreateUser instead.",
"description": "Create a new user in the API. Currently this is only allowed to be called once when a new nymea instance is set up. Call Authenticate after this to obtain a device token for this user.",
"params": {
"password": "String",
@ -936,6 +938,7 @@
}
},
"JSONRPC.RequestPushButtonAuth": {
"deprecated": "Use Users.RequestPushButtonAuth instead.",
"description": "Authenticate a client to the api via Push Button method. Provide a device name which allows the user to identify the client and revoke the token in case the device is lost or stolen. If push button hardware is available, this will return with success and start listening for push button presses. When the push button is pressed, the PushButtonAuthFinished notification will be sent to the requesting client. The procedure will be cancelled when the connection is interrupted. If another client requests push button authentication while a procedure is still going on, the second call will take over and the first one will be notified by the PushButtonAuthFinished signal about the error. The application should make it clear to the user to not press the button when the procedure fails as this can happen for 2 reasons: a) a second user is trying to auth at the same time and only the currently active user should press the button or b) it might indicate an attacker trying to take over and snooping in for tokens.",
"params": {
"deviceName": "String"
@ -1473,6 +1476,18 @@
"tagError": "$ref:TagError"
}
},
"Users.Authenticate": {
"description": "Authenticate a client to the api via user & password challenge. Provide a device name which allows the user to identify the client and revoke the token in case the device is lost or stolen. This will return a new token to be used to authorize a client at the API.",
"params": {
"deviceName": "String",
"password": "String",
"username": "String"
},
"returns": {
"o:token": "String",
"success": "Bool"
}
},
"Users.ChangePassword": {
"description": "Change the password for the currently logged in user.",
"params": {
@ -1518,6 +1533,16 @@
"returns": {
"error": "$ref:UserError"
}
},
"Users.RequestPushButtonAuth": {
"description": "Authenticate a client to the api via Push Button method. Provide a device name which allows the user to identify the client and revoke the token in case the device is lost or stolen. If push button hardware is available, this will return with success and start listening for push button presses. When the push button is pressed, the PushButtonAuthFinished notification will be sent to the requesting client. The procedure will be cancelled when the connection is interrupted. If another client requests push button authentication while a procedure is still going on, the second call will take over and the first one will be notified by the PushButtonAuthFinished signal about the error. The application should make it clear to the user to not press the button when the procedure fails as this can happen for 2 reasons: a) a second user is trying to auth at the same time and only the currently active user should press the button or b) it might indicate an attacker trying to take over and snooping in for tokens.",
"params": {
"deviceName": "String"
},
"returns": {
"success": "Bool",
"transactionId": "Int"
}
}
},
"notifications": {
@ -1670,6 +1695,7 @@
}
},
"JSONRPC.PushButtonAuthFinished": {
"deprecated": "Use Users.PushButtonAuthFinished instead.",
"description": "Emitted when a push button authentication reaches final state. NOTE: This notification is special. It will only be emitted to connections that did actively request a push button authentication, but also it will be emitted regardless of the notification settings. ",
"params": {
"o:token": "String",
@ -1868,6 +1894,14 @@
"params": {
"tag": "$ref:Tag"
}
},
"Users.PushButtonAuthFinished": {
"description": "Emitted when a push button authentication reaches final state. NOTE: This notification is special. It will only be emitted to connections that did actively request a push button authentication, but also it will be emitted regardless of the notification settings.",
"params": {
"o:token": "String",
"success": "Bool",
"transactionId": "Int"
}
}
},
"types": {

View File

@ -1,6 +1,7 @@
TEMPLATE = subdirs
SUBDIRS = versioning \
SUBDIRS = \
versioning \
devices \
jsonrpc \
events \

View File

@ -15,5 +15,5 @@ LIBS += -L$$top_builddir/libnymea/ -lnymea \
target.path = /usr/tests
INSTALLS += target
test.commands = LD_LIBRARY_PATH=../../../libnymea:../../../libnymea-core/:../../testlib/ make check TESTRUNNER=\"dbus-test-runner --bus-type=system --task\"
test.commands = LD_LIBRARY_PATH=../../../libnymea:../../../libnymea-core/:../../testlib/ make check TESTRUNNER=\"dbus-test-runner --bus-type=both --task\"
QMAKE_EXTRA_TARGETS += test

View File

@ -127,6 +127,7 @@ void TestUsermanager::initTestCase()
"Application.debug=true\n"
"Tests.debug=true\n"
"UserManager.debug=true\n"
"PushButtonAgent.debug=true\n"
"MockDevice.debug=true");
}
@ -222,6 +223,7 @@ void TestUsermanager::authenticatePushButton()
QVariantMap params;
params.insert("deviceName", "pbtestdevice");
QVariant response = injectAndWait("Users.RequestPushButtonAuth", params);
qCDebug(dcTests()) << "Pushbutton auth response:" << qUtf8Printable(QJsonDocument::fromVariant(response).toJson(QJsonDocument::Indented));
QCOMPARE(response.toMap().value("params").toMap().value("success").toBool(), true);
int transactionId = response.toMap().value("params").toMap().value("transactionId").toInt();
@ -233,6 +235,10 @@ void TestUsermanager::authenticatePushButton()
if (clientSpy.count() == 0) clientSpy.wait();
QVariantMap rsp = checkNotification(clientSpy, "Users.PushButtonAuthFinished").toMap();
for (int i = 0; i < clientSpy.count(); i++) {
qCDebug(dcTests()) << "Notification:" << clientSpy.at(i);
}
QCOMPARE(rsp.value("params").toMap().value("transactionId").toInt(), transactionId);
QVERIFY2(!rsp.value("params").toMap().value("token").toByteArray().isEmpty(), "Token not in push button auth notification");
}

View File

@ -25,6 +25,8 @@
#include <QDebug>
#include <QTimer>
Q_LOGGING_CATEGORY(dcPushButtonAgent, "PushButtonAgent")
PushButtonAgent::PushButtonAgent(QObject *parent) : QObject(parent)
{
}
@ -35,7 +37,7 @@ bool PushButtonAgent::init(QDBusConnection::BusType busType)
bool result = bus.registerObject("/nymea/pushbuttonhandler", this, QDBusConnection::ExportScriptableContents);
if (!result) {
qDebug() << "Error registering PushButton agent on D-Bus.";
qCWarning(dcPushButtonAgent()) << "Error registering PushButton agent on D-Bus" << (busType == QDBusConnection::SessionBus ? "session" : "system") << "bus.";
return false;
}
@ -43,15 +45,15 @@ bool PushButtonAgent::init(QDBusConnection::BusType busType)
message << qVariantFromValue(QDBusObjectPath("/nymea/pushbuttonhandler"));
QDBusMessage reply = bus.call(message);
if (!reply.errorName().isEmpty()) {
qDebug() << "Error registering PushButton agent:" << reply.errorMessage();
qCWarning(dcPushButtonAgent()) << "Error registering PushButton agent:" << reply.errorMessage();
return false;
}
qDebug() << "PushButton agent registered.";
qCDebug(dcPushButtonAgent()) << "PushButton agent registered.";
return true;
}
void PushButtonAgent::sendButtonPressed()
{
qDebug() << "Sending button pressed event.";
qCDebug(dcPushButtonAgent()) << "Sending button pressed event.";
emit PushButtonPressed();
}

View File

@ -24,6 +24,10 @@
#include <QObject>
#include <QDBusConnection>
#include <QLoggingCategory>
Q_DECLARE_LOGGING_CATEGORY(dcPushButtonAgent)
class PushButtonAgent : public QObject
{
Q_OBJECT