diff --git a/src/app/main.cpp b/src/app/main.cpp index 30d341b..f891c95 100644 --- a/src/app/main.cpp +++ b/src/app/main.cpp @@ -8,6 +8,7 @@ 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"; diff --git a/src/colnod/colnodapi.cpp b/src/colnod/colnodapi.cpp index be42326..87b15c5 100644 --- a/src/colnod/colnodapi.cpp +++ b/src/colnod/colnodapi.cpp @@ -1,9 +1,10 @@ #include "colnodapi.h" -ColnodAPI::ColnodAPI() +ColnodAPI::ColnodAPI(bool debug) { reqMan = new RequestManager(); dataMan = new DataManager(); + debugMode = debug; } @@ -45,7 +46,8 @@ void ColnodAPI::loadTokensFromColnod() Response* resp = reqMan->getTokens(); connect(resp, &Response::ready, [=](){ dataMan->fillFullTokensColnod(resp->getJson()); - + areChangedDataReady(); + resp->deleteLater(); }); } @@ -89,7 +91,7 @@ void ColnodAPI::loadDeletedDataFromColnod() void ColnodAPI::loadDataFromDB() { dataMan->fillTokensDB(); - dataMan->fillTokensToDeleteDB(); + } //void ColnodAPI::syncDataFromColnod() @@ -102,10 +104,12 @@ void ColnodAPI::loadDataFromDB() void ColnodAPI::syncDataFromColnod() { + dataMan->filterTokensColnod(); syncUpdatedDataFromColnod(); - syncDeletedDataFromColnod(); + if (dataMan->getLastSync() != 0) + syncDeletedDataFromColnod(); //dataMan->updateLastSync(); - dataMan->clear(); + // dataMan->clear(); } void ColnodAPI::syncUpdatedDataFromColnod() @@ -124,36 +128,71 @@ void ColnodAPI::syncDeletedDataFromColnod() void ColnodAPI::syncDataFromDB() { // TODO - dataMan->loadTokensToAdd(); - dataMan->loadTokensToDelete(); + dataMan->filterTokensDB(); processDataToColnod(); - + connect(this, &ColnodAPI::dataProcessed, dataMan, &DataManager::clear); + connect(this, &ColnodAPI::dataProcessed, dataMan, &DataManager::setLastSync); + connect(this, &ColnodAPI::dataProcessed, [=](){ + auto resp = reqMan->getTokensUpdated(dataMan->getActualSync()); + connect(resp, &Response::ready, [=](){ + dataMan->fillTokensColnod(resp->getJson()); + dataMan->setLastUpdate(); + dataMan->clear(); + emit syncFinished(); + resp->deleteLater(); + }); + }); } void ColnodAPI::processDataToColnod() { - QList* tokensToDelete = dataMan->getTokensToDelete(); - if ((*tokensToDelete)[0] != "empty") - { - Response* resp0 = reqMan->deleteTokens(tokensToDelete); - connect(resp0, &Response::ready, [=](){ - isProcessDone(); - resp0->deleteLater(); - }); + auto tokensToUpdate = dataMan->getTokensToUpdateDB(); + + if (tokensToUpdate.contains("empty")){ + qDebug() << "No tokens to be modified."; + return; } - QHash>* tokens = dataMan->getTokens(); - if (!tokens[0].contains("empty")) - { - Response* resp1 = reqMan->setTokens(tokens); - connect(resp1, &Response::ready, [=](){ - isProcessDone(); - resp1->deleteLater(); - }); - } - dataMan->clear(); - connect(this, &ColnodAPI::dataProcessed, this, &ColnodAPI::loadDataFromColnod); + auto tokensToDelete = dataMan->getTokensToDeleteDB(); + auto resp0 = reqMan->setTokens(tokensToUpdate); + auto resp1 = reqMan->deleteTokens(tokensToDelete); + connect(resp0, &Response::ready, [=](){ + updateFinished = true; + areDataProcessed(); + resp0->deleteLater(); + }); + connect(resp1, &Response::ready, [=](){ + deleteFinished = true; + areDataProcessed(); + resp1->deleteLater(); + }); } +// old version +//void ColnodAPI::processDataToColnod() +//{ +// QList* tokensToDelete = dataMan->getTokensToDelete(); +// if ((*tokensToDelete)[0] != "empty") +// { +// Response* resp0 = reqMan->deleteTokens(tokensToDelete); +// connect(resp0, &Response::ready, [=](){ +// isProcessDone(); +// resp0->deleteLater(); +// }); +// } +// QHash>* tokens = dataMan->getTokens(); +// if (!tokens[0].contains("empty")) +// { +// Response* resp1 = reqMan->setTokens(tokens); +// connect(resp1, &Response::ready, [=](){ +// isProcessDone(); +// resp1->deleteLater(); +// }); +// } +// dataMan->clear(); +// connect(this, &ColnodAPI::dataProcessed, this, &ColnodAPI::loadDataFromColnod); +//} + +// For full sync void ColnodAPI::prepareDatabase() { dataMan->emptyDatabase(); @@ -173,9 +212,9 @@ void ColnodAPI::areChangedDataReady() } -void ColnodAPI::isProcessDone() +void ColnodAPI::areDataProcessed() { - if (dataMan->haveProcessData()) + if (deleteFinished && updateFinished) { emit dataProcessed(); } diff --git a/src/colnod/colnodapi.h b/src/colnod/colnodapi.h index fea1cb1..034e8ce 100644 --- a/src/colnod/colnodapi.h +++ b/src/colnod/colnodapi.h @@ -13,19 +13,11 @@ class ColnodAPI : public QObject public: - ColnodAPI(); - /// - //void downloadData(); - //void syncDataFromColnod(); - //void syncDataToColnod(); - /// + ColnodAPI(bool debugMode = false); void syncDataFromColnod(); void syncDataFromDB(); - - - void prepareDatabase(); public slots: @@ -36,6 +28,7 @@ public slots: signals: void dataDownloaded(); void dataProcessed(); + void syncFinished(); private slots: @@ -52,17 +45,17 @@ private: void syncDeletedDataFromColnod(); void areDataReady(); void areChangedDataReady(); - void isProcessDone(); + void areDataProcessed(); void processDataToColnod(); RequestManager* reqMan = nullptr; - // Data* data = nullptr; DataManager* dataMan = nullptr; - bool dataReady[2] = {false}; - int index = 0; - const int numOfMembers = 2; + bool debugMode = false; + bool updateFinished = false; + bool deleteFinished = false; + }; #endif // COLNODAPI_H diff --git a/src/colnod/databasemanager.cpp b/src/colnod/databasemanager.cpp index 60e2aca..4874f79 100644 --- a/src/colnod/databasemanager.cpp +++ b/src/colnod/databasemanager.cpp @@ -25,20 +25,24 @@ void DatabaseManager::saveSubject(Subject* subject, QString table) QString id = subject->idToStringWithoutBraces(); if (checkIfExists(id, table)) { - query.prepare(QString("UPDATE %1 SET name = :name, last_update = :last_update " + 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()); query.exec(); } else { - query.prepare(QString("INSERT INTO %1 (id, name, last_update) " - "VALUES (:id, :name, :last_update)").arg(table)); + 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(":name", subject->getName()); + 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()); query.exec(); } } @@ -48,22 +52,41 @@ void DatabaseManager::saveToken(Token* token, QString table) 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) " + 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) " "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(":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()); 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.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(":data", token->getTokenData()); + 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()); query.exec(); } } @@ -96,10 +119,13 @@ void DatabaseManager::saveSubjectAttribute(Subject *subject, QString table) } } -void DatabaseManager::deleteItem(QString id, QString table) +void DatabaseManager::setDeleted(QString id, QString table) { - query.prepare(QString("DELETE FROM %1 WHERE id = :id").arg(table)); + quint64 now = getNow(); + QString nowString = QDateTime::fromMSecsSinceEpoch(now).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.bindValue(":now", nowString); query.exec(); } @@ -125,7 +151,6 @@ int DatabaseManager::createTestRecord(QString msg) return id; } - bool DatabaseManager::checkIfExists(QString id, QString table) { query.prepare(QString("SELECT EXISTS(SELECT 1 FROM %1 WHERE id = :id)").arg(table)); @@ -143,36 +168,51 @@ void DatabaseManager::dropTables() void DatabaseManager::createTables() { query.exec("CREATE TABLE colnod_subject (" - "id CHAR(36) primary key," - "name VARCHAR(255)," - "last_update timestamp)"); + "id character(36) primary key NOT NULL," + //"access_pin smallint," + "description character varying(255)," + "last_update timestamp NOT NULL," + "name character varying(255)," + "pin character varying(255))"); query.exec("CREATE TABLE colnod_token (" - "id CHAR(36) primary key," + "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_update timestamp)"); + "last_modified timestamp," + "deleted BOOLEAN)"); + 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)"); } -uint64_t DatabaseManager::getAndSetLastSync() +uint64_t DatabaseManager::getLastSync() { - query.exec("SELECT EXTRACT(EPOCH FROM (SELECT last_sync FROM config))*1000"); + query.exec("SELECT last_sync FROM config"); query.next(); - uint64_t temp = query.value(0).toULongLong(); - query.exec("UPDATE config SET last_sync = NOW()"); + quint64 temp = query.value(0).toULongLong(); return temp; } +void DatabaseManager::updateLastSync(quint64 lastSync) +{ + query.prepare("UPDATE config SET last_sync = :last_sync"); + query.bindValue(":last_sync", lastSync); + query.exec(); +} + void DatabaseManager::makeTestingLast_sync() { query.prepare("INSERT INTO last_changes (last_sync) " @@ -181,15 +221,6 @@ void DatabaseManager::makeTestingLast_sync() query.exec(); } -void DatabaseManager::updateLastSync() -{ - 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* DatabaseManager::getTokensToAdd() { QSqlQuery* qry = new QSqlQuery; @@ -212,3 +243,42 @@ QUuid DatabaseManager::getId(QString name) query.next(); return query.value(0).toUuid(); } + +QSqlQuery* DatabaseManager::getUpdatedTokens() +{ + QSqlQuery* qry = new QSqlQuery; + qry->exec("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 qry; +} + +QSqlQuery* DatabaseManager::getToken(QString id) +{ + QSqlQuery* qry = new QSqlQuery; + qry->prepare("SELECT 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); + qry->exec(); + if (qry->next()){ + return qry; + } + else { + return nullptr; + } +} + +quint64 DatabaseManager::getNow() +{ + query.exec("SELECT EXTRACT(EPOCH FROM NOW())*1000"); + query.next(); + return query.value(0).toULongLong(); +} + +void DatabaseManager::setLastUpdate(QString id, quint64 lastUpdate) +{ + query.prepare("UPDATE colnod_token SET last_update = :lastUpdate WHERE id = :id"); + query.bindValue(":id", id); + query.bindValue(":lastUpdate", lastUpdate); + query.exec(); +} + diff --git a/src/colnod/databasemanager.h b/src/colnod/databasemanager.h index 9b597f0..cadc248 100644 --- a/src/colnod/databasemanager.h +++ b/src/colnod/databasemanager.h @@ -23,7 +23,8 @@ public: void saveSubject(Subject* subject, QString table); void saveToken(Token* token, QString table); void saveSubjectAttribute(Subject* subject, QString table); - void deleteItem(QString id, QString table); + void setDeleted(QString id, QString table); + QString getTestMessage(int id); int createTestRecord(QString msg); @@ -35,12 +36,19 @@ public: void createTables(); bool getOpened() {return opened;} - uint64_t getAndSetLastSync(); - void updateLastSync(); + quint64 getLastSync(); + void updateLastSync(quint64 lastSync); + quint64 getNow(); + QSqlQuery* getUpdatedTokens(); + QSqlQuery* getToken(QString id); + + // Old version QSqlQuery* getTokensToAdd(); QSqlQuery* getTokensToDelete(); + void setLastUpdate(QString id, quint64 lastUpdate); + QUuid getId(QString name); diff --git a/src/colnod/datamanager.cpp b/src/colnod/datamanager.cpp index 095efaa..7606ddb 100644 --- a/src/colnod/datamanager.cpp +++ b/src/colnod/datamanager.cpp @@ -3,7 +3,9 @@ DataManager::DataManager() { db = new DatabaseManager("192.168.1.94", "deloitte", "postgres", "34rjkciea12"); - lastSync = db->getAndSetLastSync(); + nextLastSync = db->getNow(); + lastSync = db->getLastSync(); + qDebug() << lastSync; //db = new DatabaseManager("localhost", "deloitte", "postgres", "34rjkciea12"); } @@ -37,13 +39,14 @@ void DataManager::fillTokensColnod(QString response) { auto token = new Token(); token->fromJSON(item.toObject()); - tokensColnod.insert(token->idToStringWithoutBraces(), token); + token->setDeleted(false); + tokensToUpdateColnod.insert(token->idToStringWithoutBraces(), token); } } else { auto token = new Token("empty"); - tokensColnod.insert(token->idToStringWithoutBraces(), token); + tokensToUpdateColnod.insert(token->idToStringWithoutBraces(), token); } } @@ -67,10 +70,18 @@ void DataManager::fillSubjectsColnod(QString response) } } +// fills tokensDB and tokensToDeleteDB void DataManager::fillTokensDB() { - QSqlQuery* query = db->getUpdatedTokens(lastSync); - // TODO + QSqlQuery* query = db->getUpdatedTokens(); + while (query->next()) + { + auto token = new Token; + token->fromSQLRecord(query); + tokensToUpdateDB.insert(token->idToStringWithoutBraces(), token); + } + qDebug() << "Number of tokens to update from DB: "<< tokensToUpdateDB.size(); + qDebug() << "Number of tokens to delete from DB: "<< tokensToDeleteDB.size(); } void DataManager::fillSubjectsDB() @@ -84,14 +95,11 @@ void DataManager::fillSubjectsToDeleteColnod(QString json) QJsonArray items = doc.object()["items"].toArray(); if (items.size() > 0) { - for (QJsonValueRef item : items) - { + for (QJsonValueRef item : items) { subjectsToDeleteColnod.append(item.toString()); } - } - else - { + else { subjectsToDeleteColnod.append("empty"); } } @@ -102,13 +110,11 @@ void DataManager::fillTokensToDeleteColnod(QString json) QJsonArray items = doc.object()["items"].toArray(); if (items.size() > 0) { - for (QJsonValueRef item : items) - { + for (QJsonValueRef item : items) { tokensToDeleteColnod.append(item.toString()); } } - else - { + else { tokensToDeleteColnod.append("empty"); } } @@ -118,16 +124,9 @@ void DataManager::fillSubjectsToDeleteDB() // Not needed yet } -void DataManager::fillTokensToDeleteDB() -{ - // TODO - // get data from db, maybe it's better to get all tokens together then filter deleted -} - void DataManager::pushSubjectsToDB() { - if (subjectsColnod.contains("empty")) - { + if (subjectsColnod.contains("empty")) { qDebug() << "All subjects are up to date"; return; } @@ -145,19 +144,19 @@ void DataManager::pushSubjectsToDB() void DataManager::pushTokensToDB() { - if (tokensColnod.contains("empty")) + if (tokensToUpdateColnod.contains("empty")) { qDebug() << "All tokens are up to date"; return; } //QSqlDatabase::database().transaction(); qDebug() << "Tokens in progress..."; - for (auto token : tokensColnod) + for (auto token : tokensToUpdateColnod) { db->saveToken(token, "colnod_token"); } //QSqlDatabase::database().commit(); - qDebug() << tokensColnod.size() << " tokens has been updated"; + qDebug() << tokensToUpdateColnod.size() << " tokens has been updated"; } void DataManager::deleteSubjectsFromDB() @@ -168,12 +167,10 @@ void DataManager::deleteSubjectsFromDB() return; } qDebug() << "Deleted subjects in progress..."; - //QSqlDatabase::database().transaction(); for (auto subjectId : subjectsToDeleteColnod) { - db->deleteItem(subjectId, "colnod_subject"); + db->setDeleted(subjectId, "colnod_subject"); } - //QSqlDatabase::database().commit(); qDebug() << subjectsToDeleteColnod.size() << "subject has beed deleted"; } @@ -184,33 +181,35 @@ void DataManager::deleteTokensFromDB() qDebug() << "No tokens to be deleted"; return; } - // QSqlDatabase::database().transaction(); qDebug() << "Deleted tokens in progress..."; for (auto tokenId : tokensToDeleteColnod) { - db->deleteItem(tokenId, "colnod_token"); + db->setDeleted(tokenId, "colnod_token"); } - //QSqlDatabase::database().commit(); qDebug() << tokensToDeleteColnod.size() << "tokens has beed deleted"; } bool DataManager::haveData() { - if ( !subjectsColnod.isEmpty() && !tokensColnod.isEmpty() ) + if ( !subjectsColnod.isEmpty() && !tokensToUpdateColnod.isEmpty() ) return true; return false; } bool DataManager::haveChangedData() { - if ( !subjectsColnod.isEmpty() && !tokensColnod.isEmpty() && !subjectsToDeleteColnod.isEmpty() && !tokensToDeleteColnod.isEmpty() ) + if ( !subjectsColnod.isEmpty() && + !tokensToUpdateColnod.isEmpty() && + !subjectsToDeleteColnod.isEmpty() && + !tokensToDeleteColnod.isEmpty() && + !fullTokensColnod.isEmpty() ) return true; return false; } bool DataManager::haveProcessData() { - if ( !tokensColnod.isEmpty() && !tokensToDeleteColnod.isEmpty()) + if ( !tokensToUpdateColnod.isEmpty() && !tokensToDeleteColnod.isEmpty()) return true; return false; } @@ -225,19 +224,48 @@ void DataManager::clear() { subjectsColnod.clear(); subjectsToDeleteColnod.clear(); - tokensColnod.clear(); + tokensToUpdateColnod.clear(); tokensToDeleteColnod.clear(); subjectsDB.clear(); subjectsToDeleteDB.clear(); - tokensDB.clear(); + tokensToUpdateDB.clear(); tokensToDeleteDB.clear(); + fullTokensColnod.clear(); } void DataManager::updateLastSync() { - db->updateLastSync(); + db->updateLastSync(nextLastSync); } +void DataManager::filterTokensDB() +{ + for (auto token : tokensToUpdateDB) + { + QString id = token->idToStringWithoutBraces(); + Q_ASSERT(token = fullTokensColnod.value(id)); + if (fullTokensColnod.contains(id) && token < fullTokensColnod.value(id)) + tokensToUpdateDB.remove(id); + } +} + +void DataManager::filterTokensColnod() +{ + for (auto token : tokensToUpdateColnod) + { + QString id = token->idToStringWithoutBraces(); + auto record = db->getToken(id); + if (!record) + continue; + auto tokenDB = new Token; + tokenDB->fromSQLRecord(record); + Q_ASSERT(tokenDB != token); + if (tokenDB > token) + tokensToUpdateColnod.remove(id); + } +} + +// old version void DataManager::loadTokensToAdd() { QSqlQuery* query = db->getTokensToAdd(); @@ -245,10 +273,10 @@ void DataManager::loadTokensToAdd() { Token* token = new Token(query->value(0).toString(), query->value(1).toString()); token->setSubjectId(db->getId(token->getName())); - tokensDB.insert(token->idToStringWithoutBraces(), token); + tokensToUpdateDB.insert(token->idToStringWithoutBraces(), token); } - if (tokensDB.isEmpty()) - tokensDB.insert("empty", nullptr); + if (tokensToUpdateDB.isEmpty()) + tokensToUpdateDB.insert("empty", nullptr); } void DataManager::loadTokensToDelete() @@ -263,4 +291,12 @@ void DataManager::loadTokensToDelete() } +void DataManager::setLastUpdate() +{ + for (auto token : tokensToUpdateColnod){ + db->setLastUpdate(token->idToStringWithoutBraces(), token->getLastUpdate()); + } +} + + diff --git a/src/colnod/datamanager.h b/src/colnod/datamanager.h index 3d96681..7a14373 100644 --- a/src/colnod/datamanager.h +++ b/src/colnod/datamanager.h @@ -28,7 +28,9 @@ public: void fillTokensDB(); void fillSubjectsDB(); void fillSubjectsToDeleteDB(); - void fillTokensToDeleteDB(); + + void filterTokensDB(); + void filterTokensColnod(); void pushSubjectsToDB(); void pushTokensToDB(); @@ -42,26 +44,34 @@ public: bool haveProcessData(); void emptyDatabase(); - void clear(); void loadTokensToAdd(); void loadTokensToDelete(); - QHash>* getTokens() {return &tokensColnod;} - QList* getTokensToDelete() {return &tokensToDeleteColnod;} + QHash> getTokensToUpdateColnod() {return tokensToUpdateColnod;} + QList getTokensToDeleteColnod() {return tokensToDeleteColnod;} + QHash> getTokensToUpdateDB() {return tokensToUpdateDB;} + QList getTokensToDeleteDB() {return tokensToDeleteDB;} - const uint64_t &getLastSync() {return lastSync;} + const quint64 &getLastSync() {return lastSync;} + const quint64 &getActualSync() {return nextLastSync;} + +public slots: + void clear(); + void setLastSync() {db->updateLastSync(nextLastSync);} + void setLastUpdate(); private: DatabaseManager *db = nullptr; - uint64_t lastSync; + quint64 lastSync; + quint64 nextLastSync; QHash> subjectsColnod; - QHash> tokensColnod; + QHash> tokensToUpdateColnod; QHash> fullTokensColnod; QHash> subjectsDB; // in future - QHash> tokensDB; + QHash> tokensToUpdateDB; QList subjectsToDeleteColnod; diff --git a/src/colnod/entity.cpp b/src/colnod/entity.cpp index da6f98f..932e3ca 100644 --- a/src/colnod/entity.cpp +++ b/src/colnod/entity.cpp @@ -25,11 +25,11 @@ 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; } @@ -48,7 +48,7 @@ void Entity::fromJSON(const QJsonObject &json) { QJsonObject Entity::toJSON() const { QJsonObject json; - json.value("id") = id.toString(); + json.value("id") = id.toString().mid(1,36); json.value("name") = name; json.value("description") = description; json.value("lastUpdate") = lastUpdate; diff --git a/src/colnod/entity.h b/src/colnod/entity.h index d1b2aa6..de44ca0 100644 --- a/src/colnod/entity.h +++ b/src/colnod/entity.h @@ -20,8 +20,8 @@ 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(); diff --git a/src/colnod/requestmanager.cpp b/src/colnod/requestmanager.cpp index 0e57543..45733bf 100644 --- a/src/colnod/requestmanager.cpp +++ b/src/colnod/requestmanager.cpp @@ -18,6 +18,7 @@ RequestManager::RequestManager() Response* RequestManager::login() { + Q_ASSERT(!loginResponse); loginResponse = new Response; QNetworkRequest request; QString hash = encryptedPassword(this->password); @@ -157,28 +158,13 @@ QByteArray RequestManager::makeTimeStampJson(uint64_t time) return doc.toJson(); } -QByteArray RequestManager::makeTokensJson(QHash > *tokens) +QByteArray RequestManager::makeTokensJson(const QHash > &tokens) { QJsonObject items; QJsonArray jsonTokens; - for (auto token : *tokens) + for (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; @@ -186,10 +172,10 @@ QByteArray RequestManager::makeTokensJson(QHash > *toke return doc.toJson(); } -QByteArray RequestManager::makeIdsJson(QList* ids) +QByteArray RequestManager::makeIdsJson(const QList &ids) { QJsonArray jsonIds; - for (auto id : *ids) + for (auto id : ids) { jsonIds.push_back(id); } @@ -265,12 +251,12 @@ Response* RequestManager::getAccessGroupMembershipDeleted(uint64_t time) return postRequestReturnLogic("/AccessManager/getAccessGroupMembershipDeleted", makeTimeStampJson(time)); } -Response* RequestManager::setTokens(QHash > *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 f13fde4..e169b58 100644 --- a/src/colnod/requestmanager.h +++ b/src/colnod/requestmanager.h @@ -49,8 +49,8 @@ public: Response* getAccessGroupMembershipUpdated(uint64_t time); Response* getAccessGroupMembershipDeleted(uint64_t time); - Response* setTokens(QHash>* tokens); - Response* deleteTokens(QList* ids); + Response* setTokens(const QHash> &tokens); + Response* deleteTokens(const QList &ids); Response* login(); //I want it private, but unittest??? @@ -65,8 +65,8 @@ private: QString getLoginHeader(QString username, QString hash); QByteArray makeTimeStampJson(uint64_t time); - QByteArray makeTokensJson(QHash>* tokens); - QByteArray makeIdsJson(QList* ids); + QByteArray makeTokensJson(const QHash> &tokens); + QByteArray makeIdsJson(const QList &ids); Response* getLoginResponse(); private slots: diff --git a/src/colnod/token.cpp b/src/colnod/token.cpp index 941f1fc..2b48e1e 100644 --- a/src/colnod/token.cpp +++ b/src/colnod/token.cpp @@ -21,6 +21,7 @@ Token::Token(QString namee) this->name = namee; } + void Token::fromJSON(const QJsonObject &json) { Entity::fromJSON(json); @@ -49,11 +50,33 @@ QJsonObject Token::toJSON() const { json.value("timeToLive") = timeToLive; json.value("authErrors") = authErrors; json.value("flags") = QJsonArray::fromStringList(flags.toList()); - json.value("subjectId") = subjectId.toString(); + json.value("subjectId") = subjectId.toString().mid(1,36); return json; } +void Token::fromSQLRecord(QSqlQuery *query) +{ + id = query->value(0).toUuid(); + authErrors = query->value(1).toInt(); + description = 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; + lastUpdate = query->value(4).toUInt(); + name = 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(); + lastModified = query->value(12).toUInt(); + deleted = query->value(13).toBool(); +} + const QString &Token::getTokenType() const { return tokenType; } @@ -78,19 +101,19 @@ void Token::setTokenData(const QString &tokenData) { Token::tokenData = tokenData; } -qint64 Token::getValidFrom() const { +quint64 Token::getValidFrom() const { return validFrom; } -void Token::setValidFrom(qint64 validFrom) { +void Token::setValidFrom(quint64 validFrom) { Token::validFrom = validFrom; } -qint64 Token::getValidTo() const { +quint64 Token::getValidTo() const { return validTo; } -void Token::setValidTo(qint64 validTo) { +void Token::setValidTo(quint64 validTo) { Token::validTo = validTo; } @@ -129,3 +152,21 @@ 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 1ffc80f..c06dcdc 100644 --- a/src/colnod/token.h +++ b/src/colnod/token.h @@ -4,6 +4,8 @@ #include "entity.h" #include +#include +#include class Token : public Entity { @@ -13,16 +15,24 @@ public: Token() = default; Token(QString name, QString tokenData, QString decription = "mobile"); Token(QString name); + + friend bool operator<(const Token &rToken, const Token &lToken){ + return rToken.getLastModified() < lToken.getLastUpdate(); + } + friend bool operator>(const Token &rToken, const Token &lToken){ + return rToken.getLastModified() > lToken.getLastUpdate(); + } + 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); + quint64 getValidFrom() const; + void setValidFrom(quint64 validFrom); + quint64 getValidTo() const; + void setValidTo(quint64 validTo); int getTimeToLive() const; void setTimeToLive(int timeToLive); int getAuthErrors() const; @@ -31,22 +41,28 @@ 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 fromJSON(const QJsonObject &json) override; QJsonObject toJSON() const override; protected: QString tokenType; int tokenBits; QString tokenData; - qint64 validFrom; - qint64 validTo; + quint64 validFrom; + quint64 validTo; int timeToLive; int authErrors; QSet flags; QUuid subjectId; + quint64 lastModified; + bool deleted; }; diff --git a/test/unitTests/UnitTest.cpp b/test/unitTests/UnitTest.cpp index c531e0b..d907b5e 100644 --- a/test/unitTests/UnitTest.cpp +++ b/test/unitTests/UnitTest.cpp @@ -222,7 +222,7 @@ void UnitTest::setTokens() } RequestManager* 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); QVERIFY(spy.isValid()); @@ -238,7 +238,7 @@ void UnitTest::deleteTokens() 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); QVERIFY(spy.isValid()); diff --git a/test/unitTests/complextest.cpp b/test/unitTests/complextest.cpp index c3fe6eb..cbe31d5 100644 --- a/test/unitTests/complextest.cpp +++ b/test/unitTests/complextest.cpp @@ -2,25 +2,38 @@ void ComplexTest::initTestCase() { - reqMan = new RequestManager; + 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); start = QDateTime::currentMSecsSinceEpoch()-2000; api = new ColnodAPI; qDebug() << start; } + void ComplexTest::cleanupTestCase() { QList ids; ids.append("582c982d-6fd7-4856-8548-7ce542791c7a"); - Response* deleteTokensResp = reqMan->deleteTokens(&ids); + 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); } void ComplexTest::complexTest() { // LOGIN_BEGIN + reqMan = new RequestManager; QSignalSpy loginSpy(reqMan, &RequestManager::successLogin); Response* loginResp = reqMan->login(); QSignalSpy loginRespSpy(loginResp, &Response::ready); @@ -46,7 +59,7 @@ void ComplexTest::complexTest() QHash> tokens; auto token = getTestToken(); tokens.insert(token->idToStringWithoutBraces(), token); - Response* setTokensResp = reqMan->setTokens(&tokens); + Response* setTokensResp = reqMan->setTokens(tokens); QSignalSpy setTokensRespSpy(setTokensResp, &Response::ready); QCOMPARE(setTokensRespSpy.count(), 0); setTokensRespSpy.wait(10000); @@ -70,7 +83,7 @@ void ComplexTest::complexTest() // DELETE_TOKENS_CHECK_BEGIN QList ids; ids.append("582c982d-6fd7-4856-8548-7ce542791c7a"); - Response* deleteTokensResp = reqMan->deleteTokens(&ids); + Response* deleteTokensResp = reqMan->deleteTokens(ids); QSignalSpy deleteTokensRespSpy(deleteTokensResp, &Response::ready); QCOMPARE(deleteTokensRespSpy.count(), 0); deleteTokensRespSpy.wait(10000); @@ -104,7 +117,7 @@ void ComplexTest::complexTest() void ComplexTest::fullSync() { api->prepareDatabase(); - api->downloadData(); + api->loadDataFromColnod(); QSignalSpy spy(api, &ColnodAPI::dataDownloaded); spy.wait(10000); api->syncDataFromColnod(); @@ -116,11 +129,12 @@ void ComplexTest::syncLastUpdated() api->loadDataFromColnod(); QSignalSpy spy(api, &ColnodAPI::dataDownloaded); spy.wait(10000); + api->loadDataFromDB(); api->syncDataFromColnod(); - // api->syncChangedDataToColnod(); - spy.wait(10000); - api->syncDataFromColnod(); - + api->syncDataFromDB(); + QSignalSpy processSpy(api, &ColnodAPI::dataProcessed); + processSpy.wait(10000); + qDebug() << "All right, at least should be."; }