Files
GenericQtClientCore/network/servercommunicator.cpp

224 lines
6.9 KiB
C++

#include "servercommunicator.h"
#include "apiroutes.h"
#include <QJsonArray>
#include <QJsonDocument>
#include <QJsonObject>
#include <QRestReply>
#include "../formats/jsonparser.h"
using namespace Qt::StringLiterals;
ServerCommunicator::ServerCommunicator(QObject* parent)
: QObject{parent} {
m_netManager.setAutoDeleteReplies(true);
m_restManager = std::make_shared<QRestAccessManager>(&m_netManager);
m_serviceApi = std::make_shared<QNetworkRequestFactory>();
}
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;
}
}