Prevent issues when changing the enum.

Signed-off-by: alex-z <blackslayer4@gmail.com>
This commit is contained in:
alex-z 2023-11-27 22:12:26 +01:00 committed by allexzander
parent 8e38739d94
commit 4b0e1b57eb
14 changed files with 165 additions and 206 deletions

View File

@ -4,7 +4,6 @@
set(common_SOURCES
${CMAKE_CURRENT_LIST_DIR}/checksums.cpp
${CMAKE_CURRENT_LIST_DIR}/checksumcalculator.cpp
${CMAKE_CURRENT_LIST_DIR}/clientstatusreportingrecord.cpp
${CMAKE_CURRENT_LIST_DIR}/filesystembase.cpp
${CMAKE_CURRENT_LIST_DIR}/ownsql.cpp
${CMAKE_CURRENT_LIST_DIR}/preparedsqlquerymanager.cpp

View File

@ -121,10 +121,10 @@ set(client_SRCS
navigationpanehelper.cpp
networksettings.h
networksettings.cpp
"${CMAKE_SOURCE_DIR}/src/libsync/ocsjob.h"
"${CMAKE_SOURCE_DIR}/src/libsync/ocsjob.cpp"
ocsnavigationappsjob.h
ocsnavigationappsjob.cpp
ocsjob.h
ocsjob.cpp
ocssharejob.h
ocssharejob.cpp
ocsshareejob.h

View File

@ -148,13 +148,11 @@ signals:
private slots:
bool finished() override;
protected:
QByteArray _verb;
QNetworkRequest _request;
private:
QVector<int> _passStatusCodes;
QByteArray _verb;
QHash<QString, QString> _params;
QVector<int> _passStatusCodes;
QNetworkRequest _request;
};
}

View File

@ -24,7 +24,10 @@ set(libsync_SRCS
capabilities.cpp
clientproxy.h
clientproxy.cpp
clientstatusreporting.h
clientstatusreporting.cpp
clientstatusreportingrecord.h
clientstatusreportingrecord.cpp
cookiejar.h
cookiejar.cpp
discovery.h
@ -54,10 +57,6 @@ set(libsync_SRCS
owncloudpropagator.cpp
nextcloudtheme.h
nextcloudtheme.cpp
ocsjob.h
ocsjob.cpp
ocsclientstatusreportingjob.h
ocsclientstatusreportingjob.cpp
abstractpropagateremotedeleteencrypted.h
abstractpropagateremotedeleteencrypted.cpp
deletejob.h

View File

@ -64,8 +64,7 @@ constexpr int checksumRecalculateRequestServerVersionMinSupportedMajor = 24;
constexpr auto isSkipE2eeMetadataChecksumValidationAllowedInClientVersion = MIRALL_VERSION_MAJOR == 3 && MIRALL_VERSION_MINOR == 8;
}
namespace OCC
{
namespace OCC {
Q_LOGGING_CATEGORY(lcAccount, "nextcloud.sync.account", QtInfoMsg)
const char app_password[] = "_app-password";
@ -88,7 +87,7 @@ AccountPtr Account::create()
return acc;
}
ClientSideEncryption *Account::e2e()
ClientSideEncryption* Account::e2e()
{
// Qt expects everything in the connect to be a pointer, so return a pointer.
return &_e2e;
@ -268,10 +267,14 @@ void Account::setCredentials(AbstractCredentials *cred)
if (proxy.type() != QNetworkProxy::DefaultProxy) {
_am->setProxy(proxy);
}
connect(_am.data(), &QNetworkAccessManager::sslErrors, this, &Account::slotHandleSslErrors);
connect(_am.data(), &QNetworkAccessManager::proxyAuthenticationRequired, this, &Account::proxyAuthenticationRequired);
connect(_credentials.data(), &AbstractCredentials::fetched, this, &Account::slotCredentialsFetched);
connect(_credentials.data(), &AbstractCredentials::asked, this, &Account::slotCredentialsAsked);
connect(_am.data(), &QNetworkAccessManager::sslErrors,
this, &Account::slotHandleSslErrors);
connect(_am.data(), &QNetworkAccessManager::proxyAuthenticationRequired,
this, &Account::proxyAuthenticationRequired);
connect(_credentials.data(), &AbstractCredentials::fetched,
this, &Account::slotCredentialsFetched);
connect(_credentials.data(), &AbstractCredentials::asked,
this, &Account::slotCredentialsAsked);
trySetupPushNotifications();
}

View File

@ -12,16 +12,17 @@
* for more details.
*/
#include "clientstatusreporting.h"
#include "creds/abstractcredentials.h"
#include "account.h"
#include "common/clientstatusreportingrecord.h"
#include "common/syncjournaldb.h"
#include "clientstatusreportingrecord.h"
#include <configfile.h>
#include "common/c_jhash.h"
#include <networkjobs.h>
namespace
{
constexpr auto lastSentReportTimestamp = "lastClientStatusReportSentTime";
constexpr auto statusNamesHash = "statusNamesHash";
}
namespace OCC
@ -29,8 +30,8 @@ namespace OCC
Q_LOGGING_CATEGORY(lcClientStatusReporting, "nextcloud.sync.clientstatusreporting", QtInfoMsg)
ClientStatusReporting::ClientStatusReporting(Account *account, QObject *parent)
: _account(account)
, QObject(parent)
: QObject(parent)
, _account(account)
{
init();
}
@ -44,18 +45,18 @@ ClientStatusReporting::~ClientStatusReporting()
void ClientStatusReporting::init()
{
Q_ASSERT(!_isInitialized);
if (_isInitialized) {
qCDebug(lcClientStatusReporting) << "Double call to init";
return;
}
for (int i = 0; i < ClientStatusReporting::Count; ++i) {
for (int i = 0; i < ClientStatusReporting::Status::Count; ++i) {
const auto statusString = statusStringFromNumber(static_cast<Status>(i));
_statusNamesAndHashes[i] = {statusString, SyncJournalDb::getPHash(statusString)};
_statusNamesAndHashes[i] = {statusString, c_jhash64((uint8_t *)statusString.data(), statusString.size(), 0)};
}
const auto dbPath = makeDbPath();
_database = QSqlDatabase::addDatabase(QStringLiteral("QSQLITE"));
_database.setDatabaseName(dbPath);
@ -65,23 +66,42 @@ void ClientStatusReporting::init()
}
QSqlQuery query;
const auto prepareResult = query.prepare(
const auto prepareResult = query.prepare(QStringLiteral(
"CREATE TABLE IF NOT EXISTS clientstatusreporting("
"nHash INTEGER(8) PRIMARY KEY,"
"name VARCHAR(4096) PRIMARY KEY,"
"status INTEGER(8),"
"name VARCHAR(4096),"
"count INTEGER,"
"lastOccurrence INTEGER(8))");
"lastOccurrence INTEGER(8))"));
if (!prepareResult || !query.exec()) {
qCDebug(lcClientStatusReporting) << "Could not setup client clientstatusreporting table:" << query.lastError().text();
return;
}
if (!query.prepare("CREATE TABLE IF NOT EXISTS keyvalue(key VARCHAR(4096), value VARCHAR(4096), PRIMARY KEY(key))") || !query.exec()) {
if (!query.prepare(QStringLiteral("CREATE INDEX IF NOT EXISTS name ON clientstatusreporting(name);")) || !query.exec()) {
qCDebug(lcClientStatusReporting) << "Could not create index on clientstatusreporting table:" << query.lastError().text();
return;
}
if (!query.prepare(QStringLiteral("CREATE TABLE IF NOT EXISTS keyvalue(key VARCHAR(4096), value VARCHAR(4096), PRIMARY KEY(key))")) || !query.exec()) {
qCDebug(lcClientStatusReporting) << "Could not setup client keyvalue table:" << query.lastError().text();
return;
}
// prevent issues in case enum gets changed in future, hash its value and clean the db in case there was a change
QByteArray statusNamesContatenated;
for (int i = 0; i < ClientStatusReporting::Status::Count; ++i) {
statusNamesContatenated += statusStringFromNumber(static_cast<Status>(i));
}
statusNamesContatenated += QByteArray::number(ClientStatusReporting::Status::Count);
const auto statusNamesHashCurrent = QCryptographicHash::hash(statusNamesContatenated, QCryptographicHash::Md5).toHex();
const auto statusNamesHashFromDb = getStatusNamesHash();
if (statusNamesHashCurrent != statusNamesHashFromDb) {
deleteClientStatusReportingRecords();
setStatusNamesHash(statusNamesHashCurrent);
}
//
_clientStatusReportingSendTimer.setInterval(clientStatusReportingTrySendTimerInterval);
connect(&_clientStatusReportingSendTimer, &QTimer::timeout, this, &ClientStatusReporting::sendReportToServer);
_clientStatusReportingSendTimer.start();
@ -96,40 +116,31 @@ QVector<ClientStatusReportingRecord> ClientStatusReporting::getClientStatusRepor
QMutexLocker locker(&_mutex);
QSqlQuery query;
const auto prepareResult = query.prepare("SELECT * FROM clientstatusreporting");
if (!prepareResult || !query.exec()) {
const auto errorMessage = query.lastError().text();
qCDebug(lcClientStatusReporting) << "Could not get records from clientstatusreporting:" << errorMessage;
if (!query.prepare(QStringLiteral("SELECT * FROM clientstatusreporting")) || !query.exec()) {
qCDebug(lcClientStatusReporting) << "Could not get records from clientstatusreporting:" << query.lastError().text();
return records;
}
while (query.next()) {
ClientStatusReportingRecord record;
record._nameHash = query.value(query.record().indexOf("nHash")).toLongLong();
record._status = query.value(query.record().indexOf("status")).toLongLong();
record._name = query.value(query.record().indexOf("name")).toByteArray();
record._numOccurences = query.value(query.record().indexOf("count")).toLongLong();
record._lastOccurence = query.value(query.record().indexOf("lastOccurrence")).toLongLong();
record._status = query.value(query.record().indexOf(QStringLiteral("status"))).toLongLong();
record._name = query.value(query.record().indexOf(QStringLiteral("name"))).toByteArray();
record._numOccurences = query.value(query.record().indexOf(QStringLiteral("count"))).toLongLong();
record._lastOccurence = query.value(query.record().indexOf(QStringLiteral("lastOccurrence"))).toLongLong();
records.push_back(record);
}
return records;
}
bool ClientStatusReporting::deleteClientStatusReportingRecords()
void ClientStatusReporting::deleteClientStatusReportingRecords() const
{
QSqlQuery query;
const auto prepareResult = query.prepare("DELETE FROM clientstatusreporting");
if (!prepareResult || !query.exec()) {
const auto errorMessage = query.lastError().text();
qCDebug(lcClientStatusReporting) << "Could not get records from clientstatusreporting:" << errorMessage;
return false;
if (!query.prepare(QStringLiteral("DELETE FROM clientstatusreporting")) || !query.exec()) {
qCDebug(lcClientStatusReporting) << "Could not delete records from clientstatusreporting:" << query.lastError().text();
}
return true;
}
Result<void, QString> ClientStatusReporting::setClientStatusReportingRecord(const ClientStatusReportingRecord &record)
Result<void, QString> ClientStatusReporting::setClientStatusReportingRecord(const ClientStatusReportingRecord &record) const
{
Q_ASSERT(record.isValid());
if (!record.isValid()) {
@ -144,13 +155,12 @@ Result<void, QString> ClientStatusReporting::setClientStatusReportingRecord(cons
QSqlQuery query;
const auto prepareResult = query.prepare(
"INSERT OR REPLACE INTO clientstatusreporting (nHash, name, status, count, lastOccurrence) VALUES(:nHash, :name, :status, :count, :lastOccurrence) ON CONFLICT(nHash) "
"DO UPDATE SET count = count + 1, lastOccurrence = :lastOccurrence;");
query.bindValue(":nHash", recordCopy._nameHash);
query.bindValue(":name", recordCopy._name);
query.bindValue(":status", recordCopy._status);
query.bindValue(":count", 1);
query.bindValue(":lastOccurrence", recordCopy._lastOccurence);
QStringLiteral("INSERT OR REPLACE INTO clientstatusreporting (name, status, count, lastOccurrence) VALUES(:name, :status, :count, :lastOccurrence) ON CONFLICT(name) "
"DO UPDATE SET count = count + 1, lastOccurrence = :lastOccurrence;"));
query.bindValue(QStringLiteral(":name"), recordCopy._name);
query.bindValue(QStringLiteral(":status"), recordCopy._status);
query.bindValue(QStringLiteral(":count"), 1);
query.bindValue(QStringLiteral(":lastOccurrence"), recordCopy._lastOccurence);
if (!prepareResult || !query.exec()) {
const auto errorMessage = query.lastError().text();
@ -161,10 +171,10 @@ Result<void, QString> ClientStatusReporting::setClientStatusReportingRecord(cons
return {};
}
void ClientStatusReporting::reportClientStatus(const Status status)
void ClientStatusReporting::reportClientStatus(const Status status) const
{
if (!_isInitialized) {
qCWarning(lcClientStatusReporting) << "Could not report status. Status reporting is not initialized";
qCDebug(lcClientStatusReporting) << "Could not report status. Status reporting is not initialized";
return;
}
Q_ASSERT(status >= 0 && status < Count);
@ -176,7 +186,6 @@ void ClientStatusReporting::reportClientStatus(const Status status)
ClientStatusReportingRecord record;
record._name = _statusNamesAndHashes[status].first;
record._status = status;
record._nameHash = _statusNamesAndHashes[status].second;
record._lastOccurence = QDateTime::currentDateTimeUtc().toMSecsSinceEpoch();
const auto result = setClientStatusReportingRecord(record);
if (!result.isValid()) {
@ -207,8 +216,8 @@ void ClientStatusReporting::sendReportToServer()
clientStatusReportingJob->setVerb(SimpleApiJob::Verb::Put);
connect(clientStatusReportingJob, &JsonApiJob::jsonReceived, [this](const QJsonDocument &json, int statusCode) {
if (statusCode == 0 || statusCode == 200 || statusCode == 201 || statusCode == 204) {
const auto metaFromJson = json.object().value("ocs").toObject().value("meta").toObject();
const auto codeFromJson = metaFromJson.value("statuscode").toInt();
const auto metaFromJson = json.object().value(QStringLiteral("ocs")).toObject().value(QStringLiteral("meta")).toObject();
const auto codeFromJson = metaFromJson.value(QStringLiteral("statuscode")).toInt();
if (codeFromJson == 0 || codeFromJson == 200 || codeFromJson == 201 || codeFromJson == 204) {
reportToServerSentSuccessfully();
return;
@ -221,9 +230,7 @@ void ClientStatusReporting::sendReportToServer()
void ClientStatusReporting::reportToServerSentSuccessfully()
{
if (!deleteClientStatusReportingRecords()) {
qCDebug(lcClientStatusReporting) << "Error deleting client status report.";
}
deleteClientStatusReportingRecords();
setLastSentReportTimestamp(QDateTime::currentDateTimeUtc().toMSecsSinceEpoch());
}
@ -238,12 +245,12 @@ QString ClientStatusReporting::makeDbPath() const
return ConfigFile().configPath() + QStringLiteral(".userdata_%1.db").arg(QString::fromLatin1(databaseIdHash.left(6).toHex()));
}
qulonglong ClientStatusReporting::getLastSentReportTimestamp() const
quint64 ClientStatusReporting::getLastSentReportTimestamp() const
{
QMutexLocker locker(&_mutex);
QSqlQuery query;
const auto prepareResult = query.prepare("SELECT value FROM keyvalue WHERE key = (:key)");
query.bindValue(":key", lastSentReportTimestamp);
const auto prepareResult = query.prepare(QStringLiteral("SELECT value FROM keyvalue WHERE key = (:key)"));
query.bindValue(QStringLiteral(":key"), lastSentReportTimestamp);
if (!prepareResult || !query.exec()) {
qCDebug(lcClientStatusReporting) << "Could not get last sent report timestamp from keyvalue table. No such record:" << lastSentReportTimestamp;
return 0;
@ -252,9 +259,37 @@ qulonglong ClientStatusReporting::getLastSentReportTimestamp() const
qCDebug(lcClientStatusReporting) << "Could not get last sent report timestamp from keyvalue table:" << query.lastError().text();
return 0;
}
return query.value(query.record().indexOf(QStringLiteral("value"))).toULongLong();
}
int valueIndex = query.record().indexOf("value");
return query.value(valueIndex).toULongLong();
void ClientStatusReporting::setStatusNamesHash(const QByteArray &hash) const
{
QMutexLocker locker(&_mutex);
QSqlQuery query;
const auto prepareResult = query.prepare(QStringLiteral("INSERT OR REPLACE INTO keyvalue (key, value) VALUES(:key, :value);"));
query.bindValue(QStringLiteral(":key"), statusNamesHash);
query.bindValue(QStringLiteral(":value"), hash);
if (!prepareResult || !query.exec()) {
qCDebug(lcClientStatusReporting) << "Could not set status names hash.";
return;
}
}
QByteArray ClientStatusReporting::getStatusNamesHash() const
{
QMutexLocker locker(&_mutex);
QSqlQuery query;
const auto prepareResult = query.prepare(QStringLiteral("SELECT value FROM keyvalue WHERE key = (:key)"));
query.bindValue(QStringLiteral(":key"), statusNamesHash);
if (!prepareResult || !query.exec()) {
qCDebug(lcClientStatusReporting) << "Could not get status names hash. No such record:" << statusNamesHash;
return {};
}
if (!query.next()) {
qCDebug(lcClientStatusReporting) << "Could not get status names hash:" << query.lastError().text();
return {};
}
return query.value(query.record().indexOf(QStringLiteral("value"))).toByteArray();
}
QVariantMap ClientStatusReporting::prepareReport() const
@ -294,13 +329,13 @@ QVariantMap ClientStatusReporting::prepareReport() const
return report;
}
void ClientStatusReporting::setLastSentReportTimestamp(const qulonglong timestamp)
void ClientStatusReporting::setLastSentReportTimestamp(const quint64 timestamp) const
{
QMutexLocker locker(&_mutex);
QSqlQuery query;
const auto prepareResult = query.prepare("INSERT OR REPLACE INTO keyvalue (key, value) VALUES(:key, :value);");
query.bindValue(":key", lastSentReportTimestamp);
query.bindValue(":value", timestamp);
const auto prepareResult = query.prepare(QStringLiteral("INSERT OR REPLACE INTO keyvalue (key, value) VALUES(:key, :value);"));
query.bindValue(QStringLiteral(":key"), lastSentReportTimestamp);
query.bindValue(QStringLiteral(":value"), timestamp);
if (!prepareResult || !query.exec()) {
qCDebug(lcClientStatusReporting) << "Could not set last sent report timestamp from keyvalue table. No such record:" << lastSentReportTimestamp;
return;
@ -346,7 +381,7 @@ QByteArray ClientStatusReporting::statusStringFromNumber(const Status status)
return {};
}
QString ClientStatusReporting::classifyStatus(const Status status)
QByteArray ClientStatusReporting::classifyStatus(const Status status)
{
Q_ASSERT(status >= 0 && status < Count);
if (status < 0 || status >= Status::Count) {
@ -360,7 +395,7 @@ QString ClientStatusReporting::classifyStatus(const Status status)
case DownloadError_ConflictInvalidCharacters:
case UploadError_Conflict:
case UploadError_ConflictInvalidCharacters:
return QStringLiteral("sync_conflicts");
return QByteArrayLiteral("sync_conflicts");
case DownloadError_Cannot_Create_File:
case DownloadError_No_Free_Space:
case DownloadError_ServerError:
@ -375,6 +410,6 @@ QString ClientStatusReporting::classifyStatus(const Status status)
return {};
}
int ClientStatusReporting::clientStatusReportingTrySendTimerInterval = 1000 * 60 * 2; // check if the time has come, every 2 minutes
int ClientStatusReporting::repordSendIntervalMs = 24 * 60 * 60 * 1000; // once every 24 hours
quint64 ClientStatusReporting::repordSendIntervalMs = 24 * 60 * 60 * 1000; // once every 24 hours
QString ClientStatusReporting::dbPathForTesting;
}

View File

@ -14,19 +14,17 @@
#pragma once
#include "owncloudlib.h"
#include "accountfwd.h"
#include <common/result.h>
#include <QObject>
#include <QHash>
#include <QtGlobal>
#include <QByteArray>
#include <qstring.h>
#include <QTimer>
#include <QtSql>
#include <QHash>
#include <QObject>
#include <QPair>
#include <QRecursiveMutex>
class TestClientStatusReporting;
#include <QString>
#include <QTimer>
#include <QtSql>
namespace OCC {
@ -38,57 +36,73 @@ class OWNCLOUDSYNC_EXPORT ClientStatusReporting : public QObject
Q_OBJECT
public:
enum Status {
DownloadError_Cannot_Create_File = 100,
DownloadError_Conflict = 101,
DownloadError_ConflictCaseClash = 102,
DownloadError_ConflictInvalidCharacters = 103,
DownloadError_No_Free_Space = 104,
DownloadError_ServerError = 105,
DownloadError_Virtual_File_Hydration_Failure = 106,
UploadError_Conflict = 107,
UploadError_ConflictInvalidCharacters = 108,
UploadError_No_Free_Space = 109,
UploadError_No_Write_Permissions = 110,
UploadError_ServerError = 111,
Count = UploadError_ServerError + 1,
DownloadError_Cannot_Create_File = 0,
DownloadError_Conflict,
DownloadError_ConflictCaseClash,
DownloadError_ConflictInvalidCharacters,
DownloadError_No_Free_Space,
DownloadError_ServerError,
DownloadError_Virtual_File_Hydration_Failure,
UploadError_Conflict,
UploadError_ConflictInvalidCharacters,
UploadError_No_Free_Space,
UploadError_No_Write_Permissions,
UploadError_ServerError,
Count,
};
explicit ClientStatusReporting(Account *account, QObject *parent = nullptr);
~ClientStatusReporting();
~ClientStatusReporting() override;
static QByteArray statusStringFromNumber(const Status status);
private:
void init();
void reportClientStatus(const Status status);
// reporting must happen via Account
void reportClientStatus(const Status status) const;
[[nodiscard]] Result<void, QString> setClientStatusReportingRecord(const ClientStatusReportingRecord &record);
[[nodiscard]] Result<void, QString> setClientStatusReportingRecord(const ClientStatusReportingRecord &record) const;
[[nodiscard]] QVector<ClientStatusReportingRecord> getClientStatusReportingRecords() const;
[[nodiscard]] bool deleteClientStatusReportingRecords();
void setLastSentReportTimestamp(const qulonglong timestamp);
[[nodiscard]] qulonglong getLastSentReportTimestamp() const;
void deleteClientStatusReportingRecords() const;
void setLastSentReportTimestamp(const quint64 timestamp) const;
[[nodiscard]] quint64 getLastSentReportTimestamp() const;
void setStatusNamesHash(const QByteArray &hash) const;
[[nodiscard]] QByteArray getStatusNamesHash() const;
[[nodiscard]] QVariantMap prepareReport() const;
void reportToServerSentSuccessfully();
[[nodiscard]] QString makeDbPath() const;
private slots:
void sendReportToServer();
private:
static QByteArray statusStringFromNumber(const Status status);
static QString classifyStatus(const Status status);
static QByteArray classifyStatus(const Status status);
public:
static int clientStatusReportingTrySendTimerInterval;
static int repordSendIntervalMs;
static quint64 repordSendIntervalMs;
// this must be set in unit tests on init
static QString dbPathForTesting;
private:
Account *_account = nullptr;
QHash<int, QPair<QByteArray, qint64>> _statusNamesAndHashes;
QSqlDatabase _database;
bool _isInitialized = false;
QTimer _clientStatusReportingSendTimer;
QHash<int, QPair<QByteArray, quint64>> _statusNamesAndHashes;
// inspired by SyncJournalDb
mutable QRecursiveMutex _mutex;
friend class Account;
friend class TestClientStatusReporting;
};
}

View File

@ -19,6 +19,6 @@ namespace OCC
bool ClientStatusReportingRecord::isValid() const
{
return _status >= 0 && !_name.isEmpty() && _nameHash > 0 && _lastOccurence > 0;
return _status >= 0 && !_name.isEmpty() && _lastOccurence > 0;
}
}

View File

@ -12,7 +12,7 @@
* for more details.
*/
#pragma once
#include "ocsynclib.h"
#include "owncloudlib.h"
#include <QtGlobal>
#include <QByteArray>
@ -23,10 +23,10 @@ namespace OCC
* @brief The ClientStatusReportingRecord class
* @ingroup libsync
*/
struct OCSYNC_EXPORT ClientStatusReportingRecord {
struct OWNCLOUDSYNC_EXPORT ClientStatusReportingRecord {
QByteArray _name;
int _status = -1;
quint64 _nameHash = 0;
quint64 _numOccurences = 1;
quint64 _lastOccurence = 0;

View File

@ -943,7 +943,7 @@ JsonApiJob::JsonApiJob(const AccountPtr &account, const QString &path, QObject *
void JsonApiJob::setBody(const QJsonDocument &body)
{
SimpleApiJob::setBody(body.toJson(QJsonDocument::JsonFormat::Compact));
SimpleApiJob::setBody(body.toJson());
qCDebug(lcJsonApiJob) << "Set body for request:" << SimpleApiJob::body();
if (!SimpleApiJob::body().isEmpty()) {
request().setHeader(QNetworkRequest::ContentTypeHeader, "application/json");

View File

@ -1,46 +0,0 @@
/*
* Copyright (C) 2023 by Oleksandr Zolotov <alex@nextcloud.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*/
#include "ocsclientstatusreportingjob.h"
#include "networkjobs.h"
#include "account.h"
#include <QBuffer>
#include <QJsonDocument>
namespace OCC {
OcsClientStatusReportingJob::OcsClientStatusReportingJob(AccountPtr account)
: OcsJob(account)
{
setPath(QStringLiteral("ocs/v2.php/apps/security_guard/diagnostics"));
connect(this, &OcsJob::jobFinished, this, &OcsClientStatusReportingJob::jobDone);
}
void OcsClientStatusReportingJob::sendStatusReport(const QVariant &jsonData)
{
setVerb("PUT");
addRawHeader("Ocs-APIREQUEST", "true");
addRawHeader("Content-Type", "application/json");
const auto url = Utility::concatUrlPath(account()->url(), path());
sendRequest(_verb, url, _request, QJsonDocument::fromVariant(jsonData.toMap()).toJson());
AbstractNetworkJob::start();
}
void OcsClientStatusReportingJob::jobDone(QJsonDocument reply)
{
emit jobFinished(reply, {});
}
}

View File

@ -1,42 +0,0 @@
/*
* Copyright (C) 2023 by Oleksandr Zolotov <alex@nextcloud.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*/
#pragma once
#include "ocsjob.h"
#include <QJsonDocument>
#include <QVariant>
namespace OCC {
/**
* @brief The OcsClientStatusReportingJob class
* @ingroup gui
*
* Handle sending client status reports via OCS Diagnostics API.
*/
class OcsClientStatusReportingJob : public OcsJob
{
Q_OBJECT
public:
explicit OcsClientStatusReportingJob(AccountPtr account);
void sendStatusReport(const QVariant &jsonData);
signals:
void jobFinished(QJsonDocument reply, QVariant value);
private slots:
void jobDone(QJsonDocument reply);
};
}

View File

@ -1282,9 +1282,8 @@ void PropagateDownloadFile::downloadFinished()
// Maybe what we downloaded was a conflict file? If so, set a conflict record.
// (the data was prepared in slotGetFinished above)
if (_conflictRecord.isValid()) {
if (_conflictRecord.isValid())
propagator()->_journal->setConflictRecord(_conflictRecord);
}
if (vfs && vfs->mode() == Vfs::WithSuffix) {
// If the virtual file used to have a different name and db