diff --git a/src/colnod/colnod.pri b/src/colnod/colnod.pri index c6a45af..749c655 100644 --- a/src/colnod/colnod.pri +++ b/src/colnod/colnod.pri @@ -1,30 +1,32 @@ -INCLUDEPATH += $$PWD - -CONFIG += c++14 - - -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 - -include(../../server-sdk/serversdk.pri) +INCLUDEPATH += $$PWD + +CONFIG += c++14 + + +SOURCES += \ + $$PWD/colnodapi.cpp \ + $$PWD/data.cpp \ + $$PWD/databaseapi.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/data.h \ + $$PWD/databaseapi.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 + +include(../../server-sdk/serversdk.pri) diff --git a/src/colnod/colnodapi.cpp b/src/colnod/colnodapi.cpp index bd401fe..26b5f14 100644 --- a/src/colnod/colnodapi.cpp +++ b/src/colnod/colnodapi.cpp @@ -4,26 +4,36 @@ ColnodAPI::ColnodAPI() { } -ColnodAPI::ColnodAPI(serversdk::RequestManager* reqMan) - :mReqMan(reqMan) +ColnodAPI::ColnodAPI(serversdk::RequestManager* reqMan, QString userName, QString password, qint64 lastSync) + :mReqMan(reqMan), mUserName(userName), mPassword(password) { - + mLastSync.set_timestamp(lastSync); } void ColnodAPI::downloadData() { // Have to get Login auto login = requestLogin(); - connect(login.get(), &serversdk::Request::finished, this, [=](){ + connect(login.get(), &serversdk::Request::finished, this, [=](){ // TODO: error handling // Get token AuthToken token; token.fromJson(login->responseData()); + authToken = token.idWithoutCurlyBraces(); - auto data = std::make_shared(); - emit downloadDataFinished(); + // if I have all data emit downloadDataFinished + connect(this, &ColnodAPI::partOfDataReady, this, &ColnodAPI::areDataReady); + getTokensUpdated(mLastSync); + getTokensDeleted(mLastSync); + getSubjectsUpdated(mLastSync); + getSubjectsDeleted(mLastSync); }); } +void ColnodAPI::uploadData(std::shared_ptr data) +{ + setTokens(data->updatedTokens); +} + std::shared_ptr ColnodAPI::requestLogin() { Q_ASSERT(mReqMan); @@ -38,7 +48,6 @@ std::shared_ptr ColnodAPI::requestLogin() login.set_password(encodedPassword); auto loginRequest = composeRequest("/AaaManager/authSession", login.jsonData()); -// auto loginRequest = std::make_shared("POST", "https://192.168.1.3:8443/AaaManager/authSession", login->jsonData()); loginRequest->setUserName(login.username()); loginRequest->setPassword(login.password()); mReqMan->processRequest(loginRequest); @@ -46,50 +55,74 @@ std::shared_ptr ColnodAPI::requestLogin() return loginRequest; } -QList ColnodAPI::getTokensUpdated(const qint64 &time) - +void ColnodAPI::getTokensUpdated(const Timestamp &time) { -// AuthToken token; -// token.fromJson(data); -// serversdk::Request request("POST", host + "/TokenManager/getTokensUpdated", getTimestampJson(time)); -// request.setToken(mToken); -// mReqMan->processRequest(); -} - -QString ColnodAPI::login(const QString &username, const QString &password) -{ - auto login = std::make_unique(); - login->set_username(username); - login->set_password(QCryptographicHash::hash(QString(password).toLocal8Bit(), QCryptographicHash::Sha512).toHex().toUpper()); - - serversdk::RequestManager reqMan; - reqMan.setIgnoreSsl(true); - - auto loginRequest = std::make_shared("POST", "https://192.168.1.3:8443/AaaManager/authSession", login->jsonData()); - loginRequest->setUserName(login->username()); - loginRequest->setPassword(login->password()); - reqMan.processRequest(loginRequest); - - QObject::connect(loginRequest.get(), &serversdk::Request::finished, [=](){ - auto data = loginRequest->responseData(); - - AuthToken token; - token.fromJson(data); - return token.idWithoutCurlyBraces(); + auto request = composeRequest("/TokenManager/getTokensUpdated", time.jsonData()); + request->setToken(authToken); + mReqMan->processRequest(request); + connect(request.get(), &serversdk::Request::finished, [=](){ + saveUpdatedTokens(request->responseData()); + emit partOfDataReady(); }); } -QByteArray ColnodAPI::getTimestampJson(const qint64 &time) +void ColnodAPI::getTokensDeleted(const Timestamp &time) { - QJsonObject reqBody = {{"timestamp",QJsonValue(time)}}; - QJsonDocument doc; - doc.setObject(reqBody); - return doc.toJson(); + auto request = composeRequest("/TokenManager/getTokensDeleted", time.jsonData()); + request->setToken(authToken); + mReqMan->processRequest(request); + connect(request.get(), &serversdk::Request::finished, [=](){ + saveDeletedTokens(request->responseData()); + emit partOfDataReady(); + }); +} + +void ColnodAPI::getSubjectsUpdated(const Timestamp &time) +{ + auto request = composeRequest("/SubjectManager/getSubjectsUpdated", time.jsonData()); + request->setToken(authToken); + mReqMan->processRequest(request); + connect(request.get(), &serversdk::Request::finished, [=](){ + saveUpdatedSubjects(request->responseData()); + emit partOfDataReady(); + }); +} + +void ColnodAPI::getSubjectsDeleted(const Timestamp &time) +{ + auto request = composeRequest("/SubjectManager/getSubjectsDeleted", time.jsonData()); + request->setToken(authToken); + mReqMan->processRequest(request); + connect(request.get(), &serversdk::Request::finished, [=](){ + saveDeletedSubjects(request->responseData()); + emit partOfDataReady(); + }); +} + +void ColnodAPI::setTokens(const QHash &tokens) +{ + + auto request = composeRequest("/TokenManager/setTokens", Token::tokensToJSON(tokens)); + request->setToken(authToken); + mReqMan->processRequest(request); + connect(request.get(), &serversdk::Request::finished, [=](){ + if (checkResponse(request->responseData())) { + emit partOfDataProcessFinished(); + } + else { + + } + }); +} + +void ColnodAPI::deleteTokens(const QList &tokenIds) +{ + } std::shared_ptr ColnodAPI::composeRequest(const QString &endpoint, const QByteArray &data) { - QString url = host + endpoint; + QString url = mHost + endpoint; return std::make_shared("POST", url, data); } @@ -103,6 +136,17 @@ void ColnodAPI::setPassword(const QString &password) mPassword = password; } +qint64 ColnodAPI::lastSync() const +{ + return mLastSync.timestamp(); +} + +void ColnodAPI::setlastSync(const qint64 &lastSync) +{ + mLastSync.set_timestamp(lastSync); +} + + QString ColnodAPI::userName() const { return mUserName; @@ -112,3 +156,52 @@ void ColnodAPI::setUserName(const QString &userName) { mUserName = userName; } + +void ColnodAPI::areDataReady() +{ + if (++amountData == 4) { + emit downloadDataFinished(data); + } +} + +void ColnodAPI::saveUpdatedTokens(const QByteArray &responseData) +{ + QJsonDocument doc = QJsonDocument::fromJson(responseData); + QJsonArray items = doc.object()["items"].toArray(); + for (QJsonValueRef item : items) { + Token token; + token.fromJSON(item.toObject()); + token.setDeleted(false); + data->updatedTokens.insert(token.getId(), token); + } +} + +void ColnodAPI::saveDeletedTokens(const QByteArray &responseData) +{ + QJsonDocument doc = QJsonDocument::fromJson(responseData); + QJsonArray items = doc.object()["items"].toArray(); + for (QJsonValueRef item : items) { + data->deletedTokens.append(item.toString()); + } +} + +void ColnodAPI::saveUpdatedSubjects(const QByteArray &responseData) +{ + QJsonDocument doc = QJsonDocument::fromJson(responseData); + QJsonArray items = doc.object()["items"].toArray(); + for (QJsonValueRef item : items) { + Subject subject; + subject.fromJSON(item.toObject()); + subject.setDeleted(false); + data->updatedSubjects.insert(subject.getId(), subject); + } +} + +void ColnodAPI::saveDeletedSubjects(const QByteArray &responseData) +{ + QJsonDocument doc = QJsonDocument::fromJson(responseData); + QJsonArray items = doc.object()["items"].toArray(); + for (QJsonValueRef item : items) { + data->deletedSubjects.append(item.toString()); + } +} diff --git a/src/colnod/colnodapi.h b/src/colnod/colnodapi.h index c93cb3b..793916c 100644 --- a/src/colnod/colnodapi.h +++ b/src/colnod/colnodapi.h @@ -1,22 +1,10 @@ #pragma once -#include "serversdk/requestmanager.h" -#include "serversdk/request.h" -#include "token.h" -#include "subject.h" #include "serversdk/requestmanager.h" #include "serversdk/request.h" #include "serversdk/databasetable.h" - -struct ColnodData -{ - QList> updatedTokens; - QList> updatedSubjects; - QList> deletedTokens; - QList> deletedSubjects; - - bool isValid(); -}; +#include "QDateTime" +#include "data.h" class LoginResp : public serversdk::DatabaseTable { Q_OBJECT @@ -34,45 +22,75 @@ class AuthToken : public serversdk::DatabaseTable { } }; +class Timestamp : public serversdk::DatabaseTable { + Q_OBJECT + TABLE_PROPERTY(qint64, timestamp, set_timestamp, 0) + QString toDateString() + { + return QDateTime::fromMSecsSinceEpoch(a_timestamp).toString("yyyy-MM-dd hh:mm:ss.zzz"); + } +}; + class ColnodAPI: public QObject { Q_OBJECT public: ColnodAPI(); - ColnodAPI(serversdk::RequestManager* reqMan); + ColnodAPI(serversdk::RequestManager* reqMan, QString userName = "spaceti", QString password = "spaceti1", qint64 lastSync = 0); void downloadData(); + void uploadData(std::shared_ptr data); // New approach std::shared_ptr requestLogin(); - QList getTokensUpdated(const qint64 &time); - QList getTokensDeleted(const qint64 &time); - QList getSubjectsUpdated(const qint64 &time); - QList getSubjectsDeleted(const qint64 &time); + void getTokensUpdated(const Timestamp &time); + void getTokensDeleted(const Timestamp &time); + void getSubjectsUpdated(const Timestamp &time); + void getSubjectsDeleted(const Timestamp &time); - bool setTokens(const QList &tokens); - bool deleteTokens(const QList &tokenIds); + void setTokens(const QHash &tokens); + void deleteTokens(const QList &tokenIds); // Attributes QString userName() const; void setUserName(const QString &userName); QString password() const; void setPassword(const QString &password); + qint64 lastSync() const; + void setlastSync(const qint64 &lastSync); + private: - QString login(const QString &username, const QString &password); + Q_SLOT void areDataReady(); + +private: + void saveUpdatedTokens(const QByteArray &responseData); + void saveUpdatedSubjects(const QByteArray &responseData); + void saveDeletedTokens(const QByteArray &responseData); + void saveDeletedSubjects(const QByteArray &responseData); + + bool checkResponse(const QByteArray &responseData); + QByteArray getTimestampJson(const qint64 &time); std::shared_ptr composeRequest(const QString &endpoint, const QByteArray &data); signals: - void downloadDataFinished(std::shared_ptr = std::shared_ptr()); + void downloadDataFinished(std::shared_ptr = std::shared_ptr()); + void partOfDataReady(); + void partOfDataProcessFinished(); private: serversdk::RequestManager* mReqMan = nullptr; - QString host = "https://192.168.1.3:8443"; + QString mHost = "https://192.168.1.3:8443"; QString mUserName; QString mPassword; + Timestamp mLastSync; + + std::shared_ptr data; + + QString authToken; + qint16 amountData = 0; }; diff --git a/src/colnod/data.cpp b/src/colnod/data.cpp new file mode 100644 index 0000000..f23b174 --- /dev/null +++ b/src/colnod/data.cpp @@ -0,0 +1,6 @@ +#include "data.h" + +Data::Data() +{ + +} diff --git a/src/colnod/data.h b/src/colnod/data.h new file mode 100644 index 0000000..39a6dca --- /dev/null +++ b/src/colnod/data.h @@ -0,0 +1,17 @@ +#pragma once + +#include "token.h" +#include "subject.h" + + +class Data +{ +public: + Data(); + + QHash updatedTokens; + QList deletedTokens; + QHash updatedSubjects; + QList deletedSubjects; +}; + diff --git a/src/colnod/databasemanager.cpp b/src/colnod/databaseapi.cpp similarity index 78% rename from src/colnod/databasemanager.cpp rename to src/colnod/databaseapi.cpp index 74e493c..f5282d0 100644 --- a/src/colnod/databasemanager.cpp +++ b/src/colnod/databaseapi.cpp @@ -1,8 +1,99 @@ -#include "databasemanager.h" +#include "databaseapi.h" #include "logger.h" -DatabaseManager::DatabaseManager(const QString& host, const QString& dbName, const QString& user, const QString& password, const bool &dryMode) +DatabaseAPI::DatabaseAPI(serversdk::DatabaseManager *dbMan) + :mDbMan(dbMan) +{ + +} + +void DatabaseAPI::downloadData() +{ + QSqlQuery updatedQuery = mDbMan->execPlainSql("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 AND deleted = false"); + QSqlQuery deletedQuery = mDbMan->execPlainSql("SELECT id " + "FROM colnod_token WHERE EXTRACT(EPOCH FROM last_modified) * 1000 > EXTRACT(EPOCH FROM last_update) * 1000 AND deleted = true"); + emit downloadDataFinished(composeData(updatedQuery, deletedQuery)); +} + + + + +std::shared_ptr DatabaseAPI::composeData(QSqlQuery updatedQuery, QSqlQuery deletedQuery) +{ + auto data = std::make_shared(); + while (updatedQuery.next()) { + Token token; + token.fromSQLRecord(updatedQuery); + data->updatedTokens.append(token); + } + while (deletedQuery.next()) { + data->deletedTokens.append(deletedQuery.value(0).toString()); + } + return data; +} + +qint64 DatabaseAPI::getLastSync() +{ + auto query = mDbMan->execPlainSql("SELECT last_sync FROM config"); + if (query.next()){ + return query.value(0).toLongLong(); + } + else { + return -1; + } +} + +void DatabaseAPI::setLastSync(qint64 timestamp) +{ + QSqlQuery query; + query.prepare("UPDATE config SET last_sync = :last_sync"); + query.bindValue(":last_sync", timestamp); + executeQuery(query); +} + +qint64 DatabaseAPI::getNow() +{ + QSqlQuery query = mDbMan->execPlainSql("SELECT EXTRACT(EPOCH FROM NOW())*1000"); + query.next(); + return query.value(0).toLongLong(); +} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +// OLD +DatabaseAPI::DatabaseAPI(const QString& host, const QString& dbName, const QString& user, const QString& password, const bool &dryMode) :dryMode(dryMode) { db = QSqlDatabase::addDatabase("QPSQL"); @@ -22,7 +113,7 @@ DatabaseManager::DatabaseManager(const QString& host, const QString& dbName, con } // add or update subject to db -int DatabaseManager::saveSubject(const std::shared_ptr& subject, const QString& table) +int DatabaseAPI::saveSubject(const std::shared_ptr& subject, const QString& table) { QSqlQuery query; QString id = subject->idToStringWithoutBraces(); @@ -47,8 +138,17 @@ int DatabaseManager::saveSubject(const std::shared_ptr& subject, const return rtn; } +QSqlQuery DatabaseAPI::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 AND deleted = false"); + return query; +} + + // add or update token to DB -int DatabaseManager::saveToken(const std::shared_ptr& token, const QString& table) +int DatabaseAPI::saveToken(const std::shared_ptr& token, const QString& table) { QSqlQuery query; QString id = token->idToStringWithoutBraces(); @@ -81,7 +181,7 @@ int DatabaseManager::saveToken(const std::shared_ptr& token, const QStrin } // add of update subject attributes -void DatabaseManager::saveSubjectAttributes(const std::shared_ptr& subject, const QString& table) +void DatabaseAPI::saveSubjectAttributes(const std::shared_ptr& subject, const QString& table) { QSqlQuery query; auto attributes = subject->getAtr(); @@ -103,7 +203,7 @@ void DatabaseManager::saveSubjectAttributes(const std::shared_ptr& subj } // "delete" tokens from DB -> set deleted true -void DatabaseManager::setDeleted(const QString& id, const QString& table, quint64 time) +void DatabaseAPI::setDeleted(const QString& id, const QString& table, quint64 time) { QSqlQuery query; QString nowString = QDateTime::fromMSecsSinceEpoch(time).toString("yyyy-MM-dd hh:mm:ss.zzz"); @@ -113,7 +213,7 @@ void DatabaseManager::setDeleted(const QString& id, const QString& table, quint6 executeQuery(query); } -bool DatabaseManager::checkIfExists(const QString& id, const QString& table) +bool DatabaseAPI::checkIfExists(const QString& id, const QString& table) { QSqlQuery query; query.prepare(QString("SELECT EXISTS(SELECT 1 FROM %1 WHERE id = :id)").arg(table)); @@ -123,7 +223,7 @@ bool DatabaseManager::checkIfExists(const QString& id, const QString& table) return query.value(0).toBool(); } -QString DatabaseManager::getLastQuery(const QSqlQuery& query) const +QString DatabaseAPI::getLastQuery(const QSqlQuery& query) const { QString str = query.lastQuery(); QMapIterator it(query.boundValues()); @@ -135,7 +235,7 @@ QString DatabaseManager::getLastQuery(const QSqlQuery& query) const return str; } -bool DatabaseManager::executeQuery(QSqlQuery &query, const QString &statement) +bool DatabaseAPI::executeQuery(QSqlQuery &query, const QString &statement) { if (statement.isEmpty()){ if (dryMode){ @@ -164,7 +264,7 @@ bool DatabaseManager::executeQuery(QSqlQuery &query, const QString &statement) return true; } -void DatabaseManager::dropTables() +void DatabaseAPI::dropTables() { QSqlQuery query; @@ -172,7 +272,7 @@ void DatabaseManager::dropTables() } // create table after deleting, it is used for full sync -void DatabaseManager::createTables() +void DatabaseAPI::createTables() { QSqlQuery query; @@ -206,36 +306,14 @@ void DatabaseManager::createTables() "subject_id CHAR(36))"); } -// return last_sync time -quint64 DatabaseManager::getLastSync() -{ - 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 DatabaseAPI::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 " @@ -246,16 +324,10 @@ QSqlQuery DatabaseManager::getToken(const QString& id) return query; } -quint64 DatabaseManager::getNow() -{ - QSqlQuery query; - executeQuery(query, "SELECT EXTRACT(EPOCH FROM NOW())*1000"); - query.next(); - return query.value(0).toULongLong(); -} + // sync last update back to DB from Colnod after changes made to Colnod -void DatabaseManager::setLastUpdate(const QString& id, quint64 lastUpdate) +void DatabaseAPI::setLastUpdate(const QString& id, quint64 lastUpdate) { QSqlQuery query; QString lsatUpdateString = QDateTime::fromMSecsSinceEpoch(lastUpdate).toString("yyyy-MM-dd hh:mm:ss.zzz"); @@ -265,7 +337,7 @@ void DatabaseManager::setLastUpdate(const QString& id, quint64 lastUpdate) executeQuery(query); } -void DatabaseManager::log(const QString &msg) +void DatabaseAPI::log(const QString &msg) { QSqlQuery query; query.prepare("INSERT INTO logs (log_time, msg) VALUES (NOW(), :msg)"); @@ -273,7 +345,7 @@ void DatabaseManager::log(const QString &msg) query.exec(); } -QString DatabaseManager::getSubjectNameByTokenId(const QString &tokenId) +QString DatabaseAPI::getSubjectNameByTokenId(const QString &tokenId) { QSqlQuery query; query.prepare("SELECT name FROM colnod_subject WHERE id = (SELECT subject_id FROM colnod_token WHERE id = :tokenId)"); @@ -285,7 +357,7 @@ QString DatabaseManager::getSubjectNameByTokenId(const QString &tokenId) return "(No subject)"; } -QString DatabaseManager::getSubjectNameById(const QString &id) +QString DatabaseAPI::getSubjectNameById(const QString &id) { QSqlQuery query; query.prepare("SELECT name FROM colnod_subject WHERE id = :id"); @@ -297,7 +369,7 @@ QString DatabaseManager::getSubjectNameById(const QString &id) return "(No subject)"; } -bool DatabaseManager::checkDeletedToken(const QString &id) +bool DatabaseAPI::checkDeletedToken(const QString &id) { QSqlQuery query; query.prepare("SELECT deleted FROM colnod_token WHERE id = :id"); @@ -307,7 +379,7 @@ bool DatabaseManager::checkDeletedToken(const QString &id) return query.value(0).toBool(); } -qint16 DatabaseManager::getNumOfTokensOfSubject(const QString &id) +qint16 DatabaseAPI::getNumOfTokensOfSubject(const QString &id) { QSqlQuery query; query.prepare("SELECT 1 FROM colnod_token WHERE subject_id = :id AND deleted = false"); @@ -316,7 +388,7 @@ qint16 DatabaseManager::getNumOfTokensOfSubject(const QString &id) return static_cast(query.size()); } -bool DatabaseManager::isOpen() +bool DatabaseAPI::isOpen() { return opened; } diff --git a/src/colnod/databasemanager.h b/src/colnod/databaseapi.h similarity index 64% rename from src/colnod/databasemanager.h rename to src/colnod/databaseapi.h index 74fc989..605000b 100644 --- a/src/colnod/databasemanager.h +++ b/src/colnod/databaseapi.h @@ -10,13 +10,47 @@ #include "subject.h" #include "token.h" #include +#include "data.h" +#include "serversdk/databasemanager.h" +#include "serversdk/databasetable.h" -class DatabaseManager : public QObject + +class TokenTable : public serversdk::DatabaseTable { + Q_OBJECT +}; + +class DatabaseAPI : public QObject { Q_OBJECT public: - DatabaseManager(const QString& host, const QString& dbName, const QString& user, const QString& password, const bool& dryMode = false); + DatabaseAPI(serversdk::DatabaseManager *dbMan); + + void downloadData(); + qint64 getLastSync(); + void setLastSync(qint64 timestamp); + qint64 getNow(); + +private: + QSqlQuery getUpdatedTokens(); + std::shared_ptr composeData(QSqlQuery updatedQuery, QSqlQuery deletedQuery); + +signals: + void downloadDataFinished(std::shared_ptr = std::shared_ptr()); + + + +private: + serversdk::DatabaseManager *mDbMan = nullptr; + + + + + + + + // old + DatabaseAPI(const QString& host, const QString& dbName, const QString& user, const QString& password, const bool& dryMode = false); int saveSubject(const std::shared_ptr& subject, const QString& table); int saveToken(const std::shared_ptr& token, const QString& table); @@ -26,11 +60,8 @@ public: void dropTables(); void createTables(); - quint64 getLastSync(); void updateLastSync(quint64 lastSync); - quint64 getNow(); - QSqlQuery getUpdatedTokens(); QSqlQuery getToken(const QString& id); void setLastUpdate(const QString& id, quint64 lastUpdate); diff --git a/src/colnod/datamanager.cpp b/src/colnod/datamanager.cpp index 7a0dd6b..38cea70 100644 --- a/src/colnod/datamanager.cpp +++ b/src/colnod/datamanager.cpp @@ -1,7 +1,7 @@ #include "datamanager.h" DataManager::DataManager(const bool &dryMode) : - db(std::make_shared("192.168.1.94", "deloitte", "postgres", "34rjkciea12", dryMode)), + db(std::make_shared("192.168.1.94", "deloitte", "postgres", "34rjkciea12", dryMode)), dryMode(dryMode) { if (db->isOpen()){ @@ -9,7 +9,7 @@ DataManager::DataManager(const bool &dryMode) : nextLastSync = db->getNow(); lastSync = db->getLastSync(); } - connect(db.get(), &DatabaseManager::error, this, &DataManager::error, Qt::QueuedConnection); + connect(db.get(), &DatabaseAPI::error, this, &DataManager::error, Qt::QueuedConnection); } // load all tokens from colnod to comparing with working set from DB diff --git a/src/colnod/datamanager.h b/src/colnod/datamanager.h index 1793cf8..825add4 100644 --- a/src/colnod/datamanager.h +++ b/src/colnod/datamanager.h @@ -3,7 +3,7 @@ #include "token.h" #include "subject.h" #include "requestmanager.h" -#include "databasemanager.h" +#include "databaseapi.h" #include #include #include @@ -63,7 +63,7 @@ signals: void error(); private: - std::shared_ptr db; + std::shared_ptr db; quint64 lastSync; // time of last run quint64 nextLastSync; // time of begin of this run diff --git a/src/colnod/logger.cpp b/src/colnod/logger.cpp index 4c46c73..48160a0 100644 --- a/src/colnod/logger.cpp +++ b/src/colnod/logger.cpp @@ -1,9 +1,9 @@ #include "logger.h" -#include "databasemanager.h" +#include "databaseapi.h" #include -std::shared_ptr Logger::dbMan = nullptr; +std::shared_ptr Logger::dbMan = nullptr; Logger *Logger::logger = nullptr; Logger::Logger() @@ -29,7 +29,7 @@ void Logger::logToDb(const QString &msg) Logger::dbMan->log(msg); } -void Logger::setDBMan(std::shared_ptr dbMan) +void Logger::setDBMan(std::shared_ptr dbMan) { Logger::dbMan = std::move(dbMan); } diff --git a/src/colnod/logger.h b/src/colnod/logger.h index cedd633..e8b7fb5 100644 --- a/src/colnod/logger.h +++ b/src/colnod/logger.h @@ -5,7 +5,7 @@ #include #include -class DatabaseManager; +class DatabaseAPI; class Logger @@ -15,13 +15,13 @@ class Logger Logger(); - static std::shared_ptr dbMan; + 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 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); diff --git a/src/colnod/syncmanager.cpp b/src/colnod/syncmanager.cpp index 1c72bd8..7609713 100644 --- a/src/colnod/syncmanager.cpp +++ b/src/colnod/syncmanager.cpp @@ -1,4 +1,132 @@ #include "syncmanager.h" + +bool SyncManager::init() +{ + if (database.open() dbMan.openPostgres(QStringLiteral("192.168.1.94"), // move to databaseAPi + QStringLiteral("deloitte"), + QStringLiteral("postgres"), + QStringLiteral("34rjkciea12"), + QStringLiteral("postgres-connection"))){ + + mlastSync.set_timestamp(database.getLastSync()); + // -1 --> some error with getting data from DB + if (mlastSync.timestamp() >= 0){ + return true; + } + } + return false; +} + +void SyncManager::run() +{ + qint64 syncBegin = database.getNow(); + downloadData(); + connect(this, &SyncManager::dataReady, [=](){ + prepareData(); + processData(); + connect(this, &SyncManager::processDataFinished, [=](){ + updateLastUpdate(); // get last_update from colnod after seting tokens TODO: + database.setLastSync(syncBegin); + QCoreApplication::exit(); + }); + }); +} + + + + +void SyncManager::downloadData() +{ + colnod.downloadData(); + connect(&colnod, &ColnodAPI::downloadDataFinished, this, &SyncManager::saveColnodData); + connect(&colnod, &ColnodAPI::downloadDataFinished, this, &SyncManager::areDataReady); + database.downloadData(); + connect(&database, &DatabaseAPI::downloadDataFinished, this, &SyncManager::saveDatabaseData); + connect(&database, &DatabaseAPI::downloadDataFinished, this, &SyncManager::areDataReady); +} + +// finds conflicts -> changes on both sides (colnod and DB), apply newer change +void SyncManager::prepareData() +{ + colnodDataToProcess = std::make_shared(colnodData); + databaseDataToProcess = std::make_shared(databaseData); + + QList idsToDelete; + + for (const auto &colnodToken : colnodDataToProcess->updatedTokens) { + if (databaseDataToProcess->updatedTokens.contains(colnodToken.getId())) { + if (databaseDataToProcess->updatedTokens.value(colnodToken.getId()) > colnodToken) + idsToDelete.append(colnodToken.getId()); + } + } + for (const auto &id : idsToDelete) + colnodDataToProcess->updatedTokens.remove(id); + idsToDelete.clear(); + + for (const auto &databaseToken : databaseDataToProcess->updatedTokens) { + if (colnodDataToProcess->updatedTokens.contains(databaseToken.getId())) { + if (databaseToken > colnodDataToProcess->updatedTokens.value(databaseToken.getId())) + idsToDelete.append(databaseToken.getId()); + } + } + for (const auto &id : idsToDelete) + colnodDataToProcess->updatedTokens.remove(id); +} + +void SyncManager::processData() +{ + // TODO: +} + +void SyncManager::areDataReady() +{ + if (++dataAmount) + emit dataReady(); +} + + +void SyncManager::saveColnodData(std::shared_ptr data) +{ + colnodData = data; +} + +void SyncManager::saveDatabaseData(std::shared_ptr data) +{ + databaseData = data; +} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + SyncManager::SyncManager(bool dryMode) : reqMan(std::make_unique()), @@ -199,7 +327,7 @@ bool SyncManager::isValid() void SyncManager::areChangedDataReady() { if (++dataCounter == 5) - emit dataDownloaded(); + emit dataReady(); } // emit signal when writing to Colnod is finised diff --git a/src/colnod/syncmanager.h b/src/colnod/syncmanager.h index 33a9df6..6e037fe 100644 --- a/src/colnod/syncmanager.h +++ b/src/colnod/syncmanager.h @@ -1,13 +1,66 @@ #pragma once +#include "colnodapi.h" +#include "databaseapi.h" #include "requestmanager.h" #include "datamanager.h" #include "logger.h" +#include "colnodapi.h" +#include "serversdk/databasemanager.h" class SyncManager : public QObject { Q_OBJECT + // NEW +public: + bool init(); + void run(); + +private: + void downloadData(); + void prepareData(); + void processData(); + + + +private: + Q_SLOTS void saveColnodData(std::shared_ptr data); + Q_SLOTS void saveDatabaseData(std::shared_ptr data); + Q_SLOTS void areDataReady(); + +signals: + void dataReady(); + void processDataFinished(); + +private: + ColnodAPI colnod; + DatabaseAPI database; + serversdk::RequestManager reqMan; + serversdk::DatabaseManager dbMan; + Timestamp mlastSync; + + std::shared_ptr colnodData; + std::shared_ptr databaseData; + + std::shared_ptr colnodDataToProcess; + std::shared_ptr databaseDataToProcess; + + int dataAmount = 0; + + + + + + + + + + + + + + // OLD public: explicit SyncManager(bool dryMode = false); @@ -24,7 +77,7 @@ public slots: void loadDataFromDB(); signals: - void dataDownloaded(); + void dataReady(); void dataUpdatedToColnod(); void syncFinished(); void error(); @@ -49,7 +102,7 @@ private: void areDataUpdatedToColnod(); private: - std::unique_ptr reqMan; + // std::unique_ptr reqMan; std::unique_ptr dataMan; bool dryMode = false; bool updateFinished = false; diff --git a/src/colnod/token.cpp b/src/colnod/token.cpp index ff3b573..2a7ad47 100644 --- a/src/colnod/token.cpp +++ b/src/colnod/token.cpp @@ -1,6 +1,7 @@ #include "token.h" #include +#include #include @@ -52,6 +53,20 @@ QJsonObject Token::toJSON() const { return json; } +QByteArray Token::tokensToJSON(const QHash &tokens) +{ + QJsonObject items; + QJsonArray jsonTokens; + for (const auto& token : tokens) + { + jsonTokens.push_back(token.toJSON()); + } + items.insert("items", jsonTokens); + QJsonDocument doc; + doc.setObject(items); + return doc.toJson(); +} + void Token::fromSQLRecord(const QSqlQuery& query) { setId(query.value(0).toUuid()); diff --git a/src/colnod/token.h b/src/colnod/token.h index 9d49cbf..2e3261b 100644 --- a/src/colnod/token.h +++ b/src/colnod/token.h @@ -69,6 +69,8 @@ public: void fromJSON(const QJsonObject &json) override; QJsonObject toJSON() const override; + static QByteArray tokensToJSON(const QHash &tokens); + private: QString tokenType = "Token"; int tokenBits = 32; diff --git a/test/unitTests/unittest.h b/test/unitTests/unittest.h index 70c522e..c74c27a 100644 --- a/test/unitTests/unittest.h +++ b/test/unitTests/unittest.h @@ -5,7 +5,7 @@ #include #include #include "subject.h" -#include "databasemanager.h" +#include "databaseapi.h" #include #include "datamanager.h" #include "response.h"