mirror of
https://github.com/amnezia-vpn/amnezia-client.git
synced 2026-06-23 02:00:20 +07:00
fix: news fetch (#1994)
* fix: fixed news nested qml call * feat: async proxy bypass
This commit is contained in:
@@ -324,7 +324,7 @@ void CoreController::initContainerModelUpdateHandler()
|
|||||||
&ContainersModel::updateModel);
|
&ContainersModel::updateModel);
|
||||||
connect(m_serversModel.get(), &ServersModel::gatewayStacksExpanded, this, [this]() {
|
connect(m_serversModel.get(), &ServersModel::gatewayStacksExpanded, this, [this]() {
|
||||||
if (m_serversModel->hasServersFromGatewayApi()) {
|
if (m_serversModel->hasServersFromGatewayApi()) {
|
||||||
m_apiNewsController->fetchNews();
|
m_apiNewsController->fetchNews(false);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
m_serversModel->resetModel();
|
m_serversModel->resetModel();
|
||||||
|
|||||||
@@ -1,8 +1,10 @@
|
|||||||
#include "gatewayController.h"
|
#include "gatewayController.h"
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
#include <functional>
|
||||||
#include <random>
|
#include <random>
|
||||||
|
|
||||||
|
#include <QCryptographicHash>
|
||||||
#include <QJsonArray>
|
#include <QJsonArray>
|
||||||
#include <QJsonDocument>
|
#include <QJsonDocument>
|
||||||
#include <QJsonObject>
|
#include <QJsonObject>
|
||||||
@@ -107,7 +109,8 @@ GatewayController::EncryptedRequestData GatewayController::prepareRequest(const
|
|||||||
encryptedKeyPayload = rsa.encrypt(QJsonDocument(keyPayload).toJson(), publicKey, RSA_PKCS1_PADDING);
|
encryptedKeyPayload = rsa.encrypt(QJsonDocument(keyPayload).toJson(), publicKey, RSA_PKCS1_PADDING);
|
||||||
EVP_PKEY_free(publicKey);
|
EVP_PKEY_free(publicKey);
|
||||||
|
|
||||||
encryptedApiPayload = blockCipher.encryptAesBlockCipher(QJsonDocument(apiPayload).toJson(), encRequestData.key, encRequestData.iv, "", encRequestData.salt);
|
encryptedApiPayload = blockCipher.encryptAesBlockCipher(QJsonDocument(apiPayload).toJson(), encRequestData.key, encRequestData.iv,
|
||||||
|
"", encRequestData.salt);
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
Utils::logException();
|
Utils::logException();
|
||||||
qCritical() << "error when encrypting the request body";
|
qCritical() << "error when encrypting the request body";
|
||||||
@@ -146,19 +149,21 @@ ErrorCode GatewayController::post(const QString &endpoint, const QJsonObject api
|
|||||||
|
|
||||||
reply->deleteLater();
|
reply->deleteLater();
|
||||||
|
|
||||||
if (sslErrors.isEmpty() && shouldBypassProxy(replyError, encryptedResponseBody, true, encRequestData.key, encRequestData.iv, encRequestData.salt)) {
|
if (sslErrors.isEmpty()
|
||||||
|
&& shouldBypassProxy(replyError, encryptedResponseBody, true, encRequestData.key, encRequestData.iv, encRequestData.salt)) {
|
||||||
auto requestFunction = [&encRequestData, &encryptedResponseBody](const QString &url) {
|
auto requestFunction = [&encRequestData, &encryptedResponseBody](const QString &url) {
|
||||||
encRequestData.request.setUrl(url);
|
encRequestData.request.setUrl(url);
|
||||||
return amnApp->networkManager()->post(encRequestData.request, encRequestData.requestBody);
|
return amnApp->networkManager()->post(encRequestData.request, encRequestData.requestBody);
|
||||||
};
|
};
|
||||||
|
|
||||||
auto replyProcessingFunction = [&encryptedResponseBody, &replyErrorString, &replyError, &httpStatusCode, &sslErrors, &encRequestData,
|
auto replyProcessingFunction = [&encryptedResponseBody, &replyErrorString, &replyError, &httpStatusCode, &sslErrors,
|
||||||
this](QNetworkReply *reply, const QList<QSslError> &nestedSslErrors) {
|
&encRequestData, this](QNetworkReply *reply, const QList<QSslError> &nestedSslErrors) {
|
||||||
encryptedResponseBody = reply->readAll();
|
encryptedResponseBody = reply->readAll();
|
||||||
replyErrorString = reply->errorString();
|
replyErrorString = reply->errorString();
|
||||||
replyError = reply->error();
|
replyError = reply->error();
|
||||||
httpStatusCode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
|
httpStatusCode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
|
||||||
if (!sslErrors.isEmpty() || shouldBypassProxy(replyError, encryptedResponseBody, true, encRequestData.key, encRequestData.iv, encRequestData.salt)) {
|
if (!sslErrors.isEmpty()
|
||||||
|
|| shouldBypassProxy(replyError, encryptedResponseBody, true, encRequestData.key, encRequestData.iv, encRequestData.salt)) {
|
||||||
sslErrors = nestedSslErrors;
|
sslErrors = nestedSslErrors;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -177,7 +182,8 @@ ErrorCode GatewayController::post(const QString &endpoint, const QJsonObject api
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
QSimpleCrypto::QBlockCipher blockCipher;
|
QSimpleCrypto::QBlockCipher blockCipher;
|
||||||
responseBody = blockCipher.decryptAesBlockCipher(encryptedResponseBody, encRequestData.key, encRequestData.iv, "", encRequestData.salt);
|
responseBody =
|
||||||
|
blockCipher.decryptAesBlockCipher(encryptedResponseBody, encRequestData.key, encRequestData.iv, "", encRequestData.salt);
|
||||||
return ErrorCode::NoError;
|
return ErrorCode::NoError;
|
||||||
} catch (...) { // todo change error handling in QSimpleCrypto?
|
} catch (...) { // todo change error handling in QSimpleCrypto?
|
||||||
Utils::logException();
|
Utils::logException();
|
||||||
@@ -202,11 +208,9 @@ QFuture<QPair<ErrorCode, QByteArray>> GatewayController::postAsync(const QString
|
|||||||
|
|
||||||
auto sslErrors = QSharedPointer<QList<QSslError>>::create();
|
auto sslErrors = QSharedPointer<QList<QSslError>>::create();
|
||||||
|
|
||||||
connect(reply, &QNetworkReply::sslErrors, [sslErrors](const QList<QSslError> &errors) {
|
connect(reply, &QNetworkReply::sslErrors, [sslErrors](const QList<QSslError> &errors) { *sslErrors = errors; });
|
||||||
*sslErrors = errors;
|
|
||||||
});
|
|
||||||
|
|
||||||
connect(reply, &QNetworkReply::finished, reply, [=]() {
|
connect(reply, &QNetworkReply::finished, reply, [promise, sslErrors, encRequestData, endpoint, apiPayload, reply, this]() mutable {
|
||||||
QByteArray encryptedResponseBody = reply->readAll();
|
QByteArray encryptedResponseBody = reply->readAll();
|
||||||
QString replyErrorString = reply->errorString();
|
QString replyErrorString = reply->errorString();
|
||||||
auto replyError = reply->error();
|
auto replyError = reply->error();
|
||||||
@@ -214,23 +218,61 @@ QFuture<QPair<ErrorCode, QByteArray>> GatewayController::postAsync(const QString
|
|||||||
|
|
||||||
reply->deleteLater();
|
reply->deleteLater();
|
||||||
|
|
||||||
auto errorCode = apiUtils::checkNetworkReplyErrors(*sslErrors, replyErrorString, replyError, httpStatusCode, encryptedResponseBody);
|
auto processResponse = [promise, encRequestData](const QByteArray &ecryptedResponseBody, const QList<QSslError> &sslErrors,
|
||||||
if (errorCode) {
|
QNetworkReply::NetworkError replyError, const QString &replyErrorString,
|
||||||
promise->addResult(qMakePair(errorCode, QByteArray()));
|
int httpStatusCode) {
|
||||||
promise->finish();
|
auto errorCode = apiUtils::checkNetworkReplyErrors(sslErrors, replyErrorString, replyError, httpStatusCode, ecryptedResponseBody);
|
||||||
return;
|
if (errorCode) {
|
||||||
}
|
promise->addResult(qMakePair(errorCode, QByteArray()));
|
||||||
|
promise->finish();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
QSimpleCrypto::QBlockCipher blockCipher;
|
QSimpleCrypto::QBlockCipher blockCipher;
|
||||||
try {
|
try {
|
||||||
QByteArray responseBody = blockCipher.decryptAesBlockCipher(encryptedResponseBody, encRequestData.key, encRequestData.iv, "", encRequestData.salt);
|
QByteArray responseBody = blockCipher.decryptAesBlockCipher(ecryptedResponseBody, encRequestData.key, encRequestData.iv, "",
|
||||||
promise->addResult(qMakePair(ErrorCode::NoError, responseBody));
|
encRequestData.salt);
|
||||||
promise->finish();
|
promise->addResult(qMakePair(ErrorCode::NoError, responseBody));
|
||||||
} catch (...) {
|
promise->finish();
|
||||||
Utils::logException();
|
} catch (...) {
|
||||||
qCritical() << "error when decrypting the request body";
|
Utils::logException();
|
||||||
promise->addResult(qMakePair(ErrorCode::ApiConfigDecryptionError, QByteArray()));
|
qCritical() << "error when decrypting the request body";
|
||||||
promise->finish();
|
promise->addResult(qMakePair(ErrorCode::ApiConfigDecryptionError, QByteArray()));
|
||||||
|
promise->finish();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (sslErrors->isEmpty()
|
||||||
|
&& shouldBypassProxy(replyError, encryptedResponseBody, true, encRequestData.key, encRequestData.iv, encRequestData.salt)) {
|
||||||
|
auto serviceType = apiPayload.value(apiDefs::key::serviceType).toString("");
|
||||||
|
auto userCountryCode = apiPayload.value(apiDefs::key::userCountryCode).toString("");
|
||||||
|
|
||||||
|
QStringList baseUrls;
|
||||||
|
if (m_isDevEnvironment) {
|
||||||
|
baseUrls = QString(DEV_S3_ENDPOINT).split(", ");
|
||||||
|
} else {
|
||||||
|
baseUrls = QString(PROD_S3_ENDPOINT).split(", ");
|
||||||
|
}
|
||||||
|
|
||||||
|
QStringList proxyStorageUrls;
|
||||||
|
if (!serviceType.isEmpty()) {
|
||||||
|
for (const auto &baseUrl : baseUrls) {
|
||||||
|
QByteArray path = ("endpoints-" + serviceType + "-" + userCountryCode).toUtf8();
|
||||||
|
proxyStorageUrls.push_back(baseUrl + path.toBase64(QByteArray::Base64UrlEncoding | QByteArray::OmitTrailingEquals)
|
||||||
|
+ ".json");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (const auto &baseUrl : baseUrls)
|
||||||
|
proxyStorageUrls.push_back(baseUrl + "endpoints.json");
|
||||||
|
|
||||||
|
getProxyUrlsAsync(proxyStorageUrls, 0, [this, encRequestData, endpoint, processResponse](const QStringList &proxyUrls) {
|
||||||
|
getProxyUrlAsync(proxyUrls, 0, [this, encRequestData, endpoint, processResponse](const QString &proxyUrls) {
|
||||||
|
bypassProxyAsync(endpoint, proxyUrls, encRequestData, processResponse);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
} else {
|
||||||
|
processResponse(encryptedResponseBody, *sslErrors, replyError, replyErrorString, httpStatusCode);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -435,3 +477,134 @@ void GatewayController::bypassProxy(const QString &endpoint, const QString &serv
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GatewayController::getProxyUrlsAsync(const QStringList proxyStorageUrls, const int currentProxyStorageIndex,
|
||||||
|
std::function<void(const QStringList &)> onComplete)
|
||||||
|
{
|
||||||
|
if (currentProxyStorageIndex >= proxyStorageUrls.size()) {
|
||||||
|
onComplete({});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
QNetworkRequest request;
|
||||||
|
request.setTransferTimeout(m_requestTimeoutMsecs);
|
||||||
|
request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
|
||||||
|
request.setUrl(proxyStorageUrls[currentProxyStorageIndex]);
|
||||||
|
|
||||||
|
QNetworkReply *reply = amnApp->networkManager()->get(request);
|
||||||
|
|
||||||
|
// connect(reply, &QNetworkReply::sslErrors, this, [state](const QList<QSslError> &e) { *(state->sslErrors) = e; });
|
||||||
|
|
||||||
|
connect(reply, &QNetworkReply::finished, this, [this, proxyStorageUrls, currentProxyStorageIndex, onComplete, reply]() {
|
||||||
|
if (reply->error() == QNetworkReply::NoError) {
|
||||||
|
QByteArray encrypted = reply->readAll();
|
||||||
|
reply->deleteLater();
|
||||||
|
|
||||||
|
QByteArray responseBody;
|
||||||
|
try {
|
||||||
|
QByteArray key = m_isDevEnvironment ? DEV_AGW_PUBLIC_KEY : PROD_AGW_PUBLIC_KEY;
|
||||||
|
if (!m_isDevEnvironment) {
|
||||||
|
QCryptographicHash hash(QCryptographicHash::Sha512);
|
||||||
|
hash.addData(key);
|
||||||
|
QByteArray h = hash.result().toHex();
|
||||||
|
|
||||||
|
QByteArray decKey = QByteArray::fromHex(h.left(64));
|
||||||
|
QByteArray iv = QByteArray::fromHex(h.mid(64, 32));
|
||||||
|
QByteArray ba = QByteArray::fromBase64(encrypted);
|
||||||
|
|
||||||
|
QSimpleCrypto::QBlockCipher cipher;
|
||||||
|
responseBody = cipher.decryptAesBlockCipher(ba, decKey, iv);
|
||||||
|
} else {
|
||||||
|
responseBody = encrypted;
|
||||||
|
}
|
||||||
|
} catch (...) {
|
||||||
|
Utils::logException();
|
||||||
|
qCritical() << "error decrypting payload";
|
||||||
|
QMetaObject::invokeMethod(
|
||||||
|
this, [=]() { getProxyUrlsAsync(proxyStorageUrls, currentProxyStorageIndex + 1, onComplete); }, Qt::QueuedConnection);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
QJsonArray endpointsArray = QJsonDocument::fromJson(responseBody).array();
|
||||||
|
QStringList endpoints;
|
||||||
|
for (const QJsonValue &endpoint : endpointsArray)
|
||||||
|
endpoints.push_back(endpoint.toString());
|
||||||
|
|
||||||
|
QStringList shuffled = endpoints;
|
||||||
|
std::random_device randomDevice;
|
||||||
|
std::mt19937 generator(randomDevice());
|
||||||
|
std::shuffle(shuffled.begin(), shuffled.end(), generator);
|
||||||
|
|
||||||
|
onComplete(shuffled);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int httpStatusCode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
|
||||||
|
qDebug() << httpStatusCode;
|
||||||
|
qDebug() << "go to the next storage endpoint";
|
||||||
|
reply->deleteLater();
|
||||||
|
QMetaObject::invokeMethod(
|
||||||
|
this, [=]() { getProxyUrlsAsync(proxyStorageUrls, currentProxyStorageIndex + 1, onComplete); }, Qt::QueuedConnection);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void GatewayController::getProxyUrlAsync(const QStringList proxyUrls, const int currentProxyIndex, std::function<void(const QString &)> onComplete)
|
||||||
|
{
|
||||||
|
if (currentProxyIndex >= proxyUrls.size()) {
|
||||||
|
onComplete("");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
QNetworkRequest request;
|
||||||
|
request.setTransferTimeout(1000);
|
||||||
|
request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
|
||||||
|
request.setUrl(proxyUrls[currentProxyIndex] + "lmbd-health");
|
||||||
|
|
||||||
|
QNetworkReply *reply = amnApp->networkManager()->get(request);
|
||||||
|
|
||||||
|
// connect(reply, &QNetworkReply::sslErrors, this, [state](const QList<QSslError> &e) {
|
||||||
|
// *(state->sslErrors) = e;
|
||||||
|
// });
|
||||||
|
|
||||||
|
connect(reply, &QNetworkReply::finished, this, [this, proxyUrls, currentProxyIndex, onComplete, reply]() {
|
||||||
|
reply->deleteLater();
|
||||||
|
|
||||||
|
if (reply->error() == QNetworkReply::NoError) {
|
||||||
|
m_proxyUrl = proxyUrls[currentProxyIndex];
|
||||||
|
onComplete(m_proxyUrl);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
qDebug() << "go to the next proxy endpoint";
|
||||||
|
QMetaObject::invokeMethod(this, [=]() { getProxyUrlAsync(proxyUrls, currentProxyIndex + 1, onComplete); }, Qt::QueuedConnection);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void GatewayController::bypassProxyAsync(
|
||||||
|
const QString &endpoint, const QString &proxyUrl, EncryptedRequestData encRequestData,
|
||||||
|
std::function<void(const QByteArray &, const QList<QSslError> &, QNetworkReply::NetworkError, const QString &, int)> onComplete)
|
||||||
|
{
|
||||||
|
auto sslErrors = QSharedPointer<QList<QSslError>>::create();
|
||||||
|
if (proxyUrl.isEmpty()) {
|
||||||
|
onComplete(QByteArray(), *sslErrors, QNetworkReply::InternalServerError, "empty proxy url", 0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
QNetworkRequest request = encRequestData.request;
|
||||||
|
request.setUrl(endpoint.arg(proxyUrl));
|
||||||
|
|
||||||
|
QNetworkReply *reply = amnApp->networkManager()->post(request, encRequestData.requestBody);
|
||||||
|
|
||||||
|
connect(reply, &QNetworkReply::sslErrors, this, [sslErrors](const QList<QSslError> &errors) { *sslErrors = errors; });
|
||||||
|
|
||||||
|
connect(reply, &QNetworkReply::finished, this, [sslErrors, onComplete, reply]() {
|
||||||
|
QByteArray encryptedResponseBody = reply->readAll();
|
||||||
|
QString replyErrorString = reply->errorString();
|
||||||
|
auto replyError = reply->error();
|
||||||
|
int httpStatusCode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
|
||||||
|
|
||||||
|
reply->deleteLater();
|
||||||
|
|
||||||
|
onComplete(encryptedResponseBody, *sslErrors, replyError, replyErrorString, httpStatusCode);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|||||||
@@ -5,6 +5,8 @@
|
|||||||
#include <QNetworkReply>
|
#include <QNetworkReply>
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
#include <QPair>
|
#include <QPair>
|
||||||
|
#include <QPromise>
|
||||||
|
#include <QSharedPointer>
|
||||||
|
|
||||||
#include "core/defs.h"
|
#include "core/defs.h"
|
||||||
|
|
||||||
@@ -24,7 +26,8 @@ public:
|
|||||||
QFuture<QPair<amnezia::ErrorCode, QByteArray>> postAsync(const QString &endpoint, const QJsonObject apiPayload);
|
QFuture<QPair<amnezia::ErrorCode, QByteArray>> postAsync(const QString &endpoint, const QJsonObject apiPayload);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
struct EncryptedRequestData {
|
struct EncryptedRequestData
|
||||||
|
{
|
||||||
QNetworkRequest request;
|
QNetworkRequest request;
|
||||||
QByteArray requestBody;
|
QByteArray requestBody;
|
||||||
QByteArray key;
|
QByteArray key;
|
||||||
@@ -42,6 +45,13 @@ private:
|
|||||||
std::function<QNetworkReply *(const QString &url)> requestFunction,
|
std::function<QNetworkReply *(const QString &url)> requestFunction,
|
||||||
std::function<bool(QNetworkReply *reply, const QList<QSslError> &sslErrors)> replyProcessingFunction);
|
std::function<bool(QNetworkReply *reply, const QList<QSslError> &sslErrors)> replyProcessingFunction);
|
||||||
|
|
||||||
|
void getProxyUrlsAsync(const QStringList proxyStorageUrls, const int currentProxyStorageIndex,
|
||||||
|
std::function<void(const QStringList &)> onComplete);
|
||||||
|
void getProxyUrlAsync(const QStringList proxyUrls, const int currentProxyIndex, std::function<void(const QString &)> onComplete);
|
||||||
|
void bypassProxyAsync(
|
||||||
|
const QString &endpoint, const QString &proxyUrl, EncryptedRequestData encRequestData,
|
||||||
|
std::function<void(const QByteArray &, const QList<QSslError> &, QNetworkReply::NetworkError, const QString &, int)> onComplete);
|
||||||
|
|
||||||
int m_requestTimeoutMsecs;
|
int m_requestTimeoutMsecs;
|
||||||
QString m_gatewayEndpoint;
|
QString m_gatewayEndpoint;
|
||||||
bool m_isDevEnvironment = false;
|
bool m_isDevEnvironment = false;
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ ApiNewsController::ApiNewsController(const QSharedPointer<NewsModel> &newsModel,
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void ApiNewsController::fetchNews()
|
void ApiNewsController::fetchNews(bool showError)
|
||||||
{
|
{
|
||||||
if (m_serversModel.isNull()) {
|
if (m_serversModel.isNull()) {
|
||||||
qWarning() << "ServersModel is null, skip fetchNews";
|
qWarning() << "ServersModel is null, skip fetchNews";
|
||||||
@@ -30,8 +30,9 @@ void ApiNewsController::fetchNews()
|
|||||||
qDebug() << "No Gateway stacks, skip fetchNews";
|
qDebug() << "No Gateway stacks, skip fetchNews";
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
GatewayController gatewayController(m_settings->getGatewayEndpoint(), m_settings->isDevGatewayEnv(), apiDefs::requestTimeoutMsecs,
|
|
||||||
m_settings->isStrictKillSwitchEnabled());
|
auto gatewayController = QSharedPointer<GatewayController>::create(m_settings->getGatewayEndpoint(), m_settings->isDevGatewayEnv(),
|
||||||
|
apiDefs::requestTimeoutMsecs, m_settings->isStrictKillSwitchEnabled());
|
||||||
QJsonObject payload;
|
QJsonObject payload;
|
||||||
payload.insert("locale", m_settings->getAppLanguage().name().split("_").first());
|
payload.insert("locale", m_settings->getAppLanguage().name().split("_").first());
|
||||||
|
|
||||||
@@ -43,11 +44,11 @@ void ApiNewsController::fetchNews()
|
|||||||
payload.insert(configKey::serviceType, stacksJson.value(configKey::serviceType));
|
payload.insert(configKey::serviceType, stacksJson.value(configKey::serviceType));
|
||||||
}
|
}
|
||||||
|
|
||||||
auto future = gatewayController.postAsync(QString("%1v1/news"), payload);
|
auto future = gatewayController->postAsync(QString("%1v1/news"), payload);
|
||||||
future.then(this, [this](QPair<ErrorCode, QByteArray> result) {
|
future.then(this, [this, showError, gatewayController](QPair<ErrorCode, QByteArray> result) {
|
||||||
auto [errorCode, responseBody] = result;
|
auto [errorCode, responseBody] = result;
|
||||||
if (errorCode != ErrorCode::NoError) {
|
if (errorCode != ErrorCode::NoError) {
|
||||||
emit errorOccurred(errorCode);
|
emit errorOccurred(errorCode, showError);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -19,10 +19,10 @@ public:
|
|||||||
explicit ApiNewsController(const QSharedPointer<NewsModel> &newsModel, const std::shared_ptr<Settings> &settings,
|
explicit ApiNewsController(const QSharedPointer<NewsModel> &newsModel, const std::shared_ptr<Settings> &settings,
|
||||||
const QSharedPointer<ServersModel> &serversModel, QObject *parent = nullptr);
|
const QSharedPointer<ServersModel> &serversModel, QObject *parent = nullptr);
|
||||||
|
|
||||||
Q_INVOKABLE void fetchNews();
|
Q_INVOKABLE void fetchNews(bool showError);
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void errorOccurred(ErrorCode errorCode);
|
void errorOccurred(ErrorCode errorCode, bool showError);
|
||||||
void fetchNewsFinished();
|
void fetchNewsFinished();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|||||||
@@ -20,10 +20,12 @@ PageType {
|
|||||||
PageController.showBusyIndicator(false)
|
PageController.showBusyIndicator(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
function onErrorOccurred(errorCode) {
|
function onErrorOccurred(errorCode, showError) {
|
||||||
PageController.showErrorMessage(errorCode)
|
if (showError) {
|
||||||
PageController.closePage()
|
PageController.showErrorMessage(errorCode)
|
||||||
PageController.showBusyIndicator(false)
|
PageController.closePage()
|
||||||
|
PageController.showBusyIndicator(false)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -153,7 +155,7 @@ PageType {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
PageController.showBusyIndicator(true)
|
PageController.showBusyIndicator(true)
|
||||||
ApiNewsController.fetchNews()
|
ApiNewsController.fetchNews(true)
|
||||||
PageController.goToPage(PageEnum.PageSettingsNewsNotifications)
|
PageController.goToPage(PageEnum.PageSettingsNewsNotifications)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user