#include "colnodapi.h" Q_LOGGING_CATEGORY(colnod, "colnod.api"); ColnodAPI::ColnodAPI(serversdk::RequestManager* reqMan, const bool &dryMode, const QString &userName, const QString &password) :mReqMan(reqMan), mUserName(userName), mPassword(password), mDryMode(dryMode) { // ----------------------------------- mReqMan->setIgnoreSsl(true); // ----------------------------------- } void ColnodAPI::downloadData(const Timestamp &time) { // Have to get Login auto login = requestLogin(); connect(login.get(), &serversdk::Request::finished, this, [=](){ // Get login token if (!checkRequest(login)) { emit downloadDataFinished(nullptr); return; } AuthToken token; token.fromJson(login->responseData()); authToken = token.id(); auto data = std::make_shared(); auto errorHandler = [=](std::shared_ptr request){ if (!checkRequest(request)) { qWarning(colnod) << "ERROR during calling" << request->url() << ", request unsuccessful"; mValid = false; emit downloadDataFinished(nullptr); } else if (!checkResponse(request->responseData())) { qWarning(colnod) << "Data from" << request->url() << "are invalid"; mValid = false; } }; // if I have all data emit downloadDataFinished connect(this, &ColnodAPI::partOfDataReady, this, &ColnodAPI::areDataReady); auto tokensRequest = getTokensUpdated(time); connect(tokensRequest.get(), &serversdk::Request::finished, errorHandler); connect(tokensRequest.get(), &serversdk::Request::finished, [=](){ saveUpdatedTokens(data, tokensRequest->responseData()); emit partOfDataReady(data); }); auto deletedTokensRequest = getTokensDeleted(time); connect(deletedTokensRequest.get(), &serversdk::Request::finished, errorHandler); connect(deletedTokensRequest.get(), &serversdk::Request::finished, [=](){ saveDeletedTokens(data, deletedTokensRequest->responseData()); emit partOfDataReady(data); }); auto subjectsRequest = getSubjectsUpdated(time); connect(subjectsRequest.get(), &serversdk::Request::finished, errorHandler); connect(subjectsRequest.get(), &serversdk::Request::finished, [=](){ saveUpdatedSubjects(data, subjectsRequest->responseData()); emit partOfDataReady(data); }); auto deletedSubjectsRequest = getSubjectsDeleted(time); connect(deletedSubjectsRequest.get(), &serversdk::Request::finished, errorHandler); connect(deletedSubjectsRequest.get(), &serversdk::Request::finished, [=](){ saveDeletedSubjects(data, deletedSubjectsRequest->responseData()); emit partOfDataReady(data); }); }); } void ColnodAPI::processData(const std::shared_ptr &data) { for (const auto &token : data->updatedTokens) { qInfo(colnod).noquote() << Message::massageTemplate("Updating", "token", "colnod", token->name()); } for (const auto &id : data->deletedTokens) { qInfo(colnod).noquote() << Message::massageTemplate("Deleting", "token", "colnod", id); } if (!data->updatedTokens.isEmpty() || !data->deletedTokens.isEmpty()) { qInfo(colnod) << dash; } qInfo(colnod) << tab << "-> DATA PROCESSED TO COLNOD:"; qInfo(colnod) << tab << tab << data->updatedTokens.size() << "TOKENS UPDATED"; qInfo(colnod) << tab << tab << data->deletedTokens.size() << "TOKENS DELETED"; qInfo(colnod) << dash; connect(this, &ColnodAPI::partOfDataProcessFinished, this, &ColnodAPI::isDataProcessFinished); if ( !data->updatedTokens.isEmpty() && !mDryMode) { setTokens(data->updatedTokens); } else { emit partOfDataProcessFinished(); } if ( !data->deletedTokens.isEmpty() && !mDryMode) { deleteTokens(data->deletedTokens); } else { emit partOfDataProcessFinished(); } } std::shared_ptr ColnodAPI::requestLogin() { Q_ASSERT(mReqMan); LoginResp login; login.set_username(userName()); // password QString encodedPassword = QCryptographicHash::hash( password().toLocal8Bit(), // -> bytearray QCryptographicHash::Sha512 // SHA 512 ).toHex().toUpper(); login.set_password(encodedPassword); auto loginRequest = composeRequest("/AaaManager/authSession", login.jsonData()); loginRequest->setUserName(login.username()); loginRequest->setPassword(login.password()); mReqMan->processRequest(loginRequest); return loginRequest; } std::shared_ptr ColnodAPI::getTokensUpdated(const Timestamp &time) { auto request = composeRequest("/TokenManager/getTokensUpdated", time.jsonData()); request->setUserName(authToken); mReqMan->processRequest(request); return request; } std::shared_ptr ColnodAPI::getTokensDeleted(const Timestamp &time) { auto request = composeRequest("/TokenManager/getTokensDeleted", time.jsonData()); request->setUserName(authToken); mReqMan->processRequest(request); return request; } std::shared_ptr ColnodAPI::getSubjectsUpdated(const Timestamp &time) { auto request = composeRequest("/SubjectManager/getSubjectsUpdated", time.jsonData()); request->setUserName(authToken); mReqMan->processRequest(request); return request; } std::shared_ptr ColnodAPI::getSubjectsDeleted(const Timestamp &time) { auto request = composeRequest("/SubjectManager/getSubjectsDeleted", time.jsonData()); request->setUserName(authToken); mReqMan->processRequest(request); return request; } std::shared_ptr ColnodAPI::setTokens(const QHash> &tokens) { auto request = composeRequest("/TokenManager/setTokens", Token::tokensToColnodJson(tokens)); request->setUserName(authToken); mReqMan->processRequest(request); connect(request.get(), &serversdk::Request::finished, [=](){ if (!checkRequest(request)) { qCritical(colnod) << "ERROR during calling /TokenManager/setTokens, request unsuccessful. EXIT"; emit error(); } if (checkResponse(request->responseData())) { emit partOfDataProcessFinished(); } else { qWarning(colnod) << "Tokens wasn't updated"; mValid = false; emit partOfDataProcessFinished(); } }); return request; } std::shared_ptr ColnodAPI::deleteTokens(const QList &ids) { auto request = composeRequest("/TokenManager/deleteTokens", Token::idsToJSON(ids)); request->setUserName(authToken); mReqMan->processRequest(request); connect(request.get(), &serversdk::Request::finished, [=](){ if (!checkRequest(request)) { qCritical(colnod) << "ERROR during calling /TokenManager/deleteTokens, request unsuccessful. EXIT"; emit error(); } if (checkResponse(request->responseData())) { emit partOfDataProcessFinished(); } else { qWarning(colnod) << "Tokens wasn't deleted"; mValid = false; emit partOfDataProcessFinished(); } }); return request; } std::shared_ptr ColnodAPI::composeRequest(const QString &endpoint, const QByteArray &data) { QString url = mHost + endpoint; return std::make_shared("POST", url, data); } bool ColnodAPI::checkRequest(const std::shared_ptr &request) { if (request->status() == 200) { return true; } return false; } bool ColnodAPI::isValid() { return mValid; } QString ColnodAPI::password() const { return mPassword; } void ColnodAPI::setPassword(const QString &password) { mPassword = password; } qint64 ColnodAPI::lastSync() const { return mLastSync.timestamp(); } void ColnodAPI::setlastSync(const qint64 &lastSync) { mLastSync.set_timestamp(lastSync); } QString ColnodAPI::userName() const { return mUserName; } void ColnodAPI::setUserName(const QString &userName) { mUserName = userName; } void ColnodAPI::areDataReady(std::shared_ptr data) { if (++amountData == 4) { qInfo(colnod) << tab << "-> COLNOD DATA:"; qInfo(colnod) << tab << tab << data->updatedTokens.size() << "TOKENS WERE ADDED/UPDATED"; qInfo(colnod) << tab << tab << data->deletedTokens.size() << "TOKENS DELETED"; qInfo(colnod) << tab << tab << data->updatedSubjects.size() << "SUBJECTS WERE ADDED/UPDATED"; qInfo(colnod) << tab << tab << data->deletedSubjects.size() << "SUBJECTS DELETED"; qInfo(colnod) << dash; amountData = 0; emit downloadDataFinished(data); } } void ColnodAPI::isDataProcessFinished() { if (++amountProccessesFinished == 2) { emit dataProcessFinished(); } } void ColnodAPI::saveUpdatedTokens(std::shared_ptr data, const QByteArray &responseData) { data->loadTokensFromJson(responseData); } void ColnodAPI::saveDeletedTokens(std::shared_ptr data, const QByteArray &responseData) { QJsonDocument doc = QJsonDocument::fromJson(responseData); QJsonArray items = doc.object()["items"].toArray(); for (QJsonValueRef item : items) { data->deletedTokens.append(item.toString()); } } void ColnodAPI::saveUpdatedSubjects(std::shared_ptr data, const QByteArray &responseData) { data->loadSubjectsFormJson(responseData); } void ColnodAPI::saveDeletedSubjects(std::shared_ptr data, const QByteArray &responseData) { QJsonDocument doc = QJsonDocument::fromJson(responseData); QJsonArray items = doc.object()["items"].toArray(); for (QJsonValueRef item : items) { data->deletedSubjects.append(item.toString()); } } void ColnodAPI::newData() { mData = std::make_shared(); } bool ColnodAPI::checkResponse(const QByteArray &responseData) { QJsonDocument doc = QJsonDocument::fromJson(responseData); return doc.object().contains("items"); }