#include "servercommunicator.h" #include "apiroutes.h" #include #include #include #include #include "../formats/jsonparser.h" using namespace Qt::StringLiterals; ServerCommunicator::ServerCommunicator(QObject* parent) : QObject{parent} { m_netManager.setAutoDeleteReplies(true); m_restManager = std::make_shared(&m_netManager); m_serviceApi = std::make_shared(); } bool ServerCommunicator::sslSupported() { #if QT_CONFIG(ssl) return QSslSocket::supportsSsl(); #else return false; #endif } QUrl ServerCommunicator::url() const { return m_serviceApi->baseUrl(); } void ServerCommunicator::setUrl(const QUrl& url) { if (m_serviceApi->baseUrl() == url) { return; } m_serviceApi->setBaseUrl(url); QHttpHeaders authenticationHeaders; authenticationHeaders.append(QHttpHeaders::WellKnownHeader::ContentType, "application/json"); m_serviceApi->setCommonHeaders(authenticationHeaders); emit urlChanged(); } void ServerCommunicator::setServerConfiguration(const QString url, const QString email, const QString password, const QString authToken) { setUrl(url); m_email = email; m_password = password; m_authToken = authToken; if (authToken.isEmpty()) { if (validLoginCredentials()) { const QByteArray userCredentials = JsonParser::userCredentialsToJsonDocument(m_email, m_password); sendPostRequest(ROUTE_LOG_IN, userCredentials); } } else { /// authToken not empty: m_serviceApi->setBearerToken(authToken.toLatin1()); } } void ServerCommunicator::fetchItems() { sendGetRequest(ROUTE_ITEMS); } void ServerCommunicator::sendItem(const QByteArray& jsonData) { sendPostRequest(ROUTE_ITEMS, jsonData); } void ServerCommunicator::deleteItem(const QString& id) { const QString path = QString("%1/%2").arg(ROUTE_ITEMS, id); sendDeleteRequest(path); } bool ServerCommunicator::validLoginCredentials() { if (url().isEmpty()) { return false; } if (m_email.isEmpty()) { return false; } if (m_password.isEmpty()) { return false; } return true; } void ServerCommunicator::sendGetRequest(const QString& path) { // TODO check for valid path, instead of emptiness if (path.isEmpty()) { qDebug() << "Empty path -> Not sending a request."; return; } const QNetworkRequest request = m_serviceApi->createRequest(path); m_restManager->get(request, this, [this, path](QRestReply& reply) { if (reply.isSuccess()) { qInfo() << "Request successful."; const QJsonDocument doc = reply.readJson().value(); onGetReplySuccessful(path, doc); } else { if (reply.hasError()) { const QString errorString = reply.errorString(); qWarning() << "Network error:" << errorString; onGetReplyFailure(path, errorString); } else { int statusCode = reply.httpStatus(); qWarning() << "Request not successful:" << statusCode; if (statusCode == 401) { notAuthorized(path); } else { onGetReplyFailure(path, QString("HTTP status code: %1").arg(statusCode)); } } } }); } void ServerCommunicator::onGetReplySuccessful(const QString& path, const QJsonDocument doc) { if (path == ROUTE_ITEMS) { emit itemsFetched(doc.toJson()); } else { qWarning() << "Can't match request path:" << path; } } void ServerCommunicator::onGetReplyFailure(const QString& path, const QString errorString) { if (path == ROUTE_ITEMS) { emit itemsFetchFailure(errorString); } else { qWarning() << "Can't match request path:" << path; } } void ServerCommunicator::sendPostRequest(const QString& path, const QByteArray data) { const QNetworkRequest request = m_serviceApi->createRequest(path); m_restManager->post(request, data, this, [this, path](QRestReply& reply) { if (reply.isSuccess()) { int statusCode = reply.httpStatus(); qInfo() << "Request successful. Status code:" << statusCode; const QJsonDocument doc = reply.readJson().value(); onPostReplySuccessful(path, doc); } else { if (reply.hasError()) { const QString errorString = reply.errorString(); qWarning() << "Network error:" << errorString; onPostReplyFailure(path, errorString); } else { int statusCode = reply.httpStatus(); qWarning() << "Request not successful:" << statusCode; qInfo() << "Content:" << reply.readJson(); if (statusCode == 401) { notAuthorized(path); } else { onPostReplyFailure(path, QString("HTTP status code: %1").arg(statusCode)); } } } }); } void ServerCommunicator::onPostReplySuccessful(const QString& path, const QJsonDocument doc) { if (path == ROUTE_ITEMS) { emit sendItemSuccessful(doc.toJson()); } else if (path == ROUTE_LOG_IN) { qCritical() << "Login success:" << doc.toJson(QJsonDocument::Compact); emit loginSuccessful(doc.toJson(QJsonDocument::Compact)); } else { qWarning() << "Can't match request path:" << path; } } void ServerCommunicator::onPostReplyFailure(const QString& path, const QString errorString) { if (path == ROUTE_ITEMS) { emit sendItemFailure(errorString); } else if (path == ROUTE_LOG_IN) { qCritical() << "Login failure:" << errorString; emit loginFailure(errorString); } else { qWarning() << "Can't match request path:" << path; } } void ServerCommunicator::sendDeleteRequest(const QString& path) { const QNetworkRequest request = m_serviceApi->createRequest(path); m_restManager->deleteResource(request, this, [this, path](QRestReply& reply) { if (reply.isSuccess()) { qInfo() << "Request successful."; const QJsonDocument doc = reply.readJson().value(); onDeleteReplySuccessful(path, doc); } else { if (reply.hasError()) { const QString errorString = reply.errorString(); qWarning() << "Network error:" << errorString; onDeleteReplyFailure(path, errorString); } else { int statusCode = reply.httpStatus(); qWarning() << "Request not successful:" << statusCode; if (statusCode == 401) { notAuthorized(path); } else { onDeleteReplyFailure(path, QString("HTTP status code: %1").arg(statusCode)); } } } }); } void ServerCommunicator::onDeleteReplySuccessful(const QString& path, const QJsonDocument doc) { if (path.startsWith(ROUTE_ITEMS)) { emit deleteItemSuccessful(doc.toJson()); } else { qWarning() << "Can't match request path:" << path; } } void ServerCommunicator::onDeleteReplyFailure(const QString& path, const QString errorString) { if (path.startsWith(ROUTE_ITEMS)) { emit deleteItemFailure(errorString); } else { qWarning() << "Can't match request path:" << path; } }