diff --git a/README.md b/README.md index d8f034d..b652349 100644 --- a/README.md +++ b/README.md @@ -2,6 +2,23 @@ Acces Management System of Colsys: [Product info](http://produkty.colsys.cz/colnod/) +## TODO +- [ ] Debug Mode +- [ ] Logs + - Timestamp + - Id of record + - Destination + - Report + - Token `action` to `subject_id` + - Sbject `action` + - `action` - updated, deleted, added +- [ ] App output + - To Colnod + - Number of tokens added/deleted/updated + - To DB + - Number of subjects added/deleted/updated + - Number of tokens added/deleted/updated + ## Requirements - QPSQL driver must be installed (PostgreSQL) diff --git a/bugs/getTokensDeleted.sh b/bugs/getTokensDeleted.sh new file mode 100755 index 0000000..6d762b7 --- /dev/null +++ b/bugs/getTokensDeleted.sh @@ -0,0 +1,36 @@ +#!/bin/bash +# Saving login token +TOKEN=$(curl -k --user "spaceti:E7FEA07DBC82FB9BA34B2E453E2EFE89F0583E7187543507EF11E84726071FE428445372F2E46B455EB0C79747C51E362F403CE39473A2A8C2DFA0CE5C9826C0" -d '{"password":"E7FEA07DBC82FB9BA34B2E453E2EFE89F0583E7187543507EF11E84726071FE428445372F2E46B455EB0C79747C51E362F403CE39473A2A8C2DFA0CE5C9826C0","username":"spaceti"}' -H "Content-Type: application/json" https://192.168.1.3:8443/AaaManager/authSession 2>/dev/null | python -c 'import json,sys;obj=json.load(sys.stdin);print obj["id"]') +# Saving current time and timestamp +DATE=`date +"%Y-%m-%d %H:%M:%S"` +TIMESTAMP=`date +%s%N | cut -b1-13` +echo +echo "I'm going to add and delete test token," +echo "then ask for deleted tokens with time before deleting" +echo "and with time after deleting." +echo "It should return token deleted with time before," +echo "but should NOT with time after." +echo "====================================================================" +echo "Current time: $DATE / timestamp: $TIMESTAMP" +echo "====================================================================" +echo "Creating test token with id = 235c4a3c-7e20-4f2a-8ed2-2fe36cc87907" +curl -k -u "$TOKEN:" -d '{"items":[{"id":"235c4a3c-7e20-4f2a-8ed2-2fe36cc87907","name":"bug test","description":"mobile","tokenType":"Token","tokenBits":32,"tokenData":"7B9D32","timeToLive":255,"authErrors":255,"flags":["Enabled","NoValidity"],"subjectId":"72b37f7e-5761-4e6c-8e87-20c0bed0d904"}]}' -H "Content-Type: application/json" -X POST https://192.168.1.3:8443/TokenManager/setTokens +echo +echo "Deleting test token..." +curl -k -u "$TOKEN:" -d '{"items":["235c4a3c-7e20-4f2a-8ed2-2fe36cc87907"]}' -H "Content-Type: application/json" -X POST https://192.168.1.3:8443/TokenManager/deleteTokens +echo +echo +echo "getTokensDeleted with time (before deleting): $DATE" +echo "Expect only one token which has been deleted" +curl -k -u "$TOKEN:" -d "{\"timestamp\":$TIMESTAMP}" -H "Content-Type: application/json" -X POST https://192.168.1.3:8443/TokenManager/getTokensDeleted +echo +echo "====================================================================" +echo "Waiting 5 secs, so we can ask again after deleting" +echo "====================================================================" +sleep 5 +echo "getTokensDeleted with time (after deleting): $DATE + 2 sec" +echo "Expect no tokens returned, because token has been deleted before more than 5 secs" +((TIMESTAMP=TIMESTAMP+2000)) +curl -k -u "$TOKEN:" -d "{\"timestamp\":$TIMESTAMP}" -H "Content-Type: application/json" -X POST https://192.168.1.3:8443/TokenManager/getTokensDeleted +echo +exit \ No newline at end of file diff --git a/bugs/getTokensDeleted_01.sh b/bugs/getTokensDeleted_01.sh new file mode 100755 index 0000000..42aa9b3 --- /dev/null +++ b/bugs/getTokensDeleted_01.sh @@ -0,0 +1,66 @@ +#!/bin/bash +# Saving login token +TOKEN=$(curl -k --user "spaceti:E7FEA07DBC82FB9BA34B2E453E2EFE89F0583E7187543507EF11E84726071FE428445372F2E46B455EB0C79747C51E362F403CE39473A2A8C2DFA0CE5C9826C0" -d '{"password":"E7FEA07DBC82FB9BA34B2E453E2EFE89F0583E7187543507EF11E84726071FE428445372F2E46B455EB0C79747C51E362F403CE39473A2A8C2DFA0CE5C9826C0","username":"spaceti"}' -H "Content-Type: application/json" https://192.168.1.3:8443/AaaManager/authSession 2>/dev/null | python -c 'import json,sys;obj=json.load(sys.stdin);print obj["id"]') +# Saving current time and timestamp +# echo "==================================" +# echo "Saving current time ( saved_time ): $DATE / timestamp: $TIMESTAMP" +# echo "==================================" + +echo "========================" +echo "Script to show uncorrect behavior when returing deleted tokens" +echo "1. create token" +echo "2. deletet token" +echo "3. request deleted token with time after last token was deleted" +echo "------------------------" + +DATE=`date +"%Y-%m-%d %H:%M:%S"` +TIMESTAMP=`date +%s000 | cut -b1-13` + +echo "------------------------" +echo "STEPS : Create TOKEN and then deletes it" +echo "EXPECT : Token is deleted and is returned when getting deleted token with saved_time ( time before was deleted )" +echo "------------------------" +#echo "Creating test token with id = 235c4a3c-7e20-4f2a-8ed2-2fe36cc87907" +RES=$(curl -k -u "$TOKEN:" -d '{"items":[{"id":"235c4a3c-7e20-4f2a-8ed2-2fe36cc87907","name":"bug test","description":"mobile","tokenType":"Token","tokenBits":32,"tokenData":"7B9D32","timeToLive":255,"authErrors":255,"flags":["Enabled","NoValidity"],"subjectId":"72b37f7e-5761-4e6c-8e87-20c0bed0d904"}]}' -H "Content-Type: application/json" -X POST https://192.168.1.3:8443/TokenManager/setTokens 2>/dev/null ) +#echo +#echo "Deleting test token..." +RES=$(curl -k -u "$TOKEN:" -d '{"items":["235c4a3c-7e20-4f2a-8ed2-2fe36cc87907"]}' -H "Content-Type: application/json" -X POST https://192.168.1.3:8443/TokenManager/deleteTokens 2>/dev/null ) +#echo "/getTokensDeleted with time: $DATE" +#echo "Expect only one token which has been deleted" +RES=$(curl -k -u "$TOKEN:" -d "{\"timestamp\":$TIMESTAMP}" -H "Content-Type: application/json" -X POST https://192.168.1.3:8443/TokenManager/getTokensDeleted 2>/dev/null ) +echo "EXPECTED : {\"items\":[\"235c4a3c-7e20-4f2a-8ed2-2fe36cc87907\"]}" +echo "ACTUAL : $RES" +echo "------------------------" +echo "OK - expected token is returned" +echo "------------------------" +echo "" +echo "==================================" +echo "Now we wait 5 sec to ensure timestamp for deleted token is in past" +echo "==================================" +echo "" +sleep 5 +echo "------------------------" +echo "STEPS : Getting deleted tokens before 2 sec" +echo "EXPECT : no tokens ( since we have deleted token before 5 sec )" +echo "------------------------" +((TIMESTAMP=TIMESTAMP+2000)) # adding 2000 ms to saved timestamp +RES=$(curl -k -u "$TOKEN:" -d "{\"timestamp\":$TIMESTAMP}" -H "Content-Type: application/json" -X POST https://192.168.1.3:8443/TokenManager/getTokensDeleted 2>/dev/null ) +echo "EXPECTED : {"items":[]}" +echo "ACTUAL : $RES" +echo "------------------------" +echo "BUG: Token was deleted 5 seconds ago, but was returned even we requested tokens deleted 2 sec ago" +echo "------------------------" + +echo "" +echo "Another bug: future date" +echo "------------------------" +echo "STEPS : Getting deleted tokens with future date" +echo "EXPECT : no tokens" +echo "------------------------" +((TIMESTAMP=TIMESTAMP+20000)) # adding 20s to saved timestamp +RES=$(curl -k -u "$TOKEN:" -d "{\"timestamp\":$TIMESTAMP}" -H "Content-Type: application/json" -X POST https://192.168.1.3:8443/TokenManager/getTokensDeleted 2>/dev/null ) +echo "EXPECTED : {"items":[]}" +echo "ACTUAL : $RES" +echo "------------------------" +echo "BUG: Token was deleted 5 seconds ago, but was returned even we requested time in future" +echo "------------------------" diff --git a/src/app/main.cpp b/src/app/main.cpp index 70c5e9e..3a95aa2 100644 --- a/src/app/main.cpp +++ b/src/app/main.cpp @@ -1,19 +1,34 @@ #include #include "datamanager.h" -#include "colnodapi.h" +#include "syncmanager.h" +#include int main(int argc, char *argv[]) { - QCoreApplication a(argc, argv); - ColnodAPI *api = new ColnodAPI(); - - api->downloadData(); // this will start downloading data - QObject::connect(api, &ColnodAPI::dataDownloaded, [=](){ - qDebug() << "now I have all data"; - api->syncDataToColnod(); - QCoreApplication::quit(); + QCoreApplication app(argc, argv); + QCoreApplication::setApplicationName("colnod-connector"); + QCoreApplication::setApplicationVersion("1.0"); + QCommandLineParser parser; + Logger *logger = Logger::getLogger(); + parser.setApplicationDescription("Colnod sync"); + QCommandLineOption dryModeOption("dryMode", "ColnodAPI", "Read-only mode, prints changes which would normally be made"); + parser.addOption(dryModeOption); + parser.process(app); + SyncManager api(parser.isSet(dryModeOption)); + api.loadDataFromDB(); + api.loadDataFromColnod(); + QObject::connect(&api, &SyncManager::dataDownloaded, [&](){ + QObject::connect(&api, &SyncManager::syncFinished, [](){ + qDebug() << "Quit"; + QCoreApplication::exit(); + }); + api.syncDataFromColnodToDB(); + api.syncDataFromDBToColnod(); }); - - return a.exec(); + QObject::connect(&api, &SyncManager::error, [](){ + qDebug() << "error"; + QCoreApplication::exit(); + }); + return QCoreApplication::exec(); } diff --git a/src/colnod/colnod.pri b/src/colnod/colnod.pri index 51c711d..d5cabe1 100644 --- a/src/colnod/colnod.pri +++ b/src/colnod/colnod.pri @@ -2,22 +2,24 @@ INCLUDEPATH += $$PWD #SRC_DIR = $$PWD message($$PWD) SOURCES += \ - $$PWD/colnodapi.cpp \ $$PWD/databasemanager.cpp \ $$PWD/datamanager.cpp \ $$PWD/entity.cpp \ + $$PWD/logger.cpp \ $$PWD/requestmanager.cpp \ $$PWD/response.cpp \ $$PWD/subject.cpp \ + $$PWD/syncmanager.cpp \ $$PWD/token.cpp HEADERS += \ - $$PWD/colnodapi.h \ $$PWD/databasemanager.h \ $$PWD/datamanager.h \ $$PWD/entity.h \ + $$PWD/logger.h \ $$PWD/requestmanager.h \ $$PWD/response.h \ $$PWD/subject.h \ + $$PWD/syncmanager.h \ $$PWD/token.h message($$SOURCES) diff --git a/src/colnod/colnodapi.cpp b/src/colnod/colnodapi.cpp deleted file mode 100644 index 7584be2..0000000 --- a/src/colnod/colnodapi.cpp +++ /dev/null @@ -1,175 +0,0 @@ -#include "colnodapi.h" - -ColnodAPI::ColnodAPI() -{ - reqMan = new RequestManager(); - dataMan = new DataManager(); -} - - -// PUBLIC FUNCTIONS -void ColnodAPI::downloadData() -{ - Response* resp0 = reqMan->getSubjects(); - connect(resp0, &Response::ready, [=](){ - dataMan->localSaveSubjects(resp0->getJson()); - areDataReady(); - resp0->deleteLater(); - }); - - Response* resp1 = reqMan->getTokens(); - connect(resp1, &Response::ready, [=](){ - dataMan->localSaveTokens(resp1->getJson()); - areDataReady(); - resp1->deleteLater(); - }); - - /* - QNetworkReply* reply2 = reqMan->getTokens(); - connect(reply2, &QNetworkReply::finished, [=](){ - data->saveTokens(reply2->readAll()); - }); - */ -} - -void ColnodAPI::downloadChangedDataFromColnod() -{ - downloadUpdatedData(); - downloadDeletedData(); -} - -void ColnodAPI::downloadUpdatedData() -{ - uint64_t lastUpdate = dataMan->getLastUpdate(); - qDebug() << lastUpdate; - Response* resp0 = reqMan->getSubjectsUpdated(lastUpdate); - connect(resp0, &Response::ready, [=](){ - dataMan->localSaveSubjects(resp0->getJson()); - areChangedDataReady(); - resp0->deleteLater(); - }); - - Response* resp1 = reqMan->getTokensUpdated(lastUpdate); - connect(resp1, &Response::ready, [=](){ - dataMan->localSaveTokens(resp1->getJson()); - areChangedDataReady(); - resp1->deleteLater(); - }); -} - -void ColnodAPI::downloadDeletedData() -{ - uint64_t lastUpdate = dataMan->getLastUpdate(); - Response* resp2 = reqMan->getSubjectsDeleted(lastUpdate); - connect(resp2, &Response::ready, [=](){ - dataMan->localSaveSubjectsToDelete(resp2->getJson()); - areChangedDataReady(); - resp2->deleteLater(); - }); - - Response* resp3 = reqMan->getTokensDeleted(lastUpdate); - connect(resp3, &Response::ready, [=](){ - dataMan->localSaveTokensToDelete(resp3->getJson()); - areChangedDataReady(); - resp3->deleteLater(); - }); - -} - -void ColnodAPI::syncDataFromColnod() -{ - dataMan->pushTokensToDB(); - dataMan->pushSubjectsToDB(); - dataMan->updateLastSync(); - dataMan->clear(); -} - -void ColnodAPI::syncChangedDataFromColnod() -{ - syncUpdatedDataFromColnod(); - syncDeletedDataFromColnod(); - dataMan->updateLastSync(); - dataMan->clear(); -} - -void ColnodAPI::syncUpdatedDataFromColnod() -{ - dataMan->pushSubjectsToDB(); - dataMan->pushTokensToDB(); -} - - -void ColnodAPI::syncDeletedDataFromColnod() -{ - dataMan->deleteSubjectsFromDB(); - dataMan->deleteTokensFromDB(); -} - - - - -void ColnodAPI::syncDataToColnod() -{ - // TODO -} - - -void ColnodAPI::syncChangedDataToColnod() -{ - // TODO - dataMan->loadTokensToAdd(); - dataMan->loadTokensToDelete(); - processDataToColnod(); - dataMan->clear(); - -} - -void ColnodAPI::processDataToColnod() -{ - QList* tokensToDelete = dataMan->getTokensToDelete(); - if ((*tokensToDelete)[0] != "empty") - { - Response* resp0 = reqMan->deleteTokens(dataMan->getTokensToDelete()); - connect(resp0, &Response::ready, [=](){ - areProcessDataReady(); - resp0->deleteLater(); - }); - } - QList>* tokens = dataMan->getTokens(); - if ((*tokens)[0]->getName() != "empty") - { - Response* resp1 = reqMan->setTokens(dataMan->getTokens()); - connect(resp1, &Response::ready, [=](){ - areProcessDataReady(); - resp1->deleteLater(); - }); - } - connect(this, &ColnodAPI::dataLoaded, this, &ColnodAPI::syncChangedDataFromColnod); -} - -void ColnodAPI::prepareDatabase() -{ - dataMan->emptyDatabase(); -} - -// PRIVATE FUNCTIONS -void ColnodAPI::areDataReady() -{ - if (dataMan->haveData()) - emit dataDownloaded(); -} - -void ColnodAPI::areChangedDataReady() -{ - if (dataMan->haveChangedData()) - emit dataDownloaded(); -} - - -void ColnodAPI::areProcessDataReady() -{ - if (dataMan->haveProcessData()) - { - emit dataLoaded(); - } -} diff --git a/src/colnod/colnodapi.h b/src/colnod/colnodapi.h deleted file mode 100644 index 31bbb2f..0000000 --- a/src/colnod/colnodapi.h +++ /dev/null @@ -1,62 +0,0 @@ -#ifndef COLNODAPI_H -#define COLNODAPI_H - -#include "requestmanager.h" -#include "datamanager.h" - - - - -class ColnodAPI : public QObject -{ - Q_OBJECT - -public: - - ColnodAPI(); - void downloadData(); - void syncDataFromColnod(); - void syncDataToColnod(); - - - - void syncChangedDataFromColnod(); - void syncChangedDataToColnod(); - - - - - void prepareDatabase(); - -public slots: - void downloadChangedDataFromColnod(); - - -signals: - void dataDownloaded(); - void dataLoaded(); - -private slots: - - -private: - void downloadUpdatedData(); - void downloadDeletedData(); - void syncUpdatedDataFromColnod(); - void syncDeletedDataFromColnod(); - void areDataReady(); - void areChangedDataReady(); - void areProcessDataReady(); - void processDataToColnod(); - - - - RequestManager* reqMan = nullptr; - // Data* data = nullptr; - DataManager* dataMan = nullptr; - bool dataReady[2] = {false}; - int index = 0; - const int numOfMembers = 2; -}; - -#endif // COLNODAPI_H diff --git a/src/colnod/databasemanager.cpp b/src/colnod/databasemanager.cpp index f45ca8a..e2a6059 100644 --- a/src/colnod/databasemanager.cpp +++ b/src/colnod/databasemanager.cpp @@ -1,212 +1,302 @@ #include "databasemanager.h" -DatabaseManager::DatabaseManager(QString host, QString dbName, QString user, QString password) +DatabaseManager::DatabaseManager(const QString& host, const QString& dbName, const QString& user, const QString& password, const bool &dryMode) + :dryMode(dryMode) { - db = QSqlDatabase::addDatabase("QPSQL"); - db.setDatabaseName(dbName); db.setHostName(host); - db.setUserName(user); - // home-office stuff - //db.setPort(80); - // + db.setUserName(user); // home-office stuff -->> db.setPort(80); db.setPassword(password); - opened = db.open(); - if (!opened) + if (!db.open()) { - qDebug() << "Opening error" + db.lastError().text(); + log("Opening error" + db.lastError().text()); + emit error(); } - query = QSqlQuery("query", db); } -void DatabaseManager::saveSubject(Subject* subject, QString table) +// add or update subject to db +int DatabaseManager::saveSubject(const std::shared_ptr& subject, const QString& table) { + QSqlQuery query; QString id = subject->idToStringWithoutBraces(); - if (checkIfExists(id, table)) - { - query.prepare(QString("UPDATE %1 SET name = :name, last_update = :last_update " - "WHERE id = :id)").arg(table)); - query.bindValue(":id", id); - query.bindValue(":name", subject->getName()); - query.bindValue(":last_update", QDateTime::fromMSecsSinceEpoch(subject->getLastUpdate()).toString("yyyy-MM-dd hh:mm:ss.zzz")); - query.exec(); - } - else - { - query.prepare(QString("INSERT INTO %1 (id, name, last_update) " - "VALUES (:id, :name, :last_update)").arg(table)); - query.bindValue(":id", id); - query.bindValue(":name", subject->getName()); - query.bindValue(":last_update", QDateTime::fromMSecsSinceEpoch(subject->getLastUpdate()).toString("yyyy-MM-dd hh:mm:ss.zzz")); - query.exec(); + int rtn; + if (checkIfExists(id, table)){ + query.prepare(QString("UPDATE %1 SET id = :id, description = :description, last_update = :last_update, name = :name, pin = :pin, last_modified = :last_modified, deleted = :deleted " + "WHERE id = :id").arg(table)); + rtn = -1; + }else{ + query.prepare(QString("INSERT INTO %1 (id, description, last_update, name, pin, last_modified, deleted) " + "VALUES (:id, :description, :last_update, :name, :pin, :last_modified, :deleted)").arg(table)); + rtn = 1; } + query.bindValue(":id", id); + query.bindValue(":description", subject->getDescription()); + query.bindValue(":name", subject->getName()); + query.bindValue(":last_update", QDateTime::fromMSecsSinceEpoch(subject->getLastUpdate()).toString("yyyy-MM-dd hh:mm:ss.zzz")); + query.bindValue(":pin", subject->getPin()); + query.bindValue(":last_modified", QDateTime::fromMSecsSinceEpoch(subject->getLastUpdate()).toString("yyyy-MM-dd hh:mm:ss.zzz")); + query.bindValue(":deleted", subject->getDeleted()); + executeQuery(query); + return rtn; } -void DatabaseManager::saveToken(Token* token, QString table) +// add or update token to DB +int DatabaseManager::saveToken(const std::shared_ptr& token, const QString& table) { + QSqlQuery query; QString id = token->idToStringWithoutBraces(); - if (checkIfExists(id, table)) - { - query.prepare(QString("UPDATE %1 SET last_update = :last_update, token_data = :data, subject_id = :subject_id) " - "WHERE id = :id").arg(table)); - query.bindValue(":id", id); - query.bindValue(":last_update", QDateTime::fromMSecsSinceEpoch(token->getLastUpdate()).toString("yyyy-MM-dd hh:mm:ss.zzz")); - query.bindValue(":data", token->getTokenData()); - query.bindValue(":subject_id", token->subjectIdToStringWithoutBraces()); - query.exec(); - } - else - { - query.prepare(QString("INSERT INTO %1 (id, last_update, token_data, subject_id) " - "VALUES (:id, :last_update, :data, :subject_id)").arg(table)); - query.bindValue(":id", id); - query.bindValue(":last_update", QDateTime::fromMSecsSinceEpoch(token->getLastUpdate()).toString("yyyy-MM-dd hh:mm:ss.zzz")); - query.bindValue(":data", token->getTokenData()); - query.bindValue(":subject_id", token->subjectIdToStringWithoutBraces()); - query.exec(); + int rtn; + if (checkIfExists(id, table)){ + query.prepare(QString("UPDATE %1 SET id = :id, auth_errors = :auth_errors, description = :description, enabled = :enabled, last_update = :last_update, name = :name, no_validity = :no_validity, time_to_live = :time_to_live, token_bits = :token_bits, token_data = :token_data, token_type = :token_type, subject_id = :subject_id, last_modified = :last_modified, deleted = :deleted " + "WHERE id = :id").arg(table)); + rtn = -1; + }else{ + query.prepare(QString("INSERT INTO %1 (id, auth_errors, description, enabled, last_update, name, no_validity, time_to_live, token_bits, token_data, token_type, subject_id, last_modified, deleted) " + "VALUES (:id, :auth_errors, :description, :enabled, :last_update, :name, :no_validity, :time_to_live, :token_bits, :token_data, :token_type, :subject_id, :last_modified, :deleted)").arg(table)); + rtn = 1; } + query.bindValue(":id", id); + query.bindValue(":auth_errors", token->getAuthErrors()); + query.bindValue(":description", token->getDescription()); + query.bindValue(":enabled", token->getFlags().contains("Enabled")); + query.bindValue(":last_update", QDateTime::fromMSecsSinceEpoch(token->getLastUpdate()).toString("yyyy-MM-dd hh:mm:ss.zzz")); + query.bindValue(":name", token->getName()); + query.bindValue(":no_validity", token->getFlags().contains("NoValidity")); + query.bindValue(":time_to_live", token->getTimeToLive()); + query.bindValue(":token_bits", token->getTokenBits()); + query.bindValue(":token_data", token->getTokenData()); + query.bindValue(":token_type", token->getTokenType()); + query.bindValue(":subject_id", token->subjectIdToStringWithoutBraces()); + query.bindValue(":last_modified", QDateTime::fromMSecsSinceEpoch(token->getLastUpdate()).toString("yyyy-MM-dd hh:mm:ss.zzz")); + query.bindValue(":deleted", token->getDeleted()); + executeQuery(query); + return rtn; } -void DatabaseManager::saveSubjectAttribute(Subject *subject, QString table) +// add of update subject attributes +void DatabaseManager::saveSubjectAttributes(const std::shared_ptr& subject, const QString& table) { + QSqlQuery query; auto attributes = subject->getAtr(); - for (auto attribute : attributes){ + for (const auto& attribute : attributes){ QString id = subject->idToStringWithoutBraces() + " " + attribute.first; - if (checkIfExists(id, table)) - { + if (checkIfExists(id, table)){ query.prepare(QString("UPDATE %1 SET id = :id, attribute_key = :key, attribute_value = :value, subject_id = :subject_id) " "WHERE id = :id").arg(table)); - query.bindValue(":id", id); - query.bindValue(":key", attribute.first); - query.bindValue(":value", attribute.second); - query.bindValue(":subject_id", subject->idToStringWithoutBraces()); - query.exec(); - } - else - { + }else{ query.prepare(QString("INSERT INTO %1 (id, attribute_key, attribute_value, subject_id)" "VALUES (:id, :key, :value, :subject_id)").arg(table)); - query.bindValue(":id", id); - query.bindValue(":key", attribute.first); - query.bindValue(":value", attribute.second); - query.bindValue(":subject_id", subject->idToStringWithoutBraces()); - query.exec(); } + query.bindValue(":id", id); + query.bindValue(":key", attribute.first); + query.bindValue(":value", attribute.second); + query.bindValue(":subject_id", subject->idToStringWithoutBraces()); + executeQuery(query); } } -void DatabaseManager::deleteItem(QString id, QString table) +// "delete" tokens from DB -> set deleted true +void DatabaseManager::setDeleted(const QString& id, const QString& table, quint64 time) { - query.prepare(QString("DELETE FROM %1 WHERE id = :id").arg(table)); + QSqlQuery query; + QString nowString = QDateTime::fromMSecsSinceEpoch(time).toString("yyyy-MM-dd hh:mm:ss.zzz"); + query.prepare(QString("UPDATE %1 SET deleted = true, last_update = :now, last_modified = :now WHERE id = :id").arg(table)); query.bindValue(":id", id); - query.exec(); + query.bindValue(":now", nowString); + executeQuery(query); } -QString DatabaseManager::getTestMessage(int id) -{ - query.prepare("SELECT message FROM test WHERE id = :id"); - query.bindValue(":id", id); - query.exec(); - query.next(); - return query.value(0).toString(); -} - -int DatabaseManager::createTestRecord(QString msg) -{ - query.exec("SELECT MAX(id) FROM test"); - query.next(); - int id = query.value(0).toInt() + 1; - query.prepare("INSERT INTO test (id, message) VALUES (:id, :msg)"); - query.bindValue(":id", id); - query.bindValue(":msg", msg); - query.exec(); - qDebug() << "U inserted new row, id: " << id << "msg: " << getTestMessage(id); - return id; -} - - -bool DatabaseManager::checkIfExists(QString id, QString table) +bool DatabaseManager::checkIfExists(const QString& id, const QString& table) { + QSqlQuery query; query.prepare(QString("SELECT EXISTS(SELECT 1 FROM %1 WHERE id = :id)").arg(table)); query.bindValue(":id", id); - query.exec(); + executeQuery(query); query.first(); return query.value(0).toBool(); } +QString DatabaseManager::getLastQuery(const QSqlQuery& query) const +{ + QString str = query.lastQuery(); + QMapIterator it(query.boundValues()); + while (it.hasNext()) + { + it.next(); + str.replace(it.key(),it.value().toString()); + } + return str; +} + +bool DatabaseManager::executeQuery(QSqlQuery &query, const QString &statement) +{ + if (statement.isEmpty()){ + if (dryMode){ + QString sqlStatement = getLastQuery(query); + qDebug() << sqlStatement; + } + if (!dryMode || getLastQuery(query).startsWith("SELECT")){ + if (!query.exec()){ + QString msg = QString("Source: Database Manager, Error: %1").arg(query.lastError().text()); + log(QString(msg)); + emit error(); + } + } + return true; + } + if (dryMode){ + qDebug() << statement; + } + if (!dryMode || statement.startsWith("SELECT")){ + if (!query.exec(statement)){ + QString msg = QString("Source: Database Manager, Error: %1").arg(query.lastError().text()); + log(QString(msg)); + emit error(); + } + } + return true; +} + void DatabaseManager::dropTables() { - query.exec("DROP TABLE IF EXISTS colnod_token, colnod_subject, colnod_subject_attribute"); + QSqlQuery query; + + executeQuery(query, "DROP TABLE IF EXISTS colnod_token, colnod_subject, colnod_subject_attribute"); } +// create table after deleting, it is used for full sync void DatabaseManager::createTables() { - query.exec("CREATE TABLE colnod_subject (" - "id CHAR(36) primary key," - "name VARCHAR(255)," - "last_update timestamp)"); + QSqlQuery query; - query.exec("CREATE TABLE colnod_token (" - "id CHAR(36) primary key," - "token_data VARCHAR(255)," - "subject_id CHAR(36)," - "last_update timestamp)"); - query.exec("CREATE TABLE colnod_subject_attribute (" - "id VARCHAR(255) primary key," - "attribute_key VARCHAR(255)," - "attribute_value VARCHAR(255)," - "subject_id CHAR(36))"); - query.exec("CREATE TABLE users (" - "id VARCHAR(255) primary key," - "email VARCHAR(255)," - "token_data VARCHAR(255)," - "last_update timestamp)"); + executeQuery(query, "CREATE TABLE colnod_subject (" + "id character(36) primary key NOT NULL," + "description character varying(255)," + "last_update timestamp NOT NULL," + "name character varying(255)," + "pin character varying(255)," + "last_modified timestamp," + "deleted BOOLEAN)"); + executeQuery(query, "CREATE TABLE colnod_token (" + "id CHAR(36) primary key NOT NULL," + "auth_errors INTEGER NOT NULL," + "description VARCHAR(255)," + "enabled BOOLEAN NOT NULL," + "last_update timestamp NOT NULL," + "name VARCHAR(255)," + "no_validity BOOLEAN NOT NULL," + "time_to_live INTEGER NOT NULL," + "token_bits INTEGER," + "token_data VARCHAR(255)," + "token_type VARCHAR(255)," + "subject_id CHAR(36)," + "last_modified timestamp," + "deleted BOOLEAN)"); + executeQuery(query, "CREATE TABLE colnod_subject_attribute (" + "id VARCHAR(255) primary key," + "attribute_key VARCHAR(255)," + "attribute_value VARCHAR(255)," + "subject_id CHAR(36))"); } -uint64_t DatabaseManager::getLastUpdate() +// return last_sync time +quint64 DatabaseManager::getLastSync() { - query.exec("SELECT EXTRACT(EPOCH FROM (SELECT MIN(last_sync) FROM changes))*1000"); //MAX for using, MIN for testing + QSqlQuery query; + executeQuery(query, "SELECT last_sync FROM config"); + query.next(); + quint64 temp = query.value(0).toULongLong(); + return temp; +} + +// on the very end of sync set new Last_sync time (begin of this sync) +void DatabaseManager::updateLastSync(quint64 lastSync) +{ + QSqlQuery query; + query.prepare("UPDATE config SET last_sync = :last_sync"); + query.bindValue(":last_sync", lastSync); + executeQuery(query); +} + + +// return set of tokens to update form DB +QSqlQuery DatabaseManager::getUpdatedTokens() +{ + QSqlQuery query; + executeQuery(query, "SELECT id, auth_errors, description, enabled, last_update, name, no_validity, time_to_live, token_bits, token_data, token_type, subject_id, last_modified, deleted " + "FROM colnod_token WHERE EXTRACT(EPOCH FROM last_modified) * 1000 > EXTRACT(EPOCH FROM last_update) * 1000"); + return query; +} + +QSqlQuery DatabaseManager::getToken(const QString& id) +{ + QSqlQuery query; + query.prepare("SELECT id, auth_errors, description, enabled, last_update, name, no_validity, time_to_live, token_bits, token_data, token_type, subject_id, last_modified, deleted " + "FROM colnod_token WHERE id = :id"); + query.bindValue(":id", id); + executeQuery(query); + query.next(); + return query; +} + +quint64 DatabaseManager::getNow() +{ + QSqlQuery query; + executeQuery(query, "SELECT EXTRACT(EPOCH FROM NOW())*1000"); query.next(); return query.value(0).toULongLong(); } -void DatabaseManager::makeTestingLast_sync() +// sync last update back to DB from Colnod after changes made to Colnod +void DatabaseManager::setLastUpdate(const QString& id, quint64 lastUpdate) { - query.prepare("INSERT INTO last_changes (last_sync) " - "VALUES (:time)"); - query.bindValue(":time", QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss.zzz")); + QSqlQuery query; + QString lsatUpdateString = QDateTime::fromMSecsSinceEpoch(lastUpdate).toString("yyyy-MM-dd hh:mm:ss.zzz"); + query.prepare("UPDATE colnod_token SET last_update = :last_update WHERE id = :id"); + query.bindValue(":id", id); + query.bindValue(":last_update", lsatUpdateString); + executeQuery(query); +} + +void DatabaseManager::log(const QString &msg) +{ + QSqlQuery query; + query.prepare("INSERT INTO logs (log_time, msg) VALUES (NOW(), :msg)"); + query.bindValue(":msg", msg); query.exec(); } -void DatabaseManager::updateLastSync() +QString DatabaseManager::getSubjectNameByTokenId(const QString &tokenId) { - query.prepare("INSERT INTO changes (last_sync) " - "VALUES (:time)"); - query.bindValue(":time", QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss.zzz")); - query.exec(); + QSqlQuery query; + query.prepare("SELECT name FROM colnod_subject WHERE id = (SELECT subject_id FROM colnod_token WHERE id = :tokenId)"); + query.bindValue(":tokenId", tokenId); + executeQuery(query); + if (query.next()) + return query.value(0).toString(); + qWarning() << "Token:" << tokenId << "is not assigned to any subject"; + return "(No subject)"; } - -QSqlQuery* DatabaseManager::getTokensToAdd() +QString DatabaseManager::getSubjectNameById(const QString &id) { - QSqlQuery* qry = new QSqlQuery; - qry->exec("SELECT name, token_data FROM changes WHERE status = 'toBeAdd'"); - return qry; + QSqlQuery query; + query.prepare("SELECT name FROM colnod_subject WHERE id = :id"); + query.bindValue(":id", id); + executeQuery(query); + if (query.next()) + return query.value(0).toString(); + qWarning() << "Subject:" << id << "doesn't exists"; + return "(No subject)"; } -QSqlQuery* DatabaseManager::getTokensToDelete() +bool DatabaseManager::checkDeletedToken(const QString &id) { - QSqlQuery* qry = new QSqlQuery; - qry->exec("SELECT id FROM changes WHERE status = 'toBeDeleted'"); - return qry; -} - -QUuid DatabaseManager::getId(QString name) -{ - query.prepare("SELECT id FROM colnod_subject WHERE name = :name"); - query.bindValue(":name", name); - query.exec(); + QSqlQuery query; + query.prepare("SELECT deleted FROM colnod_token WHERE id = :id"); + query.bindValue(":id", id); + executeQuery(query); query.next(); - return query.value(0).toUuid(); + return query.value(0).toBool(); } diff --git a/src/colnod/databasemanager.h b/src/colnod/databasemanager.h index 0425ae5..1ce4b50 100644 --- a/src/colnod/databasemanager.h +++ b/src/colnod/databasemanager.h @@ -1,5 +1,5 @@ -#ifndef DATABASEMANAGER_H -#define DATABASEMANAGER_H +#pragma once + #include #include #include @@ -10,49 +10,47 @@ #include "subject.h" #include "token.h" #include +//#include "logger.h" class DatabaseManager : public QObject { Q_OBJECT public: - DatabaseManager(QString host, QString dbName, QString user, QString password); + DatabaseManager(const QString& host, const QString& dbName, const QString& user, const QString& password, const bool& dryMode = false); - void saveSubject(Subject* subject, QString table); - void saveToken(Token* token, QString table); - void saveSubjectAttribute(Subject* subject, QString table); - void deleteItem(QString id, QString table); - - QString getTestMessage(int id); - int createTestRecord(QString msg); - // - void makeTestingLast_sync(); - // + int saveSubject(const std::shared_ptr& subject, const QString& table); + int saveToken(const std::shared_ptr& token, const QString& table); + void saveSubjectAttributes(const std::shared_ptr& subject, const QString& table); + void setDeleted(const QString& id, const QString& table, quint64 time); void dropTables(); void createTables(); - bool getOpened() {return opened;} - uint64_t getLastUpdate(); - void updateLastSync(); + quint64 getLastSync(); + void updateLastSync(quint64 lastSync); + quint64 getNow(); - QSqlQuery* getTokensToAdd(); - QSqlQuery* getTokensToDelete(); + QSqlQuery getUpdatedTokens(); + QSqlQuery getToken(const QString& id); - QUuid getId(QString name); + void setLastUpdate(const QString& id, quint64 lastUpdate); + + void log(const QString &msg); + QString getSubjectNameByTokenId(const QString &tokenId); + QString getSubjectNameById(const QString &id); + bool checkDeletedToken(const QString &id); private: - bool checkIfExists(QString id, QString table); + bool checkIfExists(const QString& id, const QString& table); + bool executeQuery(QSqlQuery &query, const QString &statement = QString()); + QString getLastQuery(const QSqlQuery &query) const; +signals: + void error(); private: QSqlDatabase db; - QSqlQuery query; - - bool opened; - - + bool dryMode = false; }; - -#endif // DATABASEMANAGER_H diff --git a/src/colnod/datamanager.cpp b/src/colnod/datamanager.cpp index f4d195d..c74fa82 100644 --- a/src/colnod/datamanager.cpp +++ b/src/colnod/datamanager.cpp @@ -1,224 +1,342 @@ #include "datamanager.h" -DataManager::DataManager() +DataManager::DataManager(const bool &dryMode) + :dryMode(dryMode) { - db = new DatabaseManager("192.168.1.94", "deloitte", "postgres", "34rjkciea12"); - //db = new DatabaseManager("localhost", "deloitte", "postgres", "34rjkciea12"); + db = std::make_shared("192.168.1.94", "deloitte", "postgres", "34rjkciea12", dryMode); + //db = std::make_shared("localhost", "deloitte", "postgres", "34rjkciea12"); + Logger::setDBMan(db); + nextLastSync = db->getNow(); + lastSync = db->getLastSync(); + connect(db.get(), &DatabaseManager::error, this, &DataManager::error); } -void DataManager::localSaveSubjects(QString response) +// load all tokens from colnod to comparing with working set from DB +void DataManager::fillFullTokensColnod(const QString& response) { QJsonDocument doc = QJsonDocument::fromJson(response.toUtf8()); QJsonArray items = doc.object()["items"].toArray(); - if (items.size() > 0) + if (!items.empty()) { - for (QJsonValueRef item : items) - { - auto subject = new Subject(); - subject->fromJSON(item.toObject()); - subjects.append(subject); - } - } - else - { - Subject* subject = new Subject; - subject->setName("empty"); - subjects.append(subject); - } -} - -void DataManager::localSaveTokens(QString response) -{ - QJsonDocument doc = QJsonDocument::fromJson(response.toUtf8()); - QJsonArray items = doc.object()["items"].toArray(); - if (items.size() > 0) - { - for (QJsonValueRef item : items) - { - auto token = new Token(); + for (QJsonValueRef item : items){ + auto token = std::make_shared(); token->fromJSON(item.toObject()); - tokens.append(token); + allTokensFromColnodById.insert(token->idToStringWithoutBraces(), token); + allTokensFromColnodByName.insert(token->getName(), token); } } - else - { - Token* token = new Token; - token->setName("empty"); - tokens.append(token); + else{ + qCritical() << "Colnod is Empty"; } } -void DataManager::localSaveSubjectsToDelete(QString json) +// load working set with updated tokens from Colnod +void DataManager::fillTokensToUpdateColnod(const QString& response) { - QJsonDocument doc = QJsonDocument::fromJson(json.toUtf8()); + QJsonDocument doc = QJsonDocument::fromJson(response.toUtf8()); QJsonArray items = doc.object()["items"].toArray(); - if (items.size() > 0) + if (!items.empty()) { for (QJsonValueRef item : items) { - subjectsToDelete.append(item.toString()); + auto token = std::make_shared(); + token->fromJSON(item.toObject()); + token->setDeleted(false); + tokensToUpdateFromColnodToDB.insert(token->idToStringWithoutBraces(), token); } + qInfo() << "Colnod:" << tokensToUpdateFromColnodToDB.size() << "tokens to update"; } else { - subjectsToDelete.append("empty"); + qInfo() << "Colnod: 0 tokens to update"; } } -void DataManager::localSaveTokensToDelete(QString json) +// load working set with updated subjects from Colnod +void DataManager::fillSubjectsToUpdateColnod(const QString& response) { - QJsonDocument doc = QJsonDocument::fromJson(json.toUtf8()); + QJsonDocument doc = QJsonDocument::fromJson(response.toUtf8()); QJsonArray items = doc.object()["items"].toArray(); - if (items.size() > 0) + if (!items.empty()) { for (QJsonValueRef item : items) { - tokensToDelete.append(item.toString()); + auto subject = std::make_shared(); + subject->fromJSON(item.toObject()); + subject->setDeleted(false); + subjectsToUpdateFromColnodToDB.insert(subject->idToStringWithoutBraces(), subject); } + qInfo() << "Colnod:" << subjectsToUpdateFromColnodToDB.size() << "subjects to update"; } else { - tokensToDelete.append("empty"); + qInfo() << "Colnod:" << "0 subjects to update"; } } +// load working sets with updated/deleted tokens from DB +void DataManager::fillTokensToChangeDB() +{ + QSqlQuery query = db->getUpdatedTokens(); + while (query.next()) + { + auto token = std::make_shared(); + token->fromSQLRecord(query); + if (token->getDeleted()){ // sort to delete / to update + tokensFromDBToDeleteFromColnod.append(token->idToStringWithoutBraces()); + } + else{ + tokensToUpdateFromDBToColnod.insert(token->idToStringWithoutBraces(), token); + } + } + qDebug() << "DB:" << tokensToUpdateFromDBToColnod.size() << "tokens to update"; + qDebug() << "DB:" << tokensFromDBToDeleteFromColnod.size() << "tokens to delete"; +} + +void DataManager::fillSubjectsToUpdateDB() +{ + // Not needed yet +} + +// load working set with subjest to delete from Colnod +void DataManager::fillSubjectsToDeleteColnod(const QString& json) +{ + QJsonDocument doc = QJsonDocument::fromJson(json.toUtf8()); + QJsonArray items = doc.object()["items"].toArray(); + if (!items.empty()) + { + for (QJsonValueRef item : items) { + subjectsFromColnodToDeleteFromDB.append(item.toString()); + } + qInfo() << "Colnod:" << subjectsFromColnodToDeleteFromDB.size() << "subjects to delete"; + } + else { + qInfo() << "Colnod: 0 subjects to delete"; + } +} + +// load working set with tokens to delete from DB +void DataManager::fillTokensToDeleteColnod(const QString& json) +{ + QJsonDocument doc = QJsonDocument::fromJson(json.toUtf8()); + QJsonArray items = doc.object()["items"].toArray(); + if (!items.empty()) + { + for (QJsonValueRef item : items) { + tokensFromColnodToDeleteFromDB.append(item.toString()); + } + qInfo() << "Colnod:" << tokensFromColnodToDeleteFromDB.size() << "tokens to delete"; + } + else { + qInfo() << "Colnod: 0 tokens to delete"; + } +} + +void DataManager::fillSubjectsToDeleteDB() +{ + // Not needed yet +} + +// update subjects from colnod to DB void DataManager::pushSubjectsToDB() { - if (subjects.size() == 1 && subjects[0]->getName() == "empty") - { - qDebug() << "All subjects are up to date"; + if (subjectsToUpdateFromColnodToDB.isEmpty()) { + qInfo() << "DB: 0 subjects added"; + qInfo() << "DB: 0 subjects updated"; return; } - //QSqlDatabase::database().transaction(); - qDebug() << "Subjects in progress..."; - for (auto subject : subjects) + int updated = 0; + int added = 0; + for (const auto& subject : subjectsToUpdateFromColnodToDB) { - db->saveSubject(subject, "colnod_subject"); - db->saveSubjectAttribute(subject, "colnod_subject_attribute"); + if (db->saveSubject(subject, "colnod_subject") > 0){ + added++; + if (dryMode) + qInfo() << "Adding subject:" << subject->idToStringWithoutBraces() << "to DB"; + else + Logger::logToDb(Logger::makeSubjectMsg( subject->idToStringWithoutBraces(),"added", "DB")); + } + else{ + updated++; + if (dryMode) + qInfo() << "Updating subject:" << subject->idToStringWithoutBraces() << "to DB"; + else + Logger::logToDb(Logger::makeSubjectMsg( subject->idToStringWithoutBraces(),"updated", "DB")); + } + db->saveSubjectAttributes(subject, "colnod_subject_attribute"); } - //QSqlDatabase::database().commit(); - qDebug() << subjects.size() << " subjects has been updated"; - + qInfo() << "DB:" << added << "subjects added"; + qInfo() << "DB:" << updated << "subjects updated"; } +// update tokens from colnod to DB void DataManager::pushTokensToDB() { - if (tokens.size() == 1 && tokens[0]->getName() == "empty") - { - qDebug() << "All tokens are up to date"; + if (tokensToUpdateFromColnodToDB.isEmpty()){ + qInfo() << "DB: 0 tokens added"; + qInfo() << "DB: 0 tokens updated"; return; } - //QSqlDatabase::database().transaction(); - qDebug() << "Tokens in progress..."; - for (auto token : tokens) + filterTokensColnod(); + int updated = 0; + int added = 0; + for (const auto& token : tokensToUpdateFromColnodToDB) { - db->saveToken(token, "colnod_token"); + + QString text; + // 1 = adding token + // -1 = updating token + if (db->saveToken(token, "colnod_token") == 1){ + added++; + text = "Added"; + } + else { + updated++; + text = "Updating"; + } + if (dryMode) + qInfo() << text << "token:" << token->idToStringWithoutBraces() << "to DB"; + else + Logger::logToDb(Logger::makeTokenMsg(token->idToStringWithoutBraces(), text, "DB")); } - //QSqlDatabase::database().commit(); - qDebug() << tokens.size() << " tokens has been updated"; + qInfo() << "DB:" << added << "tokens added/edited"; + qInfo() << "DB:" << updated << "tokens updated"; + } void DataManager::deleteSubjectsFromDB() { - if (subjectsToDelete.size() == 1 && subjectsToDelete[0] == "empty") + if (subjectsFromColnodToDeleteFromDB.isEmpty()) { - qDebug() << "No subjects to be deleted"; + qInfo() << "DB: 0 subjects deleted"; return; } - qDebug() << "Deleted subjects in progress..."; - //QSqlDatabase::database().transaction(); - for (auto subjectId : subjectsToDelete) + for (const auto& subjectId : subjectsFromColnodToDeleteFromDB) { - db->deleteItem(subjectId, "colnod_subject"); + db->setDeleted(subjectId, "colnod_subject", nextLastSync); + if (dryMode) + qInfo() << "Deleting subject:" << subjectId << "from DB"; + else + Logger::logToDb(Logger::makeSubjectMsg(subjectId, "deleted", "DB")); } - //QSqlDatabase::database().commit(); - qDebug() << subjectsToDelete.size() << "subject has beed deleted"; + qInfo() << "DB:" << subjectsFromColnodToDeleteFromDB.size() << " subject deleted"; } -void DataManager::deleteTokensFromDB() +// "delete" (set deleted true) tokens in DB depends on Colnod +void DataManager::setDeletedToTokensFromDB() { - if (tokensToDelete.size() == 1 && tokensToDelete[0] == "empty") + if (tokensFromColnodToDeleteFromDB.isEmpty()) { - qDebug() << "No tokens to be deleted"; + qDebug() << "DB: 0 tokens deleted"; return; } - // QSqlDatabase::database().transaction(); - qDebug() << "Deleted tokens in progress..."; - for (auto tokenId : tokensToDelete) + int alreadyDeleted = 0; + for (const auto& tokenId : tokensFromColnodToDeleteFromDB) { - db->deleteItem(tokenId, "colnod_token"); + if (!db->checkDeletedToken(tokenId)){ + db->setDeleted(tokenId, "colnod_token", nextLastSync); + if (dryMode) + qInfo() << "Deleting token:" << tokenId << "from DB"; + else + Logger::logToDb(Logger::makeTokenMsg(tokenId, "deleted", "DB")); + } + else + alreadyDeleted++; } - //QSqlDatabase::database().commit(); - qDebug() << tokensToDelete.size() << "tokens has beed deleted"; -} - -bool DataManager::haveData() -{ - if ( !subjects.isEmpty() && !tokens.isEmpty() ) - return true; - return false; -} - -bool DataManager::haveChangedData() -{ - if ( !subjects.isEmpty() && !tokens.isEmpty() && !subjectsToDelete.isEmpty() && !tokensToDelete.isEmpty() ) - return true; - return false; -} - -bool DataManager::haveProcessData() -{ - if ( !tokens.isEmpty() && !tokensToDelete.isEmpty()) - return true; - return false; -} - -uint64_t DataManager::getLastUpdate() -{ - return db->getLastUpdate(); + qDebug() << "DB:" << tokensFromColnodToDeleteFromDB.size() - alreadyDeleted << "tokens deleted"; } +// recreate working tables void DataManager::emptyDatabase() { db->dropTables(); db->createTables(); } +quint64 DataManager::getLastModifiedOfToken(const QString &id) +{ + auto record = db->getToken(id); + auto token = std::make_shared(); + token->fromSQLRecord(record); + return token->getLastModified(); +} + +//clear all structures void DataManager::clear() { - subjects.clear(); - subjectsToDelete.clear(); - tokens.clear(); - tokensToDelete.clear(); + subjectsToUpdateFromColnodToDB.clear(); + subjectsFromColnodToDeleteFromDB.clear(); + tokensToUpdateFromColnodToDB.clear(); + tokensFromColnodToDeleteFromDB.clear(); + //subjectsDB.clear(); // not need yet + // subjectsToDeleteDB.clear(); // not need yet + tokensToUpdateFromDBToColnod.clear(); + tokensFromDBToDeleteFromColnod.clear(); + allTokensFromColnodById.clear(); } +// on the very end of sync update last sync time to begin time of this sync void DataManager::updateLastSync() { - db->updateLastSync(); + db->updateLastSync(nextLastSync); } -void DataManager::loadTokensToAdd() +// these to filter functions solve colision tokens -> remove when change on this token is earlier then change on the same token on the other side (Colnod/DB) +void DataManager::filterTokensDB() { - QSqlQuery* query = db->getTokensToAdd(); - while (query->next()) + QList idsToDelete; + for (const auto& token : tokensToUpdateFromDBToColnod) { - Token* token = new Token(query->value(0).toString(), query->value(1).toString()); - token->setSubjectId(db->getId(token->getName())); - tokens.append(token); + QString id = token->idToStringWithoutBraces(); + Q_ASSERT(token != allTokensFromColnodById.value(id)); // if working sets are loading correctly equels should never happend + if (allTokensFromColnodById.contains(id) && *token < *allTokensFromColnodById.value(id)) + idsToDelete.append(id); + if (allTokensFromColnodById.contains(id) && token->getLastModified() == allTokensFromColnodById.value(id)->getLastUpdate()){ + idsToDelete.append(id); + qWarning() << "Same token has been edited in colnod and db in same time. Change from Colnod has been used"; + } + if (allTokensFromColnodByName.contains(token->getName())){ + qWarning() << "Token:" << token->idToStringWithoutBraces() << "won't be added to Colnod, because token with the same name already exists, please change it manually"; + if (!dryMode){ + QString message = QString("Error: Token: %1 won't be added to Colnod, because token with the same name already exists, please change it manually").arg(token->idToStringWithoutBraces()); + Logger::logToDb(Logger::makeErrorMsg("Db", message)); + } + } } - if (tokens.isEmpty()) - tokens.append(new Token("empty")); + for (const auto &id : idsToDelete) + tokensToUpdateFromDBToColnod.remove(id); } -void DataManager::loadTokensToDelete() +void DataManager::filterTokensColnod() { - QSqlQuery* query = db->getTokensToDelete(); - while (query->next()) + QList idsToDelete; + for (const auto &token : tokensToUpdateFromColnodToDB) { - tokensToDelete.append(query->value(0).toString()); + QString id = token->idToStringWithoutBraces(); + auto record = db->getToken(id); + if (!record.isValid()) + continue; + auto tokenDB = std::make_shared(); + tokenDB->fromSQLRecord(record); + if (*tokenDB == *token || *tokenDB > *token){ + idsToDelete.append(id); + } } - if (tokensToDelete.isEmpty()) - tokensToDelete.append("empty"); + for (const auto &id : idsToDelete) + tokensToUpdateFromColnodToDB.remove(id); +} + +// sync last update from colnod to DB +void DataManager::setLastUpdate() +{ + if (!tokensToUpdateFromColnodToDB.isEmpty()) + for (const auto &token : tokensToUpdateFromColnodToDB) + db->setLastUpdate(token->idToStringWithoutBraces(), token->getLastUpdate()); +} + +void DataManager::setLastUpdate(const QString &id) +{ + db->setLastUpdate(id, nextLastSync); } diff --git a/src/colnod/datamanager.h b/src/colnod/datamanager.h index 1f51db0..0c365d2 100644 --- a/src/colnod/datamanager.h +++ b/src/colnod/datamanager.h @@ -1,5 +1,4 @@ -#ifndef DATAMANAGER_H -#define DATAMANAGER_H +#pragma once #include "token.h" #include "subject.h" @@ -7,6 +6,7 @@ #include "databasemanager.h" #include #include +#include class DataManager : public QObject @@ -15,41 +15,67 @@ class DataManager : public QObject Q_OBJECT public: - DataManager(); + DataManager(const bool& dryMode = false); - void localSaveSubjects(QString jsonResponse); - void localSaveTokens(QString jsonResponse); - void localSaveSubjectsToDelete(QString jsonResponse); - void localSaveTokensToDelete(QString jsonResponse); + void fillFullTokensColnod(const QString& jsonResponse); + + void fillTokensToUpdateColnod(const QString& jsonResponse); + void fillSubjectsToUpdateColnod(const QString& jsonResponse); + void fillSubjectsToDeleteColnod(const QString& jsonResponse); + void fillTokensToDeleteColnod(const QString& jsonResponse); + + void fillTokensToChangeDB(); + void fillSubjectsToUpdateDB(); + void fillSubjectsToDeleteDB(); + + void filterTokensDB(); + void filterTokensColnod(); void pushSubjectsToDB(); void pushTokensToDB(); void deleteSubjectsFromDB(); - void deleteTokensFromDB(); + void setDeletedToTokensFromDB(); void updateLastSync(); - uint64_t getLastUpdate(); - - bool haveData(); - bool haveChangedData(); - bool haveProcessData(); void emptyDatabase(); + + quint64 getLastModifiedOfToken(const QString &id); + + QHash> getTokensToUpdateFromColnod() {return tokensToUpdateFromColnodToDB;} + QList getTokensToDeleteColnod() {return tokensFromColnodToDeleteFromDB;} + QHash> getTokensToUpdateFromDB() {return tokensToUpdateFromDBToColnod;} + QList getTokensToDeleteDB() {return tokensFromDBToDeleteFromColnod;} + + const quint64 &getLastSync() {return lastSync;} + const quint64 &getCurrentSync() {return nextLastSync;} + +public slots: void clear(); + void setLastUpdate(); + void setLastUpdate(const QString &id); - void loadTokensToAdd(); - void loadTokensToDelete(); - - QList>* getTokens() {return &tokens;} - QList* getTokensToDelete() {return &tokensToDelete;} - +signals: + void error(); private: - DatabaseManager *db = nullptr; - QList> subjects; - QList> tokens; - QList subjectsToDelete; - QList tokensToDelete; -}; + std::shared_ptr db; -#endif // DATAMANAGER_H + quint64 lastSync; // time of last run + quint64 nextLastSync; // time of begin of this run + + QHash> allTokensFromColnodById; + QHash> allTokensFromColnodByName; + QHash> subjectsToUpdateFromColnodToDB; + QHash> tokensToUpdateFromColnodToDB; + QHash> subjectsDB; // in future + QHash> tokensToUpdateFromDBToColnod; + + QList subjectsFromColnodToDeleteFromDB; + QList tokensFromColnodToDeleteFromDB; + QList subjectsToDeleteDB; + QList tokensFromDBToDeleteFromColnod; + + bool dryMode = false; + +}; diff --git a/src/colnod/entity.cpp b/src/colnod/entity.cpp index da6f98f..2a1db6a 100644 --- a/src/colnod/entity.cpp +++ b/src/colnod/entity.cpp @@ -25,33 +25,52 @@ void Entity::setDescription(const QString &description) { Entity::description = description; } -uint64_t Entity::getLastUpdate() const { +quint64 Entity::getLastUpdate() const { return lastUpdate; } -void Entity::setLastUpdate(uint64_t lastUpdate) { +void Entity::setLastUpdate(quint64 lastUpdate) { this->lastUpdate = lastUpdate; } -QString Entity::idToStringWithoutBraces() +quint64 Entity::getLastModified() const { + return lastModified; +} + +void Entity::setLastModified(const quint64 &lastModified) { + this->lastModified = lastModified; +} + +bool Entity::getDeleted() const { - return id.toString().mid(1,36); + return deleted; +} + +void Entity::setDeleted(const bool &deleted) +{ + this->deleted = deleted; +} + +QString Entity::idToStringWithoutBraces() const +{ + const qint8 lengthOfUuid = 36; + return id.toString().mid(1, lengthOfUuid); } void Entity::fromJSON(const QJsonObject &json) { - id = json.value("id").toString(); - name = json.value("name").toString(); - description = json.value("description").toString(); - lastUpdate = json.value("lastUpdate").toDouble(); + id = json["id"].toString(); + name = json["name"].toString(); + description = json["description"].toString(); + lastUpdate = json["lastUpdate"].toDouble(); } QJsonObject Entity::toJSON() const { QJsonObject json; - json.value("id") = id.toString(); - json.value("name") = name; - json.value("description") = description; - json.value("lastUpdate") = lastUpdate; + json["id"] = this->idToStringWithoutBraces(); + json["name"] = name; + json["description"] = description; + json["lastUpdate"] = lastUpdate; return json; } diff --git a/src/colnod/entity.h b/src/colnod/entity.h index d1b2aa6..131439a 100644 --- a/src/colnod/entity.h +++ b/src/colnod/entity.h @@ -1,13 +1,14 @@ -#ifndef COLNOD_CONNECTOR_ENTITY_H -#define COLNOD_CONNECTOR_ENTITY_H +#pragma once #include #include #include +#include +#include class Entity : public QObject { -Q_OBJECT + Q_OBJECT public: using QObject::QObject; @@ -20,20 +21,27 @@ public: const QString &getDescription() const; void setDescription(const QString &description); - uint64_t getLastUpdate() const; - void setLastUpdate(uint64_t lastUpdate); + quint64 getLastUpdate() const; + void setLastUpdate(quint64 lastUpdate); - QString idToStringWithoutBraces(); + quint64 getLastModified() const; + void setLastModified(const quint64 &lastModified); + + bool getDeleted() const; + void setDeleted(const bool &deleted); + + QString idToStringWithoutBraces() const; virtual void fromJSON(const QJsonObject &json); virtual QJsonObject toJSON() const; -protected: + + + +private: QUuid id; QString name; QString description; - qint64 lastUpdate; + qint64 lastUpdate{}; + quint64 lastModified{}; + bool deleted{}; }; - - - -#endif //COLNOD_CONNECTOR_ENTITY_H diff --git a/src/colnod/logger.cpp b/src/colnod/logger.cpp new file mode 100644 index 0000000..1326479 --- /dev/null +++ b/src/colnod/logger.cpp @@ -0,0 +1,53 @@ +#include "logger.h" + +#include + +std::shared_ptr Logger::dbMan = nullptr; +Logger *Logger::logger = nullptr; + +Logger::Logger() +{ + dbMan = nullptr; +} + +Logger *Logger::getLogger() +{ + if (!logger) + logger = new Logger; + return logger; +} + +void Logger::log(const QString& msg) +{ + qDebug() << msg; +} + +void Logger::logToDb(const QString &msg) +{ + Q_ASSERT(Logger::dbMan); + Logger::dbMan->log(msg); +} + +void Logger::setDBMan(std::shared_ptr dbMan) +{ + Logger::dbMan = std::move(dbMan); +} + +QString Logger::makeTokenMsg(const QString &tokenId, const QString &action, const QString &source) +{ + return QString("Token: %1 of subject: %2 %3. Source: %4").arg(tokenId,dbMan->getSubjectNameByTokenId(tokenId), action, source); +} + +QString Logger::makeSubjectMsg(const QString &subjectId, const QString &action, const QString &source) +{ + return QString("Subject: %1 %2. Source: %3").arg(dbMan->getSubjectNameById(subjectId), action, source); +} + +QString Logger::makeErrorMsg(const QString &source, const QString &errMsg) +{ + return QString("Source: %1, Error: %2").arg(source, errMsg); +} + + + + diff --git a/src/colnod/logger.h b/src/colnod/logger.h new file mode 100644 index 0000000..7c62211 --- /dev/null +++ b/src/colnod/logger.h @@ -0,0 +1,31 @@ +#pragma once + +#include +#include +#include +#include "databasemanager.h" + + +class Logger +{ + + static Logger *logger; + + Logger(); + + static std::shared_ptr dbMan; + +public: + static Logger *getLogger(); + static void log(const QString& msg); + static void logToDb(const QString& msg); + static void setDBMan(std::shared_ptr dbMan); + static QString makeTokenMsg(const QString& tokenId, const QString& action, const QString& source); + static QString makeSubjectMsg(const QString& subjectId, const QString& action, const QString& source); + static QString makeErrorMsg(const QString& source, const QString& errMsg); + +private: + +}; + + diff --git a/src/colnod/requestmanager.cpp b/src/colnod/requestmanager.cpp index f6dd284..5d0e79c 100644 --- a/src/colnod/requestmanager.cpp +++ b/src/colnod/requestmanager.cpp @@ -2,58 +2,47 @@ RequestManager::RequestManager() { - manager = new QNetworkAccessManager(); - token = ""; - loginStatus = false; //should be false, true for testing request header -/* - 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); + manager = std::make_unique(); + connect(manager.get(), &QNetworkAccessManager::sslErrors, this, &RequestManager::onSSLError); } -Response* RequestManager::login() +std::shared_ptr RequestManager::login() { Q_ASSERT(!loginResponse); - loginResponse = new Response; + loginResponse = std::make_shared(); QNetworkRequest request; QString hash = encryptedPassword(this->password); authHeader = getLoginHeader(this->user, hash); QJsonObject reqBody = { - {"password", hash}, - {"username", this->user} + {"password", hash}, + {"username", this->user} }; request.setUrl(this->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()); loginResponse->setReply(reply); - QObject::connect(reply, &QNetworkReply::finished, [=]() { + connect(reply, &QNetworkReply::finished, [=]() { if (reply->error()) { - qDebug() << "Login failed: "<< reply->errorString(); + Logger::logToDb(Logger::makeErrorMsg("Request Manager", reply->errorString())); loginStatus = false; reply->deleteLater(); + emit error(); return; } - qDebug() << "Logged in successfully."; loginStatus = true; emit successLogin(); reply->deleteLater(); - }); - connect(this, &RequestManager::successLogin, loginResponse, &Response::ready); + }); + connect(this, &RequestManager::successLogin, loginResponse.get(), &Response::ready); connect(this, &RequestManager::successLogin, this, &RequestManager::prepareAuthHeader); return loginResponse; } -QNetworkReply* RequestManager::postRequest(QString endpoint, QByteArray json) +QNetworkReply* RequestManager::postRequest(const QString& endpoint, const QByteArray& json) { QNetworkRequest request; request.setUrl(host + endpoint); @@ -63,42 +52,37 @@ QNetworkReply* RequestManager::postRequest(QString endpoint, QByteArray json) QObject::connect(reply, &QNetworkReply::finished, [=]() { if (reply->error()) { - qDebug() << "Authorization failed: " << reply->errorString(); + Logger::logToDb(Logger::makeErrorMsg("Request Manager", reply->errorString())); loginStatus = false; reply->deleteLater(); + emit error(); return; } - qDebug() << "Authorized successfully, response ready."; emit responseReady(); reply->deleteLater(); }); return reply; } - -Response* RequestManager::getLoginResponse() { +// This will ensure login is called only once +std::shared_ptr RequestManager::getLoginResponse() { if (!loginResponse){ loginResponse = login(); - - } return loginResponse; } -Response* RequestManager::postRequestReturnLogic(QString endpoint, QByteArray data) +Response* RequestManager::postRequestReturnLogic(const QString& endpoint, const QByteArray& data) { auto loginResponse = getLoginResponse(); - // This will ensure login is called only once - Q_ASSERT(loginResponse); - Response* response = new Response; + auto response = new Response; if (!loginStatus){ - connect(this, &RequestManager::successLogin, [=](){ response->setReply(postRequest(endpoint, data)); connect(response->getReply(), &QNetworkReply::finished, response, &Response::ready); - }); + }); } else { @@ -108,9 +92,10 @@ Response* RequestManager::postRequestReturnLogic(QString endpoint, QByteArray da return response; } -QString RequestManager::getFromJson(QString json, const QString &member) +// get value of member in json +QString RequestManager::getFromJson(const QString& json, const QString &member) { - QJsonParseError err; + QJsonParseError err{}; QJsonDocument document = QJsonDocument::fromJson(json.toUtf8(),&err); if (err.error != 0) { @@ -119,12 +104,12 @@ QString RequestManager::getFromJson(QString json, const QString &member) return document.object().value(member).toString(); } -QString RequestManager::encryptedPassword(QString password) +QString RequestManager::encryptedPassword(const QString& password) { - return QCryptographicHash::hash(password.toLocal8Bit(), QCryptographicHash::Sha512).toHex().toUpper(); + return QCryptographicHash::hash(password.toLocal8Bit(), QCryptographicHash::Sha512).toHex().toUpper(); } -QString RequestManager::getLoginHeader(QString username, QString hash) +QString RequestManager::getLoginHeader(const QString& username, const QString& hash) { QString authValue = username + ":" + hash; return "Basic " + authValue.toLocal8Bit().toBase64(); @@ -133,7 +118,7 @@ QString RequestManager::getLoginHeader(QString username, QString hash) void RequestManager::prepareAuthHeader() { jsonResponse = loginResponse->getJson(); - token = getFromJson(jsonResponse, "id"); + QString token = getFromJson(jsonResponse, "id"); QString authValue = token + ":"; authHeader = "Basic " + authValue.toLocal8Bit().toBase64(); } @@ -150,7 +135,7 @@ void RequestManager::onSSLError(QNetworkReply *reply, const QList &er } -QByteArray RequestManager::makeTimeStampJson(uint64_t time) +QByteArray RequestManager::makeTimestampJson(uint64_t time) { QJsonObject reqBody = {{"timestamp",QJsonValue(static_cast(time)) }}; QJsonDocument doc; @@ -158,28 +143,13 @@ QByteArray RequestManager::makeTimeStampJson(uint64_t time) return doc.toJson(); } -QByteArray RequestManager::makeTokensJson(QList>* tokens) +QByteArray RequestManager::makeTokensJson(const QHash> &tokens) { QJsonObject items; QJsonArray jsonTokens; - for (auto token : *tokens) + for (const auto& token : tokens) { - QJsonObject jsonToken; - jsonToken.insert("id",token->idToStringWithoutBraces()); - jsonToken.insert("name",token->getName()); - jsonToken.insert("description", token->getDescription()); - jsonToken.insert("tokenType", token->getTokenType()); - jsonToken.insert("tokenBits", token->getTokenBits()); - jsonToken.insert("tokenData", token->getTokenData()); - jsonToken.insert("timeToLive", token->getTimeToLive()); - jsonToken.insert("authErrors", token->getAuthErrors()); - QJsonArray flags; - auto flagStructure = token->getFlags(); - for (auto flag : flagStructure) - flags.push_back(flag); - jsonToken.insert("flags", flags); - jsonToken.insert("subjectId", token->subjectIdToStringWithoutBraces()); - jsonTokens.push_back(jsonToken); + jsonTokens.push_back(token->toJSON()); } items.insert("items", jsonTokens); QJsonDocument doc; @@ -187,10 +157,10 @@ QByteArray RequestManager::makeTokensJson(QList>* tokens) return doc.toJson(); } -QByteArray RequestManager::makeIdsJson(QList* ids) +QByteArray RequestManager::makeIdsJson(const QList &ids) { QJsonArray jsonIds; - for (auto id : *ids) + for (const auto& id : ids) { jsonIds.push_back(id); } @@ -218,22 +188,22 @@ Response* RequestManager::getTokenSubject() Response* RequestManager::getSubjectsUpdated(uint64_t time) { - return postRequestReturnLogic("/SubjectManager/getSubjectsUpdated", makeTimeStampJson(time)); + return postRequestReturnLogic("/SubjectManager/getSubjectsUpdated", makeTimestampJson(time)); } Response* RequestManager::getSubjectsDeleted(uint64_t time) { - return postRequestReturnLogic("/SubjectManager/getSubjectsDeleted", makeTimeStampJson(time)); + return postRequestReturnLogic("/SubjectManager/getSubjectsDeleted", makeTimestampJson(time)); } Response* RequestManager::getTokensUpdated(uint64_t time) { - return postRequestReturnLogic("/TokenManager/getTokensUpdated", makeTimeStampJson(time)); + return postRequestReturnLogic("/TokenManager/getTokensUpdated", makeTimestampJson(time)); } Response* RequestManager::getTokensDeleted(uint64_t time) { - return postRequestReturnLogic("/TokenManager/getTokensDeleted", makeTimeStampJson(time)); + return postRequestReturnLogic("/TokenManager/getTokensDeleted", makeTimestampJson(time)); } Response* RequestManager::getAccessGroups() @@ -243,12 +213,12 @@ Response* RequestManager::getAccessGroups() Response* RequestManager::getAccessGroupsUpdated(uint64_t time) { - return postRequestReturnLogic("/AccessManager/getAccessGroupsUpdated", makeTimeStampJson(time)); + return postRequestReturnLogic("/AccessManager/getAccessGroupsUpdated", makeTimestampJson(time)); } Response* RequestManager::getAccessGroupsDeleted(uint64_t time) { - return postRequestReturnLogic("/AccessManager/getAccessGroupsDeleted", makeTimeStampJson(time)); + return postRequestReturnLogic("/AccessManager/getAccessGroupsDeleted", makeTimestampJson(time)); } Response* RequestManager::getAccessGroupMembership() @@ -258,20 +228,20 @@ Response* RequestManager::getAccessGroupMembership() Response* RequestManager::getAccessGroupMembershipUpdated(uint64_t time) { - return postRequestReturnLogic("/AccessManager/getAccessGroupMembershipUpdated", makeTimeStampJson(time)); + return postRequestReturnLogic("/AccessManager/getAccessGroupMembershipUpdated", makeTimestampJson(time)); } Response* RequestManager::getAccessGroupMembershipDeleted(uint64_t time) { - return postRequestReturnLogic("/AccessManager/getAccessGroupMembershipDeleted", makeTimeStampJson(time)); + return postRequestReturnLogic("/AccessManager/getAccessGroupMembershipDeleted", makeTimestampJson(time)); } -Response* RequestManager::setTokens(QList>* tokens) +Response* RequestManager::setTokens(const QHash> &tokens) { return postRequestReturnLogic("/TokenManager/setTokens", makeTokensJson(tokens)); } -Response* RequestManager::deleteTokens(QList* ids) +Response* RequestManager::deleteTokens(const QList &ids) { return postRequestReturnLogic("/TokenManager/deleteTokens", makeIdsJson(ids)); } diff --git a/src/colnod/requestmanager.h b/src/colnod/requestmanager.h index b784535..9eb37d3 100644 --- a/src/colnod/requestmanager.h +++ b/src/colnod/requestmanager.h @@ -1,5 +1,4 @@ -#ifndef REQUESTMANAGER_H -#define REQUESTMANAGER_H +#pragma once #include #include @@ -25,13 +24,19 @@ #include "token.h" #include "response.h" +#include "logger.h" class RequestManager : public QObject { Q_OBJECT public: + friend class UnitTest; + friend class ComplexTest; + RequestManager(); + + // this should be in ColnodAPI class BEGIN Response* getSubjects(); Response* getTokens(); Response* getTokenSubject(); @@ -49,49 +54,47 @@ public: Response* getAccessGroupMembershipUpdated(uint64_t time); Response* getAccessGroupMembershipDeleted(uint64_t time); - Response* setTokens(QList>* tokens); - Response* deleteTokens(QList* ids); - - Response* login(); //I want it private, but unittest??? - - const QJsonDocument &getConfig() const {return config;} - const QString &getResponse() const {return jsonResponse;} + Response* setTokens(const QHash> &tokens); + Response* deleteTokens(const QList &ids); + // END private: - QNetworkReply* postRequest(QString endpoint, QByteArray json = QByteArray()); - Response* postRequestReturnLogic(QString endpoint, QByteArray data = QByteArray()); - QString getFromJson(QString json, const QString &member); - QString encryptedPassword(QString password); - QString getLoginHeader(QString username, QString hash); + // should be public + QNetworkReply* postRequest(const QString& endpoint, const QByteArray& json = QByteArray()); + Response* postRequestReturnLogic(const QString& endpoint, const QByteArray& data = QByteArray()); - QByteArray makeTimeStampJson(uint64_t time); - QByteArray makeTokensJson(QList>* tokens); - QByteArray makeIdsJson(QList* ids); - Response* getLoginResponse(); + std::shared_ptr login(); + std::shared_ptr getLoginResponse(); + QString getFromJson(const QString& json, const QString &member); + QString encryptedPassword(const QString& password); + QString getLoginHeader(const QString& username, const QString& hash); + + // in colnod api as well + QByteArray makeTimestampJson(uint64_t time); + QByteArray makeTokensJson(const QHash> &tokens); // maybe better to be in Token class + QByteArray makeIdsJson(const QList &ids); // Entity class private slots: void onSSLError(QNetworkReply *reply, const QList &errors); + //void onReplyFinished(QNetworkReply *reply); void prepareAuthHeader(); signals: void successLogin(); void responseReady(); - + void error(); private: - QNetworkAccessManager* manager = nullptr; - Response* loginResponse = nullptr; + std::unique_ptr manager; + std::shared_ptr loginResponse; QJsonDocument config; QString authHeader; - QString host = "https://192.168.1.3:8443"; - // QString host = "https://localhost:8080"; + const QString host = "https://192.168.1.3:8443"; + //QString host = "https://localhost:8080"; - QString password = "spaceti1"; - QString user = "spaceti"; - QString token; + const QString password = "spaceti1"; + const QString user = "spaceti"; QString jsonResponse; - bool loginStatus; + bool loginStatus = false; }; - -#endif // REQUESTMANAGER_H diff --git a/src/colnod/response.h b/src/colnod/response.h index 4416f88..7c75c65 100644 --- a/src/colnod/response.h +++ b/src/colnod/response.h @@ -1,5 +1,4 @@ -#ifndef RESPONSE_H -#define RESPONSE_H +#pragma once #include #include @@ -31,5 +30,3 @@ private: QString json; QNetworkReply *reply = nullptr; }; - -#endif // RESPONSE_H diff --git a/src/colnod/subject.cpp b/src/colnod/subject.cpp index c2ae710..55e5999 100644 --- a/src/colnod/subject.cpp +++ b/src/colnod/subject.cpp @@ -4,6 +4,11 @@ #include +Subject::Subject(const QString &name) +{ + setName(name); +} + QString Subject::getEmail() const { return attributes["email"].toString(); } @@ -11,21 +16,21 @@ QString Subject::getEmail() const { void Subject::fromJSON(const QJsonObject &json) { Entity::fromJSON(json); - attributes = json.value("attributes").toObject().value("items").toObject(); - for (int i = 0; i < attributeTypes->length(); i++) + attributes = json["attributes"].toObject()["items"].toObject(); + for (const auto & attributeType : attributeTypes) { - if (!attributes[attributeTypes[i]].toString().isEmpty()){ - atr.append(qMakePair(attributeTypes[i], attributes[attributeTypes[i]].toString())); + if (!attributes[attributeType].toString().isEmpty()){ + atr.append(qMakePair(attributeType, attributes[attributeType].toString())); } } - const auto &tokenFlagsArray = json.value("tokenFlags").toArray(); + const auto &tokenFlagsArray = json["tokenFlags"].toArray(); for(const auto &flag : tokenFlagsArray){ tokenFlags.insert(flag.toString()); } - pin = json.value("pin").toString(); + pin = json["pin"].toString(); - const auto &pinFlagsArray = json.value("pinFlags").toArray(); + const auto &pinFlagsArray = json["pinFlags"].toArray(); for(const auto &flag : pinFlagsArray){ pinFlags.insert(flag.toString()); } @@ -36,10 +41,10 @@ QJsonObject Subject::toJSON() const { QJsonObject json = Entity::toJSON(); QJsonObject items({{"items", attributes}}); - json.value("atributes") = items; - json.value("tokenFlags") = QJsonArray::fromStringList(tokenFlags.toList()); - json.value("pin") = pin; - json.value("pinFlags") = QJsonArray::fromStringList(pinFlags.toList()); + json["atributes"] = items; + json["tokenFlags"] = QJsonArray::fromStringList(tokenFlags.toList()); + json["pin"] = pin; + json["pinFlags"] = QJsonArray::fromStringList(pinFlags.toList()); return json; } diff --git a/src/colnod/subject.h b/src/colnod/subject.h index 955f623..83cf489 100644 --- a/src/colnod/subject.h +++ b/src/colnod/subject.h @@ -1,5 +1,4 @@ -#ifndef COLNOD_CONNECTOR_SUBJECT_H -#define COLNOD_CONNECTOR_SUBJECT_H +#pragma once #include @@ -12,6 +11,8 @@ class Subject : public Entity { public: using Entity::Entity; + Subject() = default; + Subject(const QString& name); QString getEmail() const; @@ -23,24 +24,18 @@ public: void setPin(const QString &pin); const QSet &getPinFlags() const; void setPinFlags(const QSet &pinFlags); - // const QList> &getAtr() const; - // void setAtr(const QList> &atr); const QList> &getAtr() const; void setAtr(const QList> &atr); void fromJSON(const QJsonObject &json) override; QJsonObject toJSON() const override; -protected: +private: QJsonObject attributes; QSet tokenFlags; QString pin; QSet pinFlags; - //QList> atr; QList> atr; - const QString attributeTypes[6] = {"Jmeno", "Prijmeni", "ProfilParking", "Spolecnost", "Profil", "spz"}; + const QList attributeTypes = {"Jmeno", "Prijmeni", "ProfilParking", "Spolecnost", "Profil", "spz"}; }; - - -#endif //COLNOD_CONNECTOR_SUBJECT_H diff --git a/src/colnod/syncmanager.cpp b/src/colnod/syncmanager.cpp new file mode 100644 index 0000000..b9d794b --- /dev/null +++ b/src/colnod/syncmanager.cpp @@ -0,0 +1,202 @@ +#include "syncmanager.h" + +SyncManager::SyncManager(bool dryMode) +{ + reqMan = std::make_unique(); + dataMan = std::make_unique(dryMode); + this->dryMode = dryMode; + + connect(reqMan.get(), &RequestManager::error, this, &SyncManager::error); + connect(dataMan.get(), &DataManager::error, this, &SyncManager::error); +} + +void SyncManager::loadDataFromColnod() +{ + loadTokensFromColnod(); + loadUpdatedDataFromColnod(); + loadDeletedDataFromColnod(); +} + +// download all tokens form colnod for comparing with tokens to update from DB +void SyncManager::loadTokensFromColnod() +{ + Response* resp = reqMan->getTokens(); + connect(resp, &Response::ready, [=](){ + dataMan->fillFullTokensColnod(resp->getJson()); + areChangedDataReady(); + resp->deleteLater(); + }); +} + +// fill tokens/subjects to update in data manager +void SyncManager::loadUpdatedDataFromColnod() +{ + uint64_t lastUpdate = dataMan->getLastSync(); + Response* resp0 = reqMan->getSubjectsUpdated(lastUpdate); + connect(resp0, &Response::ready, [=](){ + dataMan->fillSubjectsToUpdateColnod(resp0->getJson()); + areChangedDataReady(); + resp0->deleteLater(); + }); + + Response* resp1 = reqMan->getTokensUpdated(lastUpdate); + connect(resp1, &Response::ready, [=](){ + dataMan->fillTokensToUpdateColnod(resp1->getJson()); + areChangedDataReady(); + resp1->deleteLater(); + }); +} + +// fill tokens/subjects to delete in data manager +void SyncManager::loadDeletedDataFromColnod() +{ + uint64_t lastUpdate = dataMan->getLastSync(); + Response* resp2 = reqMan->getSubjectsDeleted(lastUpdate); + connect(resp2, &Response::ready, [=](){ + dataMan->fillSubjectsToDeleteColnod(resp2->getJson()); + areChangedDataReady(); + resp2->deleteLater(); + }); + + Response* resp3 = reqMan->getTokensDeleted(lastUpdate); + connect(resp3, &Response::ready, [=](){ + dataMan->fillTokensToDeleteColnod(resp3->getJson()); + areChangedDataReady(); + resp3->deleteLater(); + }); + +} + +// fill structures in data manager (tokens to updata/to delte) +void SyncManager::loadDataFromDB() +{ + dataMan->fillTokensToChangeDB(); +} + +void SyncManager::syncDataFromColnodToDB() +{ + syncUpdatedDataFromColnodToDB(); + if (dataMan->getLastSync() != 0) + syncDeletedDataFromColnodToDB(); +} + +// push data from colnod to DB +void SyncManager::syncUpdatedDataFromColnodToDB() +{ + dataMan->pushSubjectsToDB(); + dataMan->pushTokensToDB(); +} + +// set deleted tokens from Colnod, delete subject +void SyncManager::syncDeletedDataFromColnodToDB() +{ + dataMan->deleteSubjectsFromDB(); + dataMan->setDeletedToTokensFromDB(); +} + +// push changes form DB to Colnod +void SyncManager::syncDataFromDBToColnod() +{ + + connect(this, &SyncManager::dataUpdatedToColnod, dataMan.get(), &DataManager::clear); + //connect(this, &SyncManager::dataUpdatedToColnod, dataMan.get(), &DataManager::setLastSync); + if (!dryMode) + connect(this, &SyncManager::dataUpdatedToColnod, [=](){ + auto resp = reqMan->getTokensUpdated(dataMan->getCurrentSync()); + connect(resp, &Response::ready, [=](){ + dataMan->fillTokensToUpdateColnod(resp->getJson()); + dataMan->setLastUpdate(); + dataMan->clear(); + dataMan->updateLastSync(); + emit syncFinished(); + resp->deleteLater(); + }); + }); + else + connect(this, &SyncManager::dataUpdatedToColnod, [=](){ + dataMan->updateLastSync(); + emit syncFinished(); + }); + if (!dataMan->getTokensToUpdateFromDB().contains("empty")){ + syncUpdatedDataFromDBToColnod(); + } + else + updateFinished = true; + if (!dataMan->getTokensToDeleteDB().contains("empty")){ + syncDeletedDataFromDBToColnod(); + } + else + deleteFinished = true; +} + +// add or update tokens to Colnod +void SyncManager::syncUpdatedDataFromDBToColnod() +{ + dataMan->filterTokensDB(); + auto tokensToUpdate = dataMan->getTokensToUpdateFromDB(); + if (dryMode){ + for (const auto &token : tokensToUpdate) + qInfo() << "Updating token:" << token->idToStringWithoutBraces() << "to Colnod"; + updateFinished = true; + areDataUpdatedToColnod(); + } + else { + Response* resp0 = reqMan->setTokens(tokensToUpdate); + connect(resp0, &Response::ready, [=](){ + qInfo() << "Colnod:" << tokensToUpdate.size() << "tokens updated"; + for(const auto &token : tokensToUpdate) + Logger::logToDb(Logger::makeTokenMsg(token->idToStringWithoutBraces(), "updated", "Colnod")); + updateFinished = true; + areDataUpdatedToColnod(); + resp0->deleteLater(); + }); + } +} + +// delete tokens in Colnod +void SyncManager::syncDeletedDataFromDBToColnod() +{ + auto tokensToDelete = dataMan->getTokensToDeleteDB(); + if (dryMode){ + for (const auto &token : tokensToDelete) + qInfo() << "Deleting token:" << token << "from Colnod"; + deleteFinished = true; + areDataUpdatedToColnod(); + } + else { + Response* resp1 = reqMan->deleteTokens(tokensToDelete); + connect(resp1, &Response::ready, [=](){ + qInfo() << "Colnod:" << tokensToDelete.size() << "tokens deleted"; + for (const auto &id : tokensToDelete){ + dataMan->setLastUpdate(id); + Logger::logToDb(Logger::makeTokenMsg(id, "deleted", "Colnod")); + } + deleteFinished = true; + areDataUpdatedToColnod(); + resp1->deleteLater(); + }); + } +} + +// For full sync +void SyncManager::prepareDatabase() +{ + dataMan->emptyDatabase(); +} + +// emit signal when all data is downloaded from Colnod +void SyncManager::areChangedDataReady() +{ + if (++dataCounter == 5) + emit dataDownloaded(); +} + +// emit signal when writing to Colnod is finised +void SyncManager::areDataUpdatedToColnod() +{ + if (deleteFinished && updateFinished) + { + emit dataUpdatedToColnod(); + } +} + diff --git a/src/colnod/syncmanager.h b/src/colnod/syncmanager.h new file mode 100644 index 0000000..b7fbf58 --- /dev/null +++ b/src/colnod/syncmanager.h @@ -0,0 +1,57 @@ +#pragma once + +#include "requestmanager.h" +#include "datamanager.h" +#include "logger.h" + +class SyncManager : public QObject +{ + Q_OBJECT + +public: + + SyncManager(bool dryMode = false); + + void syncDataFromColnodToDB(); + void syncDataFromDBToColnod(); + + void prepareDatabase(); + +public slots: + void loadDataFromColnod(); + void loadDataFromDB(); + +signals: + void dataDownloaded(); + void dataUpdatedToColnod(); + void syncFinished(); + void error(); + +private slots: + + +private: + void loadTokensFromColnod(); + void loadUpdatedDataFromColnod(); + void loadDeletedDataFromColnod(); + void loadUpdatedDataFromDB(); + void loadDeletedDataFromDB(); + + void syncUpdatedDataFromColnodToDB(); + void syncDeletedDataFromColnodToDB(); + + void syncUpdatedDataFromDBToColnod(); + void syncDeletedDataFromDBToColnod(); + + void areChangedDataReady(); + void areDataUpdatedToColnod(); + +private: + std::unique_ptr reqMan; + std::unique_ptr dataMan; + bool dryMode = false; + bool updateFinished = false; + bool deleteFinished = false; + int dataCounter = 0; +}; + diff --git a/src/colnod/token.cpp b/src/colnod/token.cpp index 941f1fc..fcf2856 100644 --- a/src/colnod/token.cpp +++ b/src/colnod/token.cpp @@ -1,13 +1,14 @@ #include "token.h" #include +#include -Token::Token(QString namee, QString tokenData, QString decription) +Token::Token(const QString& name, QString tokenData, const QString& decription) { - this->name = namee; - this->tokenData = tokenData; - this->description = decription; - this->id = QUuid::createUuid(); + this->setName(name); + this->tokenData = std::move(tokenData); + this->setDescription(decription); + this->setId(QUuid::createUuid()); this->tokenType = "Token"; this->tokenBits = 32; this->timeToLive = 255; @@ -16,44 +17,69 @@ Token::Token(QString namee, QString tokenData, QString decription) } -Token::Token(QString namee) +Token::Token(const QString &name) { - this->name = namee; + this->setName(name); } +Token::~Token() += default; + + void Token::fromJSON(const QJsonObject &json) { Entity::fromJSON(json); - tokenType = json.value("tokenType").toString(); - tokenBits = json.value("tokenBits").toInt(); - tokenData = json.value("tokenData").toString(); - validFrom = json.value("validFrom").toDouble(); - validTo = json.value("validTo").toDouble(); - timeToLive = json.value("timeToLive").toInt(); + tokenType = json["tokenType"].toString(); + tokenBits = json["tokenBits"].toInt(); + tokenData = json["tokenData"].toString(); + timeToLive = json["timeToLive"].toInt(); authErrors = json["authErrors"].toInt(); const auto &flagsArray = json["flags"].toArray(); for(const auto &flag : flagsArray){ flags.insert(flag.toString()); } - subjectId = json.value("subjectId").toString(); + subjectId = json["subjectId"].toString(); } QJsonObject Token::toJSON() const { QJsonObject json = Entity::toJSON(); - - json.value("tokenType") = tokenType; - json.value("tokenBits") = tokenBits; - json.value("tokenData") = tokenData; - json.value("validFrom") = validFrom; - json.value("validTo") = validTo; - json.value("timeToLive") = timeToLive; - json.value("authErrors") = authErrors; - json.value("flags") = QJsonArray::fromStringList(flags.toList()); - json.value("subjectId") = subjectId.toString(); + json.insert("tokenType", tokenType); + json["tokenBits"] = tokenBits; + json["tokenType"] = tokenType; + json["tokenBits"] = tokenBits; + json["tokenData"] = tokenData; + json["timeToLive"] = timeToLive; + json["authErrors"] = authErrors; + json["flags"] = QJsonArray::fromStringList(flags.toList()); + json["subjectId"] = subjectId.toString().mid(1,36); return json; } +void Token::fromSQLRecord(const QSqlQuery& query) +{ + setId(query.value(0).toUuid()); + authErrors = query.value(1).toInt(); + setDescription(query.value(2).toString()); + QSet flags; + if (query.value(6).toBool()) + flags.insert("NoValidity"); + if (query.value(3).toBool()) + flags.insert("Enabled"); + this->flags = flags; + QDateTime date = query.value(4).toDateTime(); + setLastUpdate(date.toMSecsSinceEpoch()); + setName(query.value(5).toString()); + timeToLive = query.value(7).toInt(); + tokenBits = query.value(8).toInt(); + tokenData = query.value(9).toString(); + tokenType = query.value(10).toString(); + subjectId = query.value(11).toUuid(); + date = query.value(12).toDateTime(); + setLastModified(date.toMSecsSinceEpoch()); + setDeleted(query.value(13).toBool()); +} + const QString &Token::getTokenType() const { return tokenType; } @@ -78,22 +104,6 @@ void Token::setTokenData(const QString &tokenData) { Token::tokenData = tokenData; } -qint64 Token::getValidFrom() const { - return validFrom; -} - -void Token::setValidFrom(qint64 validFrom) { - Token::validFrom = validFrom; -} - -qint64 Token::getValidTo() const { - return validTo; -} - -void Token::setValidTo(qint64 validTo) { - Token::validTo = validTo; -} - int Token::getTimeToLive() const { return timeToLive; } @@ -127,5 +137,5 @@ void Token::setSubjectId(const QUuid &subjectId) { } QString Token::subjectIdToStringWithoutBraces(){ - return subjectId.toString().mid(1,36); + return subjectId.toString().mid(1,36); } diff --git a/src/colnod/token.h b/src/colnod/token.h index 1ffc80f..abc7ff5 100644 --- a/src/colnod/token.h +++ b/src/colnod/token.h @@ -1,28 +1,48 @@ -#ifndef COLNOD_CONNECTOR_TOKEN_H -#define COLNOD_CONNECTOR_TOKEN_H +#pragma once #include "entity.h" - #include - +#include +#include +#include +#include class Token : public Entity { public: - // using Entity::Entity; + // using Entity::Entity; Token() = default; - Token(QString name, QString tokenData, QString decription = "mobile"); - Token(QString name); + Token(const QString& name, QString tokenData, const QString& decription = "mobile"); + Token(const QString& name); + ~Token() override; + + friend bool operator<(const Token &lToken, const Token &rToken){ + return lToken.getLastModified() < rToken.getLastUpdate(); + } + friend bool operator>(const Token &lToken, const Token &rToken){ + return lToken.getLastModified() > rToken.getLastUpdate(); + } + friend bool operator==(const Token &lToken, const Token &rToken){ + return lToken.getId() == rToken.getId() && + lToken.getName() == rToken.getName() && + lToken.getDescription() == rToken.getDescription() && + lToken.getLastUpdate() == rToken.getLastUpdate() && + lToken.tokenType == rToken.tokenType && + lToken.tokenBits == rToken.tokenBits && + lToken.tokenData == rToken.tokenData && + lToken.timeToLive == rToken.timeToLive && + lToken.authErrors == rToken.authErrors && + lToken.flags == rToken.flags && + lToken.subjectId == rToken.subjectId; + } + + const QString &getTokenType() const; void setTokenType(const QString &tokenType); int getTokenBits() const; void setTokenBits(int tokenBits); const QString &getTokenData() const; void setTokenData(const QString &tokenData); - qint64 getValidFrom() const; - void setValidFrom(qint64 validFrom); - qint64 getValidTo() const; - void setValidTo(qint64 validTo); int getTimeToLive() const; void setTimeToLive(int timeToLive); int getAuthErrors() const; @@ -32,22 +52,19 @@ public: const QUuid &getSubjectId() const; void setSubjectId(const QUuid &subjectId); + QString subjectIdToStringWithoutBraces(); - + void fromSQLRecord(const QSqlQuery& query); void fromJSON(const QJsonObject &json) override; QJsonObject toJSON() const override; -protected: + +private: QString tokenType; - int tokenBits; + int tokenBits{}; QString tokenData; - qint64 validFrom; - qint64 validTo; - int timeToLive; - int authErrors; + int timeToLive{}; + int authErrors{}; QSet flags; QUuid subjectId; }; - - -#endif //COLNOD_CONNECTOR_TOKEN_H diff --git a/test/unitTests/UnitTest.cpp b/test/unitTests/UnitTest.cpp index af27504..0093e95 100644 --- a/test/unitTests/UnitTest.cpp +++ b/test/unitTests/UnitTest.cpp @@ -7,15 +7,14 @@ void UnitTest::initTestCase() void UnitTest::loginSuccessfully() { - RequestManager* testAccess = new RequestManager(); - QJsonDocument config = testAccess->getConfig(); + auto testAccess = new RequestManager(); QSignalSpy spy(testAccess, SIGNAL(successLogin())); QVERIFY(spy.isValid()); testAccess->login(); - spy.wait(15000); + spy.wait(timeout); QCOMPARE(spy.count(), 1); - QString json = testAccess->getResponse(); + QString json = testAccess->jsonResponse; qDebug() << json; QJsonDocument doc = QJsonDocument::fromJson(json.toUtf8()); QVERIFY2(doc.object().value("id").isString(), "No parameter 'id' in response"); @@ -24,13 +23,13 @@ void UnitTest::loginSuccessfully() //POST request w/o datas void UnitTest::getSubjects() { - RequestManager* testAccess = new RequestManager(); + auto* testAccess = new RequestManager(); QSignalSpy spy(testAccess, SIGNAL(responseReady())); QVERIFY(spy.isValid()); Response* response = testAccess->getSubjects(); QSignalSpy spy1(response, &Response::ready); - spy.wait(15000); + spy.wait(timeout); QCOMPARE(spy.count(), 1); QCOMPARE(spy1.count(), 1); @@ -45,11 +44,11 @@ void UnitTest::getSubjects() void UnitTest::getTokens() { - RequestManager* testAccess = new RequestManager(); + auto* testAccess = new RequestManager(); Response* response = testAccess->getTokens(); QSignalSpy spy(response, &Response::ready); QCOMPARE(spy.count(), 0); - spy.wait(15000); + spy.wait(timeout); QVERIFY(spy.isValid()); QCOMPARE(spy.count(), 1); QString json = response->getJson(); @@ -62,11 +61,11 @@ void UnitTest::getTokens() void UnitTest::getTokenSubject() { - RequestManager* testAccess = new RequestManager(); + auto* testAccess = new RequestManager(); QSignalSpy spy(testAccess, SIGNAL(responseReady())); Response* response = testAccess->getTokenSubject(); QCOMPARE(spy.count(), 0); - spy.wait(15000); + spy.wait(timeout); QVERIFY(spy.isValid()); QCOMPARE(spy.count(), 1); QString json = response->getJson(); @@ -75,11 +74,11 @@ void UnitTest::getTokenSubject() void UnitTest::getSubjectsUpdated() { - RequestManager* testAccess = new RequestManager(); + auto* testAccess = new RequestManager(); QSignalSpy spy(testAccess, SIGNAL(responseReady())); - Response* response = testAccess->getSubjectsUpdated(1568646217767); + Response* response = testAccess->getSubjectsUpdated(epochMS); QCOMPARE(spy.count(), 0); - spy.wait(15000); + spy.wait(timeout); QVERIFY(spy.isValid()); QCOMPARE(spy.count(), 1); QString json = response->getJson(); @@ -88,11 +87,11 @@ void UnitTest::getSubjectsUpdated() void UnitTest::getSubjectsDeleted() { - RequestManager* testAccess = new RequestManager(); + auto* testAccess = new RequestManager(); QSignalSpy spy(testAccess, SIGNAL(responseReady())); - Response* response = testAccess->getSubjectsDeleted(1568646217767); + Response* response = testAccess->getSubjectsDeleted(epochMS); QCOMPARE(spy.count(), 0); - spy.wait(15000); + spy.wait(timeout); QVERIFY(spy.isValid()); QCOMPARE(spy.count(), 1); QString json = response->getJson(); @@ -101,11 +100,11 @@ void UnitTest::getSubjectsDeleted() void UnitTest::getTokensUpdated() { - RequestManager* testAccess = new RequestManager(); + auto* testAccess = new RequestManager(); QSignalSpy spy(testAccess, SIGNAL(responseReady())); - Response* response = testAccess->getTokensUpdated(1570109859681); + Response* response = testAccess->getTokensUpdated(epochMS); QCOMPARE(spy.count(), 0); - spy.wait(15000); + spy.wait(timeout); QVERIFY(spy.isValid()); QCOMPARE(spy.count(), 1); QString json = response->getJson(); @@ -114,11 +113,11 @@ void UnitTest::getTokensUpdated() void UnitTest::getTokensDeleted() { - RequestManager* testAccess = new RequestManager(); + auto* testAccess = new RequestManager(); QSignalSpy spy(testAccess, SIGNAL(responseReady())); - Response* response = testAccess->getTokensDeleted(1570109859681); + Response* response = testAccess->getTokensDeleted(epochMS); QCOMPARE(spy.count(), 0); - spy.wait(15000); + spy.wait(timeout); QVERIFY(spy.isValid()); QCOMPARE(spy.count(), 1); QString json = response->getJson(); @@ -127,11 +126,11 @@ void UnitTest::getTokensDeleted() void UnitTest::getAccessGroups() { - RequestManager* testAccess = new RequestManager(); + auto* testAccess = new RequestManager(); QSignalSpy spy(testAccess, SIGNAL(responseReady())); Response* response = testAccess->getAccessGroups(); QCOMPARE(spy.count(), 0); - spy.wait(15000); + spy.wait(timeout); QVERIFY(spy.isValid()); QCOMPARE(spy.count(), 1); QString json = response->getJson(); @@ -140,11 +139,11 @@ void UnitTest::getAccessGroups() void UnitTest::getAccessGroupsUpdated() { - RequestManager* testAccess = new RequestManager(); + auto* testAccess = new RequestManager(); QSignalSpy spy(testAccess, SIGNAL(responseReady())); - Response* response = testAccess->getAccessGroupsUpdated(1568646217767); + Response* response = testAccess->getAccessGroupsUpdated(epochMS); QCOMPARE(spy.count(), 0); - spy.wait(15000); + spy.wait(timeout); QVERIFY(spy.isValid()); QCOMPARE(spy.count(), 1); QString json = response->getJson(); @@ -153,11 +152,11 @@ void UnitTest::getAccessGroupsUpdated() void UnitTest::getAccessGroupsDeleted() { - RequestManager* testAccess = new RequestManager(); + auto* testAccess = new RequestManager(); QSignalSpy spy(testAccess, SIGNAL(responseReady())); - Response* response = testAccess->getAccessGroupsDeleted(1568646217767); + Response* response = testAccess->getAccessGroupsDeleted(epochMS); QCOMPARE(spy.count(), 0); - spy.wait(15000); + spy.wait(timeout); QVERIFY(spy.isValid()); QCOMPARE(spy.count(), 1); QString json = response->getJson(); @@ -166,11 +165,11 @@ void UnitTest::getAccessGroupsDeleted() void UnitTest::getAccessGroupMembership() { - RequestManager* testAccess = new RequestManager(); + auto* testAccess = new RequestManager(); QSignalSpy spy(testAccess, SIGNAL(responseReady())); Response* response = testAccess->getAccessGroupMembership(); QCOMPARE(spy.count(), 0); - spy.wait(15000); + spy.wait(timeout); QVERIFY(spy.isValid()); QCOMPARE(spy.count(), 1); QString json = response->getJson(); @@ -179,11 +178,11 @@ void UnitTest::getAccessGroupMembership() void UnitTest::getAccessGroupMembershipUpdated() { - RequestManager* testAccess = new RequestManager(); + auto* testAccess = new RequestManager(); QSignalSpy spy(testAccess, SIGNAL(responseReady())); - Response* response = testAccess->getAccessGroupMembershipUpdated(1568646217767); + Response* response = testAccess->getAccessGroupMembershipUpdated(epochMS); QCOMPARE(spy.count(), 0); - spy.wait(15000); + spy.wait(timeout); QVERIFY(spy.isValid()); QCOMPARE(spy.count(), 1); QString json = response->getJson(); @@ -192,11 +191,11 @@ void UnitTest::getAccessGroupMembershipUpdated() void UnitTest::getAccessGroupMembershipDeleted() { - RequestManager* testAccess = new RequestManager(); + auto* testAccess = new RequestManager(); QSignalSpy spy(testAccess, SIGNAL(responseReady())); - Response* response = testAccess->getAccessGroupMembershipDeleted(1568646217767); + Response* response = testAccess->getAccessGroupMembershipDeleted(epochMS); QCOMPARE(spy.count(), 0); - spy.wait(15000); + spy.wait(timeout); QVERIFY(spy.isValid()); QCOMPARE(spy.count(), 1); QString json = response->getJson(); @@ -205,26 +204,15 @@ void UnitTest::getAccessGroupMembershipDeleted() void UnitTest::setTokens() { - QFile jsonData(QDir::current().filePath("tokens.json")); - QVERIFY2(jsonData.open(QIODevice::ReadOnly), "Couldn't open config file tokens.json"); - QJsonDocument doc = QJsonDocument::fromJson(jsonData.readAll()); - QJsonObject obj = doc.object(); - QJsonArray arr = obj["items"].toArray(); - qDebug() << arr; - QList> tokens; - for (auto object : arr) - { - auto token = new Token; - token->fromJSON(object.toObject()); - qDebug() << token; - tokens.append(token); - } - RequestManager* testAccess = new RequestManager(); + QHash> tokens; + auto token = getTestToken(); + tokens.insert(token->idToStringWithoutBraces(), token); + auto testAccess = new RequestManager(); QSignalSpy spy(testAccess, SIGNAL(responseReady())); - Response* response = testAccess->setTokens(&tokens); + Response* response = testAccess->setTokens(tokens); QCOMPARE(spy.count(), 0); - spy.wait(15000); + spy.wait(timeout); QVERIFY(spy.isValid()); QCOMPARE(spy.count(), 1); QString json = response->getJson(); @@ -233,14 +221,14 @@ void UnitTest::setTokens() void UnitTest::deleteTokens() { - RequestManager* testAccess = new RequestManager(); + auto* testAccess = new RequestManager(); QSignalSpy spy(testAccess, SIGNAL(responseReady())); QList ids; ids.append("582c982d-6fd7-4856-8548-7ce542791c7a"); ids.append("3ff23b41-3da3-4b33-82ce-d8e2d8c9a546"); - Response* response = testAccess->deleteTokens(&ids); + Response* response = testAccess->deleteTokens(ids); QCOMPARE(spy.count(), 0); - spy.wait(15000); + spy.wait(timeout); QVERIFY(spy.isValid()); QCOMPARE(spy.count(), 1); QString json = response->getJson(); @@ -262,10 +250,10 @@ void UnitTest::subjectJSONParser() QJsonObject obj = doc.object(); QJsonArray arr = obj["items"].toArray(); */ - RequestManager* testAccess = new RequestManager(); + auto* testAccess = new RequestManager(); QSignalSpy spy(testAccess, SIGNAL(responseReady())); Response* response = testAccess->getSubjects(); - spy.wait(15000); + spy.wait(timeout); QString json = response->getJson(); QJsonDocument doc = QJsonDocument::fromJson(json.toUtf8()); QJsonArray arr = doc.object()["items"].toArray(); @@ -277,10 +265,10 @@ void UnitTest::subjectJSONParser() void UnitTest::tokenJSONParser() { - RequestManager* testAccess = new RequestManager(); + auto* testAccess = new RequestManager(); QSignalSpy spy(testAccess, SIGNAL(responseReady())); Response* response = testAccess->getTokens(); - spy.wait(15000); + spy.wait(timeout); QString json = response->getJson(); QJsonDocument doc = QJsonDocument::fromJson(json.toUtf8()); QJsonArray arr = doc.object()["items"].toArray(); @@ -290,15 +278,15 @@ void UnitTest::tokenJSONParser() QVERIFY(!testToken->getName().isEmpty()); } -void UnitTest::connectToDB() -{ - DatabaseManager *db = new DatabaseManager("192.168.1.94", "deloitte", "postgres", "34rjkciea12"); - QVERIFY(db->getOpened()); - qDebug() << db->getTestMessage(1); - QVERIFY(true); - QCOMPARE(db->getTestMessage(1), QStringLiteral("Hello world")); - QCOMPARE(db->getTestMessage(db->createTestRecord("Now it's diffrent")), QStringLiteral("Now it's diffrent")); -} +//void UnitTest::connectToDB() +//{ +// DatabaseManager *db = new DatabaseManager("192.168.1.94", "deloitte", "postgres", "34rjkciea12"); +// QVERIFY(db->getOpened()); +// qDebug() << db->getTestMessage(1); +// QVERIFY(true); +// QCOMPARE(db->getTestMessage(1), QStringLiteral("Hello world")); +// QCOMPARE(db->getTestMessage(db->createTestRecord("Now it's diffrent")), QStringLiteral("Now it's diffrent")); +//} /* void UnitTest::debugConnection() @@ -344,7 +332,7 @@ void UnitTest::debugConnection() void UnitTest::saveDataToDB() { - // dataMan->localSaveTokens(); + // dataMan->localSaveTokens(); QVERIFY(true); } @@ -355,6 +343,25 @@ void UnitTest::getUuid() QCOMPARE(1,1); } +std::shared_ptr UnitTest::getTestToken() +{ + QJsonObject jsonToken; + jsonToken.insert("id", "062c93f6-ba3e-46af-a3a6-7a2988d1f0e9"); + jsonToken.insert("name", "test"); + jsonToken.insert("description", "mobile"); + jsonToken.insert("tokenType", "Token"); + jsonToken.insert("tokenBits", 32); + jsonToken.insert("tokenData", "7B9D32"); + jsonToken.insert("timeToLive", 255); + jsonToken.insert("authErrors", 255); + QJsonArray flags; + flags.push_back("Enabled"); + flags.push_back("NoValidity"); + jsonToken.insert("flags", flags); + jsonToken.insert("subjectId", "72b37f7e-5761-4e6c-8e87-20c0bed0d904"); + auto token = std::make_shared(); + token->fromJSON(jsonToken); + return token; +} - -//QTEST_MAIN(UnitTest) +QTEST_MAIN(UnitTest) diff --git a/test/unitTests/complextest.cpp b/test/unitTests/complextest.cpp index 1708de8..3d84699 100644 --- a/test/unitTests/complextest.cpp +++ b/test/unitTests/complextest.cpp @@ -2,135 +2,147 @@ void ComplexTest::initTestCase() { - auto reqMan1 = new RequestManager; - QList ids; - ids.append("582c982d-6fd7-4856-8548-7ce542791c7a"); - ids.append("3ff23b41-3da3-4b33-82ce-d8e2d8c9a546"); - Response* deleteTokensResp = reqMan1->deleteTokens(&ids); - QSignalSpy deleteTokensRespSpy(deleteTokensResp, &Response::ready); - QCOMPARE(deleteTokensRespSpy.count(), 0); - deleteTokensRespSpy.wait(10000); - QTest::qWait(2500); + // auto reqMan1 = new RequestManager; + // QList ids; + // ids.append("582c982d-6fd7-4856-8548-7ce542791c7a"); + // ids.append("3ff23b41-3da3-4b33-82ce-d8e2d8c9a546"); + // Response* deleteTokensResp = reqMan1->deleteTokens(ids); + // QSignalSpy deleteTokensRespSpy(deleteTokensResp, &Response::ready); + // QCOMPARE(deleteTokensRespSpy.count(), 0); + // deleteTokensRespSpy.wait(timeout); + // QTest::qWait(2500); + // Logger *logger = Logger::getLogger(); start = QDateTime::currentMSecsSinceEpoch()-2000; - api = new ColnodAPI; + api = new SyncManager(); qDebug() << start; + } + void ComplexTest::cleanupTestCase() { - QList ids; - ids.append("582c982d-6fd7-4856-8548-7ce542791c7a"); - ids.append("3ff23b41-3da3-4b33-82ce-d8e2d8c9a546"); - auto reqMan = new RequestManager; - Response* deleteTokensResp = reqMan->deleteTokens(&ids); - QSignalSpy deleteTokensRespSpy(deleteTokensResp, &Response::ready); - QCOMPARE(deleteTokensRespSpy.count(), 0); - deleteTokensRespSpy.wait(10000); - QCOMPARE(deleteTokensRespSpy.count(), 1); + + // QList ids; + // ids.append("582c982d-6fd7-4856-8548-7ce542791c7a"); + // ids.append("3ff23b41-3da3-4b33-82ce-d8e2d8c9a546"); + // auto reqMan = new RequestManager; + // Response* deleteTokensResp = reqMan->deleteTokens(ids); + // QSignalSpy deleteTokensRespSpy(deleteTokensResp, &Response::ready); + // QCOMPARE(deleteTokensRespSpy.count(), 0); + // deleteTokensRespSpy.wait(timeout); + // QCOMPARE(deleteTokensRespSpy.count(), 1); } void ComplexTest::complexTest() { - // LOGIN_BEGIN - reqMan = new RequestManager; - QSignalSpy loginSpy(reqMan, &RequestManager::successLogin); - QVERIFY(reqMan); - Response* loginResp = reqMan->login(); - QSignalSpy loginRespSpy(loginResp, &Response::ready); - QCOMPARE(loginSpy.count(), 0); - QCOMPARE(loginRespSpy.count(), 0); - loginSpy.wait(10000); - QCOMPARE(loginResp->getStatusCode(), 200); // HTTP status code check - QCOMPARE(loginSpy.count(), 1); // Checking multiple calls - QCOMPARE(loginRespSpy.count(), 1); - auto doc0 = getJsonDoc(loginResp->getJson()); - QVERIFY(doc0.object()["id"].isString()); - // LOGIN_END +// // LOGIN_BEGIN +// reqMan = new RequestManager; +// QSignalSpy loginSpy(reqMan, &RequestManager::successLogin); +// auto loginResp = reqMan->login(); +// QSignalSpy loginRespSpy(loginResp.get(), &Response::ready); +// QCOMPARE(loginSpy.count(), 0); +// QCOMPARE(loginRespSpy.count(), 0); +// loginSpy.wait(timeout); +// QCOMPARE(loginResp->getStatusCode(), 200); // HTTP status code check +// QCOMPARE(loginSpy.count(), 1); // Checking multiple calls +// QCOMPARE(loginRespSpy.count(), 1); +// auto doc0 = getJsonDoc(loginResp->getJson()); +// QVERIFY(doc0.object()["id"].isString()); +// // LOGIN_END - // NUMBER_OF_SUBJECTS_AND_TOKENS_BEGIN - int numOfSubjects = getNumOfSubjects(); - QCOMPARE(numOfSubjects, 2893); // should be still the same, if false db has been changed - int numOfTokens = getNumOfTokens(); - QCOMPARE(numOfTokens, 2881); // should be still the same, if false db has been changed, or deleteTokens didnt work in previous test - // NUMBER_OF_SUBJECTS_AND_TOKENS_END +// // NUMBER_OF_SUBJECTS_AND_TOKENS_BEGIN +// int numOfSubjects = getNumOfSubjects(); +// QCOMPARE(numOfSubjects, 2893); // should be still the same, if false db has been changed +// int numOfTokens = getNumOfTokens(); +// QCOMPARE(numOfTokens, 2881); // should be still the same, if false db has been changed, or deleteTokens didnt work in previous test +// // NUMBER_OF_SUBJECTS_AND_TOKENS_END - // ADD_TOKENS_CHECK_BEGIN - QList> tokens; - tokens.append(getTestToken()); - Response* setTokensResp = reqMan->setTokens(&tokens); - QSignalSpy setTokensRespSpy(setTokensResp, &Response::ready); - QCOMPARE(setTokensRespSpy.count(), 0); - setTokensRespSpy.wait(10000); - QCOMPARE(setTokensRespSpy.count(), 1); - QCOMPARE(setTokensResp->getStatusCode(), 200); - QCOMPARE(getNumOfTokens(), numOfTokens + 1); - // ADD_TOKENS_CHEK_END +// // ADD_TOKENS_CHECK_BEGIN +// QHash> tokens; +// auto token = getTestToken(); +// tokens.insert(token->idToStringWithoutBraces(), token); +// Response* setTokensResp = reqMan->setTokens(tokens); +// QSignalSpy setTokensRespSpy(setTokensResp, &Response::ready); +// QCOMPARE(setTokensRespSpy.count(), 0); +// setTokensRespSpy.wait(timeout); +// QCOMPARE(setTokensRespSpy.count(), 1); +// QCOMPARE(setTokensResp->getStatusCode(), 200); +// QCOMPARE(getNumOfTokens(), numOfTokens + 1); +// // ADD_TOKENS_CHEK_END - // CHECK_UPDATED_TOKENS_BEGIN - Response* getTokensUpdatedResp = reqMan->getTokensUpdated(start); - //start = QDateTime::currentMSecsSinceEpoch(); - QSignalSpy getTokensUpdatedRespSpy(getTokensUpdatedResp, &Response::ready); - QCOMPARE(getTokensUpdatedRespSpy.count(), 0); - getTokensUpdatedRespSpy.wait(10000); - QCOMPARE(getTokensUpdatedResp->getStatusCode(), 200); - QCOMPARE(getTokensUpdatedRespSpy.count(), 1); - auto doc1 = getJsonDoc(getTokensUpdatedResp->getJson()); - QCOMPARE(doc1.object()["items"].toArray().size(), 1); - // CHECK_UPDATED_TOKENS_END +// // CHECK_UPDATED_TOKENS_BEGIN +// Response* getTokensUpdatedResp = reqMan->getTokensUpdated(start); +// //start = QDateTime::currentMSecsSinceEpoch(); +// QSignalSpy getTokensUpdatedRespSpy(getTokensUpdatedResp, &Response::ready); +// QCOMPARE(getTokensUpdatedRespSpy.count(), 0); +// getTokensUpdatedRespSpy.wait(timeout); +// QCOMPARE(getTokensUpdatedResp->getStatusCode(), 200); +// QCOMPARE(getTokensUpdatedRespSpy.count(), 1); +// auto doc1 = getJsonDoc(getTokensUpdatedResp->getJson()); +// QCOMPARE(doc1.object()["items"].toArray().size(), 1); +// // CHECK_UPDATED_TOKENS_END - // DELETE_TOKENS_CHECK_BEGIN - QList ids; - ids.append("582c982d-6fd7-4856-8548-7ce542791c7a"); - Response* deleteTokensResp = reqMan->deleteTokens(&ids); - QSignalSpy deleteTokensRespSpy(deleteTokensResp, &Response::ready); - QCOMPARE(deleteTokensRespSpy.count(), 0); - deleteTokensRespSpy.wait(10000); - QCOMPARE(deleteTokensRespSpy.count(), 1); - QCOMPARE(deleteTokensResp->getStatusCode(), 200); - // DELETE_TOKENS_CHECK_END +// // DELETE_TOKENS_CHECK_BEGIN +// QList ids; +// ids.append("062c93f6-ba3e-46af-a3a6-7a2988d1f0e9"); +// Response* deleteTokensResp = reqMan->deleteTokens(ids); +// QSignalSpy deleteTokensRespSpy(deleteTokensResp, &Response::ready); +// QCOMPARE(deleteTokensRespSpy.count(), 0); +// deleteTokensRespSpy.wait(timeout); +// QCOMPARE(deleteTokensRespSpy.count(), 1); +// QCOMPARE(deleteTokensResp->getStatusCode(), 200); +// // DELETE_TOKENS_CHECK_END - // CHECK_DELETED_TOKENS_BEGIN - Response* getTokensDeletedResp = reqMan->getTokensDeleted(start); - start = QDateTime::currentMSecsSinceEpoch(); - QSignalSpy getTokensDeletedRespSpy(getTokensDeletedResp, &Response::ready); - QCOMPARE(getTokensDeletedRespSpy.count(), 0); - getTokensDeletedRespSpy.wait(10000); - QCOMPARE(getTokensDeletedResp->getStatusCode(), 200); - QCOMPARE(getTokensDeletedRespSpy.count(), 1); - auto doc2 = getJsonDoc(getTokensDeletedResp->getJson()); - QCOMPARE(doc2.object()["items"].toArray().size(), 1); - QVERIFY(doc2.object()["items"].toArray().contains("582c982d-6fd7-4856-8548-7ce542791c7a")); - // CHECK_DELETED_TOKENS_END +// // CHECK_DELETED_TOKENS_BEGIN +// Response* getTokensDeletedResp = reqMan->getTokensDeleted(start); +// start = QDateTime::currentMSecsSinceEpoch(); +// QSignalSpy getTokensDeletedRespSpy(getTokensDeletedResp, &Response::ready); +// QCOMPARE(getTokensDeletedRespSpy.count(), 0); +// getTokensDeletedRespSpy.wait(timeout); +// QCOMPARE(getTokensDeletedResp->getStatusCode(), 200); +// QCOMPARE(getTokensDeletedRespSpy.count(), 1); +// auto doc2 = getJsonDoc(getTokensDeletedResp->getJson()); +// QCOMPARE(doc2.object()["items"].toArray().size(), 1); +// QVERIFY(doc2.object()["items"].toArray().contains("062c93f6-ba3e-46af-a3a6-7a2988d1f0e9")); +// // CHECK_DELETED_TOKENS_END - - - // LAST_TESTS (for sure) - QCOMPARE(loginSpy.count(), 1); // Checking multiple calls - QCOMPARE(loginRespSpy.count(), 1); - QCOMPARE(getNumOfSubjects(), numOfSubjects); - QCOMPARE(getNumOfTokens(), numOfTokens); +// // LAST_TESTS (for sure) +// QCOMPARE(loginSpy.count(), 1); // Checking multiple calls +// QCOMPARE(loginRespSpy.count(), 1); +// QCOMPARE(getNumOfSubjects(), numOfSubjects); +// QCOMPARE(getNumOfTokens(), numOfTokens); } - void ComplexTest::fullSync() { - api->prepareDatabase(); - api->downloadData(); - QSignalSpy spy(api, &ColnodAPI::dataDownloaded); - spy.wait(10000); - api->syncDataFromColnod(); - // api->syncDataToColnod(); + /* api->prepareDatabase(); + api->loadDataFromColnod(); + QSignalSpy spy(api, &SyncManager::dataDownloaded); + spy.wait(timeout); + api->loadDataFromDB(); + api->syncDataFromColnodToDB(); + api->syncDataFromDBToColnod(); + QSignalSpy processSpy(api, &SyncManager::dataUpdatedToColnod); + processSpy.wait(timeout); + QSignalSpy finish(api, &SyncManager::syncFinished); + finish.wait(timeout); */ } void ComplexTest::syncLastUpdated() { - api->downloadChangedDataFromColnod(); - QSignalSpy spy(api, &ColnodAPI::dataDownloaded); - spy.wait(10000); - api->syncChangedDataFromColnod(); - // api->syncChangedDataToColnod(); - +// Logger::log("ahoj"); +// api->loadDataFromColnod(); +// QSignalSpy spy(api, &SyncManager::dataDownloaded); +// spy.wait(timeout); +// api->loadDataFromDB(); +// api->syncDataFromColnodToDB(); +// api->syncDataFromDBToColnod(); +// QSignalSpy processSpy(api, &SyncManager::dataUpdatedToColnod); +// processSpy.wait(timeout); +// QSignalSpy finish(api, &SyncManager::syncFinished); +// finish.wait(timeout); +// qDebug() << "All right, at least should be."; } void ComplexTest::testingStuff() @@ -143,31 +155,33 @@ void ComplexTest::testingStuff() // HELPFUL_FUNCTIONS int ComplexTest::getNumOfSubjects() { + auto reqMan = new RequestManager; Response* subjectsResp = reqMan->getSubjects(); QSignalSpy subjectsRespSpy(subjectsResp, &Response::ready); - subjectsRespSpy.wait(10000); + subjectsRespSpy.wait(timeout); auto doc = getJsonDoc(subjectsResp->getJson()); return doc.object()["items"].toArray().size(); } int ComplexTest::getNumOfTokens() { + auto reqMan = new RequestManager; Response* tokensResp = reqMan->getTokens(); QSignalSpy tokensRespSpy(tokensResp, &Response::ready); - tokensRespSpy.wait(10000); + tokensRespSpy.wait(timeout); auto doc = getJsonDoc(tokensResp->getJson()); return doc.object()["items"].toArray().size(); } -QJsonDocument ComplexTest::getJsonDoc(QString json) +QJsonDocument ComplexTest::getJsonDoc(const QString &json) { return QJsonDocument::fromJson(json.toUtf8()); } -Token* ComplexTest::getTestToken() +std::shared_ptr ComplexTest::getTestToken() { QJsonObject jsonToken; - jsonToken.insert("id", "582c982d-6fd7-4856-8548-7ce542791c7a"); + jsonToken.insert("id", "062c93f6-ba3e-46af-a3a6-7a2988d1f0e9"); jsonToken.insert("name", "test"); jsonToken.insert("description", "mobile"); jsonToken.insert("tokenType", "Token"); @@ -180,9 +194,9 @@ Token* ComplexTest::getTestToken() flags.push_back("NoValidity"); jsonToken.insert("flags", flags); jsonToken.insert("subjectId", "72b37f7e-5761-4e6c-8e87-20c0bed0d904"); - Token* token = new Token; + auto token = std::shared_ptr(); token->fromJSON(jsonToken); return token; } -QTEST_MAIN(ComplexTest) +//QTEST_MAIN(ComplexTest) diff --git a/test/unitTests/complextest.h b/test/unitTests/complextest.h index 896b857..38ed1be 100644 --- a/test/unitTests/complextest.h +++ b/test/unitTests/complextest.h @@ -5,7 +5,8 @@ #include #include "response.h" #include "requestmanager.h" -#include "colnodapi.h" +#include "syncmanager.h" +#include "logger.h" class ComplexTest : public QObject { @@ -23,8 +24,8 @@ private: // FUNCTIONS int getNumOfSubjects(); int getNumOfTokens(); - QJsonDocument getJsonDoc(QString json); - Token* getTestToken(); + QJsonDocument getJsonDoc(const QString &json); + std::shared_ptr getTestToken(); // VARIABLES @@ -32,7 +33,8 @@ private: QString user = "spaceti"; QString password = "spaceti1"; uint64_t start = 0; - RequestManager* reqMan = nullptr; - ColnodAPI* api = nullptr; + SyncManager* api = nullptr; + + static constexpr qint16 timeout = 10000; }; diff --git a/test/unitTests/unittest.h b/test/unitTests/unittest.h index 2fabad0..0e29652 100644 --- a/test/unitTests/unittest.h +++ b/test/unitTests/unittest.h @@ -37,15 +37,20 @@ private slots: void deleteTokens(); void subjectJSONParser(); void tokenJSONParser(); - void connectToDB(); + //void connectToDB(); //void debugConnection(); void saveDataToDB(); void getUuid(); private: - //QString host = "http://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"; -}; + std::shared_ptr getTestToken(); + + //QString host = "http://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"; + + static constexpr int timeout = 10000; + static constexpr qint64 epochMS = 1568646217767; +};