Merge branch '1-modify-readme-md-and-describe-restapi' into 'master'

Resolve "Modify readme.md and describe RestAPI"

Closes #1

See merge request spaceti-app/integrations/acs/colnod-connector!1
This commit is contained in:
Filip Bucek 2019-10-01 11:22:15 +00:00
commit c1cce5fc41
13 changed files with 412 additions and 0 deletions

73
.gitignore vendored Normal file
View File

@ -0,0 +1,73 @@
# This file is used to ignore files which are generated
# ----------------------------------------------------------------------------
*~
*.autosave
*.a
*.core
*.moc
*.o
*.obj
*.orig
*.rej
*.so
*.so.*
*_pch.h.cpp
*_resource.rc
*.qm
.#*
*.*#
core
!core/
tags
.DS_Store
.directory
*.debug
Makefile*
*.prl
*.app
moc_*.cpp
ui_*.h
qrc_*.cpp
Thumbs.db
*.res
*.rc
/.qmake.cache
/.qmake.stash
# qtcreator generated files
*.pro.user*
# xemacs temporary files
*.flc
# Vim temporary files
.*.swp
# Visual Studio generated files
*.ib_pdb_index
*.idb
*.ilk
*.pdb
*.sln
*.suo
*.vcproj
*vcproj.*.*.user
*.ncb
*.sdf
*.opensdf
*.vcxproj
*vcxproj.*
# MinGW generated files
*.Debug
*.Release
# Python byte code
*.pyc
# Binaries
# --------
*.dll
*.exe

5
colnod-connector.pro Normal file
View File

@ -0,0 +1,5 @@
TEMPLATE = subdirs
SUBDIRS += \
src/app \
test

8
src/app/app.pro Normal file
View File

@ -0,0 +1,8 @@
TEMPLATE = app
QT += core sql network
CONFIG += debug console
SOURCES += main.cpp
include(../colnod/colnod.pri)

10
src/app/main.cpp Normal file
View File

@ -0,0 +1,10 @@
#include <QCoreApplication>
#include "requestmanager.h"
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
//RequestManager *reqman = new RequestManager();
return a.exec();
}

9
src/colnod/colnod.pri Normal file
View File

@ -0,0 +1,9 @@
INCLUDEPATH += $$PWD
#SRC_DIR = $$PWD
message($$PWD)
SOURCES += \
$$PWD/requestmanager.cpp
HEADERS += \
$$PWD/requestmanager.h
message($$SOURCES)

View File

@ -0,0 +1,124 @@
#include "requestmanager.h"
RequestManager::RequestManager()
{
manager = new QNetworkAccessManager();
token = "";
loginStatus = false;
QFile configFile(QDir::current().filePath("config.json"));
if (!configFile.open(QIODevice::ReadOnly)) {
qCritical() << "Couldn't open config file config.json" << QDir::current().filePath("config.json");
QCoreApplication::exit(-1);
return;
}
this->config = QJsonDocument::fromJson(configFile.readAll());
QObject::connect(manager, &QNetworkAccessManager::sslErrors, this, &RequestManager::onSSLError);
}
void RequestManager::login(QString host, QString username, QString password)
{
QNetworkRequest request;
QString hash = encryptedPassword(password);
authHeader = getLoginHeader(username, hash);
QJsonObject reqBody = {
{"password", hash},
{"username", username}
};
this->host = host;
request.setUrl(host + "/AaaManager/authSession");
request.setRawHeader("Authorization", authHeader.toLocal8Bit());
request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json; charset=UTF-8");
QJsonDocument jsonDocument;
jsonDocument.setObject(reqBody);
QNetworkReply* reply = manager->post(request, jsonDocument.toJson());
QObject::connect(reply, &QNetworkReply::finished, [=]() {
if (reply->error())
{
qDebug() << reply->errorString();
loginStatus = false;
qDebug() << reply->readAll();
return;
}
jsonResponse = reply->readAll();
prepareAuthHeader();
emit successLogin();
reply->deleteLater();
});
}
void RequestManager::getRequest(QString endpoint)
{
QNetworkRequest request;
request.setUrl(host + endpoint);
request.setRawHeader("Authorization", authHeader.toLocal8Bit());
QNetworkReply* reply = manager->post(request, QByteArray());
QObject::connect(reply, &QNetworkReply::finished, [=]() {
if (reply->error())
{
qDebug() << reply->errorString();
qDebug() << reply->readAll();
return;
}
//print reply info
auto items = reply->rawHeaderPairs();
for (auto item : items)
{
qDebug() << item;
}
auto reqHeaderName = reply->request().rawHeaderList();
for (QString header : reqHeaderName)
{
qDebug() << reply->request().rawHeader(header.toUtf8());
}
qDebug() << reply->attribute(QNetworkRequest::HttpStatusCodeAttribute);
jsonResponse = reply->readAll();
emit responseReady();
});
}
QString RequestManager::getFromJson(QString json, QString member)
{
QJsonParseError err;
QJsonDocument document = QJsonDocument::fromJson(json.toUtf8(),&err);
if (err.error != 0)
{
qDebug() << err.errorString();
}
return document[member].toString();
}
QString RequestManager::encryptedPassword(QString password)
{
return QCryptographicHash::hash(password.toLocal8Bit(), QCryptographicHash::Sha512).toHex().toUpper();
}
QString RequestManager::getLoginHeader(QString username, QString hash)
{
QString authValue = username + ":" + hash;
return "Basic " + authValue.toLocal8Bit().toBase64();
}
void RequestManager::prepareAuthHeader()
{
token = getFromJson(jsonResponse, "id");
QString authValue = token + ":";
authHeader = "Basic" + authValue.toLocal8Bit().toBase64();
}
void RequestManager::onSSLError(QNetworkReply *reply, const QList<QSslError> &errors)
{
qDebug() << "Network SSL errors";
for (const auto &error : errors)
{
if (error.error() == QSslError::SelfSignedCertificate)
reply->ignoreSslErrors(errors);
qDebug() << error.errorString();
}
}

View File

@ -0,0 +1,62 @@
#ifndef REQUESTMANAGER_H
#define REQUESTMANAGER_H
#include <QObject>
#include <QNetworkReply>
#include <QNetworkAccessManager>
#include <QNetworkRequest>
#include <QJsonDocument>
#include <QJsonObject>
#include <qcoreapplication.h>
#include <qnetworkreply.h>
#include <QByteArray>
#include <QJsonDocument>
#include <QJsonObject>
#include <QJsonParseError>
#include <QFile>
#include <QString>
#include <QMultiMap>
#include <QPointer>
#include <QDir>
#include <QSslError>
class RequestManager : public QObject
{
Q_OBJECT
public:
RequestManager();
void login(QString endpoint, QString username, QString password);
void getRequest(QString endpoint);
void fetchSubjects(QString endpoint);
const QJsonDocument &getConfig() const {return config;}
const QString &getResponse() const {return jsonResponse;}
QString getToken(){return token;}
private:
QString getFromJson(QString json, QString member);
QString encryptedPassword(QString password);
QString getLoginHeader(QString username, QString hash);
void prepareAuthHeader();
private slots:
void onSSLError(QNetworkReply *reply, const QList<QSslError> &errors);
signals:
void successLogin();
void responseReady();
private:
QNetworkAccessManager* manager;
QJsonDocument config;
QString authHeader;
QString host;
QString token;
QString jsonResponse;
bool loginStatus;
QString tenant;
};
#endif // REQUESTMANAGER_H

5
src/config.json Normal file
View File

@ -0,0 +1,5 @@
{
"host": "https://localhost:8080",
"username": "spaceti",
"password": "SuperSecretPassword"
}

5
test/test.pro Normal file
View File

@ -0,0 +1,5 @@
TEMPLATE = subdirs
SUBDIRS += \
unitTests

View File

@ -0,0 +1,66 @@
#include "unittest.h"
void UnitTest::loginSuccessfully()
{
RequestManager* testAccess = new RequestManager();
QJsonDocument config = testAccess->getConfig();
QSignalSpy spy(testAccess, SIGNAL(successLogin()));
testAccess->login(host, email, password);
spy.wait();
QVERIFY(spy.isValid());
QCOMPARE(spy.count(), 1);
QString json = testAccess->getResponse();
qDebug() << json;
QJsonDocument doc = QJsonDocument::fromJson(json.toUtf8());
QVERIFY2(doc["id"].isString(), "No parameter 'id' in response");
}
//POST request w/o datas
void UnitTest::getSubjects()
{
RequestManager* testAccess = new RequestManager();
testAccess->login(host, email, password);
QSignalSpy spy(testAccess, SIGNAL(responseReady()));
testAccess->getRequest("/SubjectManager/getSubjects");
spy.wait();
QVERIFY(spy.isValid());
QCOMPARE(spy.count(), 1);
QString json = testAccess->getResponse();
QJsonDocument doc = QJsonDocument::fromJson(json.toUtf8());
QVERIFY(doc.isObject());
QVERIFY2(doc["items"].isArray(), "No parameter 'id' in response");
qDebug() << doc["items"].toArray()[0].toObject()["id"].toString();
QVERIFY2(doc["items"].toArray()[0].toObject()["id"].isString(), "ada");
}
void UnitTest::getTokens()
{
RequestManager* testAccess = new RequestManager();
testAccess->login(host, email, password);
QSignalSpy spy(testAccess, SIGNAL(responseReady()));
testAccess->getRequest("/TokenManager/getTokens");
QCOMPARE(spy.count(), 0);
spy.wait();
QVERIFY(spy.isValid());
QCOMPARE(spy.count(), 1);
qDebug() << testAccess->getResponse();
}
void UnitTest::getTokensOpenManager()
{
RequestManager* testAccess = new RequestManager();
testAccess->login(host, email, password);
QSignalSpy spy(testAccess, SIGNAL(responseReady()));
testAccess->getRequest("/OpenManager/getTokenSubject");
QCOMPARE(spy.count(), 0);
spy.wait();
QVERIFY(spy.isValid());
QCOMPARE(spy.count(), 1);
QString response = testAccess->getResponse();
QVERIFY(!response.isEmpty());
qDebug() << response;
}
QTEST_MAIN(UnitTest)

View File

@ -0,0 +1,5 @@
{
"host": "https://localhost:8080",
"username": "spaceti",
"password": "SuperSecretPassword"
}

View File

@ -0,0 +1,14 @@
QT -= gui
QT += core sql network testlib
HEADERS += \
unittest.h
SOURCES += \
unittest.cpp
include(../../src/colnod/colnod.pri)
# Default rules for deployment.
qnx: target.path = /tmp/$${TARGET}/bin
else: unix:!android: target.path = /opt/$${TARGET}/bin
!isEmpty(target.path): INSTALLS += target

26
test/unitTests/unittest.h Normal file
View File

@ -0,0 +1,26 @@
#pragma once
#include <QtTest/QtTest>
#include <QSignalSpy>
#include <requestmanager.h>
class UnitTest : public QObject
{
Q_OBJECT
private slots:
void loginSuccessfully();
void getTokens();
void getTokensOpenManager();
void getSubjects();
private:
// QString host = "https://localhost:8080"; //colnod server (ssh -L 8080:192.168.254.11:8443 penta-master)
QString host = "https://192.168.1.3:8443"; //local testing server
QString password = "spaceti1";
QString email = "spaceti";
};