From 03b8be22d607f1e828eb204d0c294e06c439ed0c Mon Sep 17 00:00:00 2001 From: Michael Zanetti Date: Sun, 20 Oct 2019 01:23:28 +0200 Subject: [PATCH] Drop old REST server --- libnymea-core/debugserverhandler.cpp | 91 +- libnymea-core/libnymea-core.pro | 16 - libnymea-core/nymeacore.cpp | 6 - libnymea-core/nymeacore.h | 1 - libnymea-core/servermanager.cpp | 11 - libnymea-core/servermanager.h | 3 - libnymea-core/servers/httpreply.cpp | 21 + libnymea-core/servers/httpreply.h | 8 +- .../servers/rest/deviceclassesresource.cpp | 302 ----- .../servers/rest/deviceclassesresource.h | 74 -- .../servers/rest/devicesresource.cpp | 557 --------- libnymea-core/servers/rest/devicesresource.h | 81 -- libnymea-core/servers/rest/logsresource.cpp | 121 -- libnymea-core/servers/rest/logsresource.h | 57 - .../servers/rest/pluginsresource.cpp | 214 ---- libnymea-core/servers/rest/pluginsresource.h | 67 -- libnymea-core/servers/rest/restresource.cpp | 209 ---- libnymea-core/servers/rest/restresource.h | 70 -- libnymea-core/servers/rest/restserver.cpp | 180 --- libnymea-core/servers/rest/restserver.h | 75 -- libnymea-core/servers/rest/rulesresource.cpp | 329 ------ libnymea-core/servers/rest/rulesresource.h | 78 -- .../servers/rest/vendorsresource.cpp | 136 --- libnymea-core/servers/rest/vendorsresource.h | 59 - libnymea-core/servers/webserver.cpp | 46 +- tests/auto/auto.pro | 6 - .../restdeviceclasses/restdeviceclasses.pro | 5 - .../testrestdeviceclasses.cpp | 338 ------ tests/auto/restdevices/restdevices.pro | 5 - tests/auto/restdevices/testrestdevices.cpp | 805 ------------- tests/auto/restlogging/restlogging.pro | 5 - tests/auto/restlogging/testrestlogging.cpp | 379 ------ tests/auto/restplugins/restplugins.pro | 5 - tests/auto/restplugins/temp | 0 tests/auto/restplugins/testrestplugins.cpp | 280 ----- tests/auto/restrules/restrules.pro | 5 - tests/auto/restrules/testrestrules.cpp | 1016 ----------------- tests/auto/restvendors/restvendors.pro | 5 - tests/auto/restvendors/temp | 0 tests/auto/restvendors/testrestvendors.cpp | 146 --- 40 files changed, 87 insertions(+), 5725 deletions(-) delete mode 100644 libnymea-core/servers/rest/deviceclassesresource.cpp delete mode 100644 libnymea-core/servers/rest/deviceclassesresource.h delete mode 100644 libnymea-core/servers/rest/devicesresource.cpp delete mode 100644 libnymea-core/servers/rest/devicesresource.h delete mode 100644 libnymea-core/servers/rest/logsresource.cpp delete mode 100644 libnymea-core/servers/rest/logsresource.h delete mode 100644 libnymea-core/servers/rest/pluginsresource.cpp delete mode 100644 libnymea-core/servers/rest/pluginsresource.h delete mode 100644 libnymea-core/servers/rest/restresource.cpp delete mode 100644 libnymea-core/servers/rest/restresource.h delete mode 100644 libnymea-core/servers/rest/restserver.cpp delete mode 100644 libnymea-core/servers/rest/restserver.h delete mode 100644 libnymea-core/servers/rest/rulesresource.cpp delete mode 100644 libnymea-core/servers/rest/rulesresource.h delete mode 100644 libnymea-core/servers/rest/vendorsresource.cpp delete mode 100644 libnymea-core/servers/rest/vendorsresource.h delete mode 100644 tests/auto/restdeviceclasses/restdeviceclasses.pro delete mode 100644 tests/auto/restdeviceclasses/testrestdeviceclasses.cpp delete mode 100644 tests/auto/restdevices/restdevices.pro delete mode 100644 tests/auto/restdevices/testrestdevices.cpp delete mode 100644 tests/auto/restlogging/restlogging.pro delete mode 100644 tests/auto/restlogging/testrestlogging.cpp delete mode 100644 tests/auto/restplugins/restplugins.pro delete mode 100644 tests/auto/restplugins/temp delete mode 100644 tests/auto/restplugins/testrestplugins.cpp delete mode 100644 tests/auto/restrules/restrules.pro delete mode 100644 tests/auto/restrules/testrestrules.cpp delete mode 100644 tests/auto/restvendors/restvendors.pro delete mode 100644 tests/auto/restvendors/temp delete mode 100644 tests/auto/restvendors/testrestvendors.cpp diff --git a/libnymea-core/debugserverhandler.cpp b/libnymea-core/debugserverhandler.cpp index f92e8aac..2b71eb95 100644 --- a/libnymea-core/debugserverhandler.cpp +++ b/libnymea-core/debugserverhandler.cpp @@ -21,7 +21,6 @@ #include "nymeacore.h" #include "servers/httprequest.h" #include "servers/httpreply.h" -#include "servers/rest/restresource.h" #include "nymeasettings.h" #include "loggingcategories.h" #include "debugserverhandler.h" @@ -60,7 +59,7 @@ HttpReply *DebugServerHandler::processDebugRequest(const QString &requestPath, c if (requestPath == "/debug" || requestPath == "/debug/") { qCDebug(dcDebugServer()) << "Create debug interface page"; // Fallback default debug page - HttpReply *reply = RestResource::createSuccessReply(); + HttpReply *reply = HttpReply::createSuccessReply(); reply->setHeader(HttpReply::ContentTypeHeader, "text/html"); reply->setPayload(createDebugXmlDocument()); return reply; @@ -72,7 +71,7 @@ HttpReply *DebugServerHandler::processDebugRequest(const QString &requestPath, c QFile logDatabaseFile(NymeaCore::instance()->configuration()->logDBName()); if (!logDatabaseFile.exists()) { qCWarning(dcDebugServer()) << "Could not read log database file for debug download" << NymeaCore::instance()->configuration()->logDBName() << "file does not exist."; - HttpReply *reply = RestResource::createErrorReply(HttpReply::NotFound); + HttpReply *reply = HttpReply::createErrorReply(HttpReply::NotFound); reply->setHeader(HttpReply::ContentTypeHeader, "text/html"); //: The HTTP error message of the debug interface. The %1 represents the file name. reply->setPayload(createErrorXmlDocument(HttpReply::NotFound, tr("Could not find file \"%1\".").arg(logDatabaseFile.fileName()))); @@ -81,7 +80,7 @@ HttpReply *DebugServerHandler::processDebugRequest(const QString &requestPath, c if (!logDatabaseFile.open(QFile::ReadOnly)) { qCWarning(dcDebugServer()) << "Could not read log database file for debug download" << NymeaCore::instance()->configuration()->logDBName(); - HttpReply *reply = RestResource::createErrorReply(HttpReply::Forbidden); + HttpReply *reply = HttpReply::createErrorReply(HttpReply::Forbidden); reply->setHeader(HttpReply::ContentTypeHeader, "text/html"); //: The HTTP error message of the debug interface. The %1 represents the file name. reply->setPayload(createErrorXmlDocument(HttpReply::NotFound, tr("Could not open file \"%1\".").arg(logDatabaseFile.fileName()))); @@ -91,7 +90,7 @@ HttpReply *DebugServerHandler::processDebugRequest(const QString &requestPath, c QByteArray logDatabaseRawData = logDatabaseFile.readAll(); logDatabaseFile.close(); - HttpReply *reply = RestResource::createSuccessReply(); + HttpReply *reply = HttpReply::createSuccessReply(); reply->setHeader(HttpReply::ContentTypeHeader, "application/sql"); reply->setPayload(logDatabaseRawData); return reply; @@ -105,7 +104,7 @@ HttpReply *DebugServerHandler::processDebugRequest(const QString &requestPath, c QFile syslogFile(syslogFileName); if (!syslogFile.exists()) { qCWarning(dcDebugServer()) << "Could not read log database file for debug download" << syslogFileName << "file does not exist."; - HttpReply *reply = RestResource::createErrorReply(HttpReply::NotFound); + HttpReply *reply = HttpReply::createErrorReply(HttpReply::NotFound); reply->setHeader(HttpReply::ContentTypeHeader, "text/html"); reply->setPayload(createErrorXmlDocument(HttpReply::NotFound, tr("Could not find file \"%1\".").arg(syslogFileName))); return reply; @@ -113,7 +112,7 @@ HttpReply *DebugServerHandler::processDebugRequest(const QString &requestPath, c if (!syslogFile.open(QFile::ReadOnly)) { qCWarning(dcDebugServer()) << "Could not read syslog file for debug download" << syslogFileName; - HttpReply *reply = RestResource::createErrorReply(HttpReply::Forbidden); + HttpReply *reply = HttpReply::createErrorReply(HttpReply::Forbidden); reply->setHeader(HttpReply::ContentTypeHeader, "text/html"); reply->setPayload(createErrorXmlDocument(HttpReply::NotFound, tr("Could not open file \"%1\".").arg(syslogFileName))); return reply; @@ -122,7 +121,7 @@ HttpReply *DebugServerHandler::processDebugRequest(const QString &requestPath, c QByteArray syslogFileData = syslogFile.readAll(); syslogFile.close(); - HttpReply *reply = RestResource::createSuccessReply(); + HttpReply *reply = HttpReply::createSuccessReply(); reply->setHeader(HttpReply::ContentTypeHeader, "text/plain"); reply->setPayload(syslogFileData); return reply; @@ -136,7 +135,7 @@ HttpReply *DebugServerHandler::processDebugRequest(const QString &requestPath, c QFile settingsFile(settingsFileName); if (!settingsFile.exists()) { qCWarning(dcDebugServer()) << "Could not read file for debug download" << settingsFileName << "file does not exist."; - HttpReply *reply = RestResource::createErrorReply(HttpReply::NotFound); + HttpReply *reply = HttpReply::createErrorReply(HttpReply::NotFound); reply->setHeader(HttpReply::ContentTypeHeader, "text/html"); reply->setPayload(createErrorXmlDocument(HttpReply::NotFound, tr("Could not find file \"%1\".").arg(settingsFileName))); return reply; @@ -144,7 +143,7 @@ HttpReply *DebugServerHandler::processDebugRequest(const QString &requestPath, c if (!settingsFile.open(QFile::ReadOnly)) { qCWarning(dcDebugServer()) << "Could not read file for debug download" << settingsFileName; - HttpReply *reply = RestResource::createErrorReply(HttpReply::Forbidden); + HttpReply *reply = HttpReply::createErrorReply(HttpReply::Forbidden); reply->setHeader(HttpReply::ContentTypeHeader, "text/html"); reply->setPayload(createErrorXmlDocument(HttpReply::NotFound, tr("Could not open file \"%1\".").arg(settingsFileName))); return reply; @@ -153,7 +152,7 @@ HttpReply *DebugServerHandler::processDebugRequest(const QString &requestPath, c QByteArray settingsFileData = settingsFile.readAll(); settingsFile.close(); - HttpReply *reply = RestResource::createSuccessReply(); + HttpReply *reply = HttpReply::createSuccessReply(); reply->setHeader(HttpReply::ContentTypeHeader, "text/plain"); reply->setPayload(settingsFileData); return reply; @@ -165,7 +164,7 @@ HttpReply *DebugServerHandler::processDebugRequest(const QString &requestPath, c QFile settingsFile(settingsFileName); if (!settingsFile.exists()) { qCWarning(dcDebugServer()) << "Could not read file for debug download" << settingsFileName << "file does not exist."; - HttpReply *reply = RestResource::createErrorReply(HttpReply::NotFound); + HttpReply *reply = HttpReply::createErrorReply(HttpReply::NotFound); reply->setHeader(HttpReply::ContentTypeHeader, "text/html"); reply->setPayload(createErrorXmlDocument(HttpReply::NotFound, tr("Could not find file \"%1\".").arg(settingsFileName))); return reply; @@ -173,7 +172,7 @@ HttpReply *DebugServerHandler::processDebugRequest(const QString &requestPath, c if (!settingsFile.open(QFile::ReadOnly)) { qCWarning(dcDebugServer()) << "Could not read file for debug download" << settingsFileName; - HttpReply *reply = RestResource::createErrorReply(HttpReply::Forbidden); + HttpReply *reply = HttpReply::createErrorReply(HttpReply::Forbidden); reply->setHeader(HttpReply::ContentTypeHeader, "text/html"); reply->setPayload(createErrorXmlDocument(HttpReply::NotFound, tr("Could not open file \"%1\".").arg(settingsFileName))); return reply; @@ -182,7 +181,7 @@ HttpReply *DebugServerHandler::processDebugRequest(const QString &requestPath, c QByteArray settingsFileData = settingsFile.readAll(); settingsFile.close(); - HttpReply *reply = RestResource::createSuccessReply(); + HttpReply *reply = HttpReply::createSuccessReply(); reply->setHeader(HttpReply::ContentTypeHeader, "text/plain"); reply->setPayload(settingsFileData); return reply; @@ -194,7 +193,7 @@ HttpReply *DebugServerHandler::processDebugRequest(const QString &requestPath, c QFile settingsFile(settingsFileName); if (!settingsFile.exists()) { qCWarning(dcDebugServer()) << "Could not read file for debug download" << settingsFileName << "file does not exist."; - HttpReply *reply = RestResource::createErrorReply(HttpReply::NotFound); + HttpReply *reply = HttpReply::createErrorReply(HttpReply::NotFound); reply->setHeader(HttpReply::ContentTypeHeader, "text/html"); reply->setPayload(createErrorXmlDocument(HttpReply::NotFound, tr("Could not find file \"%1\".").arg(settingsFileName))); return reply; @@ -202,7 +201,7 @@ HttpReply *DebugServerHandler::processDebugRequest(const QString &requestPath, c if (!settingsFile.open(QFile::ReadOnly)) { qCWarning(dcDebugServer()) << "Could not read file for debug download" << settingsFileName; - HttpReply *reply = RestResource::createErrorReply(HttpReply::Forbidden); + HttpReply *reply = HttpReply::createErrorReply(HttpReply::Forbidden); reply->setHeader(HttpReply::ContentTypeHeader, "text/html"); reply->setPayload(createErrorXmlDocument(HttpReply::NotFound, tr("Could not open file \"%1\".").arg(settingsFileName))); return reply; @@ -211,7 +210,7 @@ HttpReply *DebugServerHandler::processDebugRequest(const QString &requestPath, c QByteArray settingsFileData = settingsFile.readAll(); settingsFile.close(); - HttpReply *reply = RestResource::createSuccessReply(); + HttpReply *reply = HttpReply::createSuccessReply(); reply->setHeader(HttpReply::ContentTypeHeader, "text/plain"); reply->setPayload(settingsFileData); return reply; @@ -223,7 +222,7 @@ HttpReply *DebugServerHandler::processDebugRequest(const QString &requestPath, c QFile settingsFile(settingsFileName); if (!settingsFile.exists()) { qCWarning(dcDebugServer()) << "Could not read file for debug download" << settingsFileName << "file does not exist."; - HttpReply *reply = RestResource::createErrorReply(HttpReply::NotFound); + HttpReply *reply = HttpReply::createErrorReply(HttpReply::NotFound); reply->setHeader(HttpReply::ContentTypeHeader, "text/html"); reply->setPayload(createErrorXmlDocument(HttpReply::NotFound, tr("Could not find file \"%1\".").arg(settingsFileName))); return reply; @@ -231,7 +230,7 @@ HttpReply *DebugServerHandler::processDebugRequest(const QString &requestPath, c if (!settingsFile.open(QFile::ReadOnly)) { qCWarning(dcDebugServer()) << "Could not read file for debug download" << settingsFileName; - HttpReply *reply = RestResource::createErrorReply(HttpReply::Forbidden); + HttpReply *reply = HttpReply::createErrorReply(HttpReply::Forbidden); reply->setHeader(HttpReply::ContentTypeHeader, "text/html"); reply->setPayload(createErrorXmlDocument(HttpReply::NotFound, tr("Could not open file \"%1\".").arg(settingsFileName))); return reply; @@ -240,7 +239,7 @@ HttpReply *DebugServerHandler::processDebugRequest(const QString &requestPath, c QByteArray settingsFileData = settingsFile.readAll(); settingsFile.close(); - HttpReply *reply = RestResource::createSuccessReply(); + HttpReply *reply = HttpReply::createSuccessReply(); reply->setHeader(HttpReply::ContentTypeHeader, "text/plain"); reply->setPayload(settingsFileData); return reply; @@ -252,7 +251,7 @@ HttpReply *DebugServerHandler::processDebugRequest(const QString &requestPath, c QFile settingsFile(settingsFileName); if (!settingsFile.exists()) { qCWarning(dcDebugServer()) << "Could not read file for debug download" << settingsFileName << "file does not exist."; - HttpReply *reply = RestResource::createErrorReply(HttpReply::NotFound); + HttpReply *reply = HttpReply::createErrorReply(HttpReply::NotFound); reply->setHeader(HttpReply::ContentTypeHeader, "text/html"); reply->setPayload(createErrorXmlDocument(HttpReply::NotFound, tr("Could not find file \"%1\".").arg(settingsFileName))); return reply; @@ -260,7 +259,7 @@ HttpReply *DebugServerHandler::processDebugRequest(const QString &requestPath, c if (!settingsFile.open(QFile::ReadOnly)) { qCWarning(dcDebugServer()) << "Could not read file for debug download" << settingsFileName; - HttpReply *reply = RestResource::createErrorReply(HttpReply::Forbidden); + HttpReply *reply = HttpReply::createErrorReply(HttpReply::Forbidden); reply->setHeader(HttpReply::ContentTypeHeader, "text/html"); reply->setPayload(createErrorXmlDocument(HttpReply::NotFound, tr("Could not open file \"%1\".").arg(settingsFileName))); return reply; @@ -269,7 +268,7 @@ HttpReply *DebugServerHandler::processDebugRequest(const QString &requestPath, c QByteArray settingsFileData = settingsFile.readAll(); settingsFile.close(); - HttpReply *reply = RestResource::createSuccessReply(); + HttpReply *reply = HttpReply::createSuccessReply(); reply->setHeader(HttpReply::ContentTypeHeader, "text/plain"); reply->setPayload(settingsFileData); return reply; @@ -281,7 +280,7 @@ HttpReply *DebugServerHandler::processDebugRequest(const QString &requestPath, c QFile settingsFile(settingsFileName); if (!settingsFile.exists()) { qCWarning(dcDebugServer()) << "Could not read file for debug download" << settingsFileName << "file does not exist."; - HttpReply *reply = RestResource::createErrorReply(HttpReply::NotFound); + HttpReply *reply = HttpReply::createErrorReply(HttpReply::NotFound); reply->setHeader(HttpReply::ContentTypeHeader, "text/html"); reply->setPayload(createErrorXmlDocument(HttpReply::NotFound, tr("Could not find file \"%1\".").arg(settingsFileName))); return reply; @@ -289,7 +288,7 @@ HttpReply *DebugServerHandler::processDebugRequest(const QString &requestPath, c if (!settingsFile.open(QFile::ReadOnly)) { qCWarning(dcDebugServer()) << "Could not read file for debug download" << settingsFileName; - HttpReply *reply = RestResource::createErrorReply(HttpReply::Forbidden); + HttpReply *reply = HttpReply::createErrorReply(HttpReply::Forbidden); reply->setHeader(HttpReply::ContentTypeHeader, "text/html"); reply->setPayload(createErrorXmlDocument(HttpReply::NotFound, tr("Could not open file \"%1\".").arg(settingsFileName))); return reply; @@ -298,7 +297,7 @@ HttpReply *DebugServerHandler::processDebugRequest(const QString &requestPath, c QByteArray settingsFileData = settingsFile.readAll(); settingsFile.close(); - HttpReply *reply = RestResource::createSuccessReply(); + HttpReply *reply = HttpReply::createSuccessReply(); reply->setHeader(HttpReply::ContentTypeHeader, "text/plain"); reply->setPayload(settingsFileData); return reply; @@ -311,7 +310,7 @@ HttpReply *DebugServerHandler::processDebugRequest(const QString &requestPath, c QFile settingsFile(settingsFileName); if (!settingsFile.exists()) { qCWarning(dcDebugServer()) << "Could not read file for debug download" << settingsFileName << "file does not exist."; - HttpReply *reply = RestResource::createErrorReply(HttpReply::NotFound); + HttpReply *reply = HttpReply::createErrorReply(HttpReply::NotFound); reply->setHeader(HttpReply::ContentTypeHeader, "text/html"); reply->setPayload(createErrorXmlDocument(HttpReply::NotFound, tr("Could not find file \"%1\".").arg(settingsFileName))); return reply; @@ -319,7 +318,7 @@ HttpReply *DebugServerHandler::processDebugRequest(const QString &requestPath, c if (!settingsFile.open(QFile::ReadOnly)) { qCWarning(dcDebugServer()) << "Could not read file for debug download" << settingsFileName; - HttpReply *reply = RestResource::createErrorReply(HttpReply::Forbidden); + HttpReply *reply = HttpReply::createErrorReply(HttpReply::Forbidden); reply->setHeader(HttpReply::ContentTypeHeader, "text/html"); reply->setPayload(createErrorXmlDocument(HttpReply::NotFound, tr("Could not open file \"%1\".").arg(settingsFileName))); return reply; @@ -328,7 +327,7 @@ HttpReply *DebugServerHandler::processDebugRequest(const QString &requestPath, c QByteArray settingsFileData = settingsFile.readAll(); settingsFile.close(); - HttpReply *reply = RestResource::createSuccessReply(); + HttpReply *reply = HttpReply::createSuccessReply(); reply->setHeader(HttpReply::ContentTypeHeader, "text/plain"); reply->setPayload(settingsFileData); return reply; @@ -337,7 +336,7 @@ HttpReply *DebugServerHandler::processDebugRequest(const QString &requestPath, c if (requestPath.startsWith("/debug/ping")) { // Only one ping process should run if (m_pingProcess || m_pingReply) - return RestResource::createErrorReply(HttpReply::InternalServerError); + return HttpReply::createErrorReply(HttpReply::InternalServerError); qCDebug(dcDebugServer()) << "Start ping nymea.io process"; m_pingProcess = new QProcess(this); @@ -345,14 +344,14 @@ HttpReply *DebugServerHandler::processDebugRequest(const QString &requestPath, c connect(m_pingProcess, SIGNAL(finished(int, QProcess::ExitStatus)), this, SLOT(onPingProcessFinished(int,QProcess::ExitStatus))); m_pingProcess->start("ping", { "-c", "4", "nymea.io" } ); - m_pingReply = RestResource::createAsyncReply(); + m_pingReply = HttpReply::createAsyncReply(); return m_pingReply; } if (requestPath.startsWith("/debug/dig")) { // Only one dig process should run if (m_digProcess || m_digReply) - return RestResource::createErrorReply(HttpReply::InternalServerError); + return HttpReply::createErrorReply(HttpReply::InternalServerError); qCDebug(dcDebugServer()) << "Start dig nymea.io process"; m_digProcess = new QProcess(this); @@ -360,14 +359,14 @@ HttpReply *DebugServerHandler::processDebugRequest(const QString &requestPath, c connect(m_digProcess, SIGNAL(finished(int, QProcess::ExitStatus)), this, SLOT(onDigProcessFinished(int,QProcess::ExitStatus))); m_digProcess->start("dig", { "nymea.io" } ); - m_digReply = RestResource::createAsyncReply(); + m_digReply = HttpReply::createAsyncReply(); return m_digReply; } if (requestPath.startsWith("/debug/tracepath")) { // Only one tracepath process should run if (m_tracePathProcess || m_tracePathReply) - return RestResource::createErrorReply(HttpReply::InternalServerError); + return HttpReply::createErrorReply(HttpReply::InternalServerError); qCDebug(dcDebugServer()) << "Start tracepath nymea.io process"; m_tracePathProcess = new QProcess(this); @@ -375,7 +374,7 @@ HttpReply *DebugServerHandler::processDebugRequest(const QString &requestPath, c connect(m_tracePathProcess, SIGNAL(finished(int, QProcess::ExitStatus)), this, SLOT(onTracePathProcessFinished(int,QProcess::ExitStatus))); m_tracePathProcess->start("tracepath", { "nymea.io" } ); - m_tracePathReply = RestResource::createAsyncReply(); + m_tracePathReply = HttpReply::createAsyncReply(); return m_tracePathReply; } @@ -401,7 +400,7 @@ HttpReply *DebugServerHandler::processDebugRequest(const QString &requestPath, c settings.endGroup(); - HttpReply *reply = RestResource::createSuccessReply(); + HttpReply *reply = HttpReply::createSuccessReply(); reply->setPayload(QJsonDocument::fromVariant(dataMap).toJson(QJsonDocument::Indented)); return reply; } else { @@ -429,7 +428,7 @@ HttpReply *DebugServerHandler::processDebugRequest(const QString &requestPath, c settings.endGroup(); QLoggingCategory::setFilterRules(loggingRules.join('\n')); - return RestResource::createSuccessReply(); + return HttpReply::createSuccessReply(); } } @@ -447,17 +446,17 @@ HttpReply *DebugServerHandler::processDebugRequest(const QString &requestPath, c if (!m_debugReportGenerator) { qCWarning(dcDebugServer()) << "There is currently no debug report generator. The requested file does not exist."; - return RestResource::createErrorReply(HttpReply::NotFound); + return HttpReply::createErrorReply(HttpReply::NotFound); } if (m_debugReportGenerator->reportFileName() != fileName) { qCWarning(dcDebugServer()) << "The requested file is not the file from the current debug report generator" << m_debugReportGenerator->reportFileName() << "!=" << fileName; - return RestResource::createErrorReply(HttpReply::NotFound); + return HttpReply::createErrorReply(HttpReply::NotFound); } // Everything looks good, send the requested debug report - HttpReply *downloadReportReply = RestResource::createSuccessReply(); + HttpReply *downloadReportReply = HttpReply::createSuccessReply(); downloadReportReply->setPayload(m_debugReportGenerator->reportFileData()); downloadReportReply->setHeader(HttpReply::ContentTypeHeader, "application/tar+gzip;"); return downloadReportReply; @@ -470,13 +469,13 @@ HttpReply *DebugServerHandler::processDebugRequest(const QString &requestPath, c connect(m_debugReportGenerator, &DebugReportGenerator::timeout, this, &DebugServerHandler::onDebugReportGeneratorTimeout); m_debugReportGenerator->generateReport(); // Note: no content will bring the client to poll this report - return RestResource::createErrorReply(HttpReply::NoContent); + return HttpReply::createErrorReply(HttpReply::NoContent); } else { // There is a running generator, check if the report is ready if (!m_debugReportGenerator->isReady()) { qCDebug(dcDebugServer()) << "Report is not ready yet"; // Note: no content tells the client the report is not ready yet - return RestResource::createErrorReply(HttpReply::NoContent); + return HttpReply::createErrorReply(HttpReply::NoContent); } else { if (m_debugReportGenerator->isValid()) { // Success, the debug report is ready and valid @@ -485,7 +484,7 @@ HttpReply *DebugServerHandler::processDebugRequest(const QString &requestPath, c reportInformation.insert("fileSize", m_debugReportGenerator->reportFileData().size()); reportInformation.insert("md5sum", m_debugReportGenerator->md5Sum()); - HttpReply * httpReply = RestResource::createSuccessReply(); + HttpReply * httpReply = HttpReply::createSuccessReply(); httpReply->setHttpStatusCode(HttpReply::Ok); httpReply->setHeader(HttpReply::ContentTypeHeader, "application/json; charset=\"utf-8\";"); httpReply->setPayload(QJsonDocument::fromVariant(reportInformation).toJson(QJsonDocument::Indented)); @@ -494,7 +493,7 @@ HttpReply *DebugServerHandler::processDebugRequest(const QString &requestPath, c qCWarning(dcDebugServer()) << "The debug report generator finished with error."; m_debugReportGenerator->deleteLater(); m_debugReportGenerator = nullptr; - return RestResource::createErrorReply(HttpReply::InternalServerError); + return HttpReply::createErrorReply(HttpReply::InternalServerError); } } } @@ -508,7 +507,7 @@ HttpReply *DebugServerHandler::processDebugRequest(const QString &requestPath, c // If nothing matches, redirect to /debug page qCWarning(dcDebugServer()) << "Resource for debug interface not found. Redirecting to /debug"; - HttpReply *reply = RestResource::createErrorReply(HttpReply::PermanentRedirect); + HttpReply *reply = HttpReply::createErrorReply(HttpReply::PermanentRedirect); reply->setHeader(HttpReply::LocationHeader, "/debug"); return reply; } @@ -570,7 +569,7 @@ HttpReply *DebugServerHandler::processDebugFileRequest(const QString &requestPat QByteArray data = loadResourceData(resourceFileName); // Create reply for resource file - HttpReply *reply = RestResource::createSuccessReply(); + HttpReply *reply = HttpReply::createSuccessReply(); reply->setPayload(data); // Check content type diff --git a/libnymea-core/libnymea-core.pro b/libnymea-core/libnymea-core.pro index c8964329..43dd82b9 100644 --- a/libnymea-core/libnymea-core.pro +++ b/libnymea-core/libnymea-core.pro @@ -32,14 +32,6 @@ HEADERS += nymeacore.h \ servers/httprequest.h \ servers/httpreply.h \ servers/bluetoothserver.h \ - servers/rest/restserver.h \ - servers/rest/restresource.h \ - servers/rest/devicesresource.h \ - servers/rest/deviceclassesresource.h \ - servers/rest/vendorsresource.h \ - servers/rest/logsresource.h \ - servers/rest/pluginsresource.h \ - servers/rest/rulesresource.h \ servers/websocketserver.h \ servers/mqttbroker.h \ jsonrpc/jsonrpcserver.h \ @@ -119,14 +111,6 @@ SOURCES += nymeacore.cpp \ servers/httpreply.cpp \ servers/websocketserver.cpp \ servers/bluetoothserver.cpp \ - servers/rest/restserver.cpp \ - servers/rest/restresource.cpp \ - servers/rest/devicesresource.cpp \ - servers/rest/deviceclassesresource.cpp \ - servers/rest/vendorsresource.cpp \ - servers/rest/logsresource.cpp \ - servers/rest/pluginsresource.cpp \ - servers/rest/rulesresource.cpp \ servers/mqttbroker.cpp \ jsonrpc/jsonrpcserver.cpp \ jsonrpc/jsonhandler.cpp \ diff --git a/libnymea-core/nymeacore.cpp b/libnymea-core/nymeacore.cpp index f4650d72..6068d8d5 100644 --- a/libnymea-core/nymeacore.cpp +++ b/libnymea-core/nymeacore.cpp @@ -853,12 +853,6 @@ JsonRPCServer *NymeaCore::jsonRPCServer() const return m_serverManager->jsonServer(); } -/*! Returns the pointer to the \l{RestServer} of this instance. */ -RestServer *NymeaCore::restServer() const -{ - return m_serverManager->restServer(); -} - void NymeaCore::onDeviceDisappeared(const DeviceId &deviceId) { Device *device = m_deviceManager->findConfiguredDevice(deviceId); diff --git a/libnymea-core/nymeacore.h b/libnymea-core/nymeacore.h index fe54ca20..a49c5576 100644 --- a/libnymea-core/nymeacore.h +++ b/libnymea-core/nymeacore.h @@ -82,7 +82,6 @@ public: NymeaConfiguration *configuration() const; LogEngine* logEngine() const; JsonRPCServer *jsonRPCServer() const; - RestServer *restServer() const; DeviceManager *deviceManager() const; RuleEngine *ruleEngine() const; TimeManager *timeManager() const; diff --git a/libnymea-core/servermanager.cpp b/libnymea-core/servermanager.cpp index 22cf6fc0..ceb023d8 100644 --- a/libnymea-core/servermanager.cpp +++ b/libnymea-core/servermanager.cpp @@ -43,7 +43,6 @@ #include "jsonrpc/jsonrpcserver.h" #include "servers/mocktcpserver.h" #include "servers/tcpserver.h" -#include "servers/rest/restserver.h" #include "servers/websocketserver.h" #include "servers/webserver.h" #include "servers/bluetoothserver.h" @@ -101,8 +100,6 @@ ServerManager::ServerManager(Platform *platform, NymeaConfiguration *configurati // Interfaces m_jsonServer = new JsonRPCServer(m_sslConfiguration, this); - m_restServer = new RestServer(m_sslConfiguration, this); - // Transports MockTcpServer *tcpServer = new MockTcpServer(this); @@ -134,7 +131,6 @@ ServerManager::ServerManager(Platform *platform, NymeaConfiguration *configurati foreach (const WebServerConfiguration &config, configuration->webServerConfigurations()) { WebServer *webServer = new WebServer(config, m_sslConfiguration, this); - m_restServer->registerWebserver(webServer); m_webServers.insert(config.id, webServer); if (webServer->startServer()) { registerZeroConfService(config, "http", "_http._tcp"); @@ -167,12 +163,6 @@ JsonRPCServer *ServerManager::jsonServer() const return m_jsonServer; } -/*! Returns the pointer to the created \l{RestServer} in this \l{ServerManager}. */ -RestServer *ServerManager::restServer() const -{ - return m_restServer; -} - /*! Returns the pointer to the created \l{BluetoothServer} in this \l{ServerManager}. */ BluetoothServer *ServerManager::bluetoothServer() const { @@ -268,7 +258,6 @@ void ServerManager::webServerConfigurationChanged(const QString &id) } else { qDebug(dcServerManager()) << "Received a Web Server config change event but don't have a Web Server instance for it. Creating new WebServer instance on" << config.address.toString() << config.port << "(SSL:" << config.sslEnabled << ")"; server = new WebServer(config, m_sslConfiguration, this); - m_restServer->registerWebserver(server); m_webServers.insert(config.id, server); } if (server->startServer()) { diff --git a/libnymea-core/servermanager.h b/libnymea-core/servermanager.h index a5c1e0ea..78a4cc26 100644 --- a/libnymea-core/servermanager.h +++ b/libnymea-core/servermanager.h @@ -39,7 +39,6 @@ class TcpServer; class WebSocketServer; class WebServer; class BluetoothServer; -class RestServer; class MqttBroker; class MockTcpServer; @@ -52,7 +51,6 @@ public: // Interfaces JsonRPCServer *jsonServer() const; - RestServer *restServer() const; BluetoothServer* bluetoothServer() const; @@ -81,7 +79,6 @@ private: // Interfaces JsonRPCServer *m_jsonServer; - RestServer *m_restServer; BluetoothServer *m_bluetoothServer; QHash m_tcpServers; diff --git a/libnymea-core/servers/httpreply.cpp b/libnymea-core/servers/httpreply.cpp index c56b70c0..73fa1b9a 100644 --- a/libnymea-core/servers/httpreply.cpp +++ b/libnymea-core/servers/httpreply.cpp @@ -188,6 +188,27 @@ HttpReply::HttpReply(const HttpReply::HttpStatusCode &statusCode, const HttpRepl packReply(); } +HttpReply *HttpReply::createSuccessReply() +{ + HttpReply *reply = new HttpReply(HttpReply::Ok, HttpReply::TypeSync); + reply->setPayload("200 Ok"); + return reply; +} + +HttpReply *HttpReply::createErrorReply(const HttpReply::HttpStatusCode &statusCode) +{ + HttpReply *reply = new HttpReply(statusCode, HttpReply::TypeSync); + reply->setPayload(QByteArray::number(reply->httpStatusCode()) + " " + reply->httpReasonPhrase()); + return reply; +} + +HttpReply *HttpReply::createAsyncReply() +{ + HttpReply *reply = new HttpReply(HttpReply::Ok, HttpReply::TypeAsync); + reply->setPayload(QByteArray::number(reply->httpStatusCode()) + " " + reply->httpReasonPhrase()); + return reply; +} + void HttpReply::setHttpStatusCode(const HttpReply::HttpStatusCode &statusCode) { m_statusCode = statusCode; diff --git a/libnymea-core/servers/httpreply.h b/libnymea-core/servers/httpreply.h index 8e406281..4965e4f1 100644 --- a/libnymea-core/servers/httpreply.h +++ b/libnymea-core/servers/httpreply.h @@ -74,8 +74,12 @@ public: TypeAsync }; - HttpReply(QObject *parent = 0); - HttpReply(const HttpStatusCode &statusCode = HttpStatusCode::Ok, const Type &type = TypeSync, QObject *parent = 0); + HttpReply(QObject *parent = nullptr); + HttpReply(const HttpStatusCode &statusCode = HttpStatusCode::Ok, const Type &type = TypeSync, QObject *parent = nullptr); + + static HttpReply* createSuccessReply(); + static HttpReply* createErrorReply(const HttpReply::HttpStatusCode &statusCode); + static HttpReply* createAsyncReply(); void setHttpStatusCode(const HttpStatusCode &statusCode); HttpStatusCode httpStatusCode() const; diff --git a/libnymea-core/servers/rest/deviceclassesresource.cpp b/libnymea-core/servers/rest/deviceclassesresource.cpp deleted file mode 100644 index 63e8cf5c..00000000 --- a/libnymea-core/servers/rest/deviceclassesresource.cpp +++ /dev/null @@ -1,302 +0,0 @@ -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - * * - * Copyright (C) 2015 Simon Stürz * - * * - * This file is part of nymea. * - * * - * nymea is free software: you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation, version 2 of the License. * - * * - * nymea is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with nymea. If not, see . * - * * - * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ - -/*! - \class nymeaserver::DeviceClassesResource - \brief This subclass of \l{RestResource} processes the REST requests for the \tt DeviceClasses namespace. - - \ingroup json - \inmodule core - - This \l{RestResource} will be created in the \l{RestServer} and used to handle REST requests - for the \tt {DeviceClasses} namespace of the API. - - \code - http://localhost:3333/api/v1/deviceclasses - \endcode - - \sa DeviceClass, RestResource, RestServer -*/ - -#include "deviceclassesresource.h" -#include "servers/httprequest.h" -#include "nymeacore.h" -#include "devices/devicediscoveryinfo.h" - -#include - -namespace nymeaserver { - -/*! Constructs a \l DeviceClassesResource with the given \a parent. */ -DeviceClassesResource::DeviceClassesResource(QObject *parent) : - RestResource(parent) -{ -} - -/*! Returns the name of the \l{RestResource}. In this case \b deviceclasses. - - \sa RestResource::name() -*/ -QString DeviceClassesResource::name() const -{ - return "deviceclasses"; -} - -/*! This method will be used to process the given \a request and the given \a urlTokens. The request - has to be in this namespace. Returns the resulting \l HttpReply. - - \sa HttpRequest, HttpReply, RestResource::proccessRequest() -*/ -HttpReply *DeviceClassesResource::proccessRequest(const HttpRequest &request, const QStringList &urlTokens) -{ - - // get the main resource - - // /api/v1/deviceclasses/{deviceClassId}/ - if (urlTokens.count() >= 4) { - DeviceClassId deviceClassId = DeviceClassId(urlTokens.at(3)); - if (deviceClassId.isNull()) { - qCWarning(dcRest) << "Could not parse DeviceClassId:" << urlTokens.at(3); - return createDeviceErrorReply(HttpReply::BadRequest, Device::DeviceErrorDeviceClassNotFound); - } - m_deviceClass = NymeaCore::instance()->deviceManager()->findDeviceClass(deviceClassId); - if (!m_deviceClass.isValid()) { - qCWarning(dcRest) << "DeviceClassId" << deviceClassId.toString() << "not found"; - return createDeviceErrorReply(HttpReply::NotFound, Device::DeviceErrorDeviceClassNotFound); - } - } - - // check method - HttpReply *reply; - switch (request.method()) { - case HttpRequest::Get: - reply = proccessGetRequest(request, urlTokens); - break; - default: - reply = createErrorReply(HttpReply::BadRequest); - break; - } - return reply; -} - -HttpReply *DeviceClassesResource::proccessGetRequest(const HttpRequest &request, const QStringList &urlTokens) -{ - Q_UNUSED(request) - - // GET /api/v1/deviceclasses?vendorId="{vendorId}" - if (urlTokens.count() == 3) { - VendorId vendorId; - if (request.url().hasQuery()) { - if (request.urlQuery().hasQueryItem("vendorId")) { - vendorId = VendorId(request.urlQuery().queryItemValue("vendorId")); - if (vendorId.isNull()) { - qCWarning(dcRest) << "Could not parse VendorId:" << request.urlQuery().queryItemValue("vendorId"); - return createDeviceErrorReply(HttpReply::BadRequest, Device::DeviceErrorVendorNotFound); - } - } - } - return getDeviceClasses(vendorId); - } - - // GET /api/v1/deviceclasses/{deviceClassId} - if (urlTokens.count() == 4) - return getDeviceClass(); - - // GET /api/v1/deviceclasses/{deviceClassId}/actiontypes - if (urlTokens.count() == 5 && urlTokens.at(4) == "actiontypes") - return getActionTypes(); - - // GET /api/v1/deviceclasses/{deviceClassId}/actiontypes/{actionTypeId} - if (urlTokens.count() == 6 && urlTokens.at(4) == "actiontypes") { - ActionTypeId actionTypeId = ActionTypeId(urlTokens.at(5)); - if (actionTypeId.isNull()) { - qCWarning(dcRest) << "Could not parse ActionTypeId:" << urlTokens.at(5); - return createDeviceErrorReply(HttpReply::BadRequest, Device::DeviceErrorActionTypeNotFound); - } - return getActionType(actionTypeId); - } - - // GET /api/v1/deviceclasses/{deviceClassId}/statetypes - if (urlTokens.count() == 5 && urlTokens.at(4) == "statetypes") - return getStateTypes(); - - // GET /api/v1/deviceclasses/{deviceClassId}/statetypes/{stateTypeId} - if (urlTokens.count() == 6 && urlTokens.at(4) == "statetypes") { - StateTypeId stateTypeId = StateTypeId(urlTokens.at(5)); - if (stateTypeId.isNull()) { - qCWarning(dcRest) << "Could not parse StateTypeId:" << urlTokens.at(5); - return createDeviceErrorReply(HttpReply::BadRequest, Device::DeviceErrorStateTypeNotFound); - } - return getStateType(stateTypeId); - } - - // GET /api/v1/deviceclasses/{deviceClassId}/eventtypes - if (urlTokens.count() == 5 && urlTokens.at(4) == "eventtypes") - return getEventTypes(); - - // GET /api/v1/deviceclasses/{deviceClassId}/eventtypes/{eventTypeId} - if (urlTokens.count() == 6 && urlTokens.at(4) == "eventtypes") { - EventTypeId eventTypeId = EventTypeId(urlTokens.at(5)); - if (eventTypeId.isNull()) { - qCWarning(dcRest) << "Could not parse EventTypeId:" << urlTokens.at(5); - return createDeviceErrorReply(HttpReply::BadRequest, Device::DeviceErrorEventTypeNotFound); - } - return getEventType(eventTypeId); - } - - // GET /api/v1/deviceclasses/{deviceClassId}/discover?name=paramName&value=paramValue - if (urlTokens.count() == 5 && urlTokens.at(4) == "discover") { - ParamList params; - if (request.urlQuery().hasQueryItem("params")) { - QString paramMapString = request.urlQuery().queryItemValue("params"); - - QPair verification = verifyPayload(paramMapString.toUtf8()); - if (!verification.first) - return createErrorReply(HttpReply::BadRequest); - - params = JsonTypes::unpackParams(verification.second.toList()); - } - return getDiscoverdDevices(params); - } - - return createErrorReply(HttpReply::BadRequest); -} - -HttpReply *DeviceClassesResource::getDeviceClass() -{ - qCDebug(dcRest) << "Get device class with id " << m_deviceClass.id(); - HttpReply *reply = createSuccessReply(); - reply->setHeader(HttpReply::ContentTypeHeader, "application/json; charset=\"utf-8\";"); - reply->setPayload(QJsonDocument::fromVariant(JsonTypes::packDeviceClass(m_deviceClass, NymeaCore::instance()->configuration()->locale())).toJson()); - return reply; -} - -HttpReply *DeviceClassesResource::getActionTypes() -{ - qCDebug(dcRest) << "Get action types for device class" << m_deviceClass.id(); - HttpReply *reply = createSuccessReply(); - reply->setHeader(HttpReply::ContentTypeHeader, "application/json; charset=\"utf-8\";"); - reply->setPayload(QJsonDocument::fromVariant(JsonTypes::packActionTypes(m_deviceClass, NymeaCore::instance()->configuration()->locale())).toJson()); - return reply; -} - -HttpReply *DeviceClassesResource::getActionType(const ActionTypeId &actionTypeId) -{ - qCDebug(dcRest) << "Get action type with id" << actionTypeId; - - foreach (const ActionType &actionType, m_deviceClass.actionTypes()) { - if (actionType.id() == actionTypeId) { - HttpReply *reply = createSuccessReply(); - reply->setHeader(HttpReply::ContentTypeHeader, "application/json; charset=\"utf-8\";"); - reply->setPayload(QJsonDocument::fromVariant(JsonTypes::packActionType(actionType, m_deviceClass.pluginId(), NymeaCore::instance()->configuration()->locale())).toJson()); - return reply; - } - } - return createDeviceErrorReply(HttpReply::NotFound, Device::DeviceErrorActionTypeNotFound); -} - -HttpReply *DeviceClassesResource::getStateTypes() -{ - qCDebug(dcRest) << "Get state types for device class" << m_deviceClass.id(); - HttpReply *reply = createSuccessReply(); - reply->setHeader(HttpReply::ContentTypeHeader, "application/json; charset=\"utf-8\";"); - reply->setPayload(QJsonDocument::fromVariant(JsonTypes::packStateTypes(m_deviceClass, NymeaCore::instance()->configuration()->locale())).toJson()); - return reply; -} - -HttpReply *DeviceClassesResource::getStateType(const StateTypeId &stateTypeId) -{ - qCDebug(dcRest) << "Get state type with id" << stateTypeId; - - foreach (const StateType &stateType, m_deviceClass.stateTypes()) { - if (stateType.id() == stateTypeId) { - HttpReply *reply = createSuccessReply(); - reply->setHeader(HttpReply::ContentTypeHeader, "application/json; charset=\"utf-8\";"); - reply->setPayload(QJsonDocument::fromVariant(JsonTypes::packStateType(stateType, m_deviceClass.pluginId(), NymeaCore::instance()->configuration()->locale())).toJson()); - return reply; - } - } - return createDeviceErrorReply(HttpReply::NotFound, Device::DeviceErrorStateTypeNotFound); -} - -HttpReply *DeviceClassesResource::getEventTypes() -{ - qCDebug(dcRest) << "Get event types for device class" << m_deviceClass.id(); - HttpReply *reply = createSuccessReply(); - reply->setHeader(HttpReply::ContentTypeHeader, "application/json; charset=\"utf-8\";"); - reply->setPayload(QJsonDocument::fromVariant(JsonTypes::packEventTypes(m_deviceClass, NymeaCore::instance()->configuration()->locale())).toJson()); - return reply; -} - -HttpReply *DeviceClassesResource::getEventType(const EventTypeId &eventTypeId) -{ - qCDebug(dcRest) << "Get event type with id" << eventTypeId; - - foreach (const EventType &eventType, m_deviceClass.eventTypes()) { - if (eventType.id() == eventTypeId) { - HttpReply *reply = createSuccessReply(); - reply->setHeader(HttpReply::ContentTypeHeader, "application/json; charset=\"utf-8\";"); - reply->setPayload(QJsonDocument::fromVariant(JsonTypes::packEventType(eventType, m_deviceClass.pluginId(), NymeaCore::instance()->configuration()->locale())).toJson()); - return reply; - } - } - return createDeviceErrorReply(HttpReply::NotFound, Device::DeviceErrorEventTypeNotFound); -} - -HttpReply *DeviceClassesResource::getDiscoverdDevices(const ParamList &discoveryParams) -{ - qCDebug(dcRest) << "Discover devices for DeviceClass" << m_deviceClass.id(); - qCDebug(dcRest) << discoveryParams; - - DeviceDiscoveryInfo *info = NymeaCore::instance()->deviceManager()->discoverDevices(m_deviceClass.id(), discoveryParams); - HttpReply *reply = createAsyncReply(); - connect(info, &DeviceDiscoveryInfo::finished, reply, [info, reply](){ - reply->setHeader(HttpReply::ContentTypeHeader, "application/json; charset=\"utf-8\";"); - QVariantMap response; - if (info->status() != Device::DeviceErrorNoError) { - reply->setHttpStatusCode(HttpReply::InternalServerError); - response.insert("error", JsonTypes::deviceErrorToString(info->status())); - reply->setPayload(QJsonDocument::fromVariant(response).toJson()); - } else { - reply->setHttpStatusCode(HttpReply::Ok); - reply->setPayload(QJsonDocument::fromVariant(JsonTypes::packDeviceDescriptors(info->deviceDescriptors())).toJson()); - } - reply->finished(); - }); - - - return reply; -} - -HttpReply *DeviceClassesResource::getDeviceClasses(const VendorId &vendorId) -{ - if (vendorId == VendorId()) { - qCDebug(dcRest) << "Get all device classes."; - } else { - qCDebug(dcRest) << "Get device classes for vendor" << vendorId.toString(); - } - - HttpReply *reply = createSuccessReply(); - reply->setHeader(HttpReply::ContentTypeHeader, "application/json; charset=\"utf-8\";"); - reply->setPayload(QJsonDocument::fromVariant(JsonTypes::packSupportedDevices(vendorId, NymeaCore::instance()->configuration()->locale())).toJson()); - return reply; -} - -} diff --git a/libnymea-core/servers/rest/deviceclassesresource.h b/libnymea-core/servers/rest/deviceclassesresource.h deleted file mode 100644 index d5397155..00000000 --- a/libnymea-core/servers/rest/deviceclassesresource.h +++ /dev/null @@ -1,74 +0,0 @@ -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - * * - * Copyright (C) 2015 Simon Stürz * - * * - * This file is part of nymea. * - * * - * nymea is free software: you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation, version 2 of the License. * - * * - * nymea is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with nymea. If not, see . * - * * - * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ - -#ifndef DEVICECLASSESRESOURCE_H -#define DEVICECLASSESRESOURCE_H - -#include -#include -#include - -#include "jsonrpc/jsontypes.h" -#include "restresource.h" -#include "servers/httpreply.h" - - -namespace nymeaserver { - -class HttpRequest; - -class DeviceClassesResource: public RestResource -{ - Q_OBJECT -public: - explicit DeviceClassesResource(QObject *parent = nullptr); - - QString name() const override; - - HttpReply *proccessRequest(const HttpRequest &request, const QStringList &urlTokens) override; - -private: - mutable QHash> m_discoverRequests; - - DeviceClass m_deviceClass; - - // Process method - HttpReply *proccessGetRequest(const HttpRequest &request, const QStringList &urlTokens) override; - - // Get methods - HttpReply *getDeviceClasses(const VendorId &vendorId); - HttpReply *getDeviceClass(); - - HttpReply *getActionTypes(); - HttpReply *getActionType(const ActionTypeId &actionTypeId); - - HttpReply *getStateTypes(); - HttpReply *getStateType(const StateTypeId &stateTypeId); - - HttpReply *getEventTypes(); - HttpReply *getEventType(const EventTypeId &eventTypeId); - - HttpReply *getDiscoverdDevices(const ParamList &discoveryParams); - -}; - -} - -#endif // DEVICECLASSESRESOURCE_H diff --git a/libnymea-core/servers/rest/devicesresource.cpp b/libnymea-core/servers/rest/devicesresource.cpp deleted file mode 100644 index 19f05523..00000000 --- a/libnymea-core/servers/rest/devicesresource.cpp +++ /dev/null @@ -1,557 +0,0 @@ -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - * * - * Copyright (C) 2015 Simon Stürz * - * * - * This file is part of nymea. * - * * - * nymea is free software: you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation, version 2 of the License. * - * * - * nymea is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with nymea. If not, see . * - * * - * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ - -/*! - \class nymeaserver::DevicesResource - \brief This subclass of \l{RestResource} processes the REST requests for the \tt Devices namespace. - - \ingroup json - \inmodule core - - This \l{RestResource} will be created in the \l{RestServer} and used to handle REST requests - for the \tt {Devices} namespace of the API. - - \code - http://localhost:3333/api/v1/devices - \endcode - - \sa Device, RestResource, RestServer -*/ - - -#include "devicesresource.h" -#include "servers/httpreply.h" -#include "servers/httprequest.h" -#include "jsonrpc/jsontypes.h" -#include "nymeacore.h" -#include "devices/devicesetupinfo.h" -#include "devices/devicepairinginfo.h" -#include "devices/deviceactioninfo.h" - -#include - -namespace nymeaserver { - -/*! Constructs a \l DevicesResource with the given \a parent. */ -DevicesResource::DevicesResource(QObject *parent) : - RestResource(parent) -{ -} - -/*! Returns the name of the \l{RestResource}. In this case \b devices. - - \sa RestResource::name() -*/ -QString DevicesResource::name() const -{ - return "devices"; -} - -/*! This method will be used to process the given \a request and the given \a urlTokens. The request - has to be in this namespace. Returns the resulting \l HttpReply. - - \sa HttpRequest, HttpReply, RestResource::proccessRequest() -*/ -HttpReply *DevicesResource::proccessRequest(const HttpRequest &request, const QStringList &urlTokens) -{ - m_device = nullptr; - - // get the main resource - if (urlTokens.count() >= 4 && urlTokens.at(3) != "pair" && urlTokens.at(3) != "confirmpairing") { - DeviceId deviceId = DeviceId(urlTokens.at(3)); - if (deviceId.isNull()) { - qCWarning(dcRest) << "Could not parse DeviceId:" << urlTokens.at(3); - return createDeviceErrorReply(HttpReply::BadRequest, Device::DeviceErrorDeviceNotFound); - } - m_device = NymeaCore::instance()->deviceManager()->findConfiguredDevice(deviceId); - if (!m_device) { - qCWarning(dcRest) << "Could find any device with DeviceId:" << urlTokens.at(3); - return createDeviceErrorReply(HttpReply::NotFound, Device::DeviceErrorDeviceNotFound); - } - } - - // check method - HttpReply *reply; - switch (request.method()) { - case HttpRequest::Get: - reply = proccessGetRequest(request, urlTokens); - break; - case HttpRequest::Post: - reply = proccessPostRequest(request, urlTokens); - break; - case HttpRequest::Put: - reply = proccessPutRequest(request, urlTokens); - break; - case HttpRequest::Delete: - reply = proccessDeleteRequest(request, urlTokens); - break; - case HttpRequest::Options: - reply = proccessOptionsRequest(request, urlTokens); - break; - default: - reply = createErrorReply(HttpReply::BadRequest); - break; - } - return reply; -} - -HttpReply *DevicesResource::proccessGetRequest(const HttpRequest &request, const QStringList &urlTokens) -{ - Q_UNUSED(request) - - // GET /api/v1/devices - if (urlTokens.count() == 3) - return getConfiguredDevices(); - - // GET /api/v1/devices/{deviceId} - if (urlTokens.count() == 4) - return getConfiguredDevice(m_device); - - // GET /api/v1/devices/{deviceId}/states - if (urlTokens.count() == 5 && urlTokens.at(4) == "states") - return getDeviceStateValues(m_device); - - // /api/v1/devices/{deviceId}/states/{stateTypeId} - if (urlTokens.count() >= 6 && urlTokens.at(4) == "states") { - StateTypeId stateTypeId = StateTypeId(urlTokens.at(5)); - if (stateTypeId.isNull()) { - qCWarning(dcRest) << "Could not parse StateTypeId:" << urlTokens.at(5); - return createDeviceErrorReply(HttpReply::BadRequest, Device::DeviceErrorStateTypeNotFound); - } - - if (!m_device->hasState(stateTypeId)){ - qCWarning(dcRest) << "This device has no StateTypeId:" << urlTokens.at(5); - return createDeviceErrorReply(HttpReply::NotFound, Device::DeviceErrorStateTypeNotFound); - } - return getDeviceStateValue(m_device, stateTypeId); - } - return createErrorReply(HttpReply::NotImplemented); -} - -HttpReply *DevicesResource::proccessDeleteRequest(const HttpRequest &request, const QStringList &urlTokens) -{ - Q_UNUSED(request) - - // DELETE /api/v1/devices - if (urlTokens.count() == 3) - return createErrorReply(HttpReply::BadRequest); - - // DELETE /api/v1/devices/{deviceId} - if (urlTokens.count() == 4) { - QVariantMap params; - if (request.urlQuery().hasQueryItem("params")) { - QString paramMapString = request.urlQuery().queryItemValue("params"); - - QPair verification = verifyPayload(paramMapString.toUtf8()); - if (!verification.first) - return createErrorReply(HttpReply::BadRequest); - - params = verification.second.toMap(); - } - return removeDevice(m_device, params); - } - - return createErrorReply(HttpReply::NotImplemented); -} - -HttpReply *DevicesResource::proccessPutRequest(const HttpRequest &request, const QStringList &urlTokens) -{ - Q_UNUSED(request) - // PUT /api/v1/devices - if (urlTokens.count() == 3) - return createErrorReply(HttpReply::BadRequest); - - // PUT /api/v1/devices/{deviceId} - if (urlTokens.count() == 4) - return reconfigureDevice(m_device, request.payload()); - - return createErrorReply(HttpReply::NotImplemented); -} - -HttpReply *DevicesResource::proccessPostRequest(const HttpRequest &request, const QStringList &urlTokens) -{ - // POST /api/v1/devices - if (urlTokens.count() == 3) - return addConfiguredDevice(request.payload()); - - // POST /api/v1/devices/pair - if (urlTokens.count() == 4 && urlTokens.at(3) == "pair") - return pairDevice(request.payload()); - - // POST /api/v1/devices/confirmpairing - if (urlTokens.count() == 4 && urlTokens.at(3) == "confirmpairing") - return confirmPairDevice(request.payload()); - - // POST /api/v1/devices/{deviceId} - if (urlTokens.count() == 4) - return editDevice(request.payload()); - - // POST /api/v1/devices/{deviceId}/execute/{actionTypeId} - if (urlTokens.count() >= 6 && urlTokens.at(4) == "execute") { - ActionTypeId actionTypeId = ActionTypeId(urlTokens.at(5)); - if (actionTypeId.isNull()) { - qCWarning(dcRest) << "Could not parse ActionTypeId:" << urlTokens.at(5); - return createDeviceErrorReply(HttpReply::BadRequest, Device::DeviceErrorActionTypeNotFound); - } - bool found = false; - DeviceClass deviceClass = NymeaCore::instance()->deviceManager()->findDeviceClass(m_device->deviceClassId()); - foreach (const ActionType actionType, deviceClass.actionTypes()) { - if (actionType.id() == actionTypeId) { - found = true; - break; - } - } - if (!found) { - qCWarning(dcRest) << "Could not find ActionTypeId:" << actionTypeId.toString(); - return createDeviceErrorReply(HttpReply::NotFound, Device::DeviceErrorActionTypeNotFound); - } - - return executeAction(m_device, actionTypeId, request.payload()); - } - - return createErrorReply(HttpReply::NotImplemented); -} - -HttpReply *DevicesResource::proccessOptionsRequest(const HttpRequest &request, const QStringList &urlTokens) -{ - Q_UNUSED(request) - Q_UNUSED(urlTokens) - return RestResource::createCorsSuccessReply(); -} - -HttpReply *DevicesResource::getConfiguredDevices() const -{ - qCDebug(dcRest) << "Get all configured devices"; - HttpReply *reply = createSuccessReply(); - reply->setHeader(HttpReply::ContentTypeHeader, "application/json; charset=\"utf-8\";"); - reply->setPayload(QJsonDocument::fromVariant(JsonTypes::packConfiguredDevices()).toJson()); - return reply; -} - -HttpReply *DevicesResource::getConfiguredDevice(Device *device) const -{ - qCDebug(dcRest) << "Get configured device with id:" << device->id().toString(); - HttpReply *reply = createSuccessReply(); - reply->setHeader(HttpReply::ContentTypeHeader, "application/json; charset=\"utf-8\";"); - reply->setPayload(QJsonDocument::fromVariant(JsonTypes::packDevice(device)).toJson()); - return reply; -} - -HttpReply *DevicesResource::getDeviceStateValues(Device *device) const -{ - qCDebug(dcRest) << "Get states of device with id:" << device->id().toString(); - HttpReply *reply = createSuccessReply(); - reply->setHeader(HttpReply::ContentTypeHeader, "application/json; charset=\"utf-8\";"); - reply->setPayload(QJsonDocument::fromVariant(JsonTypes::packDeviceStates(device)).toJson()); - return reply; -} - -HttpReply *DevicesResource::getDeviceStateValue(Device *device, const StateTypeId &stateTypeId) const -{ - qCDebug(dcRest) << "Get device state value of state with id:" << stateTypeId.toString(); - HttpReply *reply = createSuccessReply(); - QVariantMap stateValueMap; - stateValueMap.insert("value", device->state(stateTypeId).value()); - reply->setHeader(HttpReply::ContentTypeHeader, "application/json; charset=\"utf-8\";"); - reply->setPayload(QJsonDocument::fromVariant(stateValueMap).toJson()); - return reply; -} - -HttpReply *DevicesResource::removeDevice(Device *device, const QVariantMap ¶ms) const -{ - qCDebug(dcRest) << "Remove device with id:" << device->id().toString(); - qCDebug(dcRest) << QJsonDocument::fromVariant(params).toJson(); - - // global removePolicy has priority - if (params.contains("removePolicy")) { - RuleEngine::RemovePolicy removePolicy = params.value("removePolicy").toString() == "RemovePolicyCascade" ? RuleEngine::RemovePolicyCascade : RuleEngine::RemovePolicyUpdate; - Device::DeviceError result = NymeaCore::instance()->removeConfiguredDevice(device->id(), removePolicy); - return createDeviceErrorReply(HttpReply::Ok, result); - } - - QHash removePolicyList; - foreach (const QVariant &variant, params.value("removePolicyList").toList()) { - RuleId ruleId = RuleId(variant.toMap().value("ruleId").toString()); - RuleEngine::RemovePolicy policy = variant.toMap().value("policy").toString() == "RemovePolicyCascade" ? RuleEngine::RemovePolicyCascade : RuleEngine::RemovePolicyUpdate; - removePolicyList.insert(ruleId, policy); - } - - QPair > status = NymeaCore::instance()->removeConfiguredDevice(device->id(), removePolicyList); - - // if there are offending rules - if (!status.second.isEmpty()) { - QVariantList ruleIdList; - QVariantMap returns; - returns.insert("error", JsonTypes::deviceErrorToString(status.first)); - - foreach (const RuleId &ruleId, status.second) { - ruleIdList.append(ruleId.toString()); - } - returns.insert("ruleIds", ruleIdList); - - HttpReply *reply = createErrorReply(HttpReply::BadRequest); - reply->setHeader(HttpReply::ContentTypeHeader, "application/json; charset=\"utf-8\";"); - reply->setPayload(QJsonDocument::fromVariant(returns).toJson()); - return reply; - } - - if (status.first == Device::DeviceErrorNoError) - return createDeviceErrorReply(HttpReply::Ok, status.first); - - return createDeviceErrorReply(HttpReply::BadRequest, status.first); -} - -HttpReply *DevicesResource::executeAction(Device *device, const ActionTypeId &actionTypeId, const QByteArray &payload) const -{ - QPair verification = RestResource::verifyPayload(payload); - if (!verification.first) - return createErrorReply(HttpReply::BadRequest); - - QVariantMap message = verification.second.toMap(); - - if (!message.contains("params")) - return createErrorReply(HttpReply::BadRequest); - - ParamList actionParams = JsonTypes::unpackParams(message.value("params").toList()); - - qCDebug(dcRest) << "Execute action with" << actionParams; - - Action action(actionTypeId, device->id()); - action.setParams(actionParams); - - HttpReply *httpReply = createAsyncReply(); - - DeviceActionInfo *info = NymeaCore::instance()->executeAction(action); - connect(info, &DeviceActionInfo::finished, this, [info, httpReply](){ - QVariantMap response; - response.insert("error", JsonTypes::deviceErrorToString(info->status())); - - httpReply->setHeader(HttpReply::ContentTypeHeader, "application/json; charset=\"utf-8\";"); - if (info->status() == Device::DeviceErrorNoError) { - qCDebug(dcRest) << "Action execution finished successfully"; - httpReply->setHttpStatusCode(HttpReply::Ok); - httpReply->setPayload(QJsonDocument::fromVariant(response).toJson()); - } else { - qCDebug(dcRest) << "Action execution finished with error" << info->status(); - QVariantMap response; - response.insert("error", JsonTypes::deviceErrorToString(info->status())); - httpReply->setHttpStatusCode(HttpReply::InternalServerError); - httpReply->setPayload(QJsonDocument::fromVariant(response).toJson()); - } - - httpReply->finished(); - }); - - return httpReply; -} - -HttpReply *DevicesResource::addConfiguredDevice(const QByteArray &payload) const -{ - QPair verification = RestResource::verifyPayload(payload); - if (!verification.first) - return createErrorReply(HttpReply::BadRequest); - - QVariantMap params = verification.second.toMap(); - - DeviceClassId deviceClassId(params.value("deviceClassId").toString()); - if (deviceClassId.isNull()) - return createDeviceErrorReply(HttpReply::BadRequest, Device::DeviceErrorDeviceClassNotFound); - - QString deviceName = params.value("name").toString(); - ParamList deviceParams = JsonTypes::unpackParams(params.value("deviceParams").toList()); - DeviceDescriptorId deviceDescriptorId(params.value("deviceDescriptorId").toString()); - - HttpReply *httpReply = createAsyncReply(); - - DeviceSetupInfo *info; - if (deviceDescriptorId.isNull()) { - qCDebug(dcRest) << "Adding device" << deviceName << "with" << deviceParams; - info = NymeaCore::instance()->deviceManager()->addConfiguredDevice(deviceClassId, deviceParams, deviceName); - } else { - qCDebug(dcRest) << "Adding discovered device" << deviceName << "with DeviceDescriptorId" << deviceDescriptorId.toString(); - info = NymeaCore::instance()->deviceManager()->addConfiguredDevice(deviceDescriptorId, deviceParams, deviceName); - } - - connect(info, &DeviceSetupInfo::finished, httpReply, [info, httpReply](){ - httpReply->setHeader(HttpReply::ContentTypeHeader, "application/json; charset=\"utf-8\";"); - if (info->status() != Device::DeviceErrorNoError) { - qCDebug(dcRest) << "Device setup finished with error" << info->status(); - QVariantMap response; - response.insert("error", JsonTypes::deviceErrorToString(info->status())); - httpReply->setHttpStatusCode(HttpReply::InternalServerError); - httpReply->setPayload(QJsonDocument::fromVariant(response).toJson()); - } else { - httpReply->setHttpStatusCode(HttpReply::Ok); - QVariant result = JsonTypes::packDevice(info->device()); - httpReply->setPayload(QJsonDocument::fromVariant(result).toJson()); - } - qCDebug(dcRest) << "Device setup finished successfully"; - httpReply->finished(); - }); - - return httpReply; -} - -HttpReply *DevicesResource::editDevice(const QByteArray &payload) const -{ - QPair verification = RestResource::verifyPayload(payload); - if (!verification.first) - return createErrorReply(HttpReply::BadRequest); - - QVariantMap params = verification.second.toMap(); - QString name = params.value("name").toString(); - Device::DeviceError status = NymeaCore::instance()->deviceManager()->editDevice(m_device->id(), name); - - if (status != Device::DeviceErrorNoError) - return createDeviceErrorReply(HttpReply::BadRequest, status); - - return createDeviceErrorReply(HttpReply::Ok, status); -} - -HttpReply *DevicesResource::pairDevice(const QByteArray &payload) const -{ - QPair verification = RestResource::verifyPayload(payload); - if (!verification.first) - return createErrorReply(HttpReply::BadRequest); - - QVariantMap params = verification.second.toMap(); - - DeviceClassId deviceClassId(params.value("deviceClassId").toString()); - DeviceClass deviceClass = NymeaCore::instance()->deviceManager()->findDeviceClass(deviceClassId); - - if (deviceClassId.isNull()) { - qCWarning(dcRest) << "Could not find deviceClassId" << params.value("deviceClassId").toString(); - return createDeviceErrorReply(HttpReply::BadRequest, Device::DeviceErrorDeviceClassNotFound); - } - - QString deviceName = params.value("name").toString(); - ParamList deviceParams = JsonTypes::unpackParams(params.value("deviceParams").toList()); - - qCDebug(dcRest) << "Pair device" << deviceName << "with deviceClassId" << deviceClassId.toString(); - - HttpReply *httpReply = createAsyncReply(); - - DevicePairingInfo *info; - if (params.contains("deviceDescriptorId")) { - DeviceDescriptorId deviceDescriptorId(params.value("deviceDescriptorId").toString()); - info = NymeaCore::instance()->deviceManager()->pairDevice(deviceDescriptorId, deviceParams, deviceName); - } else { - info = NymeaCore::instance()->deviceManager()->pairDevice(deviceClassId, deviceParams, deviceName); - } - - connect(info, &DevicePairingInfo::finished, httpReply, [info, httpReply](){ - httpReply->setHeader(HttpReply::ContentTypeHeader, "application/json; charset=\"utf-8\";"); - if (info->status() != Device::DeviceErrorNoError) { - qCDebug(dcRest) << "Device setup finished with error" << info->status(); - QVariantMap response; - response.insert("error", JsonTypes::deviceErrorToString(info->status())); - httpReply->setHttpStatusCode(HttpReply::InternalServerError); - httpReply->setPayload(QJsonDocument::fromVariant(response).toJson()); - } else { - httpReply->setHttpStatusCode(HttpReply::Ok); - QVariantMap returns; - returns.insert("error", JsonTypes::deviceErrorToString(info->status())); - returns.insert("pairingTransactionId", info->transactionId().toString()); - returns.insert("displayMessage", info->displayMessage()); - httpReply->setPayload(QJsonDocument::fromVariant(returns).toJson()); - } - qCDebug(dcRest) << "Device pairing initiated successfully"; - httpReply->finished(); - }); - - return httpReply; -} - -HttpReply *DevicesResource::confirmPairDevice(const QByteArray &payload) const -{ - QPair verification = RestResource::verifyPayload(payload); - if (!verification.first) - return createErrorReply(HttpReply::BadRequest); - - QVariantMap params = verification.second.toMap(); - - PairingTransactionId pairingTransactionId = PairingTransactionId(params.value("pairingTransactionId").toString()); - QString username = params.value("username").toString(); - QString secret = params.value("secret").toString(); - - HttpReply *httpReply = createAsyncReply(); - - DevicePairingInfo *info = NymeaCore::instance()->deviceManager()->confirmPairing(pairingTransactionId, username, secret); - connect(info, &DevicePairingInfo::finished, httpReply, [info, httpReply](){ - qCDebug(dcRest()) << "Confirm pairing finished:" << info->status(); - QVariantMap response; - response.insert("error", JsonTypes::deviceErrorToString(info->status())); - if (info->status() != Device::DeviceErrorNoError) { - qCDebug(dcRest) << "Pairing device finished with error."; - httpReply->setHttpStatusCode(HttpReply::InternalServerError); - } else { - httpReply->setHttpStatusCode(HttpReply::Ok); - response.insert("id", info->deviceId().toString()); - } - httpReply->setHeader(HttpReply::ContentTypeHeader, "application/json; charset=\"utf-8\";"); - httpReply->setPayload(QJsonDocument::fromVariant(response).toJson()); - httpReply->finished(); - }); - - return httpReply; -} - -HttpReply *DevicesResource::reconfigureDevice(Device *device, const QByteArray &payload) const -{ - qCDebug(dcRest) << "Reconfigure device" << device->id(); - QPair verification = RestResource::verifyPayload(payload); - if (!verification.first) - return createErrorReply(HttpReply::BadRequest); - - QVariantMap params = verification.second.toMap(); - ParamList deviceParams = JsonTypes::unpackParams(params.value("deviceParams").toList()); - - HttpReply *httpReply = createAsyncReply(); - - DeviceSetupInfo *info; - DeviceDescriptorId deviceDescriptorId(params.value("deviceDescriptorId").toString()); - if (deviceDescriptorId.isNull()) { - qCDebug(dcRest) << "Reconfigure device with params:" << deviceParams; - info = NymeaCore::instance()->deviceManager()->reconfigureDevice(device->id(), deviceParams); - } else { - qCDebug(dcRest) << "Reconfigure device using the new discovered device with descriptorId:" << deviceDescriptorId.toString(); - info = NymeaCore::instance()->deviceManager()->reconfigureDevice(deviceDescriptorId); - } - - connect(info, &DeviceSetupInfo::finished, httpReply, [httpReply, info](){ - httpReply->setHeader(HttpReply::ContentTypeHeader, "application/json; charset=\"utf-8\";"); - if (info->status() != Device::DeviceErrorNoError) { - qCDebug(dcRest) << "Device reconfiguration finished with error" << info->status(); - QVariantMap response; - response.insert("error", JsonTypes::deviceErrorToString(info->status())); - httpReply->setHttpStatusCode(HttpReply::InternalServerError); - httpReply->setPayload(QJsonDocument::fromVariant(response).toJson()); - } else { - qCDebug(dcRest) << "Device reconfiguration finished successfully"; - httpReply->setHttpStatusCode(HttpReply::Ok); - QVariant result = JsonTypes::packDevice(info->device()); - httpReply->setPayload(QJsonDocument::fromVariant(result).toJson()); - } - httpReply->finished(); - }); - - return httpReply; -} -} diff --git a/libnymea-core/servers/rest/devicesresource.h b/libnymea-core/servers/rest/devicesresource.h deleted file mode 100644 index a7eb9b52..00000000 --- a/libnymea-core/servers/rest/devicesresource.h +++ /dev/null @@ -1,81 +0,0 @@ -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - * * - * Copyright (C) 2015 Simon Stürz * - * * - * This file is part of nymea. * - * * - * nymea is free software: you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation, version 2 of the License. * - * * - * nymea is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with nymea. If not, see . * - * * - * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ - -#ifndef DEVICESRESOURCE_H -#define DEVICESRESOURCE_H - -#include -#include -#include - -#include "jsonrpc/jsontypes.h" -#include "restresource.h" -#include "servers/httpreply.h" - -namespace nymeaserver { - -class HttpRequest; - -class DevicesResource: public RestResource -{ - Q_OBJECT -public: - explicit DevicesResource(QObject *parent = nullptr); - - QString name() const override; - - HttpReply *proccessRequest(const HttpRequest &request, const QStringList &urlTokens) override; - -private: - mutable QHash > m_asyncActionExecutions; - - Device *m_device; - - // Process method - HttpReply *proccessGetRequest(const HttpRequest &request, const QStringList &urlTokens) override; - HttpReply *proccessDeleteRequest(const HttpRequest &request, const QStringList &urlTokens) override; - HttpReply *proccessPutRequest(const HttpRequest &request, const QStringList &urlTokens) override; - HttpReply *proccessPostRequest(const HttpRequest &request, const QStringList &urlTokens) override; - HttpReply *proccessOptionsRequest(const HttpRequest &request, const QStringList &urlTokens) override; - - // Get methods - HttpReply *getConfiguredDevices() const; - HttpReply *getConfiguredDevice(Device *device) const; - HttpReply *getDeviceStateValues(Device *device) const; - HttpReply *getDeviceStateValue(Device *device, const StateTypeId &stateTypeId) const; - - // Delete methods - HttpReply *removeDevice(Device *device, const QVariantMap ¶ms) const; - - // Post methods - HttpReply *executeAction(Device *device, const ActionTypeId &actionTypeId, const QByteArray &payload) const; - HttpReply *addConfiguredDevice(const QByteArray &payload) const; - HttpReply *editDevice(const QByteArray &payload) const; - HttpReply *pairDevice(const QByteArray &payload) const; - HttpReply *confirmPairDevice(const QByteArray &payload) const; - - // Put methods - HttpReply *reconfigureDevice(Device *device, const QByteArray &payload) const; - -}; - -} - -#endif // DEVICESRESOURCE_H diff --git a/libnymea-core/servers/rest/logsresource.cpp b/libnymea-core/servers/rest/logsresource.cpp deleted file mode 100644 index b4a11eeb..00000000 --- a/libnymea-core/servers/rest/logsresource.cpp +++ /dev/null @@ -1,121 +0,0 @@ -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - * * - * Copyright (C) 2015 Simon Stürz * - * * - * This file is part of nymea. * - * * - * nymea is free software: you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation, version 2 of the License. * - * * - * nymea is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with nymea. If not, see . * - * * - * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ - -/*! - \class nymeaserver::LogsResource - \brief This subclass of \l{RestResource} processes the REST requests for the \tt Logs namespace. - - \ingroup json - \inmodule core - - This \l{RestResource} will be created in the \l{RestServer} and used to handle REST requests - for the \tt {Logs} namespace of the API. - - \code - http://localhost:3333/api/v1/logs - \endcode - - \sa LogEntry, RestResource, RestServer -*/ - -#include "logsresource.h" -#include "servers/httprequest.h" -#include "loggingcategories.h" -#include "nymeacore.h" -#include "logging/logengine.h" - -#include - -namespace nymeaserver { - -/*! Constructs a \l LogsResource with the given \a parent. */ -LogsResource::LogsResource(QObject *parent) : - RestResource(parent) -{ -} - -/*! Returns the name of the \l{RestResource}. In this case \b logs. - - \sa RestResource::name() -*/ -QString LogsResource::name() const -{ - return "logs"; -} - -/*! This method will be used to process the given \a request and the given \a urlTokens. The request - has to be in this namespace. Returns the resulting \l HttpReply. - - \sa HttpRequest, HttpReply, RestResource::proccessRequest() -*/ -HttpReply *LogsResource::proccessRequest(const HttpRequest &request, const QStringList &urlTokens) -{ - // check method - HttpReply *reply; - switch (request.method()) { - case HttpRequest::Get: - reply = proccessGetRequest(request, urlTokens); - break; - default: - reply = createErrorReply(HttpReply::BadRequest); - break; - } - return reply; -} - -HttpReply *LogsResource::proccessGetRequest(const HttpRequest &request, const QStringList &urlTokens) -{ - // GET /api/v1/logs?filter={ogFilter} - if (urlTokens.count() == 3) { - // check filter - QString filterString; - if (request.url().hasQuery()) { - if (request.urlQuery().hasQueryItem("filter")) { - filterString = request.urlQuery().queryItemValue("filter"); - } - } - return getLogEntries(filterString); - } - return createErrorReply(HttpReply::NotImplemented);} - -HttpReply *LogsResource::getLogEntries(const QString &filterString) -{ - qCDebug(dcRest) << "Get log entries"; - - QPair verification = RestResource::verifyPayload(filterString.toUtf8()); - if (!verification.first) - return createErrorReply(HttpReply::BadRequest); - - QVariantMap filterMap = verification.second.toMap(); - - LogFilter filter = JsonTypes::unpackLogFilter(filterMap); - - QVariantList entries; - foreach (const LogEntry &entry, NymeaCore::instance()->logEngine()->logEntries(filter)) { - entries.append(JsonTypes::packLogEntry(entry)); - } - HttpReply *reply = createSuccessReply(); - reply->setHeader(HttpReply::ContentTypeHeader, "application/json; charset=\"utf-8\";"); - reply->setPayload(QJsonDocument::fromVariant(entries).toJson()); - return reply; -} - -} - diff --git a/libnymea-core/servers/rest/logsresource.h b/libnymea-core/servers/rest/logsresource.h deleted file mode 100644 index e1d0fba4..00000000 --- a/libnymea-core/servers/rest/logsresource.h +++ /dev/null @@ -1,57 +0,0 @@ -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - * * - * Copyright (C) 2015 Simon Stürz * - * * - * This file is part of nymea. * - * * - * nymea is free software: you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation, version 2 of the License. * - * * - * nymea is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with nymea. If not, see . * - * * - * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ - -#ifndef LOGSRESOURCE_H -#define LOGSRESOURCE_H - -#include -#include - -#include "jsonrpc/jsontypes.h" -#include "restresource.h" -#include "servers/httpreply.h" - -namespace nymeaserver { - -class HttpRequest; - -class LogsResource : public RestResource -{ - Q_OBJECT -public: - explicit LogsResource(QObject *parent = 0); - - QString name() const override; - - HttpReply *proccessRequest(const HttpRequest &request, const QStringList &urlTokens) override; - -private: - // Process method - HttpReply *proccessGetRequest(const HttpRequest &request, const QStringList &urlTokens) override; - - // Get methods - HttpReply *getLogEntries(const QString &filterString); - - -}; - -} - -#endif // LOGSRESOURCE_H diff --git a/libnymea-core/servers/rest/pluginsresource.cpp b/libnymea-core/servers/rest/pluginsresource.cpp deleted file mode 100644 index e99b2973..00000000 --- a/libnymea-core/servers/rest/pluginsresource.cpp +++ /dev/null @@ -1,214 +0,0 @@ -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - * * - * Copyright (C) 2015 Simon Stürz * - * * - * This file is part of nymea. * - * * - * nymea is free software: you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation, version 2 of the License. * - * * - * nymea is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with nymea. If not, see . * - * * - * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ - -/*! - \class nymeaserver::PluginsResource - \brief This subclass of \l{RestResource} processes the REST requests for the \tt Plugins namespace. - - \ingroup json - \inmodule core - - This \l{RestResource} will be created in the \l{RestServer} and used to handle REST requests - for the \tt {Plugins} namespace of the API. - - \code - http://localhost:3333/api/v1/plugins - \endcode - - \sa DevicePlugin, RestResource, RestServer -*/ - -#include "pluginsresource.h" -#include "servers/httprequest.h" -#include "loggingcategories.h" -#include "nymeacore.h" - -#include - -namespace nymeaserver { - -/*! Constructs a \l PluginsResource with the given \a parent. */ -PluginsResource::PluginsResource(QObject *parent) : - RestResource(parent) -{ - -} - -/*! Returns the name of the \l{RestResource}. In this case \b plugins. - - \sa RestResource::name() -*/ -QString PluginsResource::name() const -{ - return "plugins"; -} - -/*! This method will be used to process the given \a request and the given \a urlTokens. The request - has to be in this namespace. Returns the resulting \l HttpReply. - - \sa HttpRequest, HttpReply, RestResource::proccessRequest() -*/ -HttpReply *PluginsResource::proccessRequest(const HttpRequest &request, const QStringList &urlTokens) -{ - // get the main resource - - // /api/v1/plugins/{pluginId}/ - if (urlTokens.count() >= 4) { - m_pluginId = PluginId(urlTokens.at(3)); - if (m_pluginId.isNull()) { - qCWarning(dcRest) << "Could not parse PluginId:" << urlTokens.at(3); - return createDeviceErrorReply(HttpReply::BadRequest, Device::DeviceErrorPluginNotFound); - } - } - - // check method - HttpReply *reply; - switch (request.method()) { - case HttpRequest::Get: - reply = proccessGetRequest(request, urlTokens); - break; - case HttpRequest::Put: - reply = proccessPutRequest(request, urlTokens); - break; - case HttpRequest::Options: - reply = proccessOptionsRequest(request, urlTokens); - break; - default: - reply = createErrorReply(HttpReply::BadRequest); - break; - } - return reply; -} - -HttpReply *PluginsResource::proccessGetRequest(const HttpRequest &request, const QStringList &urlTokens) -{ - Q_UNUSED(request) - - // GET /api/v1/plugins - if (urlTokens.count() == 3) - return getPlugins(); - - // GET /api/v1/plugins/{pluginId} - if (urlTokens.count() == 4) - return getPlugin(m_pluginId); - - // GET /api/v1/plugins/{pluginId}/configuration - if (urlTokens.count() == 5 && urlTokens.at(4) == "configuration") { - return getPluginConfiguration(m_pluginId); - } - - return createErrorReply(HttpReply::NotImplemented); -} - -HttpReply *PluginsResource::proccessPutRequest(const HttpRequest &request, const QStringList &urlTokens) -{ - // PUT /api/v1/plugins/{pluginId}/configuration - if (urlTokens.count() == 5 && urlTokens.at(4) == "configuration") { - return setPluginConfiguration(m_pluginId, request.payload()); - } - - return createErrorReply(HttpReply::NotImplemented); -} - -HttpReply *PluginsResource::proccessOptionsRequest(const HttpRequest &request, const QStringList &urlTokens) -{ - Q_UNUSED(request) - Q_UNUSED(urlTokens) - return RestResource::createCorsSuccessReply(); -} - -HttpReply *PluginsResource::getPlugins() const -{ - qCDebug(dcRest) << "Get plugins"; - HttpReply *reply = createSuccessReply(); - reply->setHeader(HttpReply::ContentTypeHeader, "application/json; charset=\"utf-8\";"); - reply->setPayload(QJsonDocument::fromVariant(JsonTypes::packPlugins(NymeaCore::instance()->configuration()->locale())).toJson()); - return reply; -} - -HttpReply *PluginsResource::getPlugin(const PluginId &pluginId) const -{ - qCDebug(dcRest) << "Get plugin with id" << pluginId; - HttpReply *reply = createSuccessReply(); - foreach (DevicePlugin *plugin, NymeaCore::instance()->deviceManager()->plugins()) { - if (plugin->pluginId() == pluginId) { - reply->setHeader(HttpReply::ContentTypeHeader, "application/json; charset=\"utf-8\";"); - reply->setPayload(QJsonDocument::fromVariant(JsonTypes::packPlugin(plugin, NymeaCore::instance()->configuration()->locale())).toJson()); - return reply; - } - } - return createDeviceErrorReply(HttpReply::NotFound, Device::DeviceErrorPluginNotFound); -} - -HttpReply *PluginsResource::getPluginConfiguration(const PluginId &pluginId) const -{ - qCDebug(dcRest) << "Get configuration of plugin with id" << pluginId.toString(); - - DevicePlugin *plugin = 0; - plugin = findPlugin(pluginId); - if (!plugin) - return createDeviceErrorReply(HttpReply::NotFound, Device::DeviceErrorPluginNotFound); - - QVariantList configurationParamsList; - foreach (const Param ¶m, plugin->configuration()) { - configurationParamsList.append(JsonTypes::packParam(param)); - } - - HttpReply *reply = createSuccessReply(); - reply->setHeader(HttpReply::ContentTypeHeader, "application/json; charset=\"utf-8\";"); - reply->setPayload(QJsonDocument::fromVariant(configurationParamsList).toJson()); - return reply; -} - -HttpReply *PluginsResource::setPluginConfiguration(const PluginId &pluginId, const QByteArray &payload) const -{ - DevicePlugin *plugin = 0; - plugin = findPlugin(pluginId); - if (!plugin) - return createDeviceErrorReply(HttpReply::NotFound, Device::DeviceErrorPluginNotFound); - - qCDebug(dcRest) << "Set configuration of plugin with id" << pluginId.toString(); - - QPair verification = RestResource::verifyPayload(payload); - if (!verification.first) - return createErrorReply(HttpReply::BadRequest); - - QVariantList configuration = verification.second.toList(); - ParamList pluginParams = JsonTypes::unpackParams(configuration); - qCDebug(dcRest) << pluginParams; - Device::DeviceError result = NymeaCore::instance()->deviceManager()->setPluginConfig(pluginId, pluginParams); - - if (result != Device::DeviceErrorNoError) - return createDeviceErrorReply(HttpReply::BadRequest, result); - - return createDeviceErrorReply(HttpReply::Ok, result); -} - -DevicePlugin *PluginsResource::findPlugin(const PluginId &pluginId) const -{ - foreach (DevicePlugin *plugin, NymeaCore::instance()->deviceManager()->plugins()) { - if (plugin->pluginId() == pluginId) { - return plugin; - } - } - return 0; -} - -} diff --git a/libnymea-core/servers/rest/pluginsresource.h b/libnymea-core/servers/rest/pluginsresource.h deleted file mode 100644 index bd329f34..00000000 --- a/libnymea-core/servers/rest/pluginsresource.h +++ /dev/null @@ -1,67 +0,0 @@ -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - * * - * Copyright (C) 2015 Simon Stürz * - * * - * This file is part of nymea. * - * * - * nymea is free software: you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation, version 2 of the License. * - * * - * nymea is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with nymea. If not, see . * - * * - * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ - -#ifndef PLUGINSRESOURCE_H -#define PLUGINSRESOURCE_H - -#include -#include - -#include "jsonrpc/jsontypes.h" -#include "restresource.h" -#include "servers/httpreply.h" - -namespace nymeaserver { - -class HttpRequest; - -class PluginsResource : public RestResource -{ - Q_OBJECT -public: - explicit PluginsResource(QObject *parent = 0); - - QString name() const override; - - HttpReply *proccessRequest(const HttpRequest &request, const QStringList &urlTokens) override; - -private: - PluginId m_pluginId; - - // Process method - HttpReply *proccessGetRequest(const HttpRequest &request, const QStringList &urlTokens) override; - HttpReply *proccessPutRequest(const HttpRequest &request, const QStringList &urlTokens) override; - HttpReply *proccessOptionsRequest(const HttpRequest &request, const QStringList &urlTokens) override; - - // Get methods - HttpReply *getPlugins() const; - HttpReply *getPlugin(const PluginId &pluginId) const; - HttpReply *getPluginConfiguration(const PluginId &pluginId) const; - HttpReply *setPluginConfiguration(const PluginId &pluginId, const QByteArray &payload) const; - - // Put methods - - - DevicePlugin *findPlugin(const PluginId &pluginId) const; -}; - -} - -#endif // PLUGINSRESOURCE_H diff --git a/libnymea-core/servers/rest/restresource.cpp b/libnymea-core/servers/rest/restresource.cpp deleted file mode 100644 index 08cf1c24..00000000 --- a/libnymea-core/servers/rest/restresource.cpp +++ /dev/null @@ -1,209 +0,0 @@ -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - * * - * Copyright (C) 2015 Simon Stürz * - * * - * This file is part of nymea. * - * * - * nymea is free software: you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation, version 2 of the License. * - * * - * nymea is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with nymea. If not, see . * - * * - * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ - -/*! - \class nymeaserver::RestResource - \brief This class provides an interface for REST API resources. - - \ingroup api - \inmodule core - - The \l{RestResource} class provides an interface for subclassing a new resource for - the REST API. A resource represents an Object in the core like \l{Device}{Devices} - or \l{DevicePlugin}{Plugins}. A \l{RestResource} will be identified by it's - \l{RestResource::name()}{name}. - - Each subclass of \l{RestResource} has to implement the method \l{RestResource::proccessRequest()} - where a valid \l{HttpRequest} will be processed. - - This name of the resource will define the endpoint of the an API call: - \code - http://localhost:3333/api/v1/ - \endcode - - \sa RestServer -*/ - -/*! \fn QString nymeaserver::RestResource::name() const; - This method must be implemented in a subclass of \l{RestResource}. It returns - the endpoint name of this \l{RestResource} i.e. if this method returns \tt "example" - the API resource will be accessable with the URL: - - \code - http://localhost:3333/api/v1/example - \endcode - -*/ - -/*! \fn HttpReply *nymeaserver::RestResource::proccessRequest(const HttpRequest &request, const QStringList &urlTokens) - This method will be called from the \l{RestServer} once a \l{HttpRequest} \a request was identified to belong - to this \l{RestResource}. The given \a urlTokens contain the full list of URL tokens from this request. -*/ - -#include "restresource.h" -#include "servers/httprequest.h" -#include "loggingcategories.h" -#include "devices/devicemanager.h" - -#include -#include - -namespace nymeaserver { - -/*! Constructs a \l{RestResource} with the given \a parent. */ -RestResource::RestResource(QObject *parent) : - QObject(parent) -{ -} - -/*! Pure virtual destructor for this \l{RestResource}. */ -RestResource::~RestResource() -{ -} - -/*! Returns the pointer to a new created \l{HttpReply} initialized with \l{HttpReply::Ok} and \l{HttpReply::TypeSync}. */ -HttpReply *RestResource::createSuccessReply() -{ - HttpReply *reply = new HttpReply(HttpReply::Ok, HttpReply::TypeSync); - reply->setPayload("200 Ok"); - return reply; -} - -/*! Returns the pointer to a new created \l{HttpReply} which represents a response to a CORS request. */ -HttpReply *RestResource::createCorsSuccessReply() -{ - HttpReply *reply = RestResource::createSuccessReply(); - reply->setRawHeader("Accept","application/json"); - reply->setRawHeader("Allow", "PUT, POST, GET, DELETE, OPTIONS"); - reply->setRawHeader("Access-Control-Allow-Methods", "PUT, POST, GET, DELETE, OPTIONS"); - reply->setRawHeader("Access-Control-Allow-Headers", "Origin, Content-Type, Accept"); - reply->setRawHeader("Access-Control-Max-Age", "1728000"); - return reply; -} - -/*! Returns the pointer to a new created error \l{HttpReply} initialized with the given \a statusCode and \l{HttpReply::TypeSync}. */ -HttpReply *RestResource::createErrorReply(const HttpReply::HttpStatusCode &statusCode) -{ - HttpReply *reply = new HttpReply(statusCode, HttpReply::TypeSync); - reply->setPayload(QByteArray::number(reply->httpStatusCode()) + " " + reply->httpReasonPhrase()); - return reply; -} - -/*! Returns the pointer to a new created error \l{HttpReply} initialized with the given \a statusCode, \l{HttpReply::TypeSync} and the \a deviceError. */ -HttpReply *RestResource::createDeviceErrorReply(const HttpReply::HttpStatusCode &statusCode, const Device::DeviceError &deviceError) -{ - HttpReply *reply = new HttpReply(statusCode, HttpReply::TypeSync); - QVariantMap response; - response.insert("error", JsonTypes::deviceErrorToString(deviceError)); - reply->setHeader(HttpReply::ContentTypeHeader, "application/json; charset=\"utf-8\";"); - reply->setPayload(QJsonDocument::fromVariant(response).toJson()); - return reply; -} - -/*! Returns the pointer to a new created \l{HttpReply} with the given \a statusCode and \a ruleError. This method will - * be used to create an error response for the \l{nymeaserver::RulesResource}{RulesResource}. The \a ruleError will be written in the payload of this reply.*/ -HttpReply *RestResource::createRuleErrorReply(const HttpReply::HttpStatusCode &statusCode, const RuleEngine::RuleError &ruleError) -{ - HttpReply *reply = new HttpReply(statusCode, HttpReply::TypeSync); - QVariantMap response; - response.insert("error", JsonTypes::ruleErrorToString(ruleError)); - reply->setHeader(HttpReply::ContentTypeHeader, "application/json; charset=\"utf-8\";"); - reply->setPayload(QJsonDocument::fromVariant(response).toJson()); - return reply; -} - -/*! Returns the pointer to a new created \l{HttpReply} with the given \a statusCode and \a loggingError. This method will - * be used to create an error response for the \l{nymeaserver::LogsResource}{LogsResource}. The \a loggingError will be written in the payload of this reply.*/ -HttpReply *RestResource::createLoggingErrorReply(const HttpReply::HttpStatusCode &statusCode, const Logging::LoggingError &loggingError) -{ - HttpReply *reply = new HttpReply(statusCode, HttpReply::TypeSync); - QVariantMap response; - response.insert("error", JsonTypes::loggingErrorToString(loggingError)); - reply->setHeader(HttpReply::ContentTypeHeader, "application/json; charset=\"utf-8\";"); - reply->setPayload(QJsonDocument::fromVariant(response).toJson()); - return reply; -} - -/*! Returns the pointer to a new created \l{HttpReply} initialized with \l{HttpReply::Ok} and \l{HttpReply::TypeAsync}. */ -HttpReply *RestResource::createAsyncReply() -{ - HttpReply *reply = new HttpReply(HttpReply::Ok, HttpReply::TypeAsync); - reply->setPayload(QByteArray::number(reply->httpStatusCode()) + " " + reply->httpReasonPhrase()); - return reply; -} - -/*! This method can be used from every \l{RestResource} in order to verify if the \a payload of a - \l{HttpRequest} is a valid JSON document. Returns \tt true and the valid \e QVariant if there - was no error while parsing JSON. Returns \tt false and an invalid \e QVariant if the \a payload - could not be parsed. -*/ -QPair RestResource::verifyPayload(const QByteArray &payload) -{ - QVariant data; - if (!payload.isEmpty()) { - QJsonParseError error; - QJsonDocument jsonDoc = QJsonDocument::fromJson(payload, &error); - - if(error.error != QJsonParseError::NoError) { - qCWarning(dcRest) << "Failed to parse JSON payload" << payload << ":" << error.errorString(); - return QPair(false, QVariant()); - } - - data = jsonDoc.toVariant(); - } - return QPair(true, data); -} - -HttpReply *RestResource::proccessPostRequest(const HttpRequest &request, const QStringList &urlTokens) -{ - Q_UNUSED(request) - Q_UNUSED(urlTokens) - return createErrorReply(HttpReply::NotImplemented); -} - -HttpReply *RestResource::proccessOptionsRequest(const HttpRequest &request, const QStringList &urlTokens) -{ - Q_UNUSED(request) - Q_UNUSED(urlTokens) - return createErrorReply(HttpReply::NotImplemented); -} - -HttpReply *RestResource::proccessPutRequest(const HttpRequest &request, const QStringList &urlTokens) -{ - Q_UNUSED(request) - Q_UNUSED(urlTokens) - return createErrorReply(HttpReply::NotImplemented); -} - -HttpReply *RestResource::proccessDeleteRequest(const HttpRequest &request, const QStringList &urlTokens) -{ - Q_UNUSED(request) - Q_UNUSED(urlTokens) - return createErrorReply(HttpReply::NotImplemented); -} - -HttpReply *RestResource::proccessGetRequest(const HttpRequest &request, const QStringList &urlTokens) -{ - Q_UNUSED(request) - Q_UNUSED(urlTokens) - return createErrorReply(HttpReply::NotImplemented); -} - -} diff --git a/libnymea-core/servers/rest/restresource.h b/libnymea-core/servers/rest/restresource.h deleted file mode 100644 index 474568ea..00000000 --- a/libnymea-core/servers/rest/restresource.h +++ /dev/null @@ -1,70 +0,0 @@ -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - * * - * Copyright (C) 2015 Simon Stürz * - * * - * This file is part of nymea. * - * * - * nymea is free software: you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation, version 2 of the License. * - * * - * nymea is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with nymea. If not, see . * - * * - * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ - -#ifndef RESTRESOURCE_H -#define RESTRESOURCE_H - -#include -#include - -#include "servers/httpreply.h" -#include "servers/httprequest.h" -#include "jsonrpc/jsontypes.h" - -class QVariant; - -namespace nymeaserver { - -class RestResource : public QObject -{ - Q_OBJECT -public: - explicit RestResource(QObject *parent = 0); - virtual ~RestResource() = 0; - - virtual QString name() const = 0; - - virtual HttpReply *proccessRequest(const HttpRequest &request, const QStringList &urlTokens) = 0; - - static HttpReply *createSuccessReply(); - static HttpReply *createCorsSuccessReply(); - static HttpReply *createErrorReply(const HttpReply::HttpStatusCode &statusCode); - static HttpReply *createDeviceErrorReply(const HttpReply::HttpStatusCode &statusCode, const Device::DeviceError &deviceError); - static HttpReply *createRuleErrorReply(const HttpReply::HttpStatusCode &statusCode, const RuleEngine::RuleError &ruleError); - static HttpReply *createLoggingErrorReply(const HttpReply::HttpStatusCode &statusCode, const Logging::LoggingError &loggingError); - static HttpReply *createAsyncReply(); - static QPair verifyPayload(const QByteArray &payload); - -private: - virtual HttpReply *proccessGetRequest(const HttpRequest &request, const QStringList &urlTokens); - virtual HttpReply *proccessDeleteRequest(const HttpRequest &request, const QStringList &urlTokens); - virtual HttpReply *proccessPutRequest(const HttpRequest &request, const QStringList &urlTokens); - virtual HttpReply *proccessPostRequest(const HttpRequest &request, const QStringList &urlTokens); - virtual HttpReply *proccessOptionsRequest(const HttpRequest &request, const QStringList &urlTokens); - - QHash, QString> m_descriptions; - QHash m_params; - QHash m_returns; - -}; - -} - -#endif // RESTRESOURCE_H diff --git a/libnymea-core/servers/rest/restserver.cpp b/libnymea-core/servers/rest/restserver.cpp deleted file mode 100644 index 24609646..00000000 --- a/libnymea-core/servers/rest/restserver.cpp +++ /dev/null @@ -1,180 +0,0 @@ -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - * * - * Copyright (C) 2015 Simon Stürz * - * * - * This file is part of nymea. * - * * - * nymea is free software: you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation, version 2 of the License. * - * * - * nymea is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with nymea. If not, see . * - * * - * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ - -/*! - \class nymeaserver::RestServer - \brief This class provides the REST API interface to the \l{WebServer}{WebServers}. - - \ingroup server - \inmodule core - - The \l{RestServer} class provides the server interface for a REST API call. The \l{RestServer} - will create a \l{WebServer} object. The \l{WebServer} will parse the \l{HttpRequest} and emits - the signal \l{WebServer::httpRequestReady()}. This signal will be handled by this \l{RestServer} - and processed by the corresponding \l{RestResource}. Once the \l{HttpRequest} is finished, the - \l{RestServer} will send a \l{HttpReply} back to the client using \l{WebServer::sendHttpReply()}. - - \sa ServerManager, WebServer, HttpRequest, HttpReply -*/ - -#include "restserver.h" -#include "loggingcategories.h" -#include "servers/httprequest.h" -#include "servers/httpreply.h" - -#include -#include - -namespace nymeaserver { - -/*! Constructs a \l{RestServer} with the given \a sslConfiguration and \a parent. */ -RestServer::RestServer(const QSslConfiguration &sslConfiguration, QObject *parent) : - QObject(parent) -{ - Q_UNUSED(sslConfiguration) - - QMetaObject::invokeMethod(this, "setup", Qt::QueuedConnection); -} - -/*! Register the given \a webServer in this \l{RestServer}. - * - * \sa WebServer - * - */ -void RestServer::registerWebserver(WebServer *webServer) -{ - connect(webServer, &WebServer::clientConnected, this, &RestServer::clientConnected); - connect(webServer, &WebServer::clientDisconnected, this, &RestServer::clientDisconnected); - connect(webServer, &WebServer::httpRequestReady, this, &RestServer::processHttpRequest); -} - -void RestServer::setup() -{ - // Create resources - m_deviceResource = new DevicesResource(this); - m_deviceClassesResource = new DeviceClassesResource(this); - m_vendorsResource = new VendorsResource(this); - m_pluginsResource = new PluginsResource(this); - m_rulesResource = new RulesResource(this); - m_logsResource = new LogsResource(this); - - m_resources.insert(m_deviceResource->name(), m_deviceResource); - m_resources.insert(m_deviceClassesResource->name(), m_deviceClassesResource); - m_resources.insert(m_vendorsResource->name(), m_vendorsResource); - m_resources.insert(m_pluginsResource->name(), m_pluginsResource); - m_resources.insert(m_rulesResource->name(), m_rulesResource); - m_resources.insert(m_logsResource->name(), m_logsResource); -} - -void RestServer::clientConnected(const QUuid &clientId) -{ - WebServer *webserver = dynamic_cast(sender()); - m_clientList.insert(clientId, webserver); -} - -void RestServer::clientDisconnected(const QUuid &clientId) -{ - m_clientList.take(clientId); -} - -void RestServer::processHttpRequest(const QUuid &clientId, const HttpRequest &request) -{ - QStringList urlTokens = request.url().path().split("/"); - urlTokens.removeAll(QString()); - - WebServer *webserver = dynamic_cast(sender()); - Q_ASSERT(webserver); - - // check token count - if (urlTokens.count() < 3) { - HttpReply *reply = RestResource::createErrorReply(HttpReply::BadRequest); - reply->setClientId(clientId); - webserver->sendHttpReply(reply); - reply->deleteLater(); - return; - } - - // check resource - QString resourceName = urlTokens.at(2); - if (!m_resources.contains(resourceName)) { - HttpReply *reply = RestResource::createErrorReply(HttpReply::BadRequest); - reply->setClientId(clientId); - webserver->sendHttpReply(reply); - reply->deleteLater(); - return; - } - - // check CORS call for main resource - if (request.method() == HttpRequest::Options && urlTokens.count() == 3) { - HttpReply *reply = RestResource::createCorsSuccessReply(); - reply->setClientId(clientId); - webserver->sendHttpReply(reply); - reply->deleteLater(); - return; - } - - - // process request in corresponding resource - RestResource *resource = m_resources.value(resourceName); - HttpReply *reply = resource->proccessRequest(request, urlTokens); - reply->setClientId(clientId); - if (reply->type() == HttpReply::TypeAsync) { - connect(reply, &HttpReply::finished, this, &RestServer::asyncReplyFinished); - m_asyncReplies.insert(clientId, reply); - reply->startWait(); - return; - } - webserver->sendHttpReply(reply); - reply->deleteLater(); -} - -void RestServer::asyncReplyFinished() -{ - HttpReply *reply = qobject_cast(sender()); - - if (!m_asyncReplies.values().contains(reply)) { - qCWarning(dcWebServer()) << "Reply for async request does no longer exist"; - reply->deleteLater(); - return; - } - - QUuid clientId = m_asyncReplies.key(reply); - m_asyncReplies.remove(clientId); - - qCDebug(dcWebServer()) << "Async reply finished"; - - // check if the reply timeouted - if (reply->timedOut()) { - reply->clear(); - reply->setHttpStatusCode(HttpReply::GatewayTimeout); - } - - // check if client is still connected - if (!m_clientList.contains(clientId)) { - qCWarning(dcWebServer()) << "Client for async reply not longer connected."; - } else { - reply->setClientId(clientId); - WebServer *webserver = m_clientList.value(clientId); - webserver->sendHttpReply(reply); - } - reply->deleteLater(); -} - -} diff --git a/libnymea-core/servers/rest/restserver.h b/libnymea-core/servers/rest/restserver.h deleted file mode 100644 index 2722e870..00000000 --- a/libnymea-core/servers/rest/restserver.h +++ /dev/null @@ -1,75 +0,0 @@ -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - * * - * Copyright (C) 2015 Simon Stürz * - * * - * This file is part of nymea. * - * * - * nymea is free software: you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation, version 2 of the License. * - * * - * nymea is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with nymea. If not, see . * - * * - * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ - -#ifndef RESTSERVER_H -#define RESTSERVER_H - -#include - -#include "servers/webserver.h" -#include "jsonrpc/jsonhandler.h" -#include "devicesresource.h" -#include "deviceclassesresource.h" -#include "vendorsresource.h" -#include "pluginsresource.h" -#include "rulesresource.h" -#include "logsresource.h" - -class QSslConfiguration; - -namespace nymeaserver { - -class HttpRequest; -class HttpReply; - -class RestServer : public QObject -{ - Q_OBJECT -public: - explicit RestServer(const QSslConfiguration &sslConfiguration = QSslConfiguration(), QObject *parent = 0); - - void registerWebserver(WebServer *webServer); - -private: - QHash m_clientList; - QHash m_resources; - - QHash m_asyncReplies; - - DevicesResource *m_deviceResource; - DeviceClassesResource *m_deviceClassesResource; - VendorsResource *m_vendorsResource; - PluginsResource *m_pluginsResource; - RulesResource *m_rulesResource; - LogsResource *m_logsResource; - -private slots: - void setup(); - void clientConnected(const QUuid &clientId); - void clientDisconnected(const QUuid &clientId); - - void processHttpRequest(const QUuid &clientId, const HttpRequest &request); - void asyncReplyFinished(); - -}; - -} - -#endif // RESTSERVER_H diff --git a/libnymea-core/servers/rest/rulesresource.cpp b/libnymea-core/servers/rest/rulesresource.cpp deleted file mode 100644 index b345c9e3..00000000 --- a/libnymea-core/servers/rest/rulesresource.cpp +++ /dev/null @@ -1,329 +0,0 @@ -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - * * - * Copyright (C) 2015 Simon Stürz * - * * - * This file is part of nymea. * - * * - * nymea is free software: you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation, version 2 of the License. * - * * - * nymea is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with nymea. If not, see . * - * * - * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ - -/*! - \class nymeaserver::RulesResource - \brief This subclass of \l{RestResource} processes the REST requests for the \tt Rules namespace. - - \ingroup json - \inmodule core - - This \l{RestResource} will be created in the \l{RestServer} and used to handle REST requests - for the \tt {Rules} namespace of the API. - - \code - http://localhost:3333/api/v1/rules - \endcode - - \sa Rule, RestResource, RestServer -*/ - -#include "rulesresource.h" -#include "servers/httprequest.h" -#include "typeutils.h" -#include "loggingcategories.h" -#include "nymeacore.h" - -#include - -namespace nymeaserver { - -/*! Constructs a \l RulesResource with the given \a parent. */ -RulesResource::RulesResource(QObject *parent) : - RestResource(parent) -{ -} - -/*! Returns the name of the \l{RestResource}. In this case \b rules. - - \sa RestResource::name() -*/ -QString RulesResource::name() const -{ - return "rules"; -} - -/*! This method will be used to process the given \a request and the given \a urlTokens. The request - has to be in this namespace. Returns the resulting \l HttpReply. - - \sa HttpRequest, HttpReply, RestResource::proccessRequest() -*/ -HttpReply *RulesResource::proccessRequest(const HttpRequest &request, const QStringList &urlTokens) -{ - // /api/v1/rules/{ruleId}/ - if (urlTokens.count() >= 4) { - m_ruleId = RuleId(urlTokens.at(3)); - if (m_ruleId.isNull()) { - qCWarning(dcRest) << "Could not parse RuleId:" << urlTokens.at(3); - return createRuleErrorReply(HttpReply::BadRequest, RuleEngine::RuleErrorRuleNotFound); - } - - if (!NymeaCore::instance()->ruleEngine()->findRule(m_ruleId).isValid()) { - qCWarning(dcRest) << "Could not find rule with id" << m_ruleId.toString(); - return createRuleErrorReply(HttpReply::NotFound, RuleEngine::RuleErrorRuleNotFound); - } - - } - - // check method - HttpReply *reply; - switch (request.method()) { - case HttpRequest::Get: - reply = proccessGetRequest(request, urlTokens); - break; - case HttpRequest::Put: - reply = proccessPutRequest(request, urlTokens); - break; - case HttpRequest::Post: - reply = proccessPostRequest(request, urlTokens); - break; - case HttpRequest::Delete: - reply = proccessDeleteRequest(request, urlTokens); - break; - case HttpRequest::Options: - reply = proccessOptionsRequest(request, urlTokens); - break; - default: - reply = createErrorReply(HttpReply::BadRequest); - break; - } - return reply; -} - -HttpReply *RulesResource::proccessGetRequest(const HttpRequest &request, const QStringList &urlTokens) -{ - Q_UNUSED(request) - - // GET /api/v1/rules - if (urlTokens.count() == 3) { - // check if we should filter for rules containing a certain device - DeviceId deviceId; - if (request.url().hasQuery() && request.urlQuery().hasQueryItem("deviceId")) { - deviceId = DeviceId(request.urlQuery().queryItemValue("deviceId")); - if (deviceId.isNull()) - return createRuleErrorReply(HttpReply::NotFound, RuleEngine::RuleErrorDeviceNotFound); - } - return getRules(deviceId); - } - - // GET /api/v1/rules/{ruleId} - if (urlTokens.count() == 4) - return getRuleDetails(m_ruleId); - - return createErrorReply(HttpReply::NotImplemented); -} - -HttpReply *RulesResource::proccessDeleteRequest(const HttpRequest &request, const QStringList &urlTokens) -{ - Q_UNUSED(request) - - // DELETE /api/v1/rules - if (urlTokens.count() == 3) - return createErrorReply(HttpReply::BadRequest); - - // DELETE /api/v1/rules/{ruleId} - if (urlTokens.count() == 4) - return removeRule(m_ruleId); - - return createErrorReply(HttpReply::NotImplemented); -} - -HttpReply *RulesResource::proccessPutRequest(const HttpRequest &request, const QStringList &urlTokens) -{ - // PUT /api/v1/rules - if (urlTokens.count() == 3) - return createErrorReply(HttpReply::BadRequest); - - // PUT /api/v1/rules/{ruleId} - if (urlTokens.count() == 4) - return editRule(m_ruleId, request.payload()); - - return createErrorReply(HttpReply::NotImplemented); -} - -HttpReply *RulesResource::proccessPostRequest(const HttpRequest &request, const QStringList &urlTokens) -{ - // POST /api/v1/rules - if (urlTokens.count() == 3) - return addRule(request.payload()); - - // POST /api/v1/rules/{ruleId}/enable - if (urlTokens.count() == 5 && urlTokens.at(4) == "enable") - return enableRule(m_ruleId); - - // POST /api/v1/rules/{ruleId}/disable - if (urlTokens.count() == 5 && urlTokens.at(4) == "disable") - return disableRule(m_ruleId); - - // POST /api/v1/rules/{ruleId}/executeactions - if (urlTokens.count() == 5 && urlTokens.at(4) == "executeactions") - return executeActions(m_ruleId); - - // POST /api/v1/rules/{ruleId}/executeexitactions - if (urlTokens.count() == 5 && urlTokens.at(4) == "executeexitactions") - return executeExitActions(m_ruleId); - - return createErrorReply(HttpReply::NotImplemented); -} - -HttpReply *RulesResource::proccessOptionsRequest(const HttpRequest &request, const QStringList &urlTokens) -{ - Q_UNUSED(request) - Q_UNUSED(urlTokens) - return RestResource::createCorsSuccessReply(); -} - -HttpReply *RulesResource::getRules(const DeviceId &deviceId) const -{ - HttpReply *reply = createSuccessReply(); - - if (deviceId.isNull()) { - qCDebug(dcRest) << "Get rule descriptions"; - reply->setPayload(QJsonDocument::fromVariant(JsonTypes::packRuleDescriptions()).toJson()); - } else { - qCDebug(dcRest) << "Get rule descriptions which contain the device with id" << deviceId.toString(); - QList ruleIdsList = NymeaCore::instance()->ruleEngine()->findRules(deviceId); - QList ruleList; - foreach (const RuleId &ruleId, ruleIdsList) { - Rule rule = NymeaCore::instance()->ruleEngine()->findRule(ruleId); - if (rule.isValid()) - ruleList.append(rule); - } - reply->setHeader(HttpReply::ContentTypeHeader, "application/json; charset=\"utf-8\";"); - reply->setPayload(QJsonDocument::fromVariant(JsonTypes::packRuleDescriptions(ruleList)).toJson()); - } - return reply; -} - -HttpReply *RulesResource::getRuleDetails(const RuleId &ruleId) const -{ - qCDebug(dcRest) << "Get rule details"; - - // Note: rule existence already checked - Rule rule = NymeaCore::instance()->ruleEngine()->findRule(ruleId); - - HttpReply *reply = createSuccessReply(); - reply->setHeader(HttpReply::ContentTypeHeader, "application/json; charset=\"utf-8\";"); - reply->setPayload(QJsonDocument::fromVariant(JsonTypes::packRule(rule)).toJson()); - return reply; -} - -HttpReply *RulesResource::removeRule(const RuleId &ruleId) const -{ - qCDebug(dcRest) << "Remove rule with id" << ruleId.toString(); - - RuleEngine::RuleError status = NymeaCore::instance()->removeRule(ruleId); - if (status != RuleEngine::RuleErrorNoError) - return createRuleErrorReply(HttpReply::InternalServerError, status); - - return createRuleErrorReply(HttpReply::Ok, status); -} - -HttpReply *RulesResource::addRule(const QByteArray &payload) const -{ - qCDebug(dcRest) << "Add new rule"; - - QPair verification = RestResource::verifyPayload(payload); - if (!verification.first) - return createErrorReply(HttpReply::BadRequest); - - QVariantMap params = verification.second.toMap(); - Rule rule = JsonTypes::unpackRule(params); - rule.setId(RuleId::createRuleId()); - - RuleEngine::RuleError status = NymeaCore::instance()->ruleEngine()->addRule(rule); - if (status == RuleEngine::RuleErrorNoError) { - QVariant returns = JsonTypes::packRule(NymeaCore::instance()->ruleEngine()->findRule(rule.id())); - HttpReply *reply = createSuccessReply(); - reply->setHeader(HttpReply::ContentTypeHeader, "application/json; charset=\"utf-8\";"); - reply->setPayload(QJsonDocument::fromVariant(returns).toJson()); - return reply; - } - - return createRuleErrorReply(HttpReply::BadRequest, status); -} - -HttpReply *RulesResource::enableRule(const RuleId &ruleId) const -{ - qCDebug(dcRest) << "Enable rule with id" << ruleId.toString(); - - RuleEngine::RuleError status = NymeaCore::instance()->ruleEngine()->enableRule(ruleId); - if (status != RuleEngine::RuleErrorNoError) - return createRuleErrorReply(HttpReply::InternalServerError, status); - - return createRuleErrorReply(HttpReply::Ok, status); -} - -HttpReply *RulesResource::disableRule(const RuleId &ruleId) const -{ - qCDebug(dcRest) << "Disable rule with id" << ruleId.toString(); - - RuleEngine::RuleError status = NymeaCore::instance()->ruleEngine()->disableRule(ruleId); - if (status != RuleEngine::RuleErrorNoError) - return createRuleErrorReply(HttpReply::InternalServerError, status); - - return createRuleErrorReply(HttpReply::Ok, status); -} - -HttpReply *RulesResource::executeActions(const RuleId &ruleId) const -{ - qCDebug(dcRest) << "Execute actions of rule with id" << ruleId.toString(); - - RuleEngine::RuleError status = NymeaCore::instance()->ruleEngine()->executeActions(ruleId); - if (status != RuleEngine::RuleErrorNoError) - return createRuleErrorReply(HttpReply::InternalServerError, status); - - return createRuleErrorReply(HttpReply::Ok, status); -} - -HttpReply *RulesResource::executeExitActions(const RuleId &ruleId) const -{ - qCDebug(dcRest) << "Execute exit actions of rule with id" << ruleId.toString(); - - RuleEngine::RuleError status = NymeaCore::instance()->ruleEngine()->executeExitActions(ruleId); - if (status != RuleEngine::RuleErrorNoError) - return createRuleErrorReply(HttpReply::InternalServerError, status); - - return createRuleErrorReply(HttpReply::Ok, status); -} - -HttpReply *RulesResource::editRule(const RuleId &ruleId, const QByteArray &payload) const -{ - qCDebug(dcRest) << "Edit rule with id" << ruleId.toString(); - - QPair verification = RestResource::verifyPayload(payload); - if (!verification.first) - return createErrorReply(HttpReply::BadRequest); - - QVariantMap params = verification.second.toMap(); - Rule rule = JsonTypes::unpackRule(params); - - RuleEngine::RuleError status = NymeaCore::instance()->ruleEngine()->editRule(rule); - if (status == RuleEngine::RuleErrorNoError) { - qCDebug(dcRest) << "Edit rule successfully finished"; - return createRuleErrorReply(HttpReply::Ok, status); - } - - qCWarning(dcRest) << "Edit rule finished with error" << JsonTypes::ruleErrorToString(status); - return createRuleErrorReply(HttpReply::BadRequest, status); -} - -} - diff --git a/libnymea-core/servers/rest/rulesresource.h b/libnymea-core/servers/rest/rulesresource.h deleted file mode 100644 index e5c8e48b..00000000 --- a/libnymea-core/servers/rest/rulesresource.h +++ /dev/null @@ -1,78 +0,0 @@ -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - * * - * Copyright (C) 2015 Simon Stürz * - * * - * This file is part of nymea. * - * * - * nymea is free software: you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation, version 2 of the License. * - * * - * nymea is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with nymea. If not, see . * - * * - * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ - -#ifndef RULESRESOURCE_H -#define RULESRESOURCE_H - -#include -#include - -#include "jsonrpc/jsontypes.h" -#include "restresource.h" -#include "servers/httpreply.h" - - -namespace nymeaserver { - -class HttpRequest; - -class RulesResource : public RestResource -{ - Q_OBJECT -public: - explicit RulesResource(QObject *parent = 0); - - QString name() const override; - - HttpReply *proccessRequest(const HttpRequest &request, const QStringList &urlTokens) override; - -private: - RuleId m_ruleId; - - // Process method - HttpReply *proccessGetRequest(const HttpRequest &request, const QStringList &urlTokens) override; - HttpReply *proccessDeleteRequest(const HttpRequest &request, const QStringList &urlTokens) override; - HttpReply *proccessPutRequest(const HttpRequest &request, const QStringList &urlTokens) override; - HttpReply *proccessPostRequest(const HttpRequest &request, const QStringList &urlTokens) override; - HttpReply *proccessOptionsRequest(const HttpRequest &request, const QStringList &urlTokens) override; - - // Get methods - HttpReply *getRules(const DeviceId &deviceId) const; - HttpReply *getRuleDetails(const RuleId &ruleId) const; - - // Delete methods - HttpReply *removeRule(const RuleId &ruleId) const; - - // Post methods - HttpReply *addRule(const QByteArray &payload) const; - HttpReply *enableRule(const RuleId &ruleId) const; - HttpReply *disableRule(const RuleId &ruleId) const; - HttpReply *executeActions(const RuleId &ruleId) const; - HttpReply *executeExitActions(const RuleId &ruleId) const; - - - // Put methods - HttpReply *editRule(const RuleId &ruleId, const QByteArray &payload) const; - -}; - -} - -#endif // RULESRESOURCE_H diff --git a/libnymea-core/servers/rest/vendorsresource.cpp b/libnymea-core/servers/rest/vendorsresource.cpp deleted file mode 100644 index a908dd04..00000000 --- a/libnymea-core/servers/rest/vendorsresource.cpp +++ /dev/null @@ -1,136 +0,0 @@ -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - * * - * Copyright (C) 2015 Simon Stürz * - * * - * This file is part of nymea. * - * * - * nymea is free software: you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation, version 2 of the License. * - * * - * nymea is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with nymea. If not, see . * - * * - * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ - -/*! - \class nymeaserver::VendorsResource - \brief This subclass of \l{RestResource} processes the REST requests for the \tt Vendors namespace. - - \ingroup json - \inmodule core - - This \l{RestResource} will be created in the \l{RestServer} and used to handle REST requests - for the \tt {Vendors} namespace of the API. - - \code - http://localhost:3333/api/v1/vendors - \endcode - - \sa Vendor, RestResource, RestServer -*/ - - -#include "vendorsresource.h" -#include "servers/httprequest.h" -#include "loggingcategories.h" -#include "nymeacore.h" - -#include - -namespace nymeaserver { - -/*! Constructs a \l VendorsResource with the given \a parent. */ -VendorsResource::VendorsResource(QObject *parent) : - RestResource(parent) -{ -} - -/*! Returns the name of the \l{RestResource}. In this case \b vendors. - - \sa RestResource::name() -*/ -QString VendorsResource::name() const -{ - return "vendors"; -} - -/*! This method will be used to process the given \a request and the given \a urlTokens. The request - has to be in this namespace. Returns the resulting \l HttpReply. - - \sa HttpRequest, HttpReply, RestResource::proccessRequest() -*/ -HttpReply *VendorsResource::proccessRequest(const HttpRequest &request, const QStringList &urlTokens) -{ - // /api/v1/vendors/{vendorId}/ - if (urlTokens.count() >= 4) { - m_vendorId = VendorId(urlTokens.at(3)); - if (m_vendorId.isNull()) { - qCWarning(dcRest) << "Could not parse VendorId:" << urlTokens.at(3); - return createDeviceErrorReply(HttpReply::BadRequest, Device::DeviceErrorVendorNotFound); - } - } - - // check method - HttpReply *reply; - switch (request.method()) { - case HttpRequest::Get: - reply = proccessGetRequest(request, urlTokens); - break; - default: - reply = createErrorReply(HttpReply::BadRequest); - break; - } - return reply; -} - -HttpReply *VendorsResource::proccessGetRequest(const HttpRequest &request, const QStringList &urlTokens) -{ - Q_UNUSED(request) - - // GET /api/v1/vendors - if (urlTokens.count() == 3) - return getVendors(); - - // GET /api/v1/vendors/{vendorId} - if (urlTokens.count() == 4) - return getVendor(m_vendorId); - - return createErrorReply(HttpReply::NotImplemented); -} - -HttpReply *VendorsResource::getVendors() const -{ - qCDebug(dcRest) << "Get vendors"; - HttpReply *reply = createSuccessReply(); - - QVariantList vendorsList; - foreach (const Vendor &vendor, NymeaCore::instance()->deviceManager()->supportedVendors()) { - vendorsList.append(JsonTypes::packVendor(vendor, NymeaCore::instance()->configuration()->locale())); - } - reply->setHeader(HttpReply::ContentTypeHeader, "application/json; charset=\"utf-8\";"); - reply->setPayload(QJsonDocument::fromVariant(vendorsList).toJson()); - return reply; -} - -HttpReply *VendorsResource::getVendor(const VendorId &vendorId) const -{ - qCDebug(dcRest) << "Get vendor with id" << vendorId; - foreach (const Vendor &vendor, NymeaCore::instance()->deviceManager()->supportedVendors()) { - if (vendor.id() == vendorId) { - HttpReply *reply = createSuccessReply(); - reply->setHeader(HttpReply::ContentTypeHeader, "application/json; charset=\"utf-8\";"); - reply->setPayload(QJsonDocument::fromVariant(JsonTypes::packVendor(vendor, NymeaCore::instance()->configuration()->locale())).toJson()); - return reply; - } - } - return createDeviceErrorReply(HttpReply::NotFound, Device::DeviceErrorVendorNotFound); -} - -} - diff --git a/libnymea-core/servers/rest/vendorsresource.h b/libnymea-core/servers/rest/vendorsresource.h deleted file mode 100644 index 80f5b752..00000000 --- a/libnymea-core/servers/rest/vendorsresource.h +++ /dev/null @@ -1,59 +0,0 @@ -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - * * - * Copyright (C) 2015 Simon Stürz * - * * - * This file is part of nymea. * - * * - * nymea is free software: you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation, version 2 of the License. * - * * - * nymea is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with nymea. If not, see . * - * * - * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ - -#ifndef VENDORSRESOURCE_H -#define VENDORSRESOURCE_H - -#include -#include - -#include "jsonrpc/jsontypes.h" -#include "restresource.h" -#include "servers/httpreply.h" - -namespace nymeaserver { - -class HttpRequest; - -class VendorsResource : public RestResource -{ - Q_OBJECT -public: - explicit VendorsResource(QObject *parent = 0); - - QString name() const override; - - HttpReply *proccessRequest(const HttpRequest &request, const QStringList &urlTokens) override; - -private: - VendorId m_vendorId; - - // Process method - HttpReply *proccessGetRequest(const HttpRequest &request, const QStringList &urlTokens) override; - - // Get methods - HttpReply *getVendors() const; - HttpReply *getVendor(const VendorId &vendorId) const; - -}; - -} - -#endif // VENDORSRESOURCE_H diff --git a/libnymea-core/servers/webserver.cpp b/libnymea-core/servers/webserver.cpp index eaa8012e..8243ce44 100644 --- a/libnymea-core/servers/webserver.cpp +++ b/libnymea-core/servers/webserver.cpp @@ -76,7 +76,6 @@ #include "nymeacore.h" #include "httpreply.h" #include "httprequest.h" -#include "rest/restresource.h" #include "debugserverhandler.h" #include @@ -150,7 +149,7 @@ bool WebServer::verifyFile(QSslSocket *socket, const QString &fileName) // make sure the file exists if (!file.exists()) { qCWarning(dcWebServer()) << "requested file" << file.filePath() << "does not exist."; - HttpReply *reply = RestResource::createErrorReply(HttpReply::NotFound); + HttpReply *reply = HttpReply::createErrorReply(HttpReply::NotFound); reply->setClientId(m_clientList.key(socket)); sendHttpReply(reply); reply->deleteLater(); @@ -160,7 +159,7 @@ bool WebServer::verifyFile(QSslSocket *socket, const QString &fileName) // make sure the file is in the public directory if (!file.canonicalFilePath().startsWith(QDir(m_configuration.publicFolder).canonicalPath())) { qCWarning(dcWebServer()) << "Requested file" << file.fileName() << "is outside the public folder."; - HttpReply *reply = RestResource::createErrorReply(HttpReply::Forbidden); + HttpReply *reply = HttpReply::createErrorReply(HttpReply::Forbidden); reply->setClientId(m_clientList.key(socket)); sendHttpReply(reply); reply->deleteLater(); @@ -170,7 +169,7 @@ bool WebServer::verifyFile(QSslSocket *socket, const QString &fileName) // make sure we can read the file if (!file.isReadable()) { qCWarning(dcWebServer()) << "Requested file" << file.fileName() << "is not readable."; - HttpReply *reply = RestResource::createErrorReply(HttpReply::Forbidden); + HttpReply *reply = HttpReply::createErrorReply(HttpReply::Forbidden); reply->setClientId(m_clientList.key(socket)); reply->setPayload("403 Forbidden. File not readable"); sendHttpReply(reply); @@ -195,7 +194,7 @@ QString WebServer::fileName(const QString &query) HttpReply *WebServer::processIconRequest(const QString &fileName) { if (!fileName.endsWith(".png")) - return RestResource::createErrorReply(HttpReply::NotFound); + return HttpReply::createErrorReply(HttpReply::NotFound); QByteArray imageData; @@ -205,13 +204,13 @@ HttpReply *WebServer::processIconRequest(const QString &fileName) image.save(&buffer, "png"); if (!imageData.isEmpty()) { - HttpReply *reply = RestResource::createSuccessReply(); + HttpReply *reply = HttpReply::createSuccessReply(); reply->setHeader(HttpReply::ContentTypeHeader, "image/png"); reply->setPayload(imageData); return reply; } - return RestResource::createErrorReply(HttpReply::NotFound); + return HttpReply::createErrorReply(HttpReply::NotFound); } void WebServer::incomingConnection(qintptr socketDescriptor) @@ -309,7 +308,7 @@ void WebServer::readClient() // Check if the request is valid if (!request.isValid()) { qCWarning(dcWebServer()) << "Got invalid request:" << request.url().path(); - HttpReply *reply = RestResource::createErrorReply(HttpReply::BadRequest); + HttpReply *reply = HttpReply::createErrorReply(HttpReply::BadRequest); reply->setClientId(clientId); sendHttpReply(reply); reply->deleteLater(); @@ -319,7 +318,7 @@ void WebServer::readClient() // Check HTTP version if (request.httpVersion() != "HTTP/1.1" && request.httpVersion() != "HTTP/1.0") { qCWarning(dcWebServer()) << "HTTP version is not supported." << request.httpVersion(); - HttpReply *reply = RestResource::createErrorReply(HttpReply::HttpVersionNotSupported); + HttpReply *reply = HttpReply::createErrorReply(HttpReply::HttpVersionNotSupported); reply->setClientId(clientId); sendHttpReply(reply); reply->deleteLater(); @@ -338,7 +337,7 @@ void WebServer::readClient() // Verify method if (request.method() == HttpRequest::Unhandled) { - HttpReply *reply = RestResource::createErrorReply(HttpReply::MethodNotAllowed); + HttpReply *reply = HttpReply::createErrorReply(HttpReply::MethodNotAllowed); reply->setClientId(clientId); reply->setHeader(HttpReply::AllowHeader, "GET, PUT, POST, DELETE, OPTIONS"); sendHttpReply(reply); @@ -346,21 +345,6 @@ void WebServer::readClient() return; } - // Verify API query - if (request.url().path().startsWith("/api/v1")) { - if (m_configuration.restServerEnabled) { - emit httpRequestReady(clientId, request); - return; - } else { - qCWarning(dcWebServer()) << "The REST server is disabled. You can enable it by adding \'restServerEnabled=true\' in the WebServer section of the nymead.conf file."; - HttpReply *reply = RestResource::createErrorReply(HttpReply::NotFound); - reply->setClientId(clientId); - sendHttpReply(reply); - reply->deleteLater(); - return; - } - } - // Check icon call if (request.url().path().startsWith("/icons/") && request.method() == HttpRequest::Get) { HttpReply *reply = processIconRequest(request.url().path()); @@ -376,7 +360,7 @@ void WebServer::readClient() if (NymeaCore::instance()->configuration()->debugServerEnabled()) { // Verify methods if (request.method() != HttpRequest::Get && request.method() != HttpRequest::Options) { - HttpReply *reply = RestResource::createErrorReply(HttpReply::MethodNotAllowed); + HttpReply *reply = HttpReply::createErrorReply(HttpReply::MethodNotAllowed); reply->setClientId(clientId); reply->setHeader(HttpReply::AllowHeader, "GET, OPTIONS"); sendHttpReply(reply); @@ -399,7 +383,7 @@ void WebServer::readClient() return; } else { qCWarning(dcWebServer()) << "The debug server handler is disabled. You can enable it by adding \'debugServerEnabled=true\' in the \'nymead\' section of the nymead.conf file."; - HttpReply *reply = RestResource::createErrorReply(HttpReply::NotFound); + HttpReply *reply = HttpReply::createErrorReply(HttpReply::NotFound); reply->setClientId(clientId); sendHttpReply(reply); reply->deleteLater(); @@ -410,7 +394,7 @@ void WebServer::readClient() // Check server.xml call if (request.url().path() == "/server.xml" && request.method() == HttpRequest::Get) { qCDebug(dcWebServer()) << "Server XML request call"; - HttpReply *reply = RestResource::createSuccessReply(); + HttpReply *reply = HttpReply::createSuccessReply(); reply->setHeader(HttpReply::ContentTypeHeader, "text/xml"); reply->setPayload(createServerXmlDocument(socket->localAddress())); reply->setClientId(clientId); @@ -426,7 +410,7 @@ void WebServer::readClient() // FIXME: return a default webpage containing server information if (!QDir(m_configuration.publicFolder).exists()) { qCWarning(dcWebServer()) << "Webinterface folder" << m_configuration.publicFolder << "does not exist."; - HttpReply *reply = RestResource::createErrorReply(HttpReply::NotFound); + HttpReply *reply = HttpReply::createErrorReply(HttpReply::NotFound); reply->setClientId(clientId); sendHttpReply(reply); reply->deleteLater(); @@ -440,7 +424,7 @@ void WebServer::readClient() QFile file(path); if (file.open(QFile::ReadOnly | QFile::Truncate)) { qCDebug(dcWebServer()) << "Load file" << file.fileName(); - HttpReply *reply = RestResource::createSuccessReply(); + HttpReply *reply = HttpReply::createSuccessReply(); // Check content type if (file.fileName().endsWith(".html")) { @@ -477,7 +461,7 @@ void WebServer::readClient() // Reject everything else... qCWarning(dcWebServer()) << "Unknown message received."; - HttpReply *reply = RestResource::createErrorReply(HttpReply::NotImplemented); + HttpReply *reply = HttpReply::createErrorReply(HttpReply::NotImplemented); reply->setClientId(clientId); sendHttpReply(reply); reply->deleteLater(); diff --git a/tests/auto/auto.pro b/tests/auto/auto.pro index df2d8ec4..fbf1e9d6 100644 --- a/tests/auto/auto.pro +++ b/tests/auto/auto.pro @@ -9,16 +9,10 @@ SUBDIRS = versioning \ rules \ plugins \ webserver \ - restdevices \ - restdeviceclasses \ - restplugins \ - restvendors \ - restrules \ websocketserver \ logging \ loggingdirect \ loggingloading \ - restlogging \ #coap \ # temporary removed until fixed configurations \ timemanager \ diff --git a/tests/auto/restdeviceclasses/restdeviceclasses.pro b/tests/auto/restdeviceclasses/restdeviceclasses.pro deleted file mode 100644 index 478e30cc..00000000 --- a/tests/auto/restdeviceclasses/restdeviceclasses.pro +++ /dev/null @@ -1,5 +0,0 @@ -include(../../../nymea.pri) -include(../autotests.pri) - -TARGET = restdeviceclasses -SOURCES += testrestdeviceclasses.cpp diff --git a/tests/auto/restdeviceclasses/testrestdeviceclasses.cpp b/tests/auto/restdeviceclasses/testrestdeviceclasses.cpp deleted file mode 100644 index a0c1bb35..00000000 --- a/tests/auto/restdeviceclasses/testrestdeviceclasses.cpp +++ /dev/null @@ -1,338 +0,0 @@ -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - * * - * Copyright (C) 2015 Simon Stürz * - * * - * This file is part of nymea. * - * * - * nymea is free software: you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation, version 2 of the License. * - * * - ** - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with nymea. If not, see . * - * * - * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ - -#include "nymeatestbase.h" -#include "nymeacore.h" - -using namespace nymeaserver; - -class TestRestDeviceClasses: public NymeaTestBase -{ - Q_OBJECT - -private slots: - void initTestCase(); - - void getSupportedDevices(); - - void invalidMethod(); - - void getActionTypes_data(); - void getActionTypes(); - - void getStateTypes_data(); - void getStateTypes(); - - void getEventTypes_data(); - void getEventTypes(); - - void discoverDevices_data(); - void discoverDevices(); - -}; - -#include "testrestdeviceclasses.moc" - -void TestRestDeviceClasses::initTestCase() -{ - NymeaTestBase::initTestCase(); - - QLoggingCategory::setFilterRules("*.debug=false\n" - "Tests.debug=true\n" - "Rest.debug=true\n" - "WebServer.debug=true\n" - "MockDevice.debug=true"); - - foreach (const WebServerConfiguration &config, NymeaCore::instance()->configuration()->webServerConfigurations()) { - if (config.port == 3333 && (config.address == QHostAddress("127.0.0.1") || config.address == QHostAddress("0.0.0.0"))) { - qDebug() << "Already have a webserver listening on 127.0.0.1:3333"; - return; - } - } - - qDebug() << "Creating new webserver instance on 127.0.0.1:3333"; - WebServerConfiguration config; - config.address = QHostAddress("127.0.0.1"); - config.port = 3333; - config.sslEnabled = true; - config.restServerEnabled = true; - NymeaCore::instance()->configuration()->setWebServerConfiguration(config); - qApp->processEvents(); -} - -void TestRestDeviceClasses::getSupportedDevices() -{ - // Get all deviceclasses - QUrl url("https://localhost:3333/api/v1/deviceclasses"); - QVariant response = getAndWait(QNetworkRequest(url)); - QVariantList deviceClassesList = response.toList(); - QVERIFY2(deviceClassesList.count() > 0, "Not enough deviceclasses."); - - // Get each of thouse devices individualy - foreach (const QVariant &deviceClass, deviceClassesList) { - QVariantMap deviceClassMap = deviceClass.toMap(); - QNetworkRequest request; - request.setHeader(QNetworkRequest::ContentTypeHeader, "text/json"); - request.setUrl(QUrl(QString("https://localhost:3333/api/v1/deviceclasses/%1").arg(deviceClassMap.value("id").toString()))); - - response = getAndWait(request); - QVERIFY2(!response.isNull(), "Could not get device"); - } - - // get with vendor filter - QUrlQuery query; - query.addQueryItem("vendorId", guhVendorId.toString()); - url.setQuery(query); - - response = getAndWait(QNetworkRequest(url)); - deviceClassesList = response.toList(); - QVERIFY2(deviceClassesList.count() > 0, "Not enough deviceclasses."); - - // get with invalid vendor filter - query.clear(); - query.addQueryItem("vendorId", "uuid"); - url.setQuery(query); - - response = getAndWait(QNetworkRequest(url), 400); - QCOMPARE(JsonTypes::deviceErrorToString(Device::DeviceErrorVendorNotFound), response.toMap().value("error").toString()); -} - -void TestRestDeviceClasses::invalidMethod() -{ - QNetworkAccessManager nam; - connect(&nam, &QNetworkAccessManager::sslErrors, [this, &nam](QNetworkReply *reply, const QList &) { - reply->ignoreSslErrors(); - }); - QSignalSpy clientSpy(&nam, SIGNAL(finished(QNetworkReply*))); - - QNetworkRequest request; - request.setUrl(QUrl("https://localhost:3333/api/v1/deviceclasses/")); - QNetworkReply *reply = nam.post(request, QByteArray()); - - clientSpy.wait(); - QVERIFY2(clientSpy.count() != 0, "expected at least 1 response from webserver"); - - bool ok = false; - int statusCode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(&ok); - QVERIFY2(ok, "Could not convert statuscode from response to int"); - QCOMPARE(statusCode, 400); - - reply->deleteLater(); -} - -void TestRestDeviceClasses::getActionTypes_data() -{ - QTest::addColumn("deviceClassId"); - QTest::addColumn("actionTypeId"); - QTest::addColumn("expectedStatusCode"); - QTest::addColumn("error"); - - QTest::newRow("all ActionTypes") << mockDeviceClassId.toString() << QString() << 200 << Device::DeviceErrorNoError; - QTest::newRow("ActionType async") << mockDeviceClassId.toString() << mockAsyncActionTypeId.toString() << 200 << Device::DeviceErrorNoError; - QTest::newRow("ActionType no params") << mockDeviceClassId.toString() << mockWithoutParamsActionTypeId.toString() << 200 << Device::DeviceErrorNoError; - QTest::newRow("ActionType failing") << mockDeviceClassId.toString() << mockFailingActionTypeId.toString() << 200 << Device::DeviceErrorNoError; - QTest::newRow("ActionType with params") << mockDeviceClassId.toString() << mockWithParamsActionTypeId.toString() << 200 << Device::DeviceErrorNoError; - QTest::newRow("invalid DeviceClassId") << DeviceClassId::createDeviceClassId().toString() << mockWithoutParamsActionTypeId.toString() << 404 << Device::DeviceErrorDeviceClassNotFound; - QTest::newRow("invalid ActionTypeId") << mockDeviceClassId.toString() << ActionTypeId::createActionTypeId().toString() << 404 << Device::DeviceErrorActionTypeNotFound; - QTest::newRow("invalid ActionTypeId format") << mockDeviceClassId.toString() << "uuid" << 400 << Device::DeviceErrorActionTypeNotFound; - QTest::newRow("invalid DeviceClassId format") << "uuid" << "uuid" << 400 << Device::DeviceErrorDeviceClassNotFound; - -} - -void TestRestDeviceClasses::getActionTypes() -{ - QFETCH(QString, deviceClassId); - QFETCH(QString, actionTypeId); - QFETCH(int, expectedStatusCode); - QFETCH(Device::DeviceError, error); - - QNetworkRequest request; - if (!actionTypeId.isEmpty()) { - request.setUrl(QUrl(QString("https://localhost:3333/api/v1/deviceclasses/%1/actiontypes/%2").arg(deviceClassId).arg(actionTypeId))); - } else { - // Get all actiontypes - request.setUrl(QUrl(QString("https://localhost:3333/api/v1/deviceclasses/%1/actiontypes").arg(deviceClassId))); - } - - QVariant response = getAndWait(request, expectedStatusCode); - QVERIFY2(!response.isNull(), "Could not read get action type response"); - if (expectedStatusCode != 200) - QCOMPARE(JsonTypes::deviceErrorToString(error), response.toMap().value("error").toString()); - -} - -void TestRestDeviceClasses::getStateTypes_data() -{ - QTest::addColumn("deviceClassId"); - QTest::addColumn("stateTypeId"); - QTest::addColumn("expectedStatusCode"); - QTest::addColumn("error"); - - QTest::newRow("all ActionTypes") << mockDeviceClassId.toString() << QString() << 200 << Device::DeviceErrorNoError; - QTest::newRow("StateType bool") << mockDeviceClassId.toString() << mockBoolStateTypeId.toString() << 200 << Device::DeviceErrorNoError; - QTest::newRow("StateType int") << mockDeviceClassId.toString() << mockIntStateTypeId.toString() << 200 << Device::DeviceErrorNoError; - QTest::newRow("invalid DeviceClassId") << DeviceClassId::createDeviceClassId().toString() << mockBoolStateTypeId.toString() << 404 << Device::DeviceErrorDeviceClassNotFound; - QTest::newRow("invalid StateTypeId") << mockDeviceClassId.toString() << StateTypeId::createStateTypeId().toString() << 404 << Device::DeviceErrorStateTypeNotFound; - QTest::newRow("invalid StateTypeId format") << mockDeviceClassId.toString() << "uuid" << 400 << Device::DeviceErrorStateTypeNotFound; - QTest::newRow("invalid DeviceClassId format") << "uuid" << "uuid" << 400 << Device::DeviceErrorDeviceClassNotFound; -} - -void TestRestDeviceClasses::getStateTypes() -{ - QFETCH(QString, deviceClassId); - QFETCH(QString, stateTypeId); - QFETCH(int, expectedStatusCode); - QFETCH(Device::DeviceError, error); - - QNetworkRequest request; - if (!stateTypeId.isEmpty()) { - request.setUrl(QUrl(QString("https://localhost:3333/api/v1/deviceclasses/%1/statetypes/%2").arg(deviceClassId).arg(stateTypeId))); - } else { - // Get all actiontypes - request.setUrl(QUrl(QString("https://localhost:3333/api/v1/deviceclasses/%1/statetypes").arg(deviceClassId))); - } - - QVariant response = getAndWait(request, expectedStatusCode); - QVERIFY2(!response.isNull(), "Could not read get action type response"); - if (expectedStatusCode != 200) - QCOMPARE(JsonTypes::deviceErrorToString(error), response.toMap().value("error").toString()); - -} - -void TestRestDeviceClasses::getEventTypes_data() -{ - QTest::addColumn("deviceClassId"); - QTest::addColumn("eventTypeId"); - QTest::addColumn("expectedStatusCode"); - QTest::addColumn("error"); - - QTest::newRow("all ActionTypes") << mockDeviceClassId.toString() << QString() << 200 << Device::DeviceErrorNoError; - QTest::newRow("EventType 1") << mockDeviceClassId.toString() << mockEvent1EventTypeId.toString() << 200 << Device::DeviceErrorNoError; - QTest::newRow("EventType 2") << mockDeviceClassId.toString() << mockEvent2EventTypeId.toString() << 200 << Device::DeviceErrorNoError; - QTest::newRow("invalid DeviceClassId") << DeviceClassId::createDeviceClassId().toString() << mockEvent2EventTypeId.toString() << 404 << Device::DeviceErrorDeviceClassNotFound; - QTest::newRow("invalid EventTypeId") << mockDeviceClassId.toString() << EventTypeId::createEventTypeId().toString() << 404 << Device::DeviceErrorEventTypeNotFound; - QTest::newRow("invalid EventTypeId format") << mockDeviceClassId.toString() << "uuid" << 400 << Device::DeviceErrorEventTypeNotFound; - QTest::newRow("invalid DeviceClassId format") << "uuid" << "uuid" << 400 << Device::DeviceErrorDeviceClassNotFound; -} - -void TestRestDeviceClasses::getEventTypes() -{ - QFETCH(QString, deviceClassId); - QFETCH(QString, eventTypeId); - QFETCH(int, expectedStatusCode); - QFETCH(Device::DeviceError, error); - - QNetworkRequest request; - if (!eventTypeId.isNull()) { - request.setUrl(QUrl(QString("https://localhost:3333/api/v1/deviceclasses/%1/eventtypes/%2").arg(deviceClassId).arg(eventTypeId))); - } else { - // Get all actiontypes - request.setUrl(QUrl(QString("https://localhost:3333/api/v1/deviceclasses/%1/eventtypes").arg(deviceClassId))); - } - - QVariant response = getAndWait(request, expectedStatusCode); - QVERIFY2(!response.isNull(), "Could not read get action type response"); - if (expectedStatusCode != 200) - QCOMPARE(JsonTypes::deviceErrorToString(error), response.toMap().value("error").toString()); - -} - -void TestRestDeviceClasses::discoverDevices_data() -{ - QTest::addColumn("deviceClassId"); - QTest::addColumn("resultCount"); - QTest::addColumn("discoveryParams"); - QTest::addColumn("expectedStatusCode"); - QTest::addColumn("error"); - - QVariantMap resultCountParam; - resultCountParam.insert("paramTypeId", mockDiscoveryResultCountParamTypeId); - resultCountParam.insert("value", 1); - - QVariantMap invalidResultCountParam; - invalidResultCountParam.insert("paramTypeId", mockDiscoveryResultCountParamTypeId); - invalidResultCountParam.insert("value", 10); - - QVariantList discoveryParams; - discoveryParams.append(resultCountParam); - - QVariantList invalidDiscoveryParams; - invalidDiscoveryParams.append(invalidResultCountParam); - - QTest::newRow("valid deviceClassId without params") << mockDeviceClassId << 2 << QVariantList() << 200 << Device::DeviceErrorNoError; - QTest::newRow("valid deviceClassId with params") << mockDeviceClassId << 1 << discoveryParams << 200 << Device::DeviceErrorNoError; - QTest::newRow("invalid deviceClassId") << DeviceClassId::createDeviceClassId() << 0 << QVariantList() << 404 << Device::DeviceErrorDeviceClassNotFound; - QTest::newRow("valid deviceClassId with invalid params") << mockDeviceClassId << 10 << invalidDiscoveryParams << 500 << Device::DeviceErrorInvalidParameter; -} - -void TestRestDeviceClasses::discoverDevices() -{ - QFETCH(DeviceClassId, deviceClassId); - QFETCH(int, resultCount); - QFETCH(QVariantList, discoveryParams); - QFETCH(int, expectedStatusCode); - QFETCH(Device::DeviceError, error); - - QVariantMap params; - params.insert("deviceClassId", deviceClassId); - params.insert("discoveryParams", discoveryParams); - - // DISCOVER - QUrl url(QString("https://localhost:3333/api/v1/deviceclasses/%1/discover").arg(deviceClassId.toString())); - if (!discoveryParams.isEmpty()) { - QUrlQuery query; - query.addQueryItem("params", QJsonDocument::fromVariant(discoveryParams).toJson(QJsonDocument::Compact)); - url.setQuery(query); - } - - QVariant response = getAndWait(QNetworkRequest(url), expectedStatusCode); - QVERIFY2(!response.isNull(), "Could not read response"); - - if (expectedStatusCode != 200) { - QCOMPARE(JsonTypes::deviceErrorToString(error), response.toMap().value("error").toString()); - return; - } - - // check response - QVariantList foundDevices = response.toList(); - QCOMPARE(foundDevices.count(), resultCount); - - // ADD the discovered device - QNetworkRequest request(QUrl("https://localhost:3333/api/v1/devices")); - request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json"); - DeviceDescriptorId descriptorId = DeviceDescriptorId(foundDevices.first().toMap().value("id").toString()); - - params.clear(); - params.insert("deviceClassId", deviceClassId); - params.insert("deviceDescriptorId", descriptorId.toString()); - - response = postAndWait(request, params, expectedStatusCode); - QVERIFY2(!response.isNull(), "Could not read response"); - - DeviceId deviceId = DeviceId(response.toMap().value("id").toString()); - QVERIFY2(!deviceId.isNull(), "got invalid device id"); - - // REMOVE added device - request.setUrl(QUrl(QString("https://localhost:3333/api/v1/devices/%1").arg(deviceId.toString()))); - response = deleteAndWait(request); - QVERIFY2(!response.isNull(), "Could not delete device"); -} - -QTEST_MAIN(TestRestDeviceClasses) diff --git a/tests/auto/restdevices/restdevices.pro b/tests/auto/restdevices/restdevices.pro deleted file mode 100644 index 77977f8d..00000000 --- a/tests/auto/restdevices/restdevices.pro +++ /dev/null @@ -1,5 +0,0 @@ -include(../../../nymea.pri) -include(../autotests.pri) - -TARGET = restdevices -SOURCES += testrestdevices.cpp diff --git a/tests/auto/restdevices/testrestdevices.cpp b/tests/auto/restdevices/testrestdevices.cpp deleted file mode 100644 index e43a43c2..00000000 --- a/tests/auto/restdevices/testrestdevices.cpp +++ /dev/null @@ -1,805 +0,0 @@ -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - * * - * Copyright (C) 2015 Simon Stürz * - * * - * This file is part of nymea. * - * * - * nymea is free software: you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation, version 2 of the License. * - * * - ** - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with nymea. If not, see . * - * * - * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ - -#include "nymeatestbase.h" -#include "nymeacore.h" - -using namespace nymeaserver; - -class TestRestDevices: public NymeaTestBase -{ - Q_OBJECT - -private slots: - void initTestCase(); - - void getConfiguredDevices(); - - void addConfiguredDevice_data(); - void addConfiguredDevice(); - - void addPushButtonDevices_data(); - void addPushButtonDevices(); - - void addDisplayPinDevices_data(); - void addDisplayPinDevices(); - - void parentChildDevices(); - - void executeAction_data(); - void executeAction(); - - void getStateValue_data(); - void getStateValue(); - - void editDevices_data(); - void editDevices(); - - void reconfigureDevices_data(); - void reconfigureDevices(); - - void reconfigureByDiscovery_data(); - void reconfigureByDiscovery(); - -}; - -void TestRestDevices::initTestCase() -{ - NymeaTestBase::initTestCase(); - - QLoggingCategory::setFilterRules("*.debug=false\nTests.debug=true\nMockDevice.debug=true\nRest.debug=true"); - - foreach (const WebServerConfiguration &config, NymeaCore::instance()->configuration()->webServerConfigurations()) { - if (config.port == 3333 && (config.address == QHostAddress("127.0.0.1") || config.address == QHostAddress("0.0.0.0"))) { - qCWarning(dcTests()) << "Already have a webserver listening on 127.0.0.1:3333"; - return; - } - } - - qCDebug(dcTests()) << "Creating new webserver instance on 127.0.0.1:3333"; - WebServerConfiguration config; - config.address = QHostAddress("127.0.0.1"); - config.port = 3333; - config.sslEnabled = true; - config.restServerEnabled = true; - NymeaCore::instance()->configuration()->setWebServerConfiguration(config); - qApp->processEvents(); - -} - -void TestRestDevices::getConfiguredDevices() -{ - // Get all devices - QVariant response = getAndWait(QNetworkRequest(QUrl("https://localhost:3333/api/v1/devices"))); - QVERIFY2(!response.isNull(), "Could not get device"); - QVariantList deviceList = response.toList(); - QVERIFY2(deviceList.count() >= 2, "not enough devices."); - - // Get each of those devices individualy - foreach (const QVariant &device, deviceList) { - QVariantMap deviceMap = device.toMap(); - QNetworkRequest request(QUrl(QString("https://localhost:3333/api/v1/devices/%1").arg(deviceMap.value("id").toString()))); - response = getAndWait(request); - QVERIFY2(!response.isNull(), "Could not get device"); - } -} - -void TestRestDevices::addConfiguredDevice_data() -{ - QTest::addColumn("deviceClassId"); - QTest::addColumn("deviceParams"); - QTest::addColumn("expectedStatusCode"); - - QVariantMap httpportParam; - httpportParam.insert("paramTypeId", mockDeviceHttpportParamTypeId); - httpportParam.insert("value", m_mockDevice1Port - 1); - QVariantMap asyncParam; - asyncParam.insert("paramTypeId", mockDeviceAsyncParamTypeId); - asyncParam.insert("value", true); - QVariantMap notAsyncParam; - notAsyncParam.insert("paramTypeId", mockDeviceAsyncParamTypeId); - notAsyncParam.insert("value", false); - QVariantMap notBrokenParam; - notBrokenParam.insert("paramTypeId", mockDeviceBrokenParamTypeId); - notBrokenParam.insert("value", false); - QVariantMap brokenParam; - brokenParam.insert("paramTypeId", mockDeviceBrokenParamTypeId); - brokenParam.insert("value", true); - - QVariantList deviceParams; - - deviceParams.clear(); deviceParams << httpportParam << notAsyncParam << notBrokenParam; - QTest::newRow("User, JustAdd") << mockDeviceClassId << deviceParams << 200; - - deviceParams.clear(); deviceParams << httpportParam << asyncParam << notBrokenParam; - QTest::newRow("User, JustAdd, Async") << mockDeviceClassId << deviceParams << 200; - - QTest::newRow("Invalid DeviceClassId") << DeviceClassId::createDeviceClassId() << deviceParams << 500; - - deviceParams.clear(); deviceParams << httpportParam << brokenParam; - QTest::newRow("Setup failure") << mockDeviceClassId << deviceParams << 500; - - deviceParams.clear(); deviceParams << httpportParam << asyncParam << brokenParam; - QTest::newRow("Setup failure, Async") << mockDeviceClassId << deviceParams << 500; - - QVariantList invalidDeviceParams; - QTest::newRow("User, JustAdd, missing params") << mockDeviceClassId << invalidDeviceParams << 500; - - QVariantMap fakeparam; - fakeparam.insert("paramTypeId", ParamTypeId::createParamTypeId()); - invalidDeviceParams.append(fakeparam); - QTest::newRow("User, JustAdd, invalid param") << mockDeviceClassId << invalidDeviceParams << 500; - - fakeparam.insert("value", "buhuu"); - invalidDeviceParams.clear(); - invalidDeviceParams.append(fakeparam); - QTest::newRow("User, JustAdd, wrong param") << mockDeviceClassId << invalidDeviceParams << 500; -} - -void TestRestDevices::addConfiguredDevice() -{ - QFETCH(DeviceClassId, deviceClassId); - QFETCH(QVariantList, deviceParams); - QFETCH(int, expectedStatusCode); - - QVariantMap params; - params.insert("deviceClassId", deviceClassId); - params.insert("name", "Mock device"); - params.insert("deviceParams", deviceParams); - - QNetworkRequest request(QUrl("https://localhost:3333/api/v1/devices")); - request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json"); - - QVariant response = postAndWait(request, params, expectedStatusCode); - qDebug() << QJsonDocument::fromVariant(response).toJson(); - - QVERIFY2(!response.isNull(), "Could not add device"); - - if (expectedStatusCode == 200) { - // remove added device - DeviceId deviceId = DeviceId(response.toMap().value("id").toString()); - QVERIFY2(!deviceId.isNull(), "invalid device id for removing"); - - QNetworkRequest deleteRequest(QUrl(QString("https://localhost:3333/api/v1/devices/%1").arg(deviceId.toString()))); - response = deleteAndWait(deleteRequest); - QVERIFY2(!response.isNull(), "Could not delete device"); - } -} - -void TestRestDevices::addPushButtonDevices_data() -{ - QTest::addColumn("deviceClassId"); - QTest::addColumn("expectedStatusCode"); - QTest::addColumn("waitForButtonPressed"); - - QTest::newRow("Valid: Add PushButton device") << mockPushButtonDeviceClassId << 200 << true; - QTest::newRow("Invalid: Add PushButton device (press to early)") << mockPushButtonDeviceClassId << 500 << false; -} - -void TestRestDevices::addPushButtonDevices() -{ - QFETCH(DeviceClassId, deviceClassId); - QFETCH(int, expectedStatusCode); - QFETCH(bool, waitForButtonPressed); - - // Discover device - QVariantList discoveryParams; - QVariantMap resultCountParam; - resultCountParam.insert("paramTypeId", mockPushButtonDiscoveryResultCountParamTypeId); - resultCountParam.insert("value", 1); - discoveryParams.append(resultCountParam); - - // Discover - QVariantMap params; - params.insert("deviceClassId", deviceClassId); - params.insert("discoveryParams", discoveryParams); - - // create URL - QUrl url(QString("https://localhost:3333/api/v1/deviceclasses/%1/discover").arg(deviceClassId.toString())); - QUrlQuery query; - query.addQueryItem("params", QJsonDocument::fromVariant(discoveryParams).toJson(QJsonDocument::Compact)); - url.setQuery(query); - - QVariant response = getAndWait(QNetworkRequest(url)); - QVariantList foundDevices = response.toList(); - QCOMPARE(foundDevices.count(), 1); - - DeviceDescriptorId deviceDescriptoId(foundDevices.first().toMap().value("id").toString()); - - // Pair - params.clear(); - params.insert("deviceClassId", deviceClassId.toString()); - params.insert("name", "Push button mock device"); - params.insert("deviceDescriptorId", deviceDescriptoId); - - QNetworkRequest pairRequest(QUrl("https://localhost:3333/api/v1/devices/pair")); - pairRequest.setHeader(QNetworkRequest::ContentTypeHeader, "text/json"); - - response = postAndWait(pairRequest, params); - QVERIFY2(!response.isNull(), "Could not pair device"); - - PairingTransactionId pairingTransactionId(response.toMap().value("pairingTransactionId").toString()); - QString displayMessage = response.toMap().value("displayMessage").toString(); - - qDebug() << "displayMessage" << displayMessage; - - if (waitForButtonPressed) - QTest::qWait(3500); - - // Confirm pairing - params.clear(); - params.insert("pairingTransactionId", pairingTransactionId.toString()); - - QNetworkRequest confirmPairingRequest(QUrl("https://localhost:3333/api/v1/devices/confirmpairing")); - confirmPairingRequest.setHeader(QNetworkRequest::ContentTypeHeader, "text/json"); - - response = postAndWait(confirmPairingRequest, params, expectedStatusCode); - QVERIFY2(!response.isNull(), "Could not confirm pairing device"); - - if (expectedStatusCode == 200) { - // remove added device - DeviceId deviceId = DeviceId(response.toMap().value("id").toString()); - QVERIFY2(!deviceId.isNull(), "invalid device id for removing"); - - QNetworkRequest deleteRequest(QUrl(QString("https://localhost:3333/api/v1/devices/%1").arg(deviceId.toString()))); - response = deleteAndWait(deleteRequest); - QVERIFY2(!response.isNull(), "Could not delete device"); - } -} - -void TestRestDevices::addDisplayPinDevices_data() -{ - QTest::addColumn("deviceClassId"); - QTest::addColumn("expectedStatusCode"); - QTest::addColumn("secret"); - - QTest::newRow("Valid: Add DisplayPin device") << mockDisplayPinDeviceClassId << 200 << "243681"; - QTest::newRow("Invalid: Add DisplayPin device (wrong pin)") << mockDisplayPinDeviceClassId << 500 << "243682"; -} - -void TestRestDevices::addDisplayPinDevices() -{ - QFETCH(DeviceClassId, deviceClassId); - QFETCH(int, expectedStatusCode); - QFETCH(QString, secret); - - // Discover device - QVariantList discoveryParams; - QVariantMap resultCountParam; - resultCountParam.insert("paramTypeId", mockDisplayPinDiscoveryResultCountParamTypeId); - resultCountParam.insert("value", 1); - discoveryParams.append(resultCountParam); - - // Discover - QVariantMap params; - params.insert("deviceClassId", deviceClassId); - params.insert("discoveryParams", discoveryParams); - - // create URL - QUrl url(QString("https://localhost:3333/api/v1/deviceclasses/%1/discover").arg(deviceClassId.toString())); - QUrlQuery query; - query.addQueryItem("params", QJsonDocument::fromVariant(discoveryParams).toJson(QJsonDocument::Compact)); - url.setQuery(query); - - QVariant response = getAndWait(QNetworkRequest(url)); - QVariantList foundDevices = response.toList(); - QCOMPARE(foundDevices.count(), 1); - - DeviceDescriptorId deviceDescriptoId(foundDevices.first().toMap().value("id").toString()); - - // Pair - params.clear(); - params.insert("deviceClassId", deviceClassId.toString()); - params.insert("name", "Display pin mock device"); - params.insert("deviceDescriptorId", deviceDescriptoId); - - QNetworkRequest pairRequest(QUrl("https://localhost:3333/api/v1/devices/pair")); - pairRequest.setHeader(QNetworkRequest::ContentTypeHeader, "text/json"); - - response = postAndWait(pairRequest, params); - QVERIFY2(!response.isNull(), "Could not pair device"); - - PairingTransactionId pairingTransactionId(response.toMap().value("pairingTransactionId").toString()); - QString displayMessage = response.toMap().value("displayMessage").toString(); - - qDebug() << "displayMessage" << displayMessage; - - // Confirm pairing - params.clear(); - params.insert("pairingTransactionId", pairingTransactionId.toString()); - params.insert("secret", secret); - - QNetworkRequest confirmPairingRequest(QUrl("https://localhost:3333/api/v1/devices/confirmpairing")); - confirmPairingRequest.setHeader(QNetworkRequest::ContentTypeHeader, "text/json"); - - response = postAndWait(confirmPairingRequest, params, expectedStatusCode); - QVERIFY2(!response.isNull(), "Could not confirm pairing device"); - - if (expectedStatusCode == 200) { - // remove added device - DeviceId deviceId = DeviceId(response.toMap().value("id").toString()); - QVERIFY2(!deviceId.isNull(), "invalid device id for removing"); - - QNetworkRequest deleteRequest(QUrl(QString("https://localhost:3333/api/v1/devices/%1").arg(deviceId.toString()))); - response = deleteAndWait(deleteRequest); - QVERIFY2(!response.isNull(), "Could not delete device"); - } -} - -void TestRestDevices::parentChildDevices() -{ - // Add parent device - QVariantMap params; - params.insert("deviceClassId", mockParentDeviceClassId); - - QNetworkRequest request(QUrl(QString("https://localhost:3333/api/v1/devices"))); - request.setHeader(QNetworkRequest::ContentTypeHeader, "text/json"); - QVariant response = postAndWait(request, params); - QVERIFY2(!response.isNull(), "Could not read add device response"); - - DeviceId parentDeviceId = DeviceId(response.toMap().value("id").toString()); - QVERIFY2(parentDeviceId != DeviceId(), "DeviceId not returned"); - - // find child device - response = getAndWait(QNetworkRequest(QUrl("https://localhost:3333/api/v1/devices"))); - QVariantList deviceList = response.toList(); - DeviceId childDeviceId; - foreach (const QVariant deviceVariant, deviceList) { - QVariantMap deviceMap = deviceVariant.toMap(); - if (deviceMap.value("deviceClassId").toString() == mockChildDeviceClassId.toString()) { - if (deviceMap.value("parentId") == parentDeviceId.toString()) { - childDeviceId = DeviceId(deviceMap.value("id").toString()); - } - } - } - QVERIFY2(!childDeviceId.isNull(), "Could not find child device"); - - // try to remove child device - QNetworkRequest deleteRequest(QUrl(QString("https://localhost:3333/api/v1/devices/%1").arg(childDeviceId.toString()))); - response = deleteAndWait(deleteRequest, 400); - //QVERIFY2(!response.isNull(), "Could not delete device"); - QCOMPARE(JsonTypes::deviceErrorToString(Device::DeviceErrorDeviceIsChild), response.toMap().value("error").toString()); - - // check if the child device is still there - response = getAndWait(QNetworkRequest(QUrl("https://localhost:3333/api/v1/devices"))); - deviceList = response.toList(); - bool found = false; - foreach (const QVariant deviceVariant, deviceList) { - QVariantMap deviceMap = deviceVariant.toMap(); - if (deviceMap.value("deviceClassId").toString() == mockChildDeviceClassId.toString()) { - if (deviceMap.value("id") == childDeviceId.toString()) { - found = true; - break; - } - } - } - QVERIFY2(found, "Could not find child device."); - - // remove the parent device - deleteRequest.setUrl(QUrl(QString("https://localhost:3333/api/v1/devices/%1").arg(parentDeviceId.toString()))); - response = deleteAndWait(deleteRequest); - QVERIFY2(!response.isNull(), "Could not delete device"); - - // check if the child device is still there - response = getAndWait(QNetworkRequest(QUrl("https://localhost:3333/api/v1/devices"))); - deviceList = response.toList(); - found = false; - foreach (const QVariant deviceVariant, deviceList) { - QVariantMap deviceMap = deviceVariant.toMap(); - if (deviceMap.value("deviceClassId").toString() == mockChildDeviceClassId.toString()) { - if (deviceMap.value("id") == childDeviceId.toString()) { - found = true; - break; - } - } - } - QVERIFY2(!found, "Could not find child device."); -} - -void TestRestDevices::executeAction_data() -{ - QTest::addColumn("deviceId"); - QTest::addColumn("actionTypeId"); - QTest::addColumn("actionParams"); - QTest::addColumn("expectedStatusCode"); - QTest::addColumn("error"); - - QVariantList params; - QVariantMap param1; - param1.insert("paramTypeId", mockWithParamsActionParam1ParamTypeId); - param1.insert("value", 5); - params.append(param1); - QVariantMap param2; - param2.insert("paramTypeId", mockWithParamsActionParam2ParamTypeId); - param2.insert("value", true); - params.append(param2); - - QTest::newRow("valid action") << m_mockDeviceId << mockWithParamsActionTypeId << params << 200 << Device::DeviceErrorNoError; - QTest::newRow("invalid deviceId") << DeviceId::createDeviceId() << mockWithParamsActionTypeId << params << 404 << Device::DeviceErrorDeviceNotFound; - QTest::newRow("invalid actionTypeId") << m_mockDeviceId << ActionTypeId::createActionTypeId() << params << 404 << Device::DeviceErrorActionTypeNotFound; - QTest::newRow("missing params") << m_mockDeviceId << mockWithParamsActionTypeId << QVariantList() << 500 << Device::DeviceErrorMissingParameter; - QTest::newRow("async action") << m_mockDeviceId << mockAsyncActionTypeId << QVariantList() << 200 << Device::DeviceErrorNoError; - QTest::newRow("broken action") << m_mockDeviceId << mockFailingActionTypeId << QVariantList() << 500 << Device::DeviceErrorSetupFailed; - QTest::newRow("async broken action") << m_mockDeviceId << mockAsyncFailingActionTypeId << QVariantList() << 500 << Device::DeviceErrorSetupFailed; -} - -void TestRestDevices::executeAction() -{ - QFETCH(DeviceId, deviceId); - QFETCH(ActionTypeId, actionTypeId); - QFETCH(QVariantList, actionParams); - QFETCH(int, expectedStatusCode); - QFETCH(Device::DeviceError, error); - - // execute action - QVariantMap params; - params.insert("params", actionParams); - - QNetworkRequest request(QUrl(QString("https://localhost:3333/api/v1/devices/%1/execute/%2").arg(deviceId.toString()).arg(actionTypeId.toString()))); - request.setHeader(QNetworkRequest::ContentTypeHeader, "text/json"); - QVariant response = postAndWait(request, params, expectedStatusCode); - QVERIFY2(!response.isNull(), "Could not read execute action response"); - QCOMPARE(JsonTypes::deviceErrorToString(error), response.toMap().value("error").toString()); - - // Fetch action execution history from mock device - QNetworkAccessManager nam; - QSignalSpy spy(&nam, SIGNAL(finished(QNetworkReply*))); - - request.setUrl(QUrl(QString("http://localhost:%1/actionhistory").arg(m_mockDevice1Port))); - QNetworkReply *reply = nam.get(request); - spy.wait(); - QCOMPARE(spy.count(), 1); - reply->deleteLater(); - QByteArray data = reply->readAll(); - - if (error == Device::DeviceErrorNoError) { - QVERIFY2(actionTypeId == ActionTypeId(data), QString("ActionTypeId mismatch. Got %1, Expected: %2") - .arg(ActionTypeId(data).toString()).arg(actionTypeId.toString()).toLatin1().data()); - } else { - QVERIFY2(data.length() == 0, QString("Data is %1, should be empty.").arg(QString(data)).toLatin1().data()); - } - - // cleanup for the next run - spy.clear(); - request.setUrl(QUrl(QString("http://localhost:%1/clearactionhistory").arg(m_mockDevice1Port))); - reply = nam.get(request); - spy.wait(); - QCOMPARE(spy.count(), 1); - reply->deleteLater(); - - spy.clear(); - request.setUrl(QUrl(QString("http://localhost:%1/actionhistory").arg(m_mockDevice1Port))); - reply = nam.get(request); - spy.wait(); - QCOMPARE(spy.count(), 1); - reply->deleteLater(); - data = reply->readAll(); - qDebug() << "cleared data:" << data; -} - -void TestRestDevices::getStateValue_data() -{ - QList devices = NymeaCore::instance()->deviceManager()->findConfiguredDevices(mockDeviceClassId); - QVERIFY2(devices.count() > 0, "There needs to be at least one configured Mock Device for this test"); - Device *device = devices.first(); - - QTest::addColumn("deviceId"); - QTest::addColumn("stateTypeId"); - QTest::addColumn("expectedStatusCode"); - QTest::addColumn("error"); - - QTest::newRow("existing state") << device->id().toString() << mockIntStateTypeId.toString() << 200 << Device::DeviceErrorNoError; - QTest::newRow("all states") << device->id().toString() << QString() << 200 << Device::DeviceErrorNoError; - QTest::newRow("invalid device") << DeviceId::createDeviceId().toString() << mockIntStateTypeId.toString() << 404 << Device::DeviceErrorDeviceNotFound; - QTest::newRow("invalid device id format") << "uuid" << StateTypeId::createStateTypeId().toString() << 400 << Device::DeviceErrorDeviceNotFound; - QTest::newRow("invalid statetype") << device->id().toString() << StateTypeId::createStateTypeId().toString() << 404 << Device::DeviceErrorStateTypeNotFound; - QTest::newRow("invalid statetype format") << device->id().toString() << "uuid" << 400 << Device::DeviceErrorStateTypeNotFound; -} - -void TestRestDevices::getStateValue() -{ - QFETCH(QString, deviceId); - QFETCH(QString, stateTypeId); - QFETCH(int, expectedStatusCode); - QFETCH(Device::DeviceError, error); - - QNetworkRequest request; - request.setHeader(QNetworkRequest::ContentTypeHeader, "text/json"); - - if (!stateTypeId.isNull()) { - request.setUrl(QUrl(QString("https://localhost:3333/api/v1/devices/%1/states/%2").arg(deviceId).arg(stateTypeId))); - } else { - // Get all states - request.setUrl(QUrl(QString("https://localhost:3333/api/v1/devices/%1/states").arg(deviceId))); - } - QVariant response = getAndWait(request, expectedStatusCode); - QVERIFY2(!response.isNull(), "Could not read get state value response"); - if (expectedStatusCode != 200) - QCOMPARE(JsonTypes::deviceErrorToString(error), response.toMap().value("error").toString()); - -} - -void TestRestDevices::editDevices_data() -{ - QTest::addColumn("name"); - - QTest::newRow("change name") << "New device name"; - QTest::newRow("change name") << "Foo device"; - QTest::newRow("change name") << "Bar device"; -} - -void TestRestDevices::editDevices() -{ - QFETCH(QString, name); - QString originalName = "Test device"; - - QVariantList deviceParams; - QVariantMap httpportParam; - httpportParam.insert("paramTypeId", mockDeviceHttpportParamTypeId); - httpportParam.insert("value", m_mockDevice1Port - 2); - deviceParams.append(httpportParam); - - QVariantMap params; - params.insert("deviceClassId", mockDeviceClassId.toString()); - params.insert("name", originalName); - params.insert("deviceParams", deviceParams); - - QNetworkRequest addRequest(QUrl("https://localhost:3333/api/v1/devices")); - addRequest.setHeader(QNetworkRequest::ContentTypeHeader, "application/json"); - - QVariant response = postAndWait(addRequest, params); - DeviceId deviceId = DeviceId(response.toMap().value("id").toString()); - QVERIFY2(!deviceId.isNull(), "invalid device id"); - - // edit device - params.clear(); - params.insert("name", name); - - QNetworkRequest deviceRequest(QUrl(QString("https://localhost:3333/api/v1/devices/%1").arg(deviceId.toString()))); - deviceRequest.setHeader(QNetworkRequest::ContentTypeHeader, "application/json"); - - response = postAndWait(deviceRequest, params); - QVERIFY2(response.toMap().value("error").toString() == JsonTypes::deviceErrorToString(Device::DeviceErrorNoError), "Could not edit device name"); - - // check device name - response = getAndWait(deviceRequest); - QCOMPARE(response.toMap().value("name").toString(), name); - - // Remove the device - response = deleteAndWait(deviceRequest); - QVERIFY2(response.toMap().value("error").toString() == JsonTypes::deviceErrorToString(Device::DeviceErrorNoError), "Could not remove device"); -} - -void TestRestDevices::reconfigureDevices_data() -{ - QVariantList asyncChangeDeviceParams; - QVariantMap asyncParamDifferent; - asyncParamDifferent.insert("paramTypeId", mockDeviceAsyncParamTypeId); - asyncParamDifferent.insert("value", true); - asyncChangeDeviceParams.append(asyncParamDifferent); - - QVariantList httpportChangeDeviceParams; - QVariantMap httpportParamDifferent; - httpportParamDifferent.insert("paramTypeId", mockDeviceHttpportParamTypeId); - httpportParamDifferent.insert("value", 8895); // if change -> change also newPort in reconfigureDevices() - httpportChangeDeviceParams.append(httpportParamDifferent); - - QVariantList brokenChangedDeviceParams; - QVariantMap brokenParamDifferent; - brokenParamDifferent.insert("paramTypeId", mockDeviceBrokenParamTypeId); - brokenParamDifferent.insert("value", true); - brokenChangedDeviceParams.append(brokenParamDifferent); - - QVariantList asyncAndPortChangeDeviceParams; - asyncAndPortChangeDeviceParams.append(asyncParamDifferent); - asyncAndPortChangeDeviceParams.append(httpportParamDifferent); - - QVariantList changeAllWritableDeviceParams; - changeAllWritableDeviceParams.append(asyncParamDifferent); - changeAllWritableDeviceParams.append(httpportParamDifferent); - - QTest::addColumn("broken"); - QTest::addColumn("newDeviceParams"); - QTest::addColumn("expectedStatusCode"); - QTest::addColumn("error"); - - QTest::newRow("invalid - change async param") << false << asyncChangeDeviceParams << 500 << Device::DeviceErrorParameterNotWritable; - QTest::newRow("valid - change httpport param") << false << httpportChangeDeviceParams << 200 << Device::DeviceErrorNoError; - QTest::newRow("valid - change httpport and async param") << false << asyncAndPortChangeDeviceParams << 500 << Device::DeviceErrorParameterNotWritable; - QTest::newRow("invalid - change all params (except broken)") << false << changeAllWritableDeviceParams << 500 << Device::DeviceErrorParameterNotWritable; -} - -void TestRestDevices::reconfigureDevices() -{ - QFETCH(bool, broken); - QFETCH(QVariantList, newDeviceParams); - QFETCH(int, expectedStatusCode); - QFETCH(Device::DeviceError, error); - - // add device - QVariantMap params; - params.insert("deviceClassId", mockDeviceClassId); - params.insert("name", "Edit mock device"); - QVariantList deviceParams; - QVariantMap asyncParam; - asyncParam.insert("paramTypeId", mockDeviceAsyncParamTypeId); - asyncParam.insert("value", false); - deviceParams.append(asyncParam); - QVariantMap brokenParam; - brokenParam.insert("paramTypeId", mockDeviceBrokenParamTypeId); - brokenParam.insert("value", broken); - deviceParams.append(brokenParam); - QVariantMap httpportParam; - httpportParam.insert("paramTypeId", mockDeviceHttpportParamTypeId); - httpportParam.insert("value", 8896); - deviceParams.append(httpportParam); - params.insert("deviceParams", deviceParams); - - // ADD a mockdevice - QNetworkRequest request(QUrl(QString("https://localhost:3333/api/v1/devices"))); - request.setHeader(QNetworkRequest::ContentTypeHeader, "text/json"); - - QVariant response = postAndWait(request, params); - QVERIFY2(!response.isNull(), "Could not read add device response"); - - DeviceId deviceId = DeviceId(response.toMap().value("id").toString()); - QVERIFY2(deviceId != DeviceId(), "DeviceId not returned"); - - // now RECONFIGURE the added device - QVariantMap editParams; - editParams.insert("deviceId", deviceId); - editParams.insert("deviceParams", newDeviceParams); - - request.setUrl(QUrl(QString("https://localhost:3333/api/v1/devices/%1").arg(deviceId.toString()))); - request.setHeader(QNetworkRequest::ContentTypeHeader, "text/json"); - - response = putAndWait(request, editParams, expectedStatusCode); - QVERIFY2(!response.isNull(), "Could not read edit device response"); - - // if the reconfigure should have been successful - if (expectedStatusCode == 200) { - request.setUrl(QUrl(QString("https://localhost:3333/api/v1/devices/%1").arg(deviceId.toString()))); - request.setHeader(QNetworkRequest::ContentTypeHeader, "text/json"); - response = getAndWait(request); - QVariantMap deviceMap = response.toMap(); - verifyParams(newDeviceParams, deviceMap.value("params").toList(), false); - } else { - QCOMPARE(JsonTypes::deviceErrorToString(error), response.toMap().value("error").toString()); - } - - // delete it - request.setUrl(QUrl(QString("https://localhost:3333/api/v1/devices/%1").arg(deviceId.toString()))); - response = deleteAndWait(request); - QVERIFY2(!response.isNull(), "Could not delete device"); -} - -void TestRestDevices::reconfigureByDiscovery_data() -{ - QTest::addColumn("deviceClassId"); - QTest::addColumn("resultCount"); - QTest::addColumn("discoveryParams"); - QTest::addColumn("expectedStatusCode"); - - QVariantList discoveryParams; - QVariantMap resultCountParam; - resultCountParam.insert("paramTypeId", mockDiscoveryResultCountParamTypeId); - resultCountParam.insert("value", 2); - discoveryParams.append(resultCountParam); - - QTest::newRow("discover 2 devices with params") << mockDeviceClassId << 2 << discoveryParams << 200; -} - -void TestRestDevices::reconfigureByDiscovery() -{ - QFETCH(DeviceClassId, deviceClassId); - QFETCH(int, resultCount); - QFETCH(QVariantList, discoveryParams); - QFETCH(int, expectedStatusCode); - - QVariantMap params; - params.insert("deviceClassId", deviceClassId); - params.insert("discoveryParams", discoveryParams); - - QUrl url(QString("https://localhost:3333/api/v1/deviceclasses/%1/discover").arg(deviceClassId.toString())); - - if (!discoveryParams.isEmpty()) { - QUrlQuery query; - query.addQueryItem("params", QJsonDocument::fromVariant(discoveryParams).toJson(QJsonDocument::Compact)); - url.setQuery(query); - } - - QNetworkRequest request(url); - QVariantList foundDevices = getAndWait(request).toList(); - QCOMPARE(foundDevices.count(), resultCount); - - // add Discovered Device 1 port 55555 - request.setUrl(QUrl("https://localhost:3333/api/v1/devices")); - request.setHeader(QNetworkRequest::ContentTypeHeader, "text/json"); - DeviceDescriptorId descriptorId; - foreach (const QVariant &descriptor, foundDevices) { - // find the device with port 55555 - if (descriptor.toMap().value("description").toString() == "55555") { - descriptorId = DeviceDescriptorId(descriptor.toMap().value("id").toString()); - qDebug() << descriptorId.toString(); - break; - } - } - params.clear(); - params.insert("deviceClassId", deviceClassId); - params.insert("name", "Discovered mock device"); - params.insert("deviceDescriptorId", descriptorId.toString()); - - QVariant response = postAndWait(request, params, expectedStatusCode); - QVERIFY2(!response.isNull(), "Could not delete device"); - - DeviceId deviceId = DeviceId(response.toMap().value("id").toString()); - QVERIFY(!deviceId.isNull()); - - // and now rediscover, and edit the first device with the second - params.clear(); - params.insert("deviceClassId", deviceClassId); - params.insert("discoveryParams", discoveryParams); - - url = QUrl(QString("https://localhost:3333/api/v1/deviceclasses/%1/discover").arg(deviceClassId.toString())); - QUrlQuery query2; - query2.addQueryItem("params", QJsonDocument::fromVariant(discoveryParams).toJson(QJsonDocument::Compact)); - url.setQuery(query2); - - response = getAndWait(QNetworkRequest(url), expectedStatusCode); - - foundDevices = response.toList(); - QCOMPARE(foundDevices.count(), resultCount); - - // find the already added device - descriptorId = DeviceDescriptorId(); // reset it first - foreach (const QVariant &descriptor, foundDevices) { - if (descriptor.toMap().value("deviceId").toUuid().toString() == deviceId.toString()) { - descriptorId = DeviceDescriptorId(descriptor.toMap().value("id").toString()); - break; - } - } - - QVERIFY(!descriptorId.isNull()); - qDebug() << "edit device 1 (55555) with descriptor 2 (55556) " << descriptorId; - - // RECONFIGURE - response.clear(); - params.clear(); - params.insert("deviceDescriptorId", descriptorId); - // override port param - QVariantMap portParam; - portParam.insert("paramTypeId", mockDeviceHttpportParamTypeId); - portParam.insert("value", "55556"); - params.insert("deviceParams", QVariantList() << portParam); - - request = QNetworkRequest(QUrl(QString("https://localhost:3333/api/v1/devices/%1").arg(deviceId.toString()))); - request.setHeader(QNetworkRequest::ContentTypeHeader, "text/json"); - - response = putAndWait(request, params, expectedStatusCode); - QVERIFY2(!response.isNull(), "Could not delete device"); - - // remove added device - request.setUrl(QUrl(QString("https://localhost:3333/api/v1/devices/%1").arg(deviceId.toString()))); - response = deleteAndWait(request); - QVERIFY2(!response.isNull(), "Could not delete device"); -} - -#include "testrestdevices.moc" -QTEST_MAIN(TestRestDevices) diff --git a/tests/auto/restlogging/restlogging.pro b/tests/auto/restlogging/restlogging.pro deleted file mode 100644 index 03f7b70e..00000000 --- a/tests/auto/restlogging/restlogging.pro +++ /dev/null @@ -1,5 +0,0 @@ -include(../../../nymea.pri) -include(../autotests.pri) - -TARGET = testrestlogging -SOURCES += testrestlogging.cpp diff --git a/tests/auto/restlogging/testrestlogging.cpp b/tests/auto/restlogging/testrestlogging.cpp deleted file mode 100644 index 54994fec..00000000 --- a/tests/auto/restlogging/testrestlogging.cpp +++ /dev/null @@ -1,379 +0,0 @@ -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - * * - * Copyright (C) 2015 Simon Stürz * - * Copyright (C) 2014 Michael Zanetti * - * * - * This file is part of nymea. * - * * - * nymea is free software: you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation, version 2 of the License. * - * * - ** - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with nymea. If not, see . * - * * - * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ - -#include "nymeatestbase.h" -#include "nymeacore.h" -#include "servers/mocktcpserver.h" - -using namespace nymeaserver; - -class TestRestLogging : public NymeaTestBase -{ - Q_OBJECT - -private: - -private slots: - void initTestCase(); - - void initLogs(); - - void invalidFilter_data(); - void invalidFilter(); - - void invalidFilterJson(); - - void eventLogs(); - - void actionLog(); - - // this has to be the last test - void removeDevice(); -}; - -void TestRestLogging::initTestCase() -{ - NymeaTestBase::initTestCase(); - - foreach (const WebServerConfiguration &config, NymeaCore::instance()->configuration()->webServerConfigurations()) { - if (config.port == 3333 && (config.address == QHostAddress("127.0.0.1") || config.address == QHostAddress("0.0.0.0"))) { - qDebug() << "Already have a webserver listening on 127.0.0.1:3333"; - return; - } - } - - qDebug() << "Creating new webserver instance on 127.0.0.1:3333"; - WebServerConfiguration config; - config.address = QHostAddress("127.0.0.1"); - config.port = 3333; - config.sslEnabled = true; - config.restServerEnabled = true; - NymeaCore::instance()->configuration()->setWebServerConfiguration(config); - qApp->processEvents(); -} - -void TestRestLogging::initLogs() -{ - QNetworkRequest request(QUrl("https://localhost:3333/api/v1/logs")); - QVariant response = getAndWait(request); - - QVariantList logEntries = response.toList(); - qDebug() << "Got" << logEntries.count() << "logs"; - QVERIFY(logEntries.count() > 0); - - clearLoggingDatabase(); - - response = getAndWait(request); - logEntries = response.toList(); - qDebug() << "Got" << logEntries.count() << "logs"; - QVERIFY(logEntries.count() == 0); - -} - -void TestRestLogging::invalidFilter_data() -{ - QVariantMap invalidSourcesFilter; - invalidSourcesFilter.insert("loggingSources", QVariantList() << "bla"); - - QVariantMap invalidFilterValue; - invalidFilterValue.insert("loggingSource", QVariantList() << "bla"); - - QVariantMap invalidTypeIds; - invalidTypeIds.insert("typeId", QVariantList() << "bla" << "blub"); - - QVariantMap invalidEventTypes; - invalidEventTypes.insert("eventTypes", QVariantList() << JsonTypes::loggingEventTypeToString(Logging::LoggingEventTypeTrigger) << "blub"); - - QTest::addColumn("filter"); - - QTest::newRow("Invalid source") << invalidSourcesFilter; - QTest::newRow("Invalid filter value") << invalidFilterValue; - QTest::newRow("Invalid typeIds") << invalidTypeIds; - QTest::newRow("Invalid eventTypes") << invalidEventTypes; -} - -void TestRestLogging::invalidFilter() -{ - QFETCH(QVariantMap, filter); - - QUrl url("https://localhost:3333/api/v1/logs"); - QUrlQuery query; - query.addQueryItem("filter", QJsonDocument::fromVariant(filter).toJson(QJsonDocument::Compact)); - url.setQuery(query); - - // there should be 2 logs, one for shutdown, one for startup (from server restart) - QVariant response = getAndWait(QNetworkRequest(url)); - QVERIFY(!response.isNull()); - - // TODO: validate filter for REST api -} - -void TestRestLogging::invalidFilterJson() -{ - QUrl url("https://localhost:3333/api/v1/logs"); - QUrlQuery query; - query.addQueryItem("filter", "blabla:!!"); - url.setQuery(query); - - getAndWait(QNetworkRequest(url), 400); -} - -void TestRestLogging::eventLogs() -{ - QList devices = NymeaCore::instance()->deviceManager()->findConfiguredDevices(mockDeviceClassId); - QVERIFY2(devices.count() > 0, "There needs to be at least one configured Mock Device for this test"); - Device *device = devices.first(); - - enableNotifications({"Logging"}); - - // Setup connection to mock client - QNetworkAccessManager nam; - QSignalSpy clientSpy(m_mockTcpServer, SIGNAL(outgoingData(QUuid,QByteArray))); - - // trigger event in mock device - int port = device->paramValue(mockDeviceHttpportParamTypeId).toInt(); - QNetworkRequest request(QUrl(QString("http://localhost:%1/generateevent?eventtypeid=%2").arg(port).arg(mockEvent1EventTypeId.toString()))); - QNetworkReply *reply = nam.get(request); - clientSpy.wait(); - - // Lets wait for the notification - QVariantList loggEntryAddedVariants = checkNotifications(clientSpy, "Logging.LogEntryAdded"); - QVERIFY2(!loggEntryAddedVariants.isEmpty(), "Did not get Logging.LogEntryAdded notification."); - qDebug() << "got" << loggEntryAddedVariants.count() << "Logging.LogEntryAdded notifications"; - reply->deleteLater(); - - - bool found = false; - qDebug() << "got" << loggEntryAddedVariants.count() << "Logging.LogEntryAdded"; - foreach (const QVariant &loggEntryAddedVariant, loggEntryAddedVariants) { - QVariantMap logEntry = loggEntryAddedVariant.toMap().value("params").toMap().value("logEntry").toMap(); - if (logEntry.value("deviceId").toString() == device->id().toString()) { - found = true; - // Make sure the notification contains all the stuff we expect - QCOMPARE(logEntry.value("typeId").toString(), mockEvent1EventTypeId.toString()); - QCOMPARE(logEntry.value("eventType").toString(), JsonTypes::loggingEventTypeToString(Logging::LoggingEventTypeTrigger)); - QCOMPARE(logEntry.value("source").toString(), JsonTypes::loggingSourceToString(Logging::LoggingSourceEvents)); - QCOMPARE(logEntry.value("loggingLevel").toString(), JsonTypes::loggingLevelToString(Logging::LoggingLevelInfo)); - break; - } - } - if (!found) - qDebug() << QJsonDocument::fromVariant(loggEntryAddedVariants).toJson(); - - QVERIFY2(found, "Could not find the corresponding Logging.LogEntryAdded notification"); - - // get this logentry with filter - QVariantMap params; - params.insert("deviceIds", QVariantList() << device->id()); - params.insert("loggingSources", QVariantList() << JsonTypes::loggingSourceToString(Logging::LoggingSourceEvents)); - params.insert("eventTypes", QVariantList() << JsonTypes::loggingEventTypeToString(Logging::LoggingEventTypeTrigger)); - params.insert("typeIds", QVariantList() << mockEvent1EventTypeId); - - QVariant response = injectAndWait("Logging.GetLogEntries", params); - verifyLoggingError(response); - - QVariantList logEntries = response.toMap().value("params").toMap().value("logEntries").toList(); - QVERIFY(logEntries.count() == 1); - - // disable notifications - QCOMPARE(disableNotifications(), true); -} - -void TestRestLogging::actionLog() -{ - QVariantList actionParams; - QVariantMap param1; - param1.insert("paramTypeId", mockWithParamsActionParam1ParamTypeId); - param1.insert("value", 7); - actionParams.append(param1); - QVariantMap param2; - param2.insert("paramTypeId", mockWithParamsActionParam2ParamTypeId); - param2.insert("value", true); - actionParams.append(param2); - - QVariantMap params; - params.insert("actionTypeId", mockWithParamsActionTypeId); - params.insert("deviceId", m_mockDeviceId); - params.insert("params", actionParams); - - // enable notifications - enableNotifications({"Logging"}); - - QSignalSpy clientSpy(m_mockTcpServer, SIGNAL(outgoingData(QUuid,QByteArray))); - - // EXECUTE with params - QVariant response = injectAndWait("Actions.ExecuteAction", params); - verifyDeviceError(response); - - // Lets wait 3for the notification - clientSpy.wait(200); - QVariant notification = checkNotification(clientSpy, "Logging.LogEntryAdded"); - QVERIFY(!notification.isNull()); - - QVariantMap logEntry = notification.toMap().value("params").toMap().value("logEntry").toMap(); - - // Make sure the notification contains all the stuff we expect - QCOMPARE(logEntry.value("typeId").toString(), mockWithParamsActionTypeId.toString()); - QCOMPARE(logEntry.value("deviceId").toString(), m_mockDeviceId.toString()); - QCOMPARE(logEntry.value("eventType").toString(), JsonTypes::loggingEventTypeToString(Logging::LoggingEventTypeTrigger)); - QCOMPARE(logEntry.value("source").toString(), JsonTypes::loggingSourceToString(Logging::LoggingSourceActions)); - QCOMPARE(logEntry.value("loggingLevel").toString(), JsonTypes::loggingLevelToString(Logging::LoggingLevelInfo)); - - // EXECUTE without params - params.clear(); clientSpy.clear(); - params.insert("actionTypeId", mockWithoutParamsActionTypeId); - params.insert("deviceId", m_mockDeviceId); - response = injectAndWait("Actions.ExecuteAction", params); - verifyDeviceError(response); - - clientSpy.wait(200); - notification = checkNotification(clientSpy, "Logging.LogEntryAdded"); - QVERIFY(!notification.isNull()); - - // get this logentry with filter - params.clear(); - params.insert("deviceIds", QVariantList() << m_mockDeviceId); - params.insert("loggingSources", QVariantList() << JsonTypes::loggingSourceToString(Logging::LoggingSourceActions)); - params.insert("eventTypes", QVariantList() << JsonTypes::loggingEventTypeToString(Logging::LoggingEventTypeTrigger)); - - // FIXME: filter for values currently disabled - //params.insert("values", QVariantList() << "7, true"); - - QUrl url("https://localhost:3333/api/v1/logs"); - QUrlQuery query; - query.addQueryItem("filter", QJsonDocument::fromVariant(params).toJson(QJsonDocument::Compact)); - url.setQuery(query); - - response = getAndWait(QNetworkRequest(url)); - QVariantList logEntries = response.toList(); - QVERIFY(!logEntries.isEmpty()); - - // EXECUTE broken action - params.clear(); clientSpy.clear(); - params.insert("actionTypeId", mockFailingActionTypeId); - params.insert("deviceId", m_mockDeviceId); - response = injectAndWait("Actions.ExecuteAction", params); - verifyDeviceError(response, Device::DeviceErrorSetupFailed); - - clientSpy.wait(200); - notification = checkNotification(clientSpy, "Logging.LogEntryAdded"); - QVERIFY(!notification.isNull()); - - logEntry = notification.toMap().value("params").toMap().value("logEntry").toMap(); - - // Make sure the notification contains all the stuff we expect - QCOMPARE(logEntry.value("typeId").toString(), mockFailingActionTypeId.toString()); - QCOMPARE(logEntry.value("deviceId").toString(), m_mockDeviceId.toString()); - QCOMPARE(logEntry.value("eventType").toString(), JsonTypes::loggingEventTypeToString(Logging::LoggingEventTypeTrigger)); - QCOMPARE(logEntry.value("source").toString(), JsonTypes::loggingSourceToString(Logging::LoggingSourceActions)); - QCOMPARE(logEntry.value("loggingLevel").toString(), JsonTypes::loggingLevelToString(Logging::LoggingLevelAlert)); - QCOMPARE(logEntry.value("errorCode").toString(), JsonTypes::deviceErrorToString(Device::DeviceErrorSetupFailed)); - - // get this logentry with filter - params.clear(); - params.insert("deviceIds", QVariantList() << m_mockDeviceId); - params.insert("loggingSources", QVariantList() << JsonTypes::loggingSourceToString(Logging::LoggingSourceActions)); - params.insert("eventTypes", QVariantList() << JsonTypes::loggingEventTypeToString(Logging::LoggingEventTypeTrigger)); - - // FIXME: filter for values currently disabled - //params.insert("values", QVariantList() << "7, true"); - - query.clear(); - query.addQueryItem("filter", QJsonDocument::fromVariant(params).toJson(QJsonDocument::Compact)); - url.setQuery(query); - - response = getAndWait(QNetworkRequest(url)); - logEntries = response.toList(); - QVERIFY(!logEntries.isEmpty()); - - // check different filters - params.clear(); - params.insert("deviceIds", QVariantList() << m_mockDeviceId); - params.insert("loggingSources", QVariantList() << JsonTypes::loggingSourceToString(Logging::LoggingSourceActions)); - params.insert("eventTypes", QVariantList() << JsonTypes::loggingEventTypeToString(Logging::LoggingEventTypeTrigger)); - params.insert("typeIds", QVariantList() << mockWithoutParamsActionTypeId); - - query.clear(); - query.addQueryItem("filter", QJsonDocument::fromVariant(params).toJson(QJsonDocument::Compact)); - url.setQuery(query); - - response = getAndWait(QNetworkRequest(url)); - logEntries = response.toList(); - QVERIFY(!logEntries.isEmpty()); - - params.clear(); - params.insert("deviceIds", QVariantList() << m_mockDeviceId); - params.insert("loggingSources", QVariantList() << JsonTypes::loggingSourceToString(Logging::LoggingSourceActions)); - params.insert("eventTypes", QVariantList() << JsonTypes::loggingEventTypeToString(Logging::LoggingEventTypeTrigger)); - params.insert("typeIds", QVariantList() << mockWithoutParamsActionTypeId << mockWithParamsActionTypeId << mockFailingActionTypeId); - - query.clear(); - query.addQueryItem("filter", QJsonDocument::fromVariant(params).toJson(QJsonDocument::Compact)); - url.setQuery(query); - - response = getAndWait(QNetworkRequest(url)); - logEntries = response.toList(); - QVERIFY(!logEntries.isEmpty()); - - // disable notifications - QCOMPARE(disableNotifications(), true); -} - -void TestRestLogging::removeDevice() -{ - // enable notifications - enableNotifications({"Logging"}); - - QSignalSpy clientSpy(m_mockTcpServer, SIGNAL(outgoingData(QUuid,QByteArray))); - - QNetworkRequest deleteRequest(QUrl(QString("https://localhost:3333/api/v1/devices/%1").arg(m_mockDeviceId.toString()))); - QVariant response = deleteAndWait(deleteRequest); - QVERIFY2(!response.isNull(), "Could not delete device"); - - clientSpy.wait(200); - QVariant notification = checkNotification(clientSpy, "Logging.LogDatabaseUpdated"); - QVERIFY(!notification.isNull()); - - // get this logentry with filter - QUrl url("https://localhost:3333/api/v1/logs"); - response = getAndWait(QNetworkRequest(url)); - QVariantList logEntries = response.toList(); - QVERIFY2(!logEntries.count() != 0, "No log entries left"); - - // verify that the logs from this device where removed from the db - QVariantMap params; - params.insert("deviceIds", QVariantList() << m_mockDeviceId); - QUrlQuery query; - query.addQueryItem("filter", QJsonDocument::fromVariant(params).toJson(QJsonDocument::Compact)); - url.setQuery(query); - - response = getAndWait(QNetworkRequest(url)); - logEntries = response.toList(); - - QCOMPARE(logEntries.count(), 0); - - // disable notifications - QCOMPARE(disableNotifications(), true); -} - -#include "testrestlogging.moc" -QTEST_MAIN(TestRestLogging) - diff --git a/tests/auto/restplugins/restplugins.pro b/tests/auto/restplugins/restplugins.pro deleted file mode 100644 index 8b05ebab..00000000 --- a/tests/auto/restplugins/restplugins.pro +++ /dev/null @@ -1,5 +0,0 @@ -include(../../../nymea.pri) -include(../autotests.pri) - -TARGET = restplugins -SOURCES += testrestplugins.cpp diff --git a/tests/auto/restplugins/temp b/tests/auto/restplugins/temp deleted file mode 100644 index e69de29b..00000000 diff --git a/tests/auto/restplugins/testrestplugins.cpp b/tests/auto/restplugins/testrestplugins.cpp deleted file mode 100644 index 11366f8b..00000000 --- a/tests/auto/restplugins/testrestplugins.cpp +++ /dev/null @@ -1,280 +0,0 @@ -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - * * - * Copyright (C) 2015 Simon Stürz * - * * - * This file is part of nymea. * - * * - * nymea is free software: you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation, version 2 of the License. * - * * - ** - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with nymea. If not, see . * - * * - * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ - -#include "nymeatestbase.h" -#include "nymeacore.h" - -using namespace nymeaserver; - -class TestRestPlugins: public NymeaTestBase -{ - Q_OBJECT - -private slots: - void initTestCase(); - - void getPlugins(); - void invalidMethod(); - void invalidPath(); - - void invalidPlugin_data(); - void invalidPlugin(); - - void getPluginConfiguration(); - -// void setPluginConfiguration_data(); -// void setPluginConfiguration(); -}; - -void TestRestPlugins::initTestCase() -{ - NymeaTestBase::initTestCase(); - - foreach (const WebServerConfiguration &config, NymeaCore::instance()->configuration()->webServerConfigurations()) { - if (config.port == 3333 && (config.address == QHostAddress("127.0.0.1") || config.address == QHostAddress("0.0.0.0"))) { - qDebug() << "Already have a webserver listening on 127.0.0.1:3333"; - return; - } - } - - qDebug() << "Creating new webserver instance on 127.0.0.1:3333"; - WebServerConfiguration config; - config.address = QHostAddress("127.0.0.1"); - config.port = 3333; - config.sslEnabled = true; - config.restServerEnabled = true; - NymeaCore::instance()->configuration()->setWebServerConfiguration(config); - qApp->processEvents(); -} - -void TestRestPlugins::getPlugins() -{ - // Get all plugins - QVariant response = getAndWait(QNetworkRequest(QUrl("https://localhost:3333/api/v1/plugins"))); - QVariantList pluginList = response.toList(); - QVERIFY2(pluginList.count() > 0, "Not enough plugins."); - - // Get each of thouse plugins individualy - foreach (const QVariant &plugin, pluginList) { - QVariantMap pluginMap = plugin.toMap(); - if (!VendorId(pluginMap.value("id").toString()).isNull()) { - QNetworkRequest request(QUrl(QString("https://localhost:3333/api/v1/plugins/%1").arg(pluginMap.value("id").toString()))); - response = getAndWait(request); - QVERIFY2(!response.isNull(), "Could not get plugin"); - } - } -} - -void TestRestPlugins::invalidMethod() -{ - QNetworkAccessManager *nam = new QNetworkAccessManager(this); - connect(nam, &QNetworkAccessManager::sslErrors, [this, nam](QNetworkReply *reply, const QList &) { - reply->ignoreSslErrors(); - }); - QSignalSpy clientSpy(nam, SIGNAL(finished(QNetworkReply*))); - - QNetworkRequest request; - request.setUrl(QUrl("https://localhost:3333/api/v1/plugins")); - QNetworkReply *reply = nam->deleteResource(request); - - clientSpy.wait(); - QVERIFY2(clientSpy.count() != 0, "expected at least 1 response from webserver"); - - bool ok = false; - int statusCode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(&ok); - QVERIFY2(ok, "Could not convert statuscode from response to int"); - QCOMPARE(statusCode, 400); - - reply->deleteLater(); - nam->deleteLater(); -} - -void TestRestPlugins::invalidPath() -{ - QNetworkAccessManager *nam = new QNetworkAccessManager(this); - connect(nam, &QNetworkAccessManager::sslErrors, [this, nam](QNetworkReply *reply, const QList &) { - reply->ignoreSslErrors(); - }); - QSignalSpy clientSpy(nam, SIGNAL(finished(QNetworkReply*))); - - QNetworkRequest request; - request.setUrl(QUrl("https://localhost:3333/api/v1/plugins/" + QUuid::createUuid().toString() + "/" + QUuid::createUuid().toString())); - QNetworkReply *reply = nam->get(request); - - clientSpy.wait(); - QVERIFY2(clientSpy.count() != 0, "expected at least 1 response from webserver"); - - bool ok = false; - int statusCode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(&ok); - QVERIFY2(ok, "Could not convert statuscode from response to int"); - QCOMPARE(statusCode, 501); - - reply->deleteLater(); - nam->deleteLater(); -} - -void TestRestPlugins::invalidPlugin_data() -{ - QTest::addColumn("path"); - QTest::addColumn("expectedStatusCode"); - - QTest::newRow("invalid PluginId") << QUuid::createUuid().toString() << 404; - QTest::newRow("invalid PluginId format") << "uuid" << 400; -} - -void TestRestPlugins::invalidPlugin() -{ - QFETCH(QString, path); - QFETCH(int, expectedStatusCode); - - QNetworkRequest request(QUrl("https://localhost:3333/api/v1/vendors/" + path)); - QVariant response = getAndWait(request, expectedStatusCode); - QCOMPARE(JsonTypes::deviceErrorToString(Device::DeviceErrorVendorNotFound), response.toMap().value("error").toString()); -} - -void TestRestPlugins::getPluginConfiguration() -{ - // Get plugin config - QNetworkRequest request(QUrl(QString("https://localhost:3333/api/v1/plugins/%1/configuration").arg(mockPluginId.toString()))); - QVariant response = getAndWait(request); - -// QVariantList configurations = response.toList(); -// QVERIFY2(configurations.count() == 2, "there should be 2 configurations"); -} - -//void TestRestPlugins::setPluginConfiguration_data() -//{ -// QTest::addColumn("pluginId"); -// QTest::addColumn("newConfigurations"); -// QTest::addColumn("expectedStatusCode"); - -// QVariantMap validIntParam; -// validIntParam.insert("name","configParamInt"); -// validIntParam.insert("value", 5); -// QVariantMap validBoolParam; -// validBoolParam.insert("name","configParamBool"); -// validBoolParam.insert("value", false); -// QVariantMap invalidIntParam; -// invalidIntParam.insert("name","configParamInt"); -// invalidIntParam.insert("value", 69); -// QVariantMap invalidIntParam2; -// invalidIntParam2.insert("name","configParamInt"); -// invalidIntParam2.insert("value", -1); - -// QVariantList validConfigurations; -// validConfigurations.append(validIntParam); -// validConfigurations.append(validBoolParam); - -// QVariantList invalidConfigurations; -// invalidConfigurations.append(invalidIntParam); - -// QVariantList invalidConfigurations2; -// invalidConfigurations2.append(invalidIntParam2); - -//// QTest::newRow("valid plugin configuration") << mockPluginId << validConfigurations << 200; -//// QTest::newRow("invalid plugin id") << PluginId::createPluginId() << validConfigurations << 404; -//// QTest::newRow("invalid plugin configuration") << mockPluginId << invalidConfigurations << 400; -//// QTest::newRow("invalid plugin configuration 2") << mockPluginId << invalidConfigurations2 << 400; -//} - -//void TestRestPlugins::setPluginConfiguration() -//{ -// QFETCH(PluginId, pluginId); -// QFETCH(QVariantList, newConfigurations); -// QFETCH(int, expectedStatusCode); - -// QNetworkAccessManager *nam = new QNetworkAccessManager(this); -// QSignalSpy clientSpy(nam, SIGNAL(finished(QNetworkReply*))); - -// // Get plugin configuration -// QNetworkRequest request; -// request.setUrl(QUrl(QString("https://localhost:3333/api/v1/plugins/%1/configuration").arg(pluginId.toString()))); -// QNetworkReply *reply = nam->get(request); -// clientSpy.wait(); -// QCOMPARE(clientSpy.count(), 1); -// int statusCode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(); -// reply->deleteLater(); -// if (expectedStatusCode == 404) -// return; - -// QByteArray data = reply->readAll(); -// reply->deleteLater(); -// QJsonParseError error; -// QJsonDocument jsonDoc = QJsonDocument::fromJson(data, &error); -// QCOMPARE(error.error, QJsonParseError::NoError); -// QVariantList originalConfigurations = jsonDoc.toVariant().toList(); -// QVERIFY2(originalConfigurations.count() == 2, "there should be 2 configurations"); - -// // Set new configuration -// clientSpy.clear(); -// request.setUrl(QUrl(QString("https://localhost:3333/api/v1/plugins/%1/configuration").arg(pluginId.toString()))); -// reply = nam->put(request, QJsonDocument::fromVariant(newConfigurations).toJson(QJsonDocument::Compact)); -// clientSpy.wait(); -// QCOMPARE(clientSpy.count(), 1); -// statusCode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(); -// QCOMPARE(statusCode, expectedStatusCode); -// reply->deleteLater(); - -// if (expectedStatusCode != 200) -// return; - -// // check new configurations -// clientSpy.clear(); -// request.setUrl(QUrl(QString("https://localhost:3333/api/v1/plugins/%1/configuration").arg(pluginId.toString()))); -// reply = nam->get(request); -// clientSpy.wait(); -// QCOMPARE(clientSpy.count(), 1); -// statusCode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(); -// QCOMPARE(statusCode, expectedStatusCode); -// data = reply->readAll(); -// reply->deleteLater(); - -// jsonDoc = QJsonDocument::fromJson(data, &error); -// QCOMPARE(error.error, QJsonParseError::NoError); -// QVariantList checkConfigurations = jsonDoc.toVariant().toList(); -// //QVERIFY2(checkConfigurations.count() == 2, "there should be 2 configurations"); - -// // verify new configurations -// verifyParams(newConfigurations, checkConfigurations); - -// // check new configurations after restart -// clientSpy.clear(); -// request.setUrl(QUrl(QString("https://localhost:3333/api/v1/plugins/%1/configuration").arg(pluginId.toString()))); -// reply = nam->get(request); -// clientSpy.wait(); -// QCOMPARE(clientSpy.count(), 1); -// statusCode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(); -// QCOMPARE(statusCode, 200); -// data = reply->readAll(); -// reply->deleteLater(); - -// jsonDoc = QJsonDocument::fromJson(data, &error); -// QCOMPARE(error.error, QJsonParseError::NoError); -// checkConfigurations = jsonDoc.toVariant().toList(); -// //QVERIFY2(checkConfigurations.count() == 2, "there should be 2 configurations"); - -// // verify new configurations -// verifyParams(newConfigurations, checkConfigurations); - -// nam->deleteLater(); -//} - -#include "testrestplugins.moc" -QTEST_MAIN(TestRestPlugins) diff --git a/tests/auto/restrules/restrules.pro b/tests/auto/restrules/restrules.pro deleted file mode 100644 index f0c81252..00000000 --- a/tests/auto/restrules/restrules.pro +++ /dev/null @@ -1,5 +0,0 @@ -include(../../../nymea.pri) -include(../autotests.pri) - -TARGET = restrules -SOURCES += testrestrules.cpp diff --git a/tests/auto/restrules/testrestrules.cpp b/tests/auto/restrules/testrestrules.cpp deleted file mode 100644 index 34b8f8fd..00000000 --- a/tests/auto/restrules/testrestrules.cpp +++ /dev/null @@ -1,1016 +0,0 @@ -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - * * - * Copyright (C) 2015 Simon Stürz * - * * - * This file is part of nymea. * - * * - * nymea is free software: you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation, version 2 of the License. * - * * - ** - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with nymea. If not, see . * - * * - * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ - -#include "nymeatestbase.h" -#include "nymeacore.h" - -using namespace nymeaserver; - -class TestRestRules: public NymeaTestBase -{ - Q_OBJECT - -private: - - void cleanupMockHistory(); - void cleanupRules(); - - void verifyRuleExecuted(const ActionTypeId &actionTypeId); - void verifyRuleNotExecuted(); - - void triggerMockEvent(); - - QVariant validIntStateBasedRule(const QString &name, const bool &executable, const bool &enabled); - -private slots: - void initTestCase(); - - void getRules(); - void findRule(); - void invalidMethod(); - void invalidPath(); - - void checkOptionCall(); - - void addRemoveRules_data(); - void addRemoveRules(); - - void emptyRule(); - - void editRules_data(); - void editRules(); - - void enableDisableRule(); - - void executeRuleActions_data(); - void executeRuleActions(); - -}; - -void TestRestRules::initTestCase() -{ - NymeaTestBase::initTestCase(); - - foreach (const WebServerConfiguration &config, NymeaCore::instance()->configuration()->webServerConfigurations()) { - if (config.port == 3333 && (config.address == QHostAddress("127.0.0.1") || config.address == QHostAddress("0.0.0.0"))) { - qDebug() << "Already have a webserver listening on 127.0.0.1:3333"; - return; - } - } - - qDebug() << "Creating new webserver instance on 127.0.0.1:3333"; - WebServerConfiguration config; - config.address = QHostAddress("127.0.0.1"); - config.port = 3333; - config.sslEnabled = true; - config.restServerEnabled = true; - NymeaCore::instance()->configuration()->setWebServerConfiguration(config); - qApp->processEvents(); -} - -void TestRestRules::cleanupMockHistory() -{ - QNetworkAccessManager nam; - QSignalSpy spy(&nam, SIGNAL(finished(QNetworkReply*))); - QNetworkRequest request(QUrl(QString("http://localhost:%1/clearactionhistory").arg(m_mockDevice1Port).arg(mockEvent1EventTypeId.toString()))); - QNetworkReply *reply = nam.get(request); - spy.wait(); - QCOMPARE(spy.count(), 1); - reply->deleteLater(); -} - -void TestRestRules::cleanupRules() -{ - // Get all rules - QNetworkRequest request(QUrl("https://localhost:3333/api/v1/rules")); - QVariant response = getAndWait(request); - QVERIFY(!response.isNull()); - QVariantList rulesList = response.toList(); - - // delete each rule - foreach (const QVariant &rule, rulesList) { - QVariantMap ruleMap = rule.toMap(); - QNetworkRequest request(QUrl(QString("https://localhost:3333/api/v1/rules/%1").arg(ruleMap.value("id").toString()))); - response = deleteAndWait(request); - QVERIFY(!response.isNull()); - } -} - -void TestRestRules::verifyRuleExecuted(const ActionTypeId &actionTypeId) -{ - // Verify rule got executed - QNetworkAccessManager nam; - QSignalSpy spy(&nam, SIGNAL(finished(QNetworkReply*))); - QNetworkRequest request(QUrl(QString("http://localhost:%1/actionhistory").arg(m_mockDevice1Port))); - QNetworkReply *reply = nam.get(request); - spy.wait(); - QCOMPARE(spy.count(), 1); - - QByteArray actionHistory = reply->readAll(); - qDebug() << "have action history" << actionHistory; - QVERIFY2(actionTypeId == ActionTypeId(actionHistory), "Action not triggered"); - reply->deleteLater(); -} - -void TestRestRules::verifyRuleNotExecuted() -{ - QNetworkAccessManager nam; - QSignalSpy spy(&nam, SIGNAL(finished(QNetworkReply*))); - QNetworkRequest request(QUrl(QString("http://localhost:%1/actionhistory").arg(m_mockDevice1Port))); - QNetworkReply *reply = nam.get(request); - spy.wait(); - QCOMPARE(spy.count(), 1); - - QByteArray actionHistory = reply->readAll(); - qDebug() << "have action history" << actionHistory; - QVERIFY2(actionHistory.isEmpty(), "Action is triggered while it should not have been."); - reply->deleteLater(); -} - -void TestRestRules::triggerMockEvent() -{ - // trigger event in mock device - QNetworkAccessManager nam; - QSignalSpy spy(&nam, SIGNAL(finished(QNetworkReply*))); - QNetworkRequest request = QNetworkRequest(QUrl(QString("http://localhost:%1/generateevent?eventtypeid=%2").arg(m_mockDevice1Port).arg(mockEvent1EventTypeId.toString()))); - QNetworkReply *reply = nam.get(request); - spy.wait(); - QCOMPARE(spy.count(), 1); - reply->deleteLater(); -} - -QVariant TestRestRules::validIntStateBasedRule(const QString &name, const bool &executable, const bool &enabled) -{ - QVariantMap params; - - // StateDescriptor - QVariantMap stateDescriptor; - stateDescriptor.insert("stateTypeId", mockIntStateTypeId); - stateDescriptor.insert("deviceId", m_mockDeviceId); - stateDescriptor.insert("operator", JsonTypes::valueOperatorToString(Types::ValueOperatorLess)); - stateDescriptor.insert("value", 25); - - // StateEvaluator - QVariantMap stateEvaluator; - stateEvaluator.insert("stateDescriptor", stateDescriptor); - stateEvaluator.insert("operator", JsonTypes::stateOperatorToString(Types::StateOperatorAnd)); - - // RuleAction - QVariantMap action; - action.insert("actionTypeId", mockWithParamsActionTypeId); - QVariantList actionParams; - QVariantMap param1; - param1.insert("paramTypeId", mockWithParamsActionParam1ParamTypeId); - param1.insert("value", 5); - actionParams.append(param1); - QVariantMap param2; - param2.insert("paramTypeId", mockWithParamsActionParam2ParamTypeId); - param2.insert("value", true); - actionParams.append(param2); - action.insert("deviceId", m_mockDeviceId); - action.insert("ruleActionParams", actionParams); - - // RuleExitAction - QVariantMap exitAction; - exitAction.insert("actionTypeId", mockWithoutParamsActionTypeId); - exitAction.insert("deviceId", m_mockDeviceId); - exitAction.insert("ruleActionParams", QVariantList()); - - params.insert("name", name); - params.insert("enabled", enabled); - params.insert("executable", executable); - params.insert("stateEvaluator", stateEvaluator); - params.insert("actions", QVariantList() << action); - params.insert("exitActions", QVariantList() << exitAction); - - return params; -} - -void TestRestRules::getRules() -{ - // Get all rules - QVariant response = getAndWait(QNetworkRequest(QUrl("https://localhost:3333/api/v1/rules"))); - QVariantList rulesList = response.toList(); - QVERIFY2(rulesList.count() == 0, "Not enough rules"); - - foreach (const QVariant &rule, rulesList) { - QVariantMap ruleMap = rule.toMap(); - QNetworkRequest request(QUrl(QString("https://localhost:3333/api/v1/rules/%1").arg(ruleMap.value("id").toString()))); - request.setHeader(QNetworkRequest::ContentTypeHeader, "text/json"); - - response = getAndWait(request); - QVERIFY2(!response.isNull(), "Could not get rule"); - } -} - -void TestRestRules::findRule() -{ - QVariant params = validIntStateBasedRule("Find", true, true); - QNetworkRequest request(QUrl(QString("https://localhost:3333/api/v1/rules"))); - request.setHeader(QNetworkRequest::ContentTypeHeader, "text/json"); - QVariant response = postAndWait(request, params); - - RuleId ruleId = RuleId(response.toMap().value("id").toString()); - QVERIFY(!ruleId.isNull()); - - QUrl url(QString("https://localhost:3333/api/v1/rules")); - QUrlQuery query; - query.addQueryItem("deviceId", m_mockDeviceId.toString()); - url.setQuery(query); - request.setUrl(QUrl(url)); - response = getAndWait(request); - QVERIFY(!response.isNull()); - - // REMOVE rule - request.setUrl(QUrl(QString("https://localhost:3333/api/v1/rules/%1").arg(ruleId.toString()))); - response = deleteAndWait(request); - QVERIFY(!response.isNull()); - QCOMPARE(JsonTypes::ruleErrorToString(RuleEngine::RuleErrorNoError), response.toMap().value("error").toString()); - - // check if removed - request.setUrl(QUrl(QString("https://localhost:3333/api/v1/rules/%1").arg(ruleId.toString()))); - response = getAndWait(request, 404); - QVERIFY(!response.isNull()); -} - -void TestRestRules::invalidMethod() -{ - QNetworkAccessManager nam; - connect(&nam, &QNetworkAccessManager::sslErrors, [this, &nam](QNetworkReply *reply, const QList &) { - reply->ignoreSslErrors(); - }); - QSignalSpy clientSpy(&nam, SIGNAL(finished(QNetworkReply*))); - - QNetworkRequest request; - request.setUrl(QUrl("https://localhost:3333/api/v1/rules")); - QNetworkReply *reply = nam.sendCustomRequest(request, "TRACE"); - - clientSpy.wait(); - QVERIFY2(clientSpy.count() != 0, "expected at least 1 response from webserver"); - - bool ok = false; - int statusCode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(&ok); - QVERIFY2(ok, "Could not convert statuscode from response to int"); - QCOMPARE(statusCode, 405); - - reply->deleteLater(); -} - -void TestRestRules::invalidPath() -{ - QNetworkAccessManager nam; - connect(&nam, &QNetworkAccessManager::sslErrors, [this, &nam](QNetworkReply *reply, const QList &) { - reply->ignoreSslErrors(); - }); - QSignalSpy clientSpy(&nam, SIGNAL(finished(QNetworkReply*))); - - QNetworkRequest request; - request.setUrl(QUrl("https://localhost:3333/api/v1/rules/" + QUuid::createUuid().toString() + "/" + QUuid::createUuid().toString())); - QNetworkReply *reply = nam.get(request); - - clientSpy.wait(); - QVERIFY2(clientSpy.count() != 0, "expected at least 1 response from webserver"); - - bool ok = false; - int statusCode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(&ok); - QVERIFY2(ok, "Could not convert statuscode from response to int"); - QCOMPARE(statusCode, 404); - - reply->deleteLater(); -} - -void TestRestRules::checkOptionCall() -{ - QNetworkRequest request(QUrl(QString("https://localhost:3333/api/v1/rules"))); - request.setHeader(QNetworkRequest::ContentTypeHeader, "text/json"); - QVariant response = postAndWait(request, validIntStateBasedRule("Options", true, true)); - - RuleId ruleId = RuleId(response.toMap().value("id").toString()); - QVERIFY(!ruleId.isNull()); - - QNetworkAccessManager nam; - connect(&nam, &QNetworkAccessManager::sslErrors, [this, &nam](QNetworkReply *reply, const QList &) { - reply->ignoreSslErrors(); - }); - QSignalSpy clientSpy(&nam, SIGNAL(finished(QNetworkReply*))); - - request.setUrl(QUrl(QString("https://localhost:3333/api/v1/rules/%1").arg(ruleId.toString()))); - QNetworkReply *reply = nam.sendCustomRequest(request, "OPTIONS"); - - clientSpy.wait(); - QCOMPARE(clientSpy.count(), 1); - - bool ok = false; - int statusCode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(&ok); - QVERIFY2(ok, "Could not convert statuscode from response to int"); - QCOMPARE(statusCode, 200); - - reply->deleteLater(); - - // REMOVE rule - request.setUrl(QUrl(QString("https://localhost:3333/api/v1/rules/%1").arg(ruleId.toString()))); - response = deleteAndWait(request); - QVERIFY(!response.isNull()); - QCOMPARE(JsonTypes::ruleErrorToString(RuleEngine::RuleErrorNoError), response.toMap().value("error").toString()); - - // check if removed - request.setUrl(QUrl(QString("https://localhost:3333/api/v1/rules/%1").arg(ruleId.toString()))); - response = getAndWait(request, 404); - QVERIFY(!response.isNull()); -} - -void TestRestRules::addRemoveRules_data() -{ - // RuleAction - QVariantMap validActionNoParams; - validActionNoParams.insert("actionTypeId", mockWithoutParamsActionTypeId); - validActionNoParams.insert("deviceId", m_mockDeviceId); - validActionNoParams.insert("ruleActionParams", QVariantList()); - - QVariantMap invalidAction; - invalidAction.insert("actionTypeId", ActionTypeId()); - invalidAction.insert("deviceId", m_mockDeviceId); - invalidAction.insert("ruleActionParams", QVariantList()); - - // RuleExitAction - QVariantMap validExitActionNoParams; - validExitActionNoParams.insert("actionTypeId", mockWithoutParamsActionTypeId); - validExitActionNoParams.insert("deviceId", m_mockDeviceId); - validExitActionNoParams.insert("ruleActionParams", QVariantList()); - - QVariantMap invalidExitAction; - invalidExitAction.insert("actionTypeId", ActionTypeId()); - invalidExitAction.insert("deviceId", m_mockDeviceId); - invalidExitAction.insert("ruleActionParams", QVariantList()); - - // StateDescriptor - QVariantMap stateDescriptor; - stateDescriptor.insert("stateTypeId", mockIntStateTypeId); - stateDescriptor.insert("deviceId", m_mockDeviceId); - stateDescriptor.insert("operator", JsonTypes::valueOperatorToString(Types::ValueOperatorLess)); - stateDescriptor.insert("value", 20); - - // StateEvaluator - QVariantMap validStateEvaluator; - validStateEvaluator.insert("stateDescriptor", stateDescriptor); - validStateEvaluator.insert("operator", JsonTypes::stateOperatorToString(Types::StateOperatorAnd)); - - QVariantMap invalidStateEvaluator; - stateDescriptor.remove("deviceId"); - invalidStateEvaluator.insert("stateDescriptor", stateDescriptor); - - // EventDescriptor - QVariantMap validEventDescriptor1; - validEventDescriptor1.insert("eventTypeId", mockEvent1EventTypeId); - validEventDescriptor1.insert("deviceId", m_mockDeviceId); - validEventDescriptor1.insert("paramDescriptors", QVariantList()); - - QVariantMap validEventDescriptor2; - validEventDescriptor2.insert("eventTypeId", mockEvent2EventTypeId); - validEventDescriptor2.insert("deviceId", m_mockDeviceId); - QVariantList params; - QVariantMap param1; - param1.insert("paramTypeId", mockEvent2EventIntParamParamTypeId); - param1.insert("value", 3); - param1.insert("operator", JsonTypes::valueOperatorToString(Types::ValueOperatorEquals)); - params.append(param1); - validEventDescriptor2.insert("paramDescriptors", params); - - QVariantMap validEventDescriptor3; - validEventDescriptor3.insert("eventTypeId", mockEvent2EventTypeId); - validEventDescriptor3.insert("deviceId", m_mockDeviceId); - validEventDescriptor3.insert("paramDescriptors", QVariantList()); - - // EventDescriptorList - QVariantList eventDescriptorList; - eventDescriptorList.append(validEventDescriptor1); - eventDescriptorList.append(validEventDescriptor2); - - QVariantMap invalidEventDescriptor; - invalidEventDescriptor.insert("eventTypeId", mockEvent1EventTypeId); - invalidEventDescriptor.insert("deviceId", DeviceId()); - invalidEventDescriptor.insert("paramDescriptors", QVariantList()); - - // RuleAction event based - QVariantMap validActionEventBased; - validActionEventBased.insert("actionTypeId", mockWithParamsActionTypeId); - validActionEventBased.insert("deviceId", m_mockDeviceId); - QVariantMap validActionEventBasedParam1; - validActionEventBasedParam1.insert("paramTypeId", mockWithParamsActionParam1ParamTypeId); - validActionEventBasedParam1.insert("eventTypeId", mockEvent2EventTypeId); - validActionEventBasedParam1.insert("eventParamTypeId", mockEvent2EventIntParamParamTypeId); - QVariantMap validActionEventBasedParam2; - validActionEventBasedParam2.insert("paramTypeId", mockWithParamsActionParam2ParamTypeId); - validActionEventBasedParam2.insert("value", false); - validActionEventBased.insert("ruleActionParams", QVariantList() << validActionEventBasedParam1 << validActionEventBasedParam2); - - QVariantMap invalidActionEventBased; - invalidActionEventBased.insert("actionTypeId", mockWithoutParamsActionTypeId); - invalidActionEventBased.insert("deviceId", m_mockDeviceId); - validActionEventBasedParam1.insert("value", 10); - invalidActionEventBased.insert("ruleActionParams", QVariantList() << validActionEventBasedParam1); - - QVariantMap invalidActionEventBased2; - invalidActionEventBased2.insert("actionTypeId", mockWithParamsActionTypeId); - invalidActionEventBased2.insert("deviceId", m_mockDeviceId); - QVariantMap invalidActionEventBasedParam2; - invalidActionEventBasedParam2.insert("paramTypeId", mockWithParamsActionParam1ParamTypeId); - invalidActionEventBasedParam2.insert("eventTypeId", mockEvent1EventTypeId); - invalidActionEventBasedParam2.insert("eventParamTypeId", ParamTypeId::createParamTypeId()); - QVariantMap invalidActionEventBasedParam3; - invalidActionEventBasedParam3.insert("paramTypeId", mockWithParamsActionParam2ParamTypeId); - invalidActionEventBasedParam3.insert("value", 2); - invalidActionEventBased2.insert("ruleActionParams", QVariantList() << invalidActionEventBasedParam2 << invalidActionEventBasedParam3); - - QVariantMap invalidActionEventBased3; - invalidActionEventBased3.insert("actionTypeId", mockWithParamsActionTypeId); - invalidActionEventBased3.insert("deviceId", m_mockDeviceId); - QVariantMap invalidActionEventBasedParam4; - invalidActionEventBasedParam4.insert("paramTypeId", mockWithParamsActionParam1ParamTypeId); - invalidActionEventBasedParam4.insert("eventTypeId", mockEvent1EventTypeId); - invalidActionEventBasedParam4.insert("eventParamTypeId", mockEvent2EventIntParamParamTypeId); - invalidActionEventBased3.insert("ruleActionParams", QVariantList() << invalidActionEventBasedParam4); - - QTest::addColumn("enabled"); - QTest::addColumn("action1"); - QTest::addColumn("exitAction1"); - QTest::addColumn("eventDescriptor"); - QTest::addColumn("eventDescriptorList"); - QTest::addColumn("stateEvaluator"); - QTest::addColumn("expectedStatusCode"); - QTest::addColumn("jsonError"); - QTest::addColumn("name"); - - // Rules with event based actions - QTest::newRow("valid rule. enabled, 1 Action (eventBased), 1 EventDescriptor, name") << true << validActionEventBased << QVariantMap() << validEventDescriptor3 << QVariantList() << QVariantMap() << 200 << true << "ActionEventRule1"; - QTest::newRow("invalid rule. enabled, 1 Action (eventBased), 1 EventDescriptor, name") << true << invalidActionEventBased2 << QVariantMap() << validEventDescriptor3 << QVariantList() << QVariantMap() << 400 << false << "TestRule"; - - QTest::newRow("invalid rule. enabled, 1 Action (eventBased), types not matching, name") << true << invalidActionEventBased3 << QVariantMap() << validEventDescriptor1 << QVariantList() << QVariantMap() << 400 << false << "TestRule"; - - QTest::newRow("invalid rule. enabled, 1 Action (eventBased), 1 EventDescriptor, name") << true << invalidActionEventBased << QVariantMap() << validEventDescriptor2 << QVariantList() << QVariantMap() << 400 << false << "TestRule"; - QTest::newRow("invalid rule. enabled, 1 Action (eventBased), 1 StateEvaluator, name") << true << validActionEventBased << QVariantMap() << QVariantMap() << QVariantList() << validStateEvaluator << 400 << false << "TestRule"; - QTest::newRow("invalid rule. enabled, 1 Action (eventBased), 1 EventDescriptor, name") << true << validActionEventBased << validActionEventBased << validEventDescriptor2 << QVariantList() << QVariantMap() << 400 << false << "TestRule"; - QTest::newRow("invalid rule. enabled, 1 Action, 1 ExitAction (EventBased), name") << true << validActionNoParams << validActionEventBased << validEventDescriptor2 << QVariantList() << QVariantMap() << 400 << false << "TestRule"; - - // Rules with exit actions - QTest::newRow("valid rule. enabled, 1 Action, 1 Exit Action, 1 StateEvaluator, name") << true << validActionNoParams << validExitActionNoParams << QVariantMap() << QVariantList() << validStateEvaluator << 200 << true << "TestRule"; - QTest::newRow("valid rule. disabled, 1 Action, 1 Exit Action, 1 StateEvaluator, name") << false << validActionNoParams << validExitActionNoParams << QVariantMap() << QVariantList() << validStateEvaluator << 200 << true << "TestRule"; - QTest::newRow("invalid rule. disabled, 1 Action, 1 invalid Exit Action, 1 StateEvaluator, name") << false << validActionNoParams << invalidExitAction << QVariantMap() << QVariantList() << validStateEvaluator << 400 << false << "TestRule"; - QTest::newRow("valid rule. 1 Action, 1 Exit Action, 1 EventDescriptor, 1 StateEvaluator, name") << true << validActionNoParams << validExitActionNoParams << validEventDescriptor1 << QVariantList() << validStateEvaluator << 200 << true << "TestRule"; - QTest::newRow("valid rule. 1 Action, 1 Exit Action, eventDescriptorList, 1 StateEvaluator, name") << true << validActionNoParams << validExitActionNoParams << QVariantMap() << eventDescriptorList << validStateEvaluator << 200 << true << "TestRule"; - - // Rules without exit actions - QTest::newRow("valid rule. enabled, 1 EventDescriptor, StateEvaluator, 1 Action, name") << true << validActionNoParams << QVariantMap() << validEventDescriptor1 << QVariantList() << validStateEvaluator << 200 << true << "TestRule"; - QTest::newRow("valid rule. disabled, 1 EventDescriptor, StateEvaluator, 1 Action, name") << false << validActionNoParams << QVariantMap() << validEventDescriptor1 << QVariantList() << validStateEvaluator << 200 << true << "TestRule"; - QTest::newRow("valid rule. 2 EventDescriptors, 1 Action, name") << true << validActionNoParams << QVariantMap() << QVariantMap() << eventDescriptorList << validStateEvaluator << 200 << true << "TestRule"; - QTest::newRow("invalid action") << true << invalidAction << QVariantMap() << validEventDescriptor1 << QVariantList() << validStateEvaluator << 400 << false << "TestRule"; - QTest::newRow("invalid event descriptor") << true << validActionNoParams << QVariantMap() << invalidEventDescriptor << QVariantList() << validStateEvaluator << 400 << false << "TestRule"; -} - -void TestRestRules::addRemoveRules() -{ - QFETCH(bool, enabled); - QFETCH(QVariantMap, action1); - QFETCH(QVariantMap, exitAction1); - QFETCH(QVariantMap, eventDescriptor); - QFETCH(QVariantList, eventDescriptorList); - QFETCH(QVariantMap, stateEvaluator); - QFETCH(int, expectedStatusCode); - QFETCH(bool, jsonError); - QFETCH(QString, name); - - Q_UNUSED(jsonError) - - // create add params for rule - QVariantMap params; - params.insert("name", name); - - QVariantList actions; - actions.append(action1); - params.insert("actions", actions); - - if (!eventDescriptor.isEmpty()) { - params.insert("eventDescriptors", QVariantList() << eventDescriptor); - } - if (!eventDescriptorList.isEmpty()) { - params.insert("eventDescriptors", eventDescriptorList); - } - - QVariantList exitActions; - if (!exitAction1.isEmpty()) { - exitActions.append(exitAction1); - params.insert("exitActions", exitActions); - } - params.insert("stateEvaluator", stateEvaluator); - if (!enabled) { - params.insert("enabled", enabled); - } - - // Get rules and verify there is no rule added - QNetworkRequest request(QUrl("https://localhost:3333/api/v1/rules")); - QVariant response = getAndWait(request); - QVariantList rulesList = response.toList(); - QVERIFY2(rulesList.count() == 0, "there should be no rules."); - - // ADD rule - request = QNetworkRequest(QUrl(QString("https://localhost:3333/api/v1/rules"))); - request.setHeader(QNetworkRequest::ContentTypeHeader, "text/json"); - - response = postAndWait(request, params, expectedStatusCode); - if (expectedStatusCode != 200) - return; - - RuleId ruleId = RuleId(response.toMap().value("id").toString()); - QVERIFY(!ruleId.isNull()); - - qDebug() << QJsonDocument::fromVariant(response).toJson(); - - // GET rule details - request = QNetworkRequest(QUrl(QString("https://localhost:3333/api/v1/rules/%1").arg(ruleId.toString()))); - //request.setHeader(QNetworkRequest::ContentTypeHeader, "text/json"); - response = getAndWait(request); - QVERIFY(!response.isNull()); - - // REMOVE rule - request = QNetworkRequest(QUrl(QString("https://localhost:3333/api/v1/rules/%1").arg(ruleId.toString()))); - request.setHeader(QNetworkRequest::ContentTypeHeader, "text/json"); - response = deleteAndWait(request); - QVERIFY(!response.isNull()); -} - -void TestRestRules::emptyRule() -{ - // create add params for rule - QVariantMap params; - params.insert("name", QString()); - params.insert("actions", QVariantList()); - - // Get rules and verify there is no rule added - QNetworkRequest request = QNetworkRequest(QUrl(QString("https://localhost:3333/api/v1/rules"))); - request.setHeader(QNetworkRequest::ContentTypeHeader, "text/json"); - - QVariant response = postAndWait(request, params, 400); - QCOMPARE(response.toMap().value("error").toString(), JsonTypes::ruleErrorToString(RuleEngine::RuleErrorInvalidRuleFormat)); -} - -void TestRestRules::editRules_data() -{ - // RuleAction - QVariantMap validActionNoParams; - validActionNoParams.insert("actionTypeId", mockWithoutParamsActionTypeId); - validActionNoParams.insert("deviceId", m_mockDeviceId); - validActionNoParams.insert("ruleActionParams", QVariantList()); - - QVariantMap invalidAction; - invalidAction.insert("actionTypeId", ActionTypeId()); - invalidAction.insert("deviceId", m_mockDeviceId); - invalidAction.insert("ruleActionParams", QVariantList()); - - // RuleExitAction - QVariantMap validExitActionNoParams; - validExitActionNoParams.insert("actionTypeId", mockWithoutParamsActionTypeId); - validExitActionNoParams.insert("deviceId", m_mockDeviceId); - validExitActionNoParams.insert("ruleActionParams", QVariantList()); - - QVariantMap invalidExitAction; - invalidExitAction.insert("actionTypeId", ActionTypeId()); - invalidExitAction.insert("deviceId", m_mockDeviceId); - invalidExitAction.insert("ruleActionParams", QVariantList()); - - // StateDescriptor - QVariantMap stateDescriptor; - stateDescriptor.insert("stateTypeId", mockIntStateTypeId); - stateDescriptor.insert("deviceId", m_mockDeviceId); - stateDescriptor.insert("operator", JsonTypes::valueOperatorToString(Types::ValueOperatorLess)); - stateDescriptor.insert("value", 20); - - // StateEvaluator - QVariantMap validStateEvaluator; - validStateEvaluator.insert("stateDescriptor", stateDescriptor); - validStateEvaluator.insert("operator", JsonTypes::stateOperatorToString(Types::StateOperatorAnd)); - - QVariantMap invalidStateEvaluator; - stateDescriptor.remove("deviceId"); - invalidStateEvaluator.insert("stateDescriptor", stateDescriptor); - - // EventDescriptor - QVariantMap validEventDescriptor1; - validEventDescriptor1.insert("eventTypeId", mockEvent1EventTypeId); - validEventDescriptor1.insert("deviceId", m_mockDeviceId); - validEventDescriptor1.insert("paramDescriptors", QVariantList()); - - QVariantMap validEventDescriptor2; - validEventDescriptor2.insert("eventTypeId", mockEvent2EventTypeId); - validEventDescriptor2.insert("deviceId", m_mockDeviceId); - QVariantList params; - QVariantMap param1; - param1.insert("paramTypeId", mockEvent2EventIntParamParamTypeId); - param1.insert("value", 3); - param1.insert("operator", JsonTypes::valueOperatorToString(Types::ValueOperatorEquals)); - params.append(param1); - validEventDescriptor2.insert("paramDescriptors", params); - - QVariantMap validEventDescriptor3; - validEventDescriptor3.insert("eventTypeId", mockEvent2EventTypeId); - validEventDescriptor3.insert("deviceId", m_mockDeviceId); - validEventDescriptor3.insert("paramDescriptors", QVariantList()); - - // EventDescriptorList - QVariantList eventDescriptorList; - eventDescriptorList.append(validEventDescriptor1); - eventDescriptorList.append(validEventDescriptor2); - - QVariantMap invalidEventDescriptor; - invalidEventDescriptor.insert("eventTypeId", mockEvent1EventTypeId); - invalidEventDescriptor.insert("deviceId", DeviceId()); - invalidEventDescriptor.insert("paramDescriptors", QVariantList()); - - // RuleAction event based - QVariantMap validActionEventBased; - validActionEventBased.insert("actionTypeId", mockWithParamsActionTypeId); - validActionEventBased.insert("deviceId", m_mockDeviceId); - QVariantMap validActionEventBasedParam1; - validActionEventBasedParam1.insert("paramTypeId", mockWithParamsActionParam1ParamTypeId); - validActionEventBasedParam1.insert("eventTypeId", mockEvent2EventTypeId); - validActionEventBasedParam1.insert("eventParamTypeId", mockEvent2EventIntParamParamTypeId); - QVariantMap validActionEventBasedParam2; - validActionEventBasedParam2.insert("paramTypeId", mockWithParamsActionParam2ParamTypeId); - validActionEventBasedParam2.insert("value", false); - validActionEventBased.insert("ruleActionParams", QVariantList() << validActionEventBasedParam1 << validActionEventBasedParam2); - - QVariantMap invalidActionEventBased; - invalidActionEventBased.insert("actionTypeId", mockWithoutParamsActionTypeId); - invalidActionEventBased.insert("deviceId", m_mockDeviceId); - validActionEventBasedParam1.insert("value", 10); - invalidActionEventBased.insert("ruleActionParams", QVariantList() << validActionEventBasedParam1); - - QVariantMap invalidActionEventBased2; - invalidActionEventBased2.insert("actionTypeId", mockWithoutParamsActionTypeId); - invalidActionEventBased2.insert("deviceId", m_mockDeviceId); - QVariantMap invalidActionEventBasedParam2; - invalidActionEventBasedParam2.insert("paramTypeId", mockWithParamsActionParam1ParamTypeId); - invalidActionEventBasedParam2.insert("eventTypeId", mockEvent1EventTypeId); - invalidActionEventBasedParam2.insert("eventParamTypeId", mockEvent2EventIntParamParamTypeId); - QVariantMap invalidActionEventBasedParam3; - invalidActionEventBasedParam3.insert("paramTypeId", mockWithParamsActionParam2ParamTypeId); - invalidActionEventBasedParam3.insert("value", 2); - invalidActionEventBased2.insert("ruleActionParams", QVariantList() << invalidActionEventBasedParam2 << invalidActionEventBasedParam3); - - QVariantMap invalidActionEventBased3; - invalidActionEventBased3.insert("actionTypeId", mockWithParamsActionTypeId); - invalidActionEventBased3.insert("deviceId", m_mockDeviceId); - QVariantMap invalidActionEventBasedParam4; - invalidActionEventBasedParam4.insert("paramTypeId", mockWithParamsActionParam1ParamTypeId); - invalidActionEventBasedParam4.insert("eventTypeId", mockEvent1EventTypeId); - invalidActionEventBasedParam4.insert("eventParamTypeId", mockEvent2EventIntParamParamTypeId); - invalidActionEventBased3.insert("ruleActionParams", QVariantList() << invalidActionEventBasedParam4); - - QTest::addColumn("enabled"); - QTest::addColumn("action"); - QTest::addColumn("exitAction"); - QTest::addColumn("eventDescriptor"); - QTest::addColumn("eventDescriptorList"); - QTest::addColumn("stateEvaluator"); - QTest::addColumn("expectedStatusCode"); - QTest::addColumn("name"); - - // Rules with event based actions - QTest::newRow("valid rule. enabled, 1 Action (eventBased), 1 EventDescriptor, name") << true << validActionEventBased << QVariantMap() << validEventDescriptor3 << QVariantList() << QVariantMap() << 200 << "ActionEventRule1"; - QTest::newRow("invalid rule. enabled, 1 Action (eventBased), 1 EventDescriptor, name") << true << invalidActionEventBased2 << QVariantMap() << validEventDescriptor3 << QVariantList() << QVariantMap() << 400 << "TestRule"; - - QTest::newRow("invalid rule. enabled, 1 Action (eventBased), types not matching, name") << true << invalidActionEventBased3 << QVariantMap() << validEventDescriptor1 << QVariantList() << QVariantMap() << 400 << "TestRule"; - - QTest::newRow("invalid rule. enabled, 1 Action (eventBased), 1 EventDescriptor, name") << true << invalidActionEventBased << QVariantMap() << validEventDescriptor2 << QVariantList() << QVariantMap() << 400 << "TestRule"; - QTest::newRow("invalid rule. enabled, 1 Action (eventBased), 1 StateEvaluator, name") << true << validActionEventBased << QVariantMap() << QVariantMap() << QVariantList() << validStateEvaluator << 400 << "TestRule"; - QTest::newRow("invalid rule. enabled, 1 Action (eventBased), 1 EventDescriptor, name") << true << validActionEventBased << validActionEventBased << validEventDescriptor2 << QVariantList() << QVariantMap() << 400 << "TestRule"; - QTest::newRow("invalid rule. enabled, 1 Action, 1 ExitAction (EventBased), name") << true << validActionNoParams << validActionEventBased << validEventDescriptor2 << QVariantList() << QVariantMap() << 400 << "TestRule"; - - // Rules with exit actions - QTest::newRow("valid rule. enabled, 1 Action, 1 Exit Action, 1 StateEvaluator, name") << true << validActionNoParams << validExitActionNoParams << QVariantMap() << QVariantList() << validStateEvaluator << 200 << "TestRule"; - QTest::newRow("valid rule. disabled, 1 Action, 1 Exit Action, 1 StateEvaluator, name") << false << validActionNoParams << validExitActionNoParams << QVariantMap() << QVariantList() << validStateEvaluator << 200 << "TestRule"; - QTest::newRow("valid rule. 1 Action, 1 Exit Action, 1 EventDescriptor, 1 StateEvaluator, name") << true << validActionNoParams << validExitActionNoParams << validEventDescriptor1 << QVariantList() << validStateEvaluator << 200 << "TestRule"; - QTest::newRow("valid rule. 1 Action, 1 Exit Action, eventDescriptorList, 1 StateEvaluator, name") << true << validActionNoParams << validExitActionNoParams << QVariantMap() << eventDescriptorList << validStateEvaluator << 200 << "TestRule"; - - // Rules without exit actions - QTest::newRow("valid rule. enabled, 1 EventDescriptor, StateEvaluator, 1 Action, name") << true << validActionNoParams << QVariantMap() << validEventDescriptor1 << QVariantList() << validStateEvaluator << 200 << "TestRule"; - QTest::newRow("valid rule. disabled, 1 EventDescriptor, StateEvaluator, 1 Action, name") << false << validActionNoParams << QVariantMap() << validEventDescriptor1 << QVariantList() << validStateEvaluator << 200 << "TestRule"; - QTest::newRow("valid rule. 2 EventDescriptors, 1 Action, name") << true << validActionNoParams << QVariantMap() << QVariantMap() << eventDescriptorList << validStateEvaluator << 200 << "TestRule"; -} - -void TestRestRules::editRules() -{ - QFETCH(bool, enabled); - QFETCH(QVariantMap, action); - QFETCH(QVariantMap, exitAction); - QFETCH(QVariantMap, eventDescriptor); - QFETCH(QVariantList, eventDescriptorList); - QFETCH(QVariantMap, stateEvaluator); - QFETCH(int, expectedStatusCode); - QFETCH(QString, name); - - // Add the rule we want to edit - QVariantList eventParamDescriptors; - QVariantMap eventDescriptor1; - eventDescriptor1.insert("eventTypeId", mockEvent1EventTypeId); - eventDescriptor1.insert("deviceId", m_mockDeviceId); - eventDescriptor1.insert("paramDescriptors", QVariantList()); - QVariantMap eventDescriptor2; - eventDescriptor2.insert("eventTypeId", mockEvent2EventTypeId); - eventDescriptor2.insert("deviceId", m_mockDeviceId); - eventDescriptor2.insert("paramDescriptors", QVariantList()); - QVariantMap eventParam1; - eventParam1.insert("paramTypeId", mockEvent2EventIntParamParamTypeId); - eventParam1.insert("value", 3); - eventParam1.insert("operator", JsonTypes::valueOperatorToString(Types::ValueOperatorEquals)); - eventParamDescriptors.append(eventParam1); - eventDescriptor2.insert("paramDescriptors", eventParamDescriptors); - - QVariantList eventDescriptorList1; - eventDescriptorList1.append(eventDescriptor1); - eventDescriptorList1.append(eventDescriptor2); - - QVariantMap stateEvaluator0; - QVariantMap stateDescriptor1; - stateDescriptor1.insert("deviceId", m_mockDeviceId); - stateDescriptor1.insert("operator", JsonTypes::valueOperatorToString(Types::ValueOperatorEquals)); - stateDescriptor1.insert("stateTypeId", mockIntStateTypeId); - stateDescriptor1.insert("value", 1); - QVariantMap stateDescriptor2; - stateDescriptor2.insert("deviceId", m_mockDeviceId); - stateDescriptor2.insert("operator", JsonTypes::valueOperatorToString(Types::ValueOperatorEquals)); - stateDescriptor2.insert("stateTypeId", mockBoolStateTypeId); - stateDescriptor2.insert("value", true); - QVariantMap stateEvaluator1; - stateEvaluator1.insert("stateDescriptor", stateDescriptor1); - stateEvaluator1.insert("operator", JsonTypes::stateOperatorToString(Types::StateOperatorAnd)); - QVariantMap stateEvaluator2; - stateEvaluator2.insert("stateDescriptor", stateDescriptor2); - stateEvaluator2.insert("operator", JsonTypes::stateOperatorToString(Types::StateOperatorAnd)); - QVariantList childEvaluators; - childEvaluators.append(stateEvaluator1); - childEvaluators.append(stateEvaluator2); - stateEvaluator0.insert("childEvaluators", childEvaluators); - stateEvaluator0.insert("operator", JsonTypes::stateOperatorToString(Types::StateOperatorAnd)); - - QVariantMap action1; - action1.insert("actionTypeId", mockWithoutParamsActionTypeId); - action1.insert("deviceId", m_mockDeviceId); - action1.insert("ruleActionParams", QVariantList()); - QVariantMap action2; - action2.insert("actionTypeId", mockWithParamsActionTypeId); - action2.insert("deviceId", m_mockDeviceId); - QVariantList action2Params; - QVariantMap action2Param1; - action2Param1.insert("paramTypeId", mockWithParamsActionParam1ParamTypeId); - action2Param1.insert("value", 5); - action2Params.append(action2Param1); - QVariantMap action2Param2; - action2Param2.insert("paramTypeId", mockWithParamsActionParam2ParamTypeId); - action2Param2.insert("value", true); - action2Params.append(action2Param2); - action2.insert("ruleActionParams", action2Params); - - // RuleAction event based - QVariantMap validActionEventBased; - validActionEventBased.insert("actionTypeId", mockWithParamsActionTypeId); - validActionEventBased.insert("deviceId", m_mockDeviceId); - QVariantMap validActionEventBasedParam1; - validActionEventBasedParam1.insert("paramTypeId", mockWithParamsActionParam1ParamTypeId); - validActionEventBasedParam1.insert("eventTypeId", mockEvent2EventTypeId); - validActionEventBasedParam1.insert("eventParamTypeId", mockEvent2EventIntParamParamTypeId); - QVariantMap validActionEventBasedParam2; - validActionEventBasedParam2.insert("paramTypeId", mockWithParamsActionParam2ParamTypeId); - validActionEventBasedParam2.insert("value", false); - validActionEventBased.insert("ruleActionParams", QVariantList() << validActionEventBasedParam1 << validActionEventBasedParam2); - - QVariantList validEventDescriptors3; - QVariantMap validEventDescriptor3; - validEventDescriptor3.insert("eventTypeId", mockEvent2EventTypeId); - validEventDescriptor3.insert("deviceId", m_mockDeviceId); - validEventDescriptor3.insert("paramDescriptors", QVariantList()); - validEventDescriptors3.append(validEventDescriptor3); - - QVariantMap params; - QVariantList actions; - actions.append(action1); - actions.append(action2); - params.insert("actions", actions); - params.insert("eventDescriptors", eventDescriptorList1); - params.insert("stateEvaluator", stateEvaluator0); - params.insert("name", "TestRule"); - - // Get rules and verify there is no rule added - QNetworkRequest request(QUrl("https://localhost:3333/api/v1/rules")); - QVariant response = getAndWait(request); - QVariantList rulesList = response.toList(); - QVERIFY2(rulesList.count() == 0, "there should be no rules."); - - // ADD rule - request.setUrl(QUrl(QString("https://localhost:3333/api/v1/rules"))); - request.setHeader(QNetworkRequest::ContentTypeHeader, "text/json"); - response = postAndWait(request, params); - QVERIFY(!response.isNull()); - - RuleId ruleId = RuleId(response.toMap().value("id").toString()); - QVERIFY(!ruleId.isNull()); - - // now create the new rule and edit the original one - params.clear(); - params.insert("ruleId", ruleId.toString()); - params.insert("name", name); - - if (!eventDescriptor.isEmpty()) { - params.insert("eventDescriptors", QVariantList() << eventDescriptor); - } - if (!eventDescriptorList.isEmpty()) { - params.insert("eventDescriptors", eventDescriptorList); - } - actions.clear(); - actions.append(action); - params.insert("actions", actions); - - QVariantList exitActions; - if (!exitAction.isEmpty()) { - exitActions.append(exitAction); - params.insert("exitActions", exitActions); - } - params.insert("stateEvaluator", stateEvaluator); - if (!enabled) { - params.insert("enabled", enabled); - } - - // EDIT rule - request.setUrl(QUrl(QString("https://localhost:3333/api/v1/rules/%1").arg(ruleId.toString()))); - request.setHeader(QNetworkRequest::ContentTypeHeader, "text/json"); - response = putAndWait(request, params, expectedStatusCode); - QVERIFY(!response.isNull()); - - if (expectedStatusCode == 200) { - // get edit rule and verify params - request.setUrl(QUrl(QString("https://localhost:3333/api/v1/rules"))); - response = getAndWait(request); - QVERIFY(!response.isNull()); - } - - // REMOVE rule - request.setUrl(QUrl(QString("https://localhost:3333/api/v1/rules/%1").arg(ruleId.toString()))); - response = deleteAndWait(request); - QVERIFY(!response.isNull()); - - // check if removed - request.setUrl(QUrl(QString("https://localhost:3333/api/v1/rules/%1").arg(ruleId.toString()))); - response = getAndWait(request, 404); - QVERIFY(!response.isNull()); -} - -void TestRestRules::enableDisableRule() -{ - QVariantMap addRuleParams; - QVariantList events; - QVariantMap event1; - event1.insert("eventTypeId", mockEvent1EventTypeId); - event1.insert("deviceId", m_mockDeviceId); - events.append(event1); - addRuleParams.insert("eventDescriptors", events); - addRuleParams.insert("name", "TestRule"); - - QVariantList actions; - QVariantMap action; - action.insert("actionTypeId", mockWithoutParamsActionTypeId); - action.insert("deviceId", m_mockDeviceId); - actions.append(action); - addRuleParams.insert("actions", actions); - - // ADD rule - QNetworkRequest request = QNetworkRequest(QUrl(QString("https://localhost:3333/api/v1/rules"))); - request.setHeader(QNetworkRequest::ContentTypeHeader, "text/json"); - QVariant response = postAndWait(request, addRuleParams); - RuleId ruleId = RuleId(response.toMap().value("id").toString()); - QVERIFY(!ruleId.isNull()); - - // ENABLE rule - request = QNetworkRequest(QUrl(QString("https://localhost:3333/api/v1/rules/%1/enable").arg(ruleId.toString()))); - response = postAndWait(request, QVariant()); - QVERIFY2(!response.isNull(), "Could not read response"); - - // Trigger an event - triggerMockEvent(); - verifyRuleExecuted(mockWithoutParamsActionTypeId); - - cleanupMockHistory(); - - // DISABLE the rule - request = QNetworkRequest(QUrl(QString("https://localhost:3333/api/v1/rules/%1/disable").arg(ruleId.toString()))); - response = postAndWait(request, QVariant()); - QVERIFY2(!response.isNull(), "Could not read response"); - - // trigger event in mock device - triggerMockEvent(); - verifyRuleNotExecuted(); - - cleanupMockHistory(); - - // ENABLE again - request = QNetworkRequest(QUrl(QString("https://localhost:3333/api/v1/rules/%1/enable").arg(ruleId.toString()))); - response = postAndWait(request, QVariant()); - QVERIFY2(!response.isNull(), "Could not read response"); - - // trigger event in mock device - triggerMockEvent(); - verifyRuleExecuted(mockWithoutParamsActionTypeId); - - cleanupRules(); -} - -void TestRestRules::executeRuleActions_data() -{ - QTest::addColumn("params"); - QTest::addColumn("expectedStatusCode"); - QTest::addColumn("ruleError"); - - QTest::newRow("executable rule, enabled") << validIntStateBasedRule("Executeable", true, true) << 200 << RuleEngine::RuleErrorNoError; - QTest::newRow("executable rule, disabled") << validIntStateBasedRule("Executeable", true, false) << 200 << RuleEngine::RuleErrorNoError; - QTest::newRow("not executable rule, enabled") << validIntStateBasedRule("Not Executable", false, true) << 500 << RuleEngine::RuleErrorNotExecutable; - QTest::newRow("not executable rule, disabled") << validIntStateBasedRule("Not Executable", false, false) << 500 << RuleEngine::RuleErrorNotExecutable; -} - -void TestRestRules::executeRuleActions() -{ - QFETCH(QVariant, params); - QFETCH(int, expectedStatusCode); - QFETCH(RuleEngine::RuleError, ruleError); - - // ADD rule - QNetworkRequest request(QUrl(QString("https://localhost:3333/api/v1/rules"))); - request.setHeader(QNetworkRequest::ContentTypeHeader, "text/json"); - QVariant response = postAndWait(request, params); - - RuleId ruleId = RuleId(response.toMap().value("id").toString()); - QVERIFY(!ruleId.isNull()); - - request.setUrl(QUrl(QString("https://localhost:3333/api/v1/rules/%1").arg(ruleId.toString()))); - response = getAndWait(request); - - cleanupMockHistory(); - - // EXECUTE actions - request.setUrl(QUrl(QString("https://localhost:3333/api/v1/rules/%1/executeactions").arg(ruleId.toString()))); - response = postAndWait(request, QVariant(), expectedStatusCode); - QVERIFY(!response.isNull()); - QCOMPARE(JsonTypes::ruleErrorToString(ruleError), response.toMap().value("error").toString()); - - if (ruleError == RuleEngine::RuleErrorNoError) { - verifyRuleExecuted(mockWithParamsActionTypeId); - } else { - verifyRuleNotExecuted(); - } - - cleanupMockHistory(); - - // EXECUTE exit actions - request.setUrl(QUrl(QString("https://localhost:3333/api/v1/rules/%1/executeexitactions").arg(ruleId.toString()))); - response = postAndWait(request, QVariant(), expectedStatusCode); - QVERIFY(!response.isNull()); - QCOMPARE(JsonTypes::ruleErrorToString(ruleError), response.toMap().value("error").toString()); - - if (ruleError == RuleEngine::RuleErrorNoError) { - verifyRuleExecuted(mockWithoutParamsActionTypeId); - } else { - verifyRuleNotExecuted(); - } - - cleanupMockHistory(); - - // REMOVE rule - request.setUrl(QUrl(QString("https://localhost:3333/api/v1/rules/%1").arg(ruleId.toString()))); - response = deleteAndWait(request); - QVERIFY(!response.isNull()); - QCOMPARE(JsonTypes::ruleErrorToString(RuleEngine::RuleErrorNoError), response.toMap().value("error").toString()); - - // check if removed - request.setUrl(QUrl(QString("https://localhost:3333/api/v1/rules/%1").arg(ruleId.toString()))); - response = getAndWait(request, 404); - QVERIFY(!response.isNull()); -} - - - -#include "testrestrules.moc" -QTEST_MAIN(TestRestRules) diff --git a/tests/auto/restvendors/restvendors.pro b/tests/auto/restvendors/restvendors.pro deleted file mode 100644 index 7854165a..00000000 --- a/tests/auto/restvendors/restvendors.pro +++ /dev/null @@ -1,5 +0,0 @@ -include(../../../nymea.pri) -include(../autotests.pri) - -TARGET = restvendors -SOURCES += testrestvendors.cpp diff --git a/tests/auto/restvendors/temp b/tests/auto/restvendors/temp deleted file mode 100644 index e69de29b..00000000 diff --git a/tests/auto/restvendors/testrestvendors.cpp b/tests/auto/restvendors/testrestvendors.cpp deleted file mode 100644 index 0a41ebe7..00000000 --- a/tests/auto/restvendors/testrestvendors.cpp +++ /dev/null @@ -1,146 +0,0 @@ -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - * * - * Copyright (C) 2015 Simon Stürz * - * * - * This file is part of nymea. * - * * - * nymea is free software: you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation, version 2 of the License. * - * * - ** - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with nymea. If not, see . * - * * - * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ - -#include "nymeatestbase.h" -#include "nymeacore.h" - -using namespace nymeaserver; - -class TestRestVendors: public NymeaTestBase -{ - Q_OBJECT - -private slots: - void initTestCase(); - - void getVendors(); - void invalidMethod(); - void invalidPath(); - - void invalidVendor_data(); - void invalidVendor(); -}; - -void TestRestVendors::initTestCase() -{ - NymeaTestBase::initTestCase(); - - foreach (const WebServerConfiguration &config, NymeaCore::instance()->configuration()->webServerConfigurations()) { - if (config.port == 3333 && (config.address == QHostAddress("127.0.0.1") || config.address == QHostAddress("0.0.0.0"))) { - qDebug() << "Already have a webserver listening on 127.0.0.1:3333"; - return; - } - } - - qDebug() << "Creating new webserver instance on 127.0.0.1:3333"; - WebServerConfiguration config; - config.address = QHostAddress("127.0.0.1"); - config.port = 3333; - config.sslEnabled = true; - config.restServerEnabled = true; - NymeaCore::instance()->configuration()->setWebServerConfiguration(config); - qApp->processEvents(); -} - -void TestRestVendors::getVendors() -{ - // Get all vendors - QVariant response = getAndWait(QNetworkRequest(QUrl("https://localhost:3333/api/v1/vendors"))); - QVariantList vendorList = response.toList(); - QVERIFY2(vendorList.count() > 0, "Not enough vendors."); - - // Get each of thouse vendors individualy - foreach (const QVariant &vendor, vendorList) { - QVariantMap vendorMap = vendor.toMap(); - if (!VendorId(vendorMap.value("id").toString()).isNull()) { - QNetworkRequest request(QUrl(QString("https://localhost:3333/api/v1/vendors/%1").arg(vendorMap.value("id").toString()))); - response = getAndWait(request); - QVERIFY2(!response.isNull(), "Could not get vendor"); - } - } -} - -void TestRestVendors::invalidMethod() -{ - QNetworkAccessManager nam; - connect(&nam, &QNetworkAccessManager::sslErrors, [this, &nam](QNetworkReply *reply, const QList &) { - reply->ignoreSslErrors(); - }); - QSignalSpy clientSpy(&nam, SIGNAL(finished(QNetworkReply*))); - - QNetworkRequest request; - request.setUrl(QUrl("https://localhost:3333/api/v1/vendors")); - QNetworkReply *reply = nam.post(request, QByteArray()); - - clientSpy.wait(); - QVERIFY2(clientSpy.count() != 0, "expected at least 1 response from webserver"); - - bool ok = false; - int statusCode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(&ok); - QVERIFY2(ok, "Could not convert statuscode from response to int"); - QCOMPARE(statusCode, 400); - - reply->deleteLater(); -} - -void TestRestVendors::invalidPath() -{ - QNetworkAccessManager nam; - connect(&nam, &QNetworkAccessManager::sslErrors, [this, &nam](QNetworkReply *reply, const QList &) { - reply->ignoreSslErrors(); - }); - QSignalSpy clientSpy(&nam, SIGNAL(finished(QNetworkReply*))); - - QNetworkRequest request; - request.setUrl(QUrl("https://localhost:3333/api/v1/vendors/" + QUuid::createUuid().toString() + "/" + QUuid::createUuid().toString())); - QNetworkReply *reply = nam.get(request); - - clientSpy.wait(); - QVERIFY2(clientSpy.count() != 0, "expected at least 1 response from webserver"); - - bool ok = false; - int statusCode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(&ok); - QVERIFY2(ok, "Could not convert statuscode from response to int"); - QCOMPARE(statusCode, 501); - - reply->deleteLater(); -} - -void TestRestVendors::invalidVendor_data() -{ - QTest::addColumn("path"); - QTest::addColumn("expectedStatusCode"); - - QTest::newRow("invalid VendorId") << QUuid::createUuid().toString() << 404; - QTest::newRow("invalid VendorId format") << "uuid" << 400; -} - -void TestRestVendors::invalidVendor() -{ - QFETCH(QString, path); - QFETCH(int, expectedStatusCode); - - QNetworkRequest request(QUrl("https://localhost:3333/api/v1/vendors/" + path)); - QVariant response = getAndWait(request, expectedStatusCode); - QCOMPARE(JsonTypes::deviceErrorToString(Device::DeviceErrorVendorNotFound), response.toMap().value("error").toString()); -} - -#include "testrestvendors.moc" -QTEST_MAIN(TestRestVendors)