forked from ondra/colnod-connector
322 lines
11 KiB
C++
322 lines
11 KiB
C++
#include "colnodapi.h"
|
|
|
|
#include <utility>
|
|
|
|
Q_LOGGING_CATEGORY(colnod, "colnod.api");
|
|
|
|
|
|
ColnodAPI::ColnodAPI(serversdk::RequestManager* reqMan, const bool &dryMode, QString userName, QString password)
|
|
:mReqMan(reqMan), mUserName(std::move(userName)), mPassword(std::move(password)), mDryMode(dryMode)
|
|
{
|
|
// -----------------------------------
|
|
mReqMan->setIgnoreSsl(true);
|
|
// -----------------------------------
|
|
}
|
|
|
|
/**
|
|
* @brief Downloads new data from Colnod -> emits downloadDataFinished signal
|
|
* @param time
|
|
*
|
|
* @return signal with nullptr when something went wrong
|
|
* @return signal with data when valid data returned
|
|
*/
|
|
void ColnodAPI::downloadData(const qint64 &time)
|
|
{
|
|
// Have to get Login
|
|
auto login = requestLogin();
|
|
connect(login.get(), &serversdk::Request::finished, this, [=](){
|
|
// Get login token
|
|
if (login->status() != 200) {
|
|
emit downloadDataFinished(nullptr);
|
|
return;
|
|
}
|
|
AuthToken token;
|
|
|
|
if (checkResponse(login->responseData())) {
|
|
qCWarning(colnod) << "empty response data when logging in";
|
|
emit downloadDataFinished(nullptr);
|
|
return;
|
|
}
|
|
|
|
token.fromJson(login->responseData());
|
|
authToken = token.id();
|
|
if (authToken.isEmpty()) {
|
|
qCCritical(colnod) << "Token uuid is empty";
|
|
emit downloadDataFinished(nullptr);
|
|
return;
|
|
}
|
|
|
|
auto data = std::make_shared<Data>();
|
|
|
|
auto errorHandler = [=](const std::shared_ptr<serversdk::Request>& 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;
|
|
emit downloadDataFinished(nullptr);
|
|
}
|
|
};
|
|
|
|
|
|
// if I have all data emit downloadDataFinished
|
|
connect(this, &ColnodAPI::partOfDataReady, this, &ColnodAPI::areDataReady);
|
|
|
|
Timestamp timestamp;
|
|
timestamp.setTimestamp(time);
|
|
|
|
auto tokensRequest = getTokensUpdated(timestamp);
|
|
connect(tokensRequest.get(), &serversdk::Request::finished, errorHandler);
|
|
connect(tokensRequest.get(), &serversdk::Request::finished, [=](){
|
|
saveUpdatedTokens(data, tokensRequest->responseData());
|
|
emit partOfDataReady(data);
|
|
});
|
|
|
|
auto deletedTokensRequest = getTokensDeleted(timestamp);
|
|
connect(deletedTokensRequest.get(), &serversdk::Request::finished, errorHandler);
|
|
connect(deletedTokensRequest.get(), &serversdk::Request::finished, [=](){
|
|
saveDeletedTokens(data, deletedTokensRequest->responseData());
|
|
emit partOfDataReady(data);
|
|
});
|
|
|
|
auto subjectsRequest = getSubjectsUpdated(timestamp);
|
|
connect(subjectsRequest.get(), &serversdk::Request::finished, errorHandler);
|
|
connect(subjectsRequest.get(), &serversdk::Request::finished, [=](){
|
|
saveUpdatedSubjects(data, subjectsRequest->responseData());
|
|
emit partOfDataReady(data);
|
|
});
|
|
|
|
auto deletedSubjectsRequest = getSubjectsDeleted(timestamp);
|
|
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> &data)
|
|
{
|
|
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<serversdk::Request> ColnodAPI::requestLogin()
|
|
{
|
|
Q_ASSERT(mReqMan);
|
|
LoginResp login;
|
|
login.setUsername(userName());
|
|
|
|
// password
|
|
QString encodedPassword = QCryptographicHash::hash(
|
|
password().toLocal8Bit(), // -> bytearray
|
|
QCryptographicHash::Sha512 // SHA 512
|
|
).toHex().toUpper();
|
|
login.setPassword(encodedPassword);
|
|
|
|
auto loginRequest = composeRequest("/AaaManager/authSession", login.jsonData());
|
|
loginRequest->setUserName(login.username());
|
|
loginRequest->setPassword(login.password());
|
|
mReqMan->processRequest(loginRequest);
|
|
|
|
return loginRequest;
|
|
}
|
|
|
|
std::shared_ptr<serversdk::Request> ColnodAPI::getTokensUpdated(const Timestamp &time)
|
|
{
|
|
auto request = composeRequest("/TokenManager/getTokensUpdated", time.jsonData());
|
|
request->setUserName(authToken);
|
|
mReqMan->processRequest(request);
|
|
return request;
|
|
}
|
|
|
|
std::shared_ptr<serversdk::Request> ColnodAPI::getTokensDeleted(const Timestamp &time)
|
|
{
|
|
auto request = composeRequest("/TokenManager/getTokensDeleted", time.jsonData());
|
|
request->setUserName(authToken);
|
|
mReqMan->processRequest(request);
|
|
return request;
|
|
}
|
|
|
|
std::shared_ptr<serversdk::Request> ColnodAPI::getSubjectsUpdated(const Timestamp &time)
|
|
{
|
|
auto request = composeRequest("/SubjectManager/getSubjectsUpdated", time.jsonData());
|
|
request->setUserName(authToken);
|
|
mReqMan->processRequest(request);
|
|
return request;
|
|
}
|
|
|
|
std::shared_ptr<serversdk::Request> ColnodAPI::getSubjectsDeleted(const Timestamp &time)
|
|
{
|
|
auto request = composeRequest("/SubjectManager/getSubjectsDeleted", time.jsonData());
|
|
request->setUserName(authToken);
|
|
mReqMan->processRequest(request);
|
|
return request;
|
|
}
|
|
|
|
std::shared_ptr<serversdk::Request> ColnodAPI::setTokens(const QHash<QString, std::shared_ptr<Token>> &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";
|
|
}
|
|
if (checkResponse(request->responseData())) {
|
|
|
|
for (const auto &token : tokens) {
|
|
qInfo(colnod).noquote() << Message::massageTemplate("Updating", "token", "colnod", token->name());
|
|
}
|
|
emit partOfDataProcessFinished();
|
|
}
|
|
else {
|
|
qWarning(colnod) << "Tokens wasn't updated";
|
|
mValid = false;
|
|
emit partOfDataProcessFinished(false);
|
|
}
|
|
});
|
|
return request;
|
|
}
|
|
|
|
std::shared_ptr<serversdk::Request> ColnodAPI::deleteTokens(const QList<QString> &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";
|
|
}
|
|
if (checkResponse(request->responseData())) {
|
|
for (const auto &id : ids) {
|
|
qInfo(colnod).noquote() << Message::massageTemplate("Deleting", "token", "colnod", id);
|
|
}
|
|
emit partOfDataProcessFinished();
|
|
}
|
|
else {
|
|
qWarning(colnod) << "Tokens wasn't deleted";
|
|
mValid = false;
|
|
emit partOfDataProcessFinished(false);
|
|
}
|
|
});
|
|
return request;
|
|
}
|
|
|
|
std::shared_ptr<serversdk::Request> ColnodAPI::composeRequest(const QString &endpoint, const QByteArray &data)
|
|
{
|
|
QString url = mHost + endpoint;
|
|
return std::make_shared<serversdk::Request>("POST", url, data);
|
|
}
|
|
|
|
bool ColnodAPI::checkRequest(const std::shared_ptr<serversdk::Request> &request)
|
|
{
|
|
return request->status() == 200;
|
|
}
|
|
|
|
bool ColnodAPI::isValid()
|
|
{
|
|
return mValid;
|
|
}
|
|
|
|
QString ColnodAPI::password() const
|
|
{
|
|
return mPassword;
|
|
}
|
|
|
|
void ColnodAPI::setPassword(const QString &password)
|
|
{
|
|
mPassword = password;
|
|
}
|
|
|
|
QString ColnodAPI::userName() const
|
|
{
|
|
return mUserName;
|
|
}
|
|
|
|
void ColnodAPI::setUserName(const QString &userName)
|
|
{
|
|
mUserName = userName;
|
|
}
|
|
|
|
void ColnodAPI::areDataReady(const std::shared_ptr<Data> &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(bool success)
|
|
{
|
|
if (!success) {
|
|
mSuccess = false;
|
|
}
|
|
if (++amountProccessesFinished == 2) {
|
|
emit dataProcessFinished(mSuccess);
|
|
}
|
|
}
|
|
|
|
void ColnodAPI::saveUpdatedTokens(const std::shared_ptr<Data>& data, const QByteArray &responseData)
|
|
{
|
|
data->loadTokensFromJson(responseData);
|
|
}
|
|
|
|
void ColnodAPI::saveDeletedTokens(const std::shared_ptr<Data>& 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(const std::shared_ptr<Data>& data, const QByteArray &responseData)
|
|
{
|
|
data->loadSubjectsFormJson(responseData);
|
|
}
|
|
|
|
void ColnodAPI::saveDeletedSubjects(const std::shared_ptr<Data>& data, const QByteArray &responseData)
|
|
{
|
|
QJsonDocument doc = QJsonDocument::fromJson(responseData);
|
|
QJsonArray items = doc.object()["items"].toArray();
|
|
for (QJsonValueRef item : items) {
|
|
data->deletedSubjects.append(item.toString());
|
|
}
|
|
}
|
|
|
|
bool ColnodAPI::checkResponse(const QByteArray &responseData)
|
|
{
|
|
QJsonDocument doc = QJsonDocument::fromJson(responseData);
|
|
return doc.object().contains("items");
|
|
}
|