diff --git a/server-sdk b/server-sdk index eddfc40..9623578 160000 --- a/server-sdk +++ b/server-sdk @@ -1 +1 @@ -Subproject commit eddfc401b0282d53ba7289bb5c3ffa41e0287dda +Subproject commit 9623578997c33de0700131a40592a83e6cef3289 diff --git a/src/colnod/colnodapi.cpp b/src/colnod/colnodapi.cpp index b589702..5cd1f28 100644 --- a/src/colnod/colnodapi.cpp +++ b/src/colnod/colnodapi.cpp @@ -18,10 +18,10 @@ void ColnodAPI::downloadData() { // Have to get Login auto login = requestLogin(); - connect(login.get(), &serversdk::Request::finished, this, [=](){ // TODO: error handling - // Get token - if (login->status() != 0) { - qCritical(colnod) << "Login unsuccessful, Status:" << login->status() << "Error message:" ; + connect(login.get(), &serversdk::Request::finished, this, [=](){ + // Get login token + if (login->status() != 200) { + emit error(); } AuthToken token; @@ -86,6 +86,14 @@ void ColnodAPI::getTokensUpdated(const Timestamp &time) request->setUserName(authToken); mReqMan->processRequest(request); connect(request.get(), &serversdk::Request::finished, [=](){ + if (!checkRequest(request)) { + qWarning(colnod) << "ERROR during calling /TokenManager/getTokensUpdated, request unsuccessful"; + mValid = false; + } + else if (!checkResponse(request->responseData())) { + qWarning(colnod) << "Data from /TokenManager/getTokensUpdated are invalid"; + mValid = false; + } saveUpdatedTokens(request->responseData()); emit partOfDataReady(mData); }); @@ -97,6 +105,14 @@ void ColnodAPI::getTokensDeleted(const Timestamp &time) request->setUserName(authToken); mReqMan->processRequest(request); connect(request.get(), &serversdk::Request::finished, [=](){ + if (!checkRequest(request)) { + qWarning(colnod) << "ERROR during calling /TokenManager/getTokensDeleted, request unsuccessful"; + mValid = false; + } + else if (!checkResponse(request->responseData())) { + qWarning(colnod) << "Data from /TokenManager/getTokensDeleted are invalid"; + mValid = false; + } saveDeletedTokens(request->responseData()); emit partOfDataReady(); }); @@ -108,6 +124,14 @@ void ColnodAPI::getSubjectsUpdated(const Timestamp &time) request->setUserName(authToken); mReqMan->processRequest(request); connect(request.get(), &serversdk::Request::finished, [=](){ + if (!checkRequest(request)) { + qWarning(colnod) << "ERROR during calling /SubjectManager/getSubjectsUpdated, request unsuccessful"; + mValid = false; + } + else if (!checkResponse(request->responseData())) { + qWarning(colnod) << "Data from /SubjectManager/getSubjectsUpdated are invalid"; + mValid = false; + } saveUpdatedSubjects(request->responseData()); emit partOfDataReady(); }); @@ -119,6 +143,14 @@ void ColnodAPI::getSubjectsDeleted(const Timestamp &time) request->setUserName(authToken); mReqMan->processRequest(request); connect(request.get(), &serversdk::Request::finished, [=](){ + if (!checkRequest(request)) { + qWarning(colnod) << "ERROR during calling /SubjectManager/getSubjectsDeleted, request unsuccessful"; + mValid = false; + } + else if (!checkResponse(request->responseData())) { + qWarning(colnod) << "Data from /SubjectManager/getSubjectsDeleted are invalid"; + mValid = false; + } saveDeletedSubjects(request->responseData()); emit partOfDataReady(); }); @@ -130,12 +162,17 @@ void ColnodAPI::setTokens(const QHash> &tokens) request->setUserName(authToken); mReqMan->processRequest(request); connect(request.get(), &serversdk::Request::finished, [=](){ + if (!checkRequest(request)) { + qCritical(colnod) << "ERROR during calling /TokenManager/setTokens, request unsuccessful. EXIT"; + emit error(); + } if (checkResponse(request->responseData())) { emit partOfDataProcessFinished(); } else { qWarning(colnod) << "Tokens wasn't updated"; - // TODO: error: data wasnt upload to colnod + mValid = false; + emit partOfDataProcessFinished(); } }); } @@ -146,12 +183,17 @@ void ColnodAPI::deleteTokens(const QList &ids) request->setUserName(authToken); mReqMan->processRequest(request); connect(request.get(), &serversdk::Request::finished, [=](){ + if (!checkRequest(request)) { + qCritical(colnod) << "ERROR during calling /TokenManager/deleteTokens, request unsuccessful. EXIT"; + emit error(); + } if (checkResponse(request->responseData())) { emit partOfDataProcessFinished(); } else { qWarning(colnod) << "Tokens wasn't deleted"; - // TODO: error: data wasnt upload to colnod + mValid = false; + emit partOfDataProcessFinished(); } }); @@ -163,6 +205,19 @@ std::shared_ptr ColnodAPI::composeRequest(const QString &end return std::make_shared("POST", url, data); } +bool ColnodAPI::checkRequest(const std::shared_ptr &request) +{ + if (request->status() == 200) { + return true; + } + return false; +} + +bool ColnodAPI::isValid() +{ + return mValid; +} + QString ColnodAPI::password() const { return mPassword; diff --git a/src/colnod/colnodapi.h b/src/colnod/colnodapi.h index c239c14..2e7fbcf 100644 --- a/src/colnod/colnodapi.h +++ b/src/colnod/colnodapi.h @@ -77,12 +77,18 @@ private: QByteArray getTimestampJson(const qint64 &time); std::shared_ptr composeRequest(const QString &endpoint, const QByteArray &data); + bool checkRequest(const std::shared_ptr &request); + + bool isValid(); + signals: void downloadDataFinished(std::shared_ptr = std::shared_ptr()); void partOfDataReady(std::shared_ptr = std::shared_ptr()); void partOfDataProcessFinished(); void dataProcessFinished(); + void error(); + private: serversdk::RequestManager* mReqMan = nullptr; QString mHost = "https://192.168.1.3:8443"; @@ -90,6 +96,7 @@ private: QString mPassword; Timestamp mLastSync; bool mDryMode = false; + bool mValid = false; std::shared_ptr mData; diff --git a/src/colnod/databaseapi.cpp b/src/colnod/databaseapi.cpp index 542f13b..420f0da 100644 --- a/src/colnod/databaseapi.cpp +++ b/src/colnod/databaseapi.cpp @@ -19,12 +19,31 @@ bool DatabaseAPI::open() QStringLiteral("postgres-connection")); } +bool DatabaseAPI::executeQuery(QSqlQuery &query, const QString &statement) +{ + if (statement.isEmpty()) { + query = mDbMan->executeQuery(query); + } + else { + query = mDbMan->executeQuery(query, statement); + } + if (!query.isActive()) { + this->mValid = false; + return false; + } + return true; +} + void DatabaseAPI::downloadData() { - auto updatedQuery = mDbMan->execPlainSql("SELECT * " - "FROM colnod_token WHERE last_modified > last_update AND deleted = false"); - auto deletedQuery = mDbMan->execPlainSql("SELECT id " - "FROM colnod_token WHERE last_modified > last_update AND deleted = true"); + auto updatedQuery = mDbMan->createQuery(); + auto deletedQuery = mDbMan->createQuery(); + if (!executeQuery(updatedQuery, "SELECT * FROM colnod_token WHERE last_modified > last_update AND deleted = false")) { + qWarning(database) << "ERROR during geting new/updated tokens from db."; + } + if (!executeQuery(deletedQuery, "SELECT id FROM colnod_token WHERE last_modified > last_update AND deleted = true")) { + qWarning(database) << "ERROR during geting marked tokens for deletion from db."; + } emit downloadDataFinished(composeData(updatedQuery, deletedQuery)); } @@ -65,7 +84,11 @@ std::shared_ptr DatabaseAPI::composeData(const QSqlQuery &updatedQuery, QS qint64 DatabaseAPI::getLastSync() { - auto query = mDbMan->execPlainSql("SELECT last_sync FROM config"); + auto query = mDbMan->createQuery(); + if (!executeQuery(query, "SELECT last_sync FROM config")) { + qCritical(database) << "ERROR during getting time of last sync. Exit."; + emit error(); + } if (query.next()){ return query.value(0).toLongLong(); } @@ -77,7 +100,10 @@ void DatabaseAPI::setLastSync(qint64 timestamp) auto query = mDbMan->createQuery(); query.prepare("UPDATE config SET last_sync = :last_sync"); query.bindValue(":last_sync", timestamp); - mDbMan->executeQuery(query); + if (!executeQuery(query)) { + qCritical(database) << "ERROR during set time of this synchronization as last sync time"; + emit error(); + } } void DatabaseAPI::setLastUpdate(const QHash> &tokens) @@ -87,7 +113,9 @@ void DatabaseAPI::setLastUpdate(const QHash> &to query.prepare("UPDATE colnod_token SET last_update = :last_update WHERE id = :id"); query.bindValue(":last_update", token->lastUpdate()); query.bindValue(":id", token->id()); - mDbMan->executeQuery(query); + if (!executeQuery(query)) { + qWarning(database) << "ERROR during updating last update of token:" << token->name() << ", it will be synced from Colnod to db in next sync. Last modified will be invalid"; + } } qInfo(database) << equals; @@ -102,21 +130,32 @@ void DatabaseAPI::setLastUpdate(const QList ids) query.prepare("UPDATE colnod_token SET last_update = :last_update WHERE id = :id"); query.bindValue(":last_update", QDateTime::fromMSecsSinceEpoch(getNow()).toString("yyyy-MM-dd hh:mm:ss.zzz")); query.bindValue(":id", id); - mDbMan->executeQuery(query); + if (!executeQuery(query)) { + if (!executeQuery(query)) { + qWarning(database) << "ERROR during updating last update of deleted token:" << id << ", it will be synced from Colnod to db in next sync. Last modified will be invalid"; + } + } } } qint64 DatabaseAPI::getNow() { - auto query = mDbMan->execPlainSql("SELECT EXTRACT(EPOCH FROM NOW())*1000"); + auto query = mDbMan->createQuery(); + if (!executeQuery(query, "SELECT EXTRACT(EPOCH FROM NOW())*1000")) { + qCritical(database) << "ERROR during getting acctual time from db"; + emit error(); + } query.next(); return query.value(0).toLongLong(); } void DatabaseAPI::initNewTokens() { - auto query = mDbMan->execPlainSql("SELECT * FROM colnod_token WHERE name IS NULL"); + auto query = mDbMan->createQuery(); + if (!executeQuery(query, "SELECT * FROM colnod_token WHERE name IS NULL")) { + qWarning(database) << "ERROR during getting uninitialized tokens"; + } QHash> tokensToInit; auto list = utils->tableFromQuery(query); for (const auto &token : list) { @@ -143,6 +182,10 @@ void DatabaseAPI::uploadTokens(const QHash> &tok query = utils->insertIntoTable(token.get(), "colnod_token"); qInfo(database).noquote() << Message::massageTemplate("Adding", "token", "database", token->name()); } + if (!query.isActive()) { + mValid = false; + qWarning(database) << "ERROR durning inserting/updating of token:" << token->name(); + } } } @@ -154,14 +197,15 @@ void DatabaseAPI::uploadSubjects(const QHash> if (exists(attribute->id(), "colnod_subject_attribute")) { query = utils->updateTable(attribute.get(), "colnod_subject_attribute"); - } else { query = utils->insertIntoTable(attribute.get(), "colnod_subject_attribute"); - + } + if (!query.isActive()) { + mValid = false; + qWarning(database) << "ERROR durning inserting/updating of subject attribute:" << attribute->attributeValue(); } } - // NOTE: about actions if (exists(subject->id(), "colnod_subject")) { query = utils->updateTable(subject.get(), "colnod_subject"); qInfo(database).noquote() << Message::massageTemplate("Updating", "subject", "database", subject->name()); @@ -170,6 +214,10 @@ void DatabaseAPI::uploadSubjects(const QHash> query = utils->insertIntoTable(subject.get(), "colnod_subject"); qInfo(database).noquote() << Message::massageTemplate("Adding", "subject", "database", subject->name()); } + if (!query.isActive()) { + mValid = false; + qWarning(database) << "ERROR durning inserting/updating of subject attribute:" << subject->name(); + } } } @@ -183,7 +231,9 @@ void DatabaseAPI::deleteItems(const QList &ids, const QString &tableNam query.prepare(QString("UPDATE %1 SET deleted = true, last_update = :now, last_modified = :now WHERE id = :id").arg(tableName)); query.bindValue(":id", id); query.bindValue(":now", nowString); - mDbMan->executeQuery(query); + if (!executeQuery(query)) { + qWarning(database) << "ERROR during marking token as deleted:" << id; + } } } @@ -192,7 +242,10 @@ std::shared_ptr DatabaseAPI::getToken(const QString &id) auto query = mDbMan->createQuery(); query.prepare("SELECT * FROM colnod_token WHERE id = :id"); query.bindValue(":id", id); - mDbMan->executeQuery(query); + if (!executeQuery(query)) { + qCritical(database) << "ERROR during accessing existing tokens"; + emit error(); + } auto list = utils->tableFromQuery(query); if (list.isEmpty()) return nullptr; @@ -208,12 +261,20 @@ bool DatabaseAPI::isAlreadyDeleted(const QString &id) } +bool DatabaseAPI::isValid() +{ + return mValid; +} + bool DatabaseAPI::exists(const QString &id, const QString &tableName) { auto query = mDbMan->createQuery(); query.prepare(QString("SELECT 1 FROM %1 WHERE id = :id").arg(tableName)); query.bindValue(":id", id); - query = mDbMan->executeQuery(query); + if (!executeQuery(query)) { + qCritical(database) << "ERROR during accessing existing tokens. EXIT(1)"; + emit error(); + } return query.next(); } @@ -222,7 +283,11 @@ qint16 DatabaseAPI::getNumOfTokensOfSubject(const QString &id) auto query = mDbMan->createQuery(); query.prepare("SELECT 1 FROM colnod_token WHERE subject_id = :id AND deleted = false"); query.bindValue(":id", id); - return static_cast(mDbMan->executeQuery(query).size()); + if (!executeQuery(query)) { + qCritical(database) << "ERROR during accessing existing tokens. EXIT(1)"; + emit error(); + } + return static_cast(query.size()); } QString DatabaseAPI::getSubjectNameByTokenId(const QString &tokenId) @@ -230,7 +295,11 @@ QString DatabaseAPI::getSubjectNameByTokenId(const QString &tokenId) auto query = mDbMan->createQuery(); query.prepare("SELECT name FROM colnod_subject WHERE id = (SELECT subject_id FROM colnod_token WHERE id = :tokenId)"); query.bindValue(":tokenId", tokenId); - if (mDbMan->executeQuery(query).next()) + if (!executeQuery(query)) { + qCritical(database) << "ERROR during accessing existing subject. EXIT(1)"; + emit error(); + } + if (query.next()) return query.value(0).toString(); qWarning() << "Token:" << tokenId << "is not assigned to any subject"; return "(No subject)"; diff --git a/src/colnod/databaseapi.h b/src/colnod/databaseapi.h index e72c0ee..2990cec 100644 --- a/src/colnod/databaseapi.h +++ b/src/colnod/databaseapi.h @@ -19,6 +19,8 @@ public: bool open(); + bool executeQuery(QSqlQuery &query, const QString &statement = QString()); + void downloadData(); void processData(const std::shared_ptr &data); qint64 getLastSync(); @@ -38,6 +40,8 @@ public: bool isAlreadyDeleted(const QString &id); + bool isValid(); + private: bool exists(const QString &id, const QString &tableName); @@ -52,6 +56,7 @@ signals: private: bool mDryMode; + bool mValid = true; serversdk::DatabaseManager *mDbMan = nullptr; std::unique_ptr utils; }; diff --git a/src/colnod/syncmanager.cpp b/src/colnod/syncmanager.cpp index ed47cad..4356785 100644 --- a/src/colnod/syncmanager.cpp +++ b/src/colnod/syncmanager.cpp @@ -13,6 +13,12 @@ SyncManager::SyncManager(bool dryMode) bool SyncManager::init() { database = std::make_shared(&dbMan, mDryMode); + connect(database.get(), &DatabaseAPI::error, [=](){ + QCoreApplication::exit(1); + }); + connect(colnod.get(), &ColnodAPI::error, [=](){ + QCoreApplication::exit(1); + }); if (database->open()){ mlastSync.set_timestamp(database->getLastSync()); @@ -23,7 +29,10 @@ bool SyncManager::init() if (mlastSync.timestamp() >= 0){ return true; } + qCritical(syncmanager) << "Couldn't get time of last synchronization"; } + else + qCritical(syncmanager) << "Opening database wasn't successful"; return false; } @@ -48,7 +57,12 @@ void SyncManager::run() updateLastUpdate(syncBegin); connect(this, &SyncManager::syncFinished, [=](){ - database->setLastSync(syncBegin); + if (database->isValid() && colnod.isValid()) { + database->setLastSync(syncBegin); + } + else { + qWarning(syncmanager) << "Synchronization was unsuccessful, next run of sync will be with same last sync time, check warnings"; + } qInfo(syncmanager).noquote() << "Update last synchronization time to time of this sync (" << QDateTime::fromMSecsSinceEpoch(syncBegin).toString("yyyy-MM-dd hh:mm:ss.zzz")