#include "databaseapi.h" #include "logger.h" DatabaseAPI::DatabaseAPI(serversdk::DatabaseManager *dbMan) :mDbMan(dbMan), utils(std::make_unique(dbMan)) { } bool DatabaseAPI::open() { return mDbMan->openPostgres(QStringLiteral("192.168.1.94"), QStringLiteral("deloitte"), QStringLiteral("postgres"), QStringLiteral("34rjkciea12"), QStringLiteral("postgres-connection")); } void DatabaseAPI::downloadData() { auto updatedQuery = mDbMan->execPlainSql("SELECT id, auth_errors, description, enabled, last_update, name, no_validity, time_to_live, token_bits, token_data, token_type, subject_id, last_modified, deleted " "FROM colnod_token WHERE EXTRACT(EPOCH FROM last_modified) * 1000 > EXTRACT(EPOCH FROM last_update) * 1000 AND deleted = false"); auto deletedQuery = mDbMan->execPlainSql("SELECT id " "FROM colnod_token WHERE EXTRACT(EPOCH FROM last_modified) * 1000 > EXTRACT(EPOCH FROM last_update) * 1000 AND deleted = true"); emit downloadDataFinished(composeData(updatedQuery, deletedQuery)); } void DatabaseAPI::processData(std::shared_ptr data) { uploadTokens(data->updatedTokens); uploadSubjects(data->updatedSubjects); deleteItems(data->deletedTokens, "colnod_token"); deleteItems(data->deletedSubjects, "colnod_subject"); } std::shared_ptr DatabaseAPI::composeData(QSqlQuery updatedQuery, QSqlQuery deletedQuery) { auto data = std::make_shared(); while (updatedQuery.next()) { auto token = std::make_shared(); token->fromSQLRecord(updatedQuery); data->updatedTokens.insert(token->id(), token); } while (deletedQuery.next()) { data->deletedTokens.append(deletedQuery.value(0).toString()); } return data; } qint64 DatabaseAPI::getLastSync() { auto query = mDbMan->execPlainSql("SELECT last_sync FROM config"); if (query.next()){ return query.value(0).toLongLong(); } else { return -1; } } void DatabaseAPI::setLastSync(qint64 timestamp) { auto query = mDbMan->createQuery(); query.prepare("UPDATE config SET last_sync = :last_sync"); query.bindValue(":last_sync", timestamp); mDbMan->executeQuery(query); } void DatabaseAPI::setLastUpdate(QHash> tokens) { auto query = mDbMan->createQuery(); for (const auto &token : tokens){ 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); } } qint64 DatabaseAPI::getNow() { auto query = mDbMan->execPlainSql("SELECT EXTRACT(EPOCH FROM NOW())*1000"); query.next(); return query.value(0).toLongLong(); } void DatabaseAPI::initNewTokens() { auto query = mDbMan->execPlainSql("SELECT id, auth_errors, description, enabled, last_update, name, no_validity, time_to_live, token_bits, token_data, token_type, subject_id, last_modified, deleted " "FROM colnod_token WHERE name IS NULL"); QHash> tokensToInit; while (query.next()){ auto token = std::make_shared(); token->fromSQLRecord(query); qint16 num = getNumOfTokensOfSubject(token->subjectId()); token->setName(getSubjectNameByTokenId(token->id()) + "_mobile_" + QString::number(num + 1)); token->setDescription("mobile"); tokensToInit.insert(token->id(), token); } uploadTokens(tokensToInit); } void DatabaseAPI::uploadTokens(QHash> tokens) { // TODO: auto query = mDbMan->createQuery(); for (const auto &token : tokens) { if (exists(token->id(), "colnod_token")) { query = utils->updateTable(token.get(), "colnod_token"); } else { query = utils->insertIntoTable(token.get(), "colnod_token"); } query = mDbMan->executeQuery(query); } } void DatabaseAPI::uploadSubjects(QHash> subjects) { // TODO: auto query = mDbMan->createQuery(); for (const auto &subject : subjects) { if (exists(subject->id(), "colnod_subject")) { query = utils->updateTable(subject.get(), "colnod_subject"); } else { query = utils->insertIntoTable(subject.get(), "colnod_subject"); } query = mDbMan->executeQuery(query); } } void DatabaseAPI::deleteItems(QList ids, const QString &tableName) { // TODO: auto query = mDbMan->createQuery(); QString nowString = QDateTime::fromMSecsSinceEpoch(getLastSync()).toString("yyyy-MM-dd hh:mm:ss.zzz"); for (const auto &id : ids) { 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); } } //TODO: return whole token QDateTime DatabaseAPI::getLastUpdate(const QString &id) { auto query = mDbMan->createQuery(); query.prepare("SELECT last_update FROM colnod_token WHERE id = :id"); query.bindValue(":id", id); mDbMan->executeQuery(query); if (query.next()) { return query.value(0).toDateTime(); } else { return QDateTime(); } } 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); return query.next(); } 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()); } 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()) return query.value(0).toString(); qWarning() << "Token:" << tokenId << "is not assigned to any subject"; return "(No subject)"; } // OLD //DatabaseAPI::DatabaseAPI(const QString& host, const QString& dbName, const QString& user, const QString& password, const bool &dryMode) // :dryMode(dryMode) //{ // db = QSqlDatabase::addDatabase("QPSQL"); // db.setDatabaseName(dbName); // db.setHostName(host); // db.setUserName(user); // home-office stuff -->> db.setPort(80); // db.setPassword(password); // if (!db.open()) // { // opened = false; // Logger::log("Opening error" + db.lastError().text()); // emit error(); // } // else{ // opened = true; // } //} //// add or update subject to db //int DatabaseAPI::saveSubject(const std::shared_ptr& subject, const QString& table) //{ // QSqlQuery query; // QString id = subject->idToStringWithoutBraces(); // 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; //} //QSqlQuery DatabaseAPI::getUpdatedTokens() //{ // QSqlQuery query; // executeQuery(query, "SELECT id, auth_errors, description, enabled, last_update, name, no_validity, time_to_live, token_bits, token_data, token_type, subject_id, last_modified, deleted " // "FROM colnod_token WHERE EXTRACT(EPOCH FROM last_modified) * 1000 > EXTRACT(EPOCH FROM last_update) * 1000 AND deleted = false"); // return query; //} //// add or update token to DB //int DatabaseAPI::saveToken(const std::shared_ptr& token, const QString& table) //{ // QSqlQuery query; // QString id = token->idToStringWithoutBraces(); // int rtn; // if (checkIfExists(id, table)){ // query.prepare(QString("UPDATE %1 SET id = :id, auth_errors = :auth_errors, description = :description, enabled = :enabled, last_update = :last_update, name = :name, no_validity = :no_validity, time_to_live = :time_to_live, token_bits = :token_bits, token_data = :token_data, token_type = :token_type, subject_id = :subject_id, last_modified = :last_modified, deleted = :deleted " // "WHERE id = :id").arg(table)); // rtn = -1; // }else{ // query.prepare(QString("INSERT INTO %1 (id, auth_errors, description, enabled, last_update, name, no_validity, time_to_live, token_bits, token_data, token_type, subject_id, last_modified, deleted) " // "VALUES (:id, :auth_errors, :description, :enabled, :last_update, :name, :no_validity, :time_to_live, :token_bits, :token_data, :token_type, :subject_id, :last_modified, :deleted)").arg(table)); // rtn = 1; // } // query.bindValue(":id", id); // query.bindValue(":auth_errors", token->getAuthErrors()); // query.bindValue(":description", token->getDescription()); // query.bindValue(":enabled", token->getFlags().contains("Enabled")); // query.bindValue(":last_update", QDateTime::fromMSecsSinceEpoch(token->getLastUpdate()).toString("yyyy-MM-dd hh:mm:ss.zzz")); // query.bindValue(":name", token->getName()); // query.bindValue(":no_validity", token->getFlags().contains("NoValidity")); // query.bindValue(":time_to_live", token->getTimeToLive()); // query.bindValue(":token_bits", token->getTokenBits()); // query.bindValue(":token_data", token->getTokenData()); // query.bindValue(":token_type", token->getTokenType()); // query.bindValue(":subject_id", token->subjectIdToStringWithoutBraces()); // query.bindValue(":last_modified", QDateTime::fromMSecsSinceEpoch(token->getLastUpdate()).toString("yyyy-MM-dd hh:mm:ss.zzz")); // query.bindValue(":deleted", token->getDeleted()); // executeQuery(query); // return rtn; //} //// add of update subject attributes //void DatabaseAPI::saveSubjectAttributes(const 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)); // }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); // } //} //// "delete" tokens from DB -> set deleted true //void DatabaseAPI::setDeleted(const QString& id, const QString& table, quint64 time) //{ // QSqlQuery query; // QString nowString = QDateTime::fromMSecsSinceEpoch(time).toString("yyyy-MM-dd hh:mm:ss.zzz"); // 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); // executeQuery(query); //} //bool DatabaseAPI::checkIfExists(const QString& id, const QString& table) //{ // QSqlQuery query; // query.prepare(QString("SELECT EXISTS(SELECT 1 FROM %1 WHERE id = :id)").arg(table)); // query.bindValue(":id", id); // executeQuery(query); // query.first(); // return query.value(0).toBool(); //} //QString DatabaseAPI::getLastQuery(const QSqlQuery& query) const //{ // QString str = query.lastQuery(); // QMapIterator it(query.boundValues()); // while (it.hasNext()) // { // it.next(); // str.replace(it.key(),it.value().toString()); // } // return str; //} //bool DatabaseAPI::executeQuery(QSqlQuery &query, const QString &statement) //{ // if (statement.isEmpty()){ // if (dryMode){ // QString sqlStatement = getLastQuery(query); // qDebug() << sqlStatement; // } // if (!dryMode || getLastQuery(query).startsWith("SELECT")){ // if (!query.exec()){ // QString msg = QString("Source: Database Manager, Error: %1").arg(query.lastError().text()); // Logger::logToDb(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()); // Logger::logToDb(QString(msg)); // emit error(); // } // } // return true; //} //void DatabaseAPI::dropTables() //{ // 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 DatabaseAPI::createTables() //{ // 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)," // "last_modified timestamp," // "deleted BOOLEAN)"); // executeQuery(query, "CREATE TABLE colnod_token (" // "id CHAR(36) primary key NOT NULL," // "auth_errors INTEGER DEFAULT 255," // "description VARCHAR(255)," // "enabled BOOLEAN DEFAULT true," // "last_update timestamp DEFAULT '1970-01-01 00:00:00'::timestamp without time zone," // "name VARCHAR(255)," // "no_validity BOOLEAN DEFAULT true," // "time_to_live INTEGER DEFAULT 255," // "token_bits INTEGER DEFAULT 32," // "token_data VARCHAR(255)," // "token_type VARCHAR(255) DEFAULT 'Token'::character varying," // "subject_id CHAR(36)," // "last_modified timestamp NOT NULL," // "deleted BOOLEAN DEFAULT false)"); // executeQuery(query, "CREATE TABLE colnod_subject_attribute (" // "id VARCHAR(255) primary key," // "attribute_key VARCHAR(255)," // "attribute_value VARCHAR(255)," // "subject_id CHAR(36))"); //} //// on the very end of sync set new Last_sync time (begin of this sync) //// return set of tokens to update form DB //QSqlQuery DatabaseAPI::getToken(const QString& id) //{ // QSqlQuery query; // query.prepare("SELECT id, auth_errors, description, enabled, last_update, name, no_validity, time_to_live, token_bits, token_data, token_type, subject_id, last_modified, deleted " // "FROM colnod_token WHERE id = :id"); // query.bindValue(":id", id); // executeQuery(query); // query.next(); // return query; //} //// sync last update back to DB from Colnod after changes made to Colnod //void DatabaseAPI::log(const QString &msg) //{ // QSqlQuery query; // query.prepare("INSERT INTO logs (log_time, msg) VALUES (NOW(), :msg)"); // query.bindValue(":msg", msg); // query.exec(); //} //QString DatabaseAPI::getSubjectNameByTokenId(const QString &tokenId) //{ // QSqlQuery query; // query.prepare("SELECT name FROM colnod_subject WHERE id = (SELECT subject_id FROM colnod_token WHERE id = :tokenId)"); // query.bindValue(":tokenId", tokenId); // executeQuery(query); // if (query.next()) // return query.value(0).toString(); // qWarning() << "Token:" << tokenId << "is not assigned to any subject"; // return "(No subject)"; //} //QString DatabaseAPI::getSubjectNameById(const QString &id) //{ // QSqlQuery query; // query.prepare("SELECT name FROM colnod_subject WHERE id = :id"); // query.bindValue(":id", id); // executeQuery(query); // if (query.next()) // return query.value(0).toString(); // qWarning() << "Subject:" << id << "doesn't exists"; // return "(No subject)"; //} //bool DatabaseAPI::checkDeletedToken(const QString &id) //{ // QSqlQuery query; // query.prepare("SELECT deleted FROM colnod_token WHERE id = :id"); // query.bindValue(":id", id); // executeQuery(query); // query.next(); // return query.value(0).toBool(); //} //bool DatabaseAPI::isOpen() //{ // return opened; //}