diff --git a/src/app/main.cpp b/src/app/main.cpp index 3c951e3..3a95aa2 100644 --- a/src/app/main.cpp +++ b/src/app/main.cpp @@ -19,15 +19,16 @@ int main(int argc, char *argv[]) api.loadDataFromDB(); api.loadDataFromColnod(); QObject::connect(&api, &SyncManager::dataDownloaded, [&](){ - api.syncDataFromColnodToDB(); - api.syncDataFromDBToColnod(); QObject::connect(&api, &SyncManager::syncFinished, [](){ qDebug() << "Quit"; QCoreApplication::exit(); }); + api.syncDataFromColnodToDB(); + api.syncDataFromDBToColnod(); }); QObject::connect(&api, &SyncManager::error, [](){ - QCoreApplication::exit(1); + qDebug() << "error"; + QCoreApplication::exit(); }); return QCoreApplication::exec(); } diff --git a/src/colnod/databasemanager.cpp b/src/colnod/databasemanager.cpp index 7c5a158..94109b8 100644 --- a/src/colnod/databasemanager.cpp +++ b/src/colnod/databasemanager.cpp @@ -1,6 +1,7 @@ #include "databasemanager.h" 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); @@ -12,118 +13,93 @@ DatabaseManager::DatabaseManager(const QString& host, const QString& dbName, con log("Opening error" + db.lastError().text()); emit error(); } - query = QSqlQuery("query", db); - this->dryMode = dryMode; } // add or update subject to db int DatabaseManager::saveSubject(std::shared_ptr subject, const QString& table) { + QSqlQuery query; QString id = subject->idToStringWithoutBraces(); - if (checkIfExists(id, table)) - { - query.prepare(QString("UPDATE %1 SET id = :id, description = :description, last_update = last_update:, name = :name, pin = :pin" - "WHERE id = :id)").arg(table)); - 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()); - executeQuery(query); - return -1; - } - - - query.prepare(QString("INSERT INTO %1 (id, description, last_update, name, pin) " - "VALUES (:id, :description, :last_update, :name, :pin)").arg(table)); - query.bindValue(":id", id); - query.bindValue(":description", subject->getDescription()); - query.bindValue(":last_update", QDateTime::fromMSecsSinceEpoch(subject->getLastUpdate()).toString("yyyy-MM-dd hh:mm:ss.zzz")); - query.bindValue(":name", subject->getName()); - query.bindValue(":pin", subject->getPin()); - executeQuery(query); - return 1; - + 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; } // add or update token to DB int DatabaseManager::saveToken(std::shared_ptr token, const QString& table) { + QSqlQuery query; QString id = token->idToStringWithoutBraces(); - if (checkIfExists(id, table)) - { - query.prepare(QString("UPDATE %1 SET id = :id, auth_errors = :auth_errors, description = :description, enabled = :enabled, 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) " + 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)); - query.bindValue(":id", id); - query.bindValue(":auth_errors", token->getAuthErrors()); - query.bindValue(":description", token->getDescription()); - query.bindValue(":enabled", token->getFlags().contains("Enabled")); - 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 -1; - } - - + 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)); - 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 1; - + 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; } // add of update subject attributes void DatabaseManager::saveSubjectAttributes(std::shared_ptr subject, const QString& table) { + QSqlQuery query; auto attributes = subject->getAtr(); for (const auto& attribute : attributes){ QString id = subject->idToStringWithoutBraces() + " " + attribute.first; 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()); - executeQuery(query); - } - 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()); - executeQuery(query); } + query.bindValue(":id", id); + query.bindValue(":key", attribute.first); + query.bindValue(":value", attribute.second); + query.bindValue(":subject_id", subject->idToStringWithoutBraces()); + executeQuery(query); } } // "delete" tokens from DB -> set deleted true void DatabaseManager::setDeleted(const QString& id, const QString& table, quint64 time) { - //quint64 now = getNow(); + 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); @@ -133,6 +109,7 @@ void DatabaseManager::setDeleted(const QString& id, const QString& table, quint6 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); executeQuery(query); @@ -152,54 +129,56 @@ QString DatabaseManager::getLastQuery(const QSqlQuery& query) const return str; } -void DatabaseManager::executeNonPreperedQuery(const QString &statement, QSqlQuery &query) - +bool DatabaseManager::executeQuery(QSqlQuery &query, const QString &statement) { - if (dryMode){ - QString sqlStatement = getLastQuery(query); - qDebug() << sqlStatement; + 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 || statement.startsWith("SELECT")){ - if (!query.exec(statement)){ - QString msg = QString("Source: Database Manager, Error: %1").arg(query.lastError().text()); - log(QString(msg)); - emit error(); - } - } -} - -bool DatabaseManager::executeQuery(QSqlQuery &query) -{ - if (dryMode){ - QString sqlStatement = getLastQuery(query); - qDebug() << sqlStatement; - - } - if (!dryMode || query.isSelect()){ - 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() { - executeNonPreperedQuery("DROP TABLE IF EXISTS colnod_token, colnod_subject, colnod_subject_attribute", query); + 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() { - executeNonPreperedQuery("CREATE TABLE colnod_subject (" + QSqlQuery query; + + 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))", query); - executeNonPreperedQuery("CREATE TABLE colnod_token (" + "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)," @@ -213,18 +192,19 @@ void DatabaseManager::createTables() "token_type VARCHAR(255)," "subject_id CHAR(36)," "last_modified timestamp," - "deleted BOOLEAN)", query); - executeNonPreperedQuery("CREATE TABLE colnod_subject_attribute (" + "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))", query); + "subject_id CHAR(36))"); } // return last_sync time quint64 DatabaseManager::getLastSync() { - executeNonPreperedQuery("SELECT last_sync FROM config", query); + QSqlQuery query; + executeQuery(query, "SELECT last_sync FROM config"); query.next(); quint64 temp = query.value(0).toULongLong(); return temp; @@ -233,6 +213,7 @@ quint64 DatabaseManager::getLastSync() // 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); @@ -240,30 +221,29 @@ void DatabaseManager::updateLastSync(quint64 lastSync) // return set of tokens to update form DB -QSqlQuery* DatabaseManager::getUpdatedTokens() +QSqlQuery DatabaseManager::getUpdatedTokens() { - QSqlQuery* qry = new QSqlQuery; - executeNonPreperedQuery("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", *qry); - return qry; + 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 DatabaseManager::getToken(const QString& id) { - QSqlQuery* qry = new QSqlQuery; - qry->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 " + 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"); - qry->bindValue(":id", id); - executeQuery(*qry); - if (qry->next()){ - return qry; - } - return nullptr; + query.bindValue(":id", id); + executeQuery(query); + query.next(); + return query; } quint64 DatabaseManager::getNow() { - executeNonPreperedQuery("SELECT EXTRACT(EPOCH FROM NOW())*1000", query); + QSqlQuery query; + executeQuery(query, "SELECT EXTRACT(EPOCH FROM NOW())*1000"); query.next(); return query.value(0).toULongLong(); } @@ -271,14 +251,17 @@ quint64 DatabaseManager::getNow() // sync last update back to DB from Colnod after changes made to Colnod void DatabaseManager::setLastUpdate(const QString& id, quint64 lastUpdate) { - query.prepare("UPDATE colnod_token SET last_update = :lastUpdate WHERE id = :id"); + 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(":lastUpdate", lastUpdate); + 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(); @@ -286,6 +269,7 @@ void DatabaseManager::log(const QString &msg) QString DatabaseManager::getSubjectNameByTokenId(const QString &tokenId) { + 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); @@ -297,6 +281,7 @@ QString DatabaseManager::getSubjectNameByTokenId(const QString &tokenId) QString DatabaseManager::getSubjectNameById(const QString &id) { + QSqlQuery query; query.prepare("SELECT name FROM colnod_subject WHERE id = :id"); query.bindValue(":id", id); executeQuery(query); @@ -308,6 +293,7 @@ QString DatabaseManager::getSubjectNameById(const QString &id) bool DatabaseManager::checkDeletedToken(const QString &id) { + QSqlQuery query; query.prepare("SELECT deleted FROM colnod_token WHERE id = :id"); query.bindValue(":id", id); executeQuery(query); diff --git a/src/colnod/databasemanager.h b/src/colnod/databasemanager.h index 6a56cb2..3d3fef6 100644 --- a/src/colnod/databasemanager.h +++ b/src/colnod/databasemanager.h @@ -31,8 +31,8 @@ public: void updateLastSync(quint64 lastSync); quint64 getNow(); - QSqlQuery* getUpdatedTokens(); - QSqlQuery* getToken(const QString& id); + QSqlQuery getUpdatedTokens(); + QSqlQuery getToken(const QString& id); void setLastUpdate(const QString& id, quint64 lastUpdate); @@ -44,15 +44,13 @@ public: private: bool checkIfExists(const QString& id, const QString& table); - bool executeQuery(QSqlQuery &query); + bool executeQuery(QSqlQuery &query, const QString &statement = QString()); QString getLastQuery(const QSqlQuery &query) const; - void executeNonPreperedQuery(const QString &statement, QSqlQuery& query); signals: void error(); private: QSqlDatabase db; - QSqlQuery query; bool dryMode = false; }; diff --git a/src/colnod/datamanager.cpp b/src/colnod/datamanager.cpp index bf0382a..2ea2eac 100644 --- a/src/colnod/datamanager.cpp +++ b/src/colnod/datamanager.cpp @@ -1,13 +1,13 @@ #include "datamanager.h" DataManager::DataManager(const bool &dryMode) + :dryMode(dryMode) { 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(); - this->dryMode = dryMode; connect(db.get(), &DatabaseManager::error, this, &DataManager::error); } @@ -21,13 +21,12 @@ void DataManager::fillFullTokensColnod(const QString& response) for (QJsonValueRef item : items){ auto token = std::make_shared(); token->fromJSON(item.toObject()); - allTokensFromColnod.insert(token->idToStringWithoutBraces(), token); + allTokensFromColnodById.insert(token->idToStringWithoutBraces(), token); + allTokensFromColnodByName.insert(token->getName(), token); } } else{ qCritical() << "Colnod is Empty"; - auto token = std::make_shared("empty"); - allTokensFromColnod.insert(token->idToStringWithoutBraces(), token); } } @@ -50,8 +49,6 @@ void DataManager::fillTokensToUpdateColnod(const QString& response) else { qInfo() << "Colnod: 0 tokens to update"; - auto token = std::make_shared("empty"); - tokensToUpdateFromColnodToDB.insert(token->getName(), token); } } @@ -66,6 +63,7 @@ void DataManager::fillSubjectsToUpdateColnod(const QString& response) { auto subject = std::make_shared(); subject->fromJSON(item.toObject()); + subject->setDeleted(false); subjectsToUpdateFromColnodToDB.insert(subject->idToStringWithoutBraces(), subject); } qInfo() << "Colnod:" << subjectsToUpdateFromColnodToDB.size() << "subjects to update"; @@ -73,16 +71,14 @@ void DataManager::fillSubjectsToUpdateColnod(const QString& response) else { qInfo() << "Colnod:" << "0 subjects to update"; - auto subject = std::make_shared("empty"); - subjectsToUpdateFromColnodToDB.insert(subject->getName(), subject); } } // load working sets with updated/deleted tokens from DB void DataManager::fillTokensToChangeDB() { - QSqlQuery* query = db->getUpdatedTokens(); - while (query->next()) + QSqlQuery query = db->getUpdatedTokens(); + while (query.next()) { auto token = std::make_shared(); token->fromSQLRecord(query); @@ -116,7 +112,6 @@ void DataManager::fillSubjectsToDeleteColnod(const QString& json) } else { qInfo() << "Colnod: 0 subjects to delete"; - subjectsFromColnodToDeleteFromDB.append("empty"); } } @@ -134,7 +129,6 @@ void DataManager::fillTokensToDeleteColnod(const QString& json) } else { qInfo() << "Colnod: 0 tokens to delete"; - tokensFromColnodToDeleteFromDB.append("empty"); } } @@ -146,7 +140,7 @@ void DataManager::fillSubjectsToDeleteDB() // update subjects from colnod to DB void DataManager::pushSubjectsToDB() { - if (subjectsToUpdateFromColnodToDB.contains("empty")) { + if (subjectsToUpdateFromColnodToDB.isEmpty()) { qInfo() << "DB: 0 subjects added"; qInfo() << "DB: 0 subjects updated"; return; @@ -157,11 +151,17 @@ void DataManager::pushSubjectsToDB() { if (db->saveSubject(subject, "colnod_subject") > 0){ added++; - Logger::logToDb(Logger::makeSubjectMsg( subject->idToStringWithoutBraces(),"added", "DB")); + if (dryMode) + qInfo() << "Adding subject:" << subject->idToStringWithoutBraces() << "to DB"; + else + Logger::logToDb(Logger::makeSubjectMsg( subject->idToStringWithoutBraces(),"added", "DB")); } else{ updated++; - Logger::logToDb(Logger::makeSubjectMsg( subject->idToStringWithoutBraces(),"updated", "DB")); + if (dryMode) + qInfo() << "Updating subject:" << subject->idToStringWithoutBraces() << "to DB"; + else + Logger::logToDb(Logger::makeSubjectMsg( subject->idToStringWithoutBraces(),"updated", "DB")); } db->saveSubjectAttributes(subject, "colnod_subject_attribute"); } @@ -172,7 +172,7 @@ void DataManager::pushSubjectsToDB() // update tokens from colnod to DB void DataManager::pushTokensToDB() { - if (tokensToUpdateFromColnodToDB.contains("empty")){ + if (tokensToUpdateFromColnodToDB.isEmpty()){ qInfo() << "DB: 0 tokens added"; qInfo() << "DB: 0 tokens updated"; return; @@ -182,23 +182,31 @@ void DataManager::pushTokensToDB() int added = 0; for (const auto& token : tokensToUpdateFromColnodToDB) { - if (db->saveToken(token, "colnod_token") > 0){ + + QString text; + // 1 = adding token + // -1 = updating token + if (db->saveToken(token, "colnod_token") == 1){ added++; - Logger::logToDb(Logger::makeTokenMsg(token->idToStringWithoutBraces(), "added", "DB")); - } - else{ + text = "Added"; + } + else { updated++; - Logger::logToDb(Logger::makeTokenMsg(token->idToStringWithoutBraces(), "updated", "DB")); - } + text = "Updating"; + } + if (dryMode) + qInfo() << text << "token:" << token->idToStringWithoutBraces() << "to DB"; + else + Logger::logToDb(Logger::makeTokenMsg(token->idToStringWithoutBraces(), text, "DB")); } - qInfo() << "DB:" << added << " tokens added"; - qInfo() << "DB:" << updated << " tokens updated"; + qInfo() << "DB:" << added << "tokens added/edited"; + qInfo() << "DB:" << updated << "tokens updated"; } void DataManager::deleteSubjectsFromDB() { - if (subjectsFromColnodToDeleteFromDB[0] == "empty") + if (subjectsFromColnodToDeleteFromDB.isEmpty()) { qInfo() << "DB: 0 subjects deleted"; return; @@ -206,7 +214,10 @@ void DataManager::deleteSubjectsFromDB() for (const auto& subjectId : subjectsFromColnodToDeleteFromDB) { db->setDeleted(subjectId, "colnod_subject", nextLastSync); - Logger::logToDb(Logger::makeSubjectMsg(subjectId, "deleted", "DB")); + if (dryMode) + qInfo() << "Deleting subject:" << subjectId << "from DB"; + else + Logger::logToDb(Logger::makeSubjectMsg(subjectId, "deleted", "DB")); } qInfo() << "DB:" << subjectsFromColnodToDeleteFromDB.size() << " subject deleted"; } @@ -214,7 +225,7 @@ void DataManager::deleteSubjectsFromDB() // "delete" (set deleted true) tokens in DB depends on Colnod void DataManager::setDeletedToTokensFromDB() { - if (tokensFromColnodToDeleteFromDB[0] == "empty") + if (tokensFromColnodToDeleteFromDB.isEmpty()) { qDebug() << "DB: 0 tokens deleted"; return; @@ -224,7 +235,10 @@ void DataManager::setDeletedToTokensFromDB() { if (!db->checkDeletedToken(tokenId)){ db->setDeleted(tokenId, "colnod_token", nextLastSync); - Logger::logToDb(Logger::makeTokenMsg(tokenId, "deleted", "DB")); + if (dryMode) + qInfo() << "Deleting token:" << tokenId << "from DB"; + else + Logger::logToDb(Logger::makeTokenMsg(tokenId, "deleted", "DB")); } else alreadyDeleted++; @@ -232,16 +246,6 @@ void DataManager::setDeletedToTokensFromDB() qDebug() << "DB:" << tokensFromColnodToDeleteFromDB.size() - alreadyDeleted << "tokens deleted"; } -// do I have loaded all data -bool DataManager::haveChangedData() -{ - return !subjectsToUpdateFromColnodToDB.isEmpty() && - !tokensToUpdateFromColnodToDB.isEmpty() && - !subjectsFromColnodToDeleteFromDB.isEmpty() && - !tokensFromColnodToDeleteFromDB.isEmpty() && - !allTokensFromColnod.isEmpty(); -} - // recreate working tables void DataManager::emptyDatabase() { @@ -249,6 +253,14 @@ void DataManager::emptyDatabase() 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() { @@ -260,7 +272,7 @@ void DataManager::clear() // subjectsToDeleteDB.clear(); // not need yet tokensToUpdateFromDBToColnod.clear(); tokensFromDBToDeleteFromColnod.clear(); - allTokensFromColnod.clear(); + allTokensFromColnodById.clear(); } // on the very end of sync update last sync time to begin time of this sync @@ -272,37 +284,59 @@ void DataManager::updateLastSync() // 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() { + QList idsToDelete; for (const auto& token : tokensToUpdateFromDBToColnod) { QString id = token->idToStringWithoutBraces(); - Q_ASSERT(token != allTokensFromColnod.value(id)); // if working sets are loading correctly equels should never happend - if (allTokensFromColnod.contains(id) && *token < *allTokensFromColnod.value(id)) - tokensToUpdateFromDBToColnod.remove(id); + 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)); + } + } } + for (const auto &id : idsToDelete) + tokensToUpdateFromDBToColnod.remove(id); } void DataManager::filterTokensColnod() { + QList idsToDelete; for (const auto &token : tokensToUpdateFromColnodToDB) { QString id = token->idToStringWithoutBraces(); auto record = db->getToken(id); - if (!record) + if (!record.isValid()) continue; - auto tokenDB = std::shared_ptr(); + auto tokenDB = std::make_shared(); tokenDB->fromSQLRecord(record); - Q_ASSERT(tokenDB != token); - if (*tokenDB > *token) - tokensToUpdateFromColnodToDB.remove(id); + if (*tokenDB == *token || *tokenDB > *token){ + idsToDelete.append(id); + } } + for (const auto &id : idsToDelete) + tokensToUpdateFromColnodToDB.remove(id); } // sync last update from colnod to DB void DataManager::setLastUpdate() { - for (const auto &token : tokensToUpdateFromColnodToDB){ - db->setLastUpdate(token->idToStringWithoutBraces(), token->getLastUpdate()); - } + 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 24ebbd1..0c365d2 100644 --- a/src/colnod/datamanager.h +++ b/src/colnod/datamanager.h @@ -38,13 +38,13 @@ public: void updateLastSync(); - bool haveChangedData(); - void emptyDatabase(); - QHash> getTokensToUpdateColnod() {return tokensToUpdateFromColnodToDB;} + quint64 getLastModifiedOfToken(const QString &id); + + QHash> getTokensToUpdateFromColnod() {return tokensToUpdateFromColnodToDB;} QList getTokensToDeleteColnod() {return tokensFromColnodToDeleteFromDB;} - QHash> getTokensToUpdateDB() {return tokensToUpdateFromDBToColnod;} + QHash> getTokensToUpdateFromDB() {return tokensToUpdateFromDBToColnod;} QList getTokensToDeleteDB() {return tokensFromDBToDeleteFromColnod;} const quint64 &getLastSync() {return lastSync;} @@ -52,8 +52,8 @@ public: public slots: void clear(); - void setLastSync() {db->updateLastSync(nextLastSync);} void setLastUpdate(); + void setLastUpdate(const QString &id); signals: void error(); @@ -64,9 +64,10 @@ private: quint64 lastSync; // time of last run quint64 nextLastSync; // time of begin of this run + QHash> allTokensFromColnodById; + QHash> allTokensFromColnodByName; QHash> subjectsToUpdateFromColnodToDB; QHash> tokensToUpdateFromColnodToDB; - QHash> allTokensFromColnod; QHash> subjectsDB; // in future QHash> tokensToUpdateFromDBToColnod; diff --git a/src/colnod/entity.cpp b/src/colnod/entity.cpp index fcae765..2a1db6a 100644 --- a/src/colnod/entity.cpp +++ b/src/colnod/entity.cpp @@ -33,6 +33,24 @@ void Entity::setLastUpdate(quint64 lastUpdate) { this->lastUpdate = lastUpdate; } +quint64 Entity::getLastModified() const { + return lastModified; +} + +void Entity::setLastModified(const quint64 &lastModified) { + this->lastModified = lastModified; +} + +bool Entity::getDeleted() const +{ + return deleted; +} + +void Entity::setDeleted(const bool &deleted) +{ + this->deleted = deleted; +} + QString Entity::idToStringWithoutBraces() const { const qint8 lengthOfUuid = 36; diff --git a/src/colnod/entity.h b/src/colnod/entity.h index e9d0d7d..07fb22d 100644 --- a/src/colnod/entity.h +++ b/src/colnod/entity.h @@ -24,13 +24,24 @@ public: quint64 getLastUpdate() const; void setLastUpdate(quint64 lastUpdate); + 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; + + + private: QUuid id; QString name; QString description; qint64 lastUpdate{}; + quint64 lastModified{}; + bool deleted{}; }; diff --git a/src/colnod/subject.h b/src/colnod/subject.h index cc7f4ac..83cf489 100644 --- a/src/colnod/subject.h +++ b/src/colnod/subject.h @@ -24,8 +24,6 @@ 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); @@ -37,7 +35,6 @@ private: QSet tokenFlags; QString pin; QSet pinFlags; - //QList> atr; QList> atr; const QList attributeTypes = {"Jmeno", "Prijmeni", "ProfilParking", "Spolecnost", "Profil", "spz"}; diff --git a/src/colnod/syncmanager.cpp b/src/colnod/syncmanager.cpp index a048118..b9d794b 100644 --- a/src/colnod/syncmanager.cpp +++ b/src/colnod/syncmanager.cpp @@ -98,42 +98,54 @@ void SyncManager::syncDeletedDataFromColnodToDB() void SyncManager::syncDataFromDBToColnod() { - if (!dataMan->getTokensToUpdateDB().contains("empty")){ - syncDeletedDataFromDBToColnod(); - } + 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 - deleteFinished = true; - if (!dataMan->getTokensToDeleteDB().contains("empty")){ + connect(this, &SyncManager::dataUpdatedToColnod, [=](){ + dataMan->updateLastSync(); + emit syncFinished(); + }); + if (!dataMan->getTokensToUpdateFromDB().contains("empty")){ syncUpdatedDataFromDBToColnod(); } else updateFinished = true; - connect(this, &SyncManager::dataUpdatedToColnod, dataMan.get(), &DataManager::clear); - connect(this, &SyncManager::dataUpdatedToColnod, dataMan.get(), &DataManager::setLastSync); - 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(); - }); - }); + if (!dataMan->getTokensToDeleteDB().contains("empty")){ + syncDeletedDataFromDBToColnod(); + } + else + deleteFinished = true; } // add or update tokens to Colnod void SyncManager::syncUpdatedDataFromDBToColnod() { - auto tokensToUpdate = dataMan->getTokensToUpdateDB(); + dataMan->filterTokensDB(); + auto tokensToUpdate = dataMan->getTokensToUpdateFromDB(); if (dryMode){ for (const auto &token : tokensToUpdate) - qInfo() << "Updating token: " << token->idToStringWithoutBraces() << "to Colnod"; + 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(); @@ -144,15 +156,21 @@ void SyncManager::syncUpdatedDataFromDBToColnod() // delete tokens in Colnod void SyncManager::syncDeletedDataFromDBToColnod() { - dataMan->filterTokensDB(); auto tokensToDelete = dataMan->getTokensToDeleteDB(); if (dryMode){ for (const auto &token : tokensToDelete) - qInfo() << "Deleting token: " << token << "from Colnod"; + 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(); @@ -169,7 +187,7 @@ void SyncManager::prepareDatabase() // emit signal when all data is downloaded from Colnod void SyncManager::areChangedDataReady() { - if (dataMan->haveChangedData()) + if (++dataCounter == 5) emit dataDownloaded(); } diff --git a/src/colnod/syncmanager.h b/src/colnod/syncmanager.h index c3209e7..b7fbf58 100644 --- a/src/colnod/syncmanager.h +++ b/src/colnod/syncmanager.h @@ -52,5 +52,6 @@ private: 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 6f26430..add8e9a 100644 --- a/src/colnod/token.cpp +++ b/src/colnod/token.cpp @@ -57,28 +57,28 @@ QJsonObject Token::toJSON() const { return json; } -void Token::fromSQLRecord(QSqlQuery *query) +void Token::fromSQLRecord(QSqlQuery query) { - setId(query->value(0).toUuid()); - authErrors = query->value(1).toInt(); - setDescription(query->value(2).toString()); + setId(query.value(0).toUuid()); + authErrors = query.value(1).toInt(); + setDescription(query.value(2).toString()); QSet flags; - if (query->value(6).toBool()) + if (query.value(6).toBool()) flags.insert("NoValidity"); - if (query->value(3).toBool()) + if (query.value(3).toBool()) flags.insert("Enabled"); this->flags = flags; - QDateTime date = query->value(4).toDateTime(); + 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(); - lastModified = date.toMSecsSinceEpoch(); - deleted = query->value(13).toBool(); + 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 { @@ -140,21 +140,3 @@ void Token::setSubjectId(const QUuid &subjectId) { QString Token::subjectIdToStringWithoutBraces(){ return subjectId.toString().mid(1,36); } - -quint64 Token::getLastModified() const { - return lastModified; -} - -void Token::setLastModified(const quint64 &lastModified) { - Token::lastModified = lastModified; -} - -bool Token::getDeleted() const -{ - return deleted; -} - -void Token::setDeleted(const bool &deleted) -{ - this->deleted = deleted; -} diff --git a/src/colnod/token.h b/src/colnod/token.h index 89c6f9d..1e3f2b6 100644 --- a/src/colnod/token.h +++ b/src/colnod/token.h @@ -22,6 +22,22 @@ public: friend bool operator>(const Token &lToken, const Token &rToken){ return lToken.getLastModified() > rToken.getLastUpdate(); } + friend bool operator==(const Token &lToken, const Token &rToken){ + if ( 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) + return true; + return false; + } + const QString &getTokenType() const; void setTokenType(const QString &tokenType); @@ -37,14 +53,11 @@ public: void setFlags(const QSet &flags); const QUuid &getSubjectId() const; void setSubjectId(const QUuid &subjectId); - quint64 getLastModified() const; - void setLastModified(const quint64 &lastModified); - bool getDeleted() const; - void setDeleted(const bool &deleted); + QString subjectIdToStringWithoutBraces(); - void fromSQLRecord(QSqlQuery* query); + void fromSQLRecord(QSqlQuery query); void fromJSON(const QJsonObject &json) override; QJsonObject toJSON() const override; @@ -56,6 +69,4 @@ private: int authErrors{}; QSet flags; QUuid subjectId; - quint64 lastModified{}; - bool deleted{}; };