solver.setRemoteVersionFilename(target);
}
+void SocketApi::command_LOCK_FILE(const QString &localFile, SocketListener *listener)
+{
+ Q_UNUSED(listener)
+
+ setFileLock(localFile, SyncFileItem::LockStatus::LockedItem);
+}
+
+void SocketApi::command_UNLOCK_FILE(const QString &localFile, SocketListener *listener)
+{
+ Q_UNUSED(listener)
+
+ setFileLock(localFile, SyncFileItem::LockStatus::UnlockedItem);
+}
+
+void SocketApi::setFileLock(const QString &localFile, const SyncFileItem::LockStatus lockState) const
+{
+ const auto fileData = FileData::get(localFile);
+
+ const auto shareFolder = fileData.folder;
+ if (!shareFolder || !shareFolder->accountState()->isConnected()) {
+ return;
+ }
+
+ shareFolder->accountState()->account()->setLockFileState(fileData.serverRelativePath, shareFolder->journalDb(), lockState);
+}
+
void SocketApi::command_V2_LIST_ACCOUNTS(const QSharedPointer<SocketApiJobV2> &job) const
{
QJsonArray out;
//listener->sendMessage(QLatin1String("MENU_ITEM:EMAIL_PRIVATE_LINK") + flagString + tr("Send private link by email …"));
}
+void SocketApi::sendLockFileCommandMenuEntries(const QFileInfo &fileInfo,
+ Folder* const syncFolder,
+ const FileData &fileData,
+ const OCC::SocketListener* const listener) const
+{
+ if (!fileInfo.isDir() && syncFolder->accountState()->account()->capabilities().filesLockAvailable()) {
+ if (syncFolder->accountState()->account()->fileLockStatus(syncFolder->journalDb(), fileData.folderRelativePath) == SyncFileItem::LockStatus::UnlockedItem) {
+ listener->sendMessage(QLatin1String("MENU_ITEM:LOCK_FILE::") + tr("Lock file"));
+ } else {
+ if (syncFolder->accountState()->account()->fileCanBeUnlocked(syncFolder->journalDb(), fileData.folderRelativePath)) {
+ listener->sendMessage(QLatin1String("MENU_ITEM:UNLOCK_FILE::") + tr("Unlock file"));
+ }
+ }
+ }
+}
+
+void SocketApi::sendLockFileInfoMenuEntries(const QFileInfo &fileInfo,
+ Folder * const syncFolder,
+ const FileData &fileData,
+ const SocketListener * const listener,
+ const SyncJournalFileRecord &record) const
+{
+ static constexpr auto SECONDS_PER_MINUTE = 60;
+ if (!fileInfo.isDir() && syncFolder->accountState()->account()->capabilities().filesLockAvailable() &&
+ syncFolder->accountState()->account()->fileLockStatus(syncFolder->journalDb(), fileData.folderRelativePath) == SyncFileItem::LockStatus::LockedItem) {
+ listener->sendMessage(QLatin1String("MENU_ITEM:LOCKED_FILE_OWNER:d:") + tr("Locked by %1").arg(record._lockstate._lockOwnerDisplayName));
+ const auto lockExpirationTime = record._lockstate._lockTime + record._lockstate._lockTimeout;
+ const auto remainingTime = QDateTime::currentDateTime().secsTo(QDateTime::fromSecsSinceEpoch(lockExpirationTime));
+ const auto remainingTimeInMinute = static_cast<int>(remainingTime > 0 ? remainingTime / SECONDS_PER_MINUTE : 0);
+ listener->sendMessage(QLatin1String("MENU_ITEM:LOCKED_FILE_DATE:d:") + tr("Expire in %1 minutes", "remaining time before lock expire", remainingTimeInMinute).arg(remainingTimeInMinute));
+ }
+}
+
SocketApi::FileData SocketApi::FileData::get(const QString &localFile)
{
FileData data;
auto flagString = isOnTheServer && !isE2eEncryptedPath ? QLatin1String("::") : QLatin1String(":d:");
const QFileInfo fileInfo(fileData.localPath);
+ sendLockFileInfoMenuEntries(fileInfo, syncFolder, fileData, listener, record);
if (!fileInfo.isDir()) {
listener->sendMessage(QLatin1String("MENU_ITEM:ACTIVITY") + flagString + tr("Activity"));
}
listener->sendMessage(QLatin1String("MENU_ITEM:OPEN_PRIVATE_LINK") + flagString + tr("Open in browser"));
}
+ sendLockFileCommandMenuEntries(fileInfo, syncFolder, fileData, listener);
sendSharingContextMenuOptions(fileData, listener, !isE2eEncryptedPath);
// Conflict files get conflict resolution actions
class QUrl;
class QLocalSocket;
class QStringList;
+class QFileInfo;
namespace OCC {
Q_INVOKABLE void command_RESOLVE_CONFLICT(const QString &localFile, SocketListener *listener);
Q_INVOKABLE void command_DELETE_ITEM(const QString &localFile, SocketListener *listener);
Q_INVOKABLE void command_MOVE_ITEM(const QString &localFile, SocketListener *listener);
+ Q_INVOKABLE void command_LOCK_FILE(const QString &localFile, SocketListener *listener);
+ Q_INVOKABLE void command_UNLOCK_FILE(const QString &localFile, SocketListener *listener);
+
+ void setFileLock(const QString &localFile, const SyncFileItem::LockStatus lockState) const;
// Windows Shell / Explorer pinning fallbacks, see issue: https://github.com/nextcloud/desktop/issues/1599
#ifdef Q_OS_WIN
// Sends the context menu options relating to sharing to listener
void sendSharingContextMenuOptions(const FileData &fileData, SocketListener *listener, bool enabled);
+ void sendLockFileCommandMenuEntries(const QFileInfo &fileInfo,
+ Folder * const syncFolder,
+ const FileData &fileData,
+ const SocketListener * const listener) const;
+
+ void sendLockFileInfoMenuEntries(const QFileInfo &fileInfo,
+ Folder * const syncFolder,
+ const FileData &fileData,
+ const SocketListener * const listener,
+ const SyncJournalFileRecord &record) const;
+
/** Send the list of menu item. (added in version 1.1)
* argument is a list of files for which the menu should be shown, separated by '\x1e'
* Reply with GET_MENU_ITEMS:BEGIN
#include "pushnotifications.h"
#include "version.h"
-#include <deletejob.h>
+#include "deletejob.h"
+#include "lockfilejobs.h"
+#include "common/syncjournaldb.h"
#include "common/asserts.h"
#include "clientsideencryption.h"
#include "ocsuserstatusconnector.h"
return _sharedThis.toStrongRef();
}
+AccountPtr Account::sharedFromThis() const
+{
+ return _sharedThis.toStrongRef();
+}
+
QString Account::davUser() const
{
return _davUser.isEmpty() && _credentials ? _credentials->user() : _davUser;
return _userStatusConnector;
}
+void Account::setLockFileState(const QString &serverRelativePath,
+ SyncJournalDb * const journal,
+ const SyncFileItem::LockStatus lockStatus)
+{
+ auto job = std::make_unique<LockFileJob>(sharedFromThis(), journal, serverRelativePath, lockStatus);
+ connect(job.get(), &LockFileJob::finishedWithoutError, this, [this]() {
+ Q_EMIT lockFileSuccess();
+ });
+ connect(job.get(), &LockFileJob::finishedWithError, this, [lockStatus, serverRelativePath, this](const int httpErrorCode, const QString &errorString, const QString &lockOwnerName) {
+ auto errorMessage = QString{};
+ const auto filePath = serverRelativePath.mid(1);
+
+ if (httpErrorCode == LockFileJob::LOCKED_HTTP_ERROR_CODE) {
+ errorMessage = tr("File %1 is already locked by %2.").arg(filePath, lockOwnerName);
+ } else if (lockStatus == SyncFileItem::LockStatus::LockedItem) {
+ errorMessage = tr("Lock operation on %1 failed with error %2").arg(filePath, errorString);
+ } else if (lockStatus == SyncFileItem::LockStatus::UnlockedItem) {
+ errorMessage = tr("Unlock operation on %1 failed with error %2").arg(filePath, errorString);
+ }
+ Q_EMIT lockFileError(errorMessage);
+ });
+ job->start();
+ static_cast<void>(job.release());
+}
+
+SyncFileItem::LockStatus Account::fileLockStatus(SyncJournalDb * const journal,
+ const QString &folderRelativePath) const
+{
+ SyncJournalFileRecord record;
+ if (journal->getFileRecord(folderRelativePath, &record)) {
+ return record._lockstate._locked ? SyncFileItem::LockStatus::LockedItem : SyncFileItem::LockStatus::UnlockedItem;
+ }
+
+ return SyncFileItem::LockStatus::UnlockedItem;
+}
+
+bool Account::fileCanBeUnlocked(SyncJournalDb * const journal,
+ const QString &folderRelativePath) const
+{
+ SyncJournalFileRecord record;
+ if (journal->getFileRecord(folderRelativePath, &record)) {
+ if (record._lockstate._lockOwnerType != static_cast<int>(SyncFileItem::LockOwnerType::UserLock)) {
+ return false;
+ }
+
+ if (record._lockstate._lockOwnerId != sharedFromThis()->davUser()) {
+ return false;
+ }
+
+ return true;
+ }
+ return false;
+}
+
} // namespace OCC
#include <memory>
#include "capabilities.h"
#include "clientsideencryption.h"
+#include "syncfileitem.h"
class QSettings;
class QNetworkReply;
class SimpleNetworkJob;
class PushNotifications;
class UserStatusConnector;
+class SyncJournalDb;
/**
* @brief Reimplement this to handle SSL errors from libsync
AccountPtr sharedFromThis();
+ AccountPtr sharedFromThis() const;
+
/**
* The user that can be used in dav url.
*
std::shared_ptr<UserStatusConnector> userStatusConnector() const;
+ void setLockFileState(const QString &serverRelativePath,
+ SyncJournalDb * const journal,
+ const SyncFileItem::LockStatus lockStatus);
+
+ SyncFileItem::LockStatus fileLockStatus(SyncJournalDb * const journal,
+ const QString &folderRelativePath) const;
+
+ bool fileCanBeUnlocked(SyncJournalDb * const journal, const QString &folderRelativePath) const;
+
public slots:
/// Used when forgetting credentials
void clearQNAMCache();
void capabilitiesChanged();
+ void lockFileSuccess();
+ void lockFileError(const QString&);
+
protected Q_SLOTS:
void slotCredentialsFetched();
void slotCredentialsAsked();
{
}
+ void testLockFile_lockFile_lockSuccess()
+ {
+ const auto testFileName = QStringLiteral("file.txt");
+
+ FakeFolder fakeFolder{FileInfo{}};
+ QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState());
+
+ QSignalSpy lockFileSuccessSpy(fakeFolder.account().data(), &OCC::Account::lockFileSuccess);
+ QSignalSpy lockFileErrorSpy(fakeFolder.account().data(), &OCC::Account::lockFileError);
+
+ fakeFolder.localModifier().insert(testFileName);
+
+ QVERIFY(fakeFolder.syncOnce());
+
+ fakeFolder.account()->setLockFileState(QStringLiteral("/") + testFileName, &fakeFolder.syncJournal(), OCC::SyncFileItem::LockStatus::LockedItem);
+
+ QVERIFY(lockFileSuccessSpy.wait());
+ QCOMPARE(lockFileErrorSpy.count(), 0);
+ }
+
+ void testLockFile_lockFile_lockError()
+ {
+ const auto testFileName = QStringLiteral("file.txt");
+ static constexpr auto LockedHttpErrorCode = 423;
+ const auto replyData = QByteArray("<?xml version=\"1.0\"?>\n"
+ "<d:prop xmlns:d=\"DAV:\" xmlns:s=\"http://sabredav.org/ns\" xmlns:oc=\"http://owncloud.org/ns\" xmlns:nc=\"http://nextcloud.org/ns\">\n"
+ " <nc:lock/>\n"
+ " <nc:lock-owner-type>0</nc:lock-owner-type>\n"
+ " <nc:lock-owner>john</nc:lock-owner>\n"
+ " <nc:lock-owner-displayname>John Doe</nc:lock-owner-displayname>\n"
+ " <nc:lock-owner-editor>john</nc:lock-owner-editor>\n"
+ " <nc:lock-time>1650619678</nc:lock-time>\n"
+ " <nc:lock-timeout>300</nc:lock-timeout>\n"
+ " <nc:lock-token>files_lock/310997d7-0aae-4e48-97e1-eeb6be6e2202</nc:lock-token>\n"
+ "</d:prop>\n");
+
+ FakeFolder fakeFolder{FileInfo{}};
+ QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState());
+
+ fakeFolder.setServerOverride([replyData] (FakeQNAM::Operation op, const QNetworkRequest &request, QIODevice *) {
+ QNetworkReply *reply = nullptr;
+ if (op == QNetworkAccessManager::CustomOperation && request.attribute(QNetworkRequest::CustomVerbAttribute).toString() == QStringLiteral("LOCK")) {
+ reply = new FakeErrorReply(op, request, nullptr, LockedHttpErrorCode, replyData);
+ }
+
+ return reply;
+ });
+
+ QSignalSpy lockFileSuccessSpy(fakeFolder.account().data(), &OCC::Account::lockFileSuccess);
+ QSignalSpy lockFileErrorSpy(fakeFolder.account().data(), &OCC::Account::lockFileError);
+
+ fakeFolder.localModifier().insert(testFileName);
+
+ QVERIFY(fakeFolder.syncOnce());
+
+ fakeFolder.account()->setLockFileState(QStringLiteral("/") + testFileName, &fakeFolder.syncJournal(), OCC::SyncFileItem::LockStatus::LockedItem);
+
+ QVERIFY(lockFileErrorSpy.wait());
+ QCOMPARE(lockFileSuccessSpy.count(), 0);
+ }
+
+ void testLockFile_fileLockStatus_queryLockStatus()
+ {
+ const auto testFileName = QStringLiteral("file.txt");
+
+ FakeFolder fakeFolder{FileInfo{}};
+ QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState());
+
+ QSignalSpy lockFileSuccessSpy(fakeFolder.account().data(), &OCC::Account::lockFileSuccess);
+ QSignalSpy lockFileErrorSpy(fakeFolder.account().data(), &OCC::Account::lockFileError);
+
+ fakeFolder.localModifier().insert(testFileName);
+
+ QVERIFY(fakeFolder.syncOnce());
+
+ fakeFolder.account()->setLockFileState(QStringLiteral("/") + testFileName, &fakeFolder.syncJournal(), OCC::SyncFileItem::LockStatus::LockedItem);
+
+ QVERIFY(lockFileSuccessSpy.wait());
+ QCOMPARE(lockFileErrorSpy.count(), 0);
+
+ auto lockStatus = fakeFolder.account()->fileLockStatus(&fakeFolder.syncJournal(), testFileName);
+ QCOMPARE(lockStatus, OCC::SyncFileItem::LockStatus::LockedItem);
+ }
+
+ void testLockFile_fileCanBeUnlocked_canUnlock()
+ {
+ const auto testFileName = QStringLiteral("file.txt");
+
+ FakeFolder fakeFolder{FileInfo{}};
+ QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState());
+
+ QSignalSpy lockFileSuccessSpy(fakeFolder.account().data(), &OCC::Account::lockFileSuccess);
+ QSignalSpy lockFileErrorSpy(fakeFolder.account().data(), &OCC::Account::lockFileError);
+
+ fakeFolder.localModifier().insert(testFileName);
+
+ QVERIFY(fakeFolder.syncOnce());
+
+ fakeFolder.account()->setLockFileState(QStringLiteral("/") + testFileName, &fakeFolder.syncJournal(), OCC::SyncFileItem::LockStatus::LockedItem);
+
+ QVERIFY(lockFileSuccessSpy.wait());
+ QCOMPARE(lockFileErrorSpy.count(), 0);
+
+ auto lockStatus = fakeFolder.account()->fileCanBeUnlocked(&fakeFolder.syncJournal(), testFileName);
+ QCOMPARE(lockStatus, true);
+ }
+
void testLockFile_lockFile_jobSuccess()
{
const auto testFileName = QStringLiteral("file.txt");
+++ /dev/null
-#include "lockfilejobs.h"
-
-#include "account.h"
-#include "accountstate.h"
-#include "common/syncjournaldb.h"
-#include "common/syncjournalfilerecord.h"
-#include "syncenginetestutils.h"
-
-#include <QTest>
-#include <QSignalSpy>
-
-class TestLockFileJobs : public QObject
-{
- Q_OBJECT
-
-public:
- TestLockFileJobs() = default;
-
-private slots:
- void initTestCase()
- {
- }
-
- void testLockFileJob_lockFile_jobSuccess()
- {
- const auto testFileName = QStringLiteral("file.txt");
- FakeFolder fakeFolder{FileInfo{}};
- QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState());
-
- fakeFolder.localModifier().insert(testFileName);
-
- QVERIFY(fakeFolder.syncOnce());
-
- auto job = new OCC::LockFileJob(fakeFolder.account(), &fakeFolder.syncJournal(), QStringLiteral("/") + testFileName, OCC::SyncFileItem::LockStatus::LockedItem);
-
- QSignalSpy jobSuccess(job, &OCC::LockFileJob::finishedWithoutError);
- QSignalSpy jobFailure(job, &OCC::LockFileJob::finishedWithError);
-
- job->start();
-
- QVERIFY(jobSuccess.wait());
- QCOMPARE(jobFailure.count(), 0);
-
- auto fileRecord = OCC::SyncJournalFileRecord{};
- QVERIFY(fakeFolder.syncJournal().getFileRecord(testFileName, &fileRecord));
- QCOMPARE(fileRecord._locked, true);
- QCOMPARE(fileRecord._lockEditorApp, QString{});
- QCOMPARE(fileRecord._lockOwnerDisplayName, QStringLiteral("John Doe"));
- QCOMPARE(fileRecord._lockOwnerId, QStringLiteral("john"));
- QCOMPARE(fileRecord._lockOwnerType, static_cast<qint64>(OCC::SyncFileItem::LockOwnerType::UserLock));
- QCOMPARE(fileRecord._lockTime, 1234560);
- QCOMPARE(fileRecord._lockTimeout, 1800);
-
- QVERIFY(fakeFolder.syncOnce());
- }
-
- void testLockFileJob_lockFile_unlockFile_jobSuccess()
- {
- const auto testFileName = QStringLiteral("file.txt");
- FakeFolder fakeFolder{FileInfo{}};
- QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState());
-
- fakeFolder.localModifier().insert(testFileName);
-
- QVERIFY(fakeFolder.syncOnce());
-
- auto lockFileJob = new OCC::LockFileJob(fakeFolder.account(), &fakeFolder.syncJournal(), QStringLiteral("/") + testFileName, OCC::SyncFileItem::LockStatus::LockedItem);
-
- QSignalSpy lockFileJobSuccess(lockFileJob, &OCC::LockFileJob::finishedWithoutError);
- QSignalSpy lockFileJobFailure(lockFileJob, &OCC::LockFileJob::finishedWithError);
-
- lockFileJob->start();
-
- QVERIFY(lockFileJobSuccess.wait());
- QCOMPARE(lockFileJobFailure.count(), 0);
-
- QVERIFY(fakeFolder.syncOnce());
-
- auto unlockFileJob = new OCC::LockFileJob(fakeFolder.account(), &fakeFolder.syncJournal(), QStringLiteral("/") + testFileName, OCC::SyncFileItem::LockStatus::UnlockedItem);
-
- QSignalSpy unlockFileJobSuccess(unlockFileJob, &OCC::LockFileJob::finishedWithoutError);
- QSignalSpy unlockFileJobFailure(unlockFileJob, &OCC::LockFileJob::finishedWithError);
-
- unlockFileJob->start();
-
- QVERIFY(unlockFileJobSuccess.wait());
- QCOMPARE(unlockFileJobFailure.count(), 0);
-
- auto fileRecord = OCC::SyncJournalFileRecord{};
- QVERIFY(fakeFolder.syncJournal().getFileRecord(testFileName, &fileRecord));
- QCOMPARE(fileRecord._locked, false);
-
- QVERIFY(fakeFolder.syncOnce());
- }
-
- void testLockFileJob_lockFile_alreadyLocked()
- {
- static constexpr auto LockedHttpErrorCode = 423;
- static constexpr auto PreconditionFailedHttpErrorCode = 412;
-
- const auto testFileName = QStringLiteral("file.txt");
-
- const auto replyData = QByteArray("<?xml version=\"1.0\"?>\n"
- "<d:prop xmlns:d=\"DAV:\" xmlns:s=\"http://sabredav.org/ns\" xmlns:oc=\"http://owncloud.org/ns\" xmlns:nc=\"http://nextcloud.org/ns\">\n"
- " <nc:lock>1</nc:lock>\n"
- " <nc:lock-owner-type>0</nc:lock-owner-type>\n"
- " <nc:lock-owner>john</nc:lock-owner>\n"
- " <nc:lock-owner-displayname>John Doe</nc:lock-owner-displayname>\n"
- " <nc:lock-owner-editor>john</nc:lock-owner-editor>\n"
- " <nc:lock-time>1650619678</nc:lock-time>\n"
- " <nc:lock-timeout>300</nc:lock-timeout>\n"
- " <nc:lock-token>files_lock/310997d7-0aae-4e48-97e1-eeb6be6e2202</nc:lock-token>\n"
- "</d:prop>\n");
-
- FakeFolder fakeFolder{FileInfo{}};
- QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState());
-
- fakeFolder.setServerOverride([replyData] (FakeQNAM::Operation op, const QNetworkRequest &request, QIODevice *) {
- QNetworkReply *reply = nullptr;
- if (op == QNetworkAccessManager::CustomOperation && request.attribute(QNetworkRequest::CustomVerbAttribute).toString() == QStringLiteral("LOCK")) {
- reply = new FakeErrorReply(op, request, nullptr, LockedHttpErrorCode, replyData);
- } else if (op == QNetworkAccessManager::CustomOperation && request.attribute(QNetworkRequest::CustomVerbAttribute).toString() == QStringLiteral("UNLOCK")) {
- reply = new FakeErrorReply(op, request, nullptr, PreconditionFailedHttpErrorCode, replyData);
- }
-
- return reply;
- });
-
- fakeFolder.localModifier().insert(testFileName);
-
- QVERIFY(fakeFolder.syncOnce());
-
- auto job = new OCC::LockFileJob(fakeFolder.account(), &fakeFolder.syncJournal(), QStringLiteral("/") + testFileName, OCC::SyncFileItem::LockStatus::LockedItem);
-
- QSignalSpy jobSuccess(job, &OCC::LockFileJob::finishedWithoutError);
- QSignalSpy jobFailure(job, &OCC::LockFileJob::finishedWithError);
-
- job->start();
-
- QVERIFY(jobFailure.wait());
- QCOMPARE(jobSuccess.count(), 0);
- }
-
- void testLockFileJob_unlockFile_alreadyUnlocked()
- {
- static constexpr auto LockedHttpErrorCode = 423;
- static constexpr auto PreconditionFailedHttpErrorCode = 412;
-
- const auto testFileName = QStringLiteral("file.txt");
-
- const auto replyData = QByteArray("<?xml version=\"1.0\"?>\n"
- "<d:prop xmlns:d=\"DAV:\" xmlns:s=\"http://sabredav.org/ns\" xmlns:oc=\"http://owncloud.org/ns\" xmlns:nc=\"http://nextcloud.org/ns\">\n"
- " <nc:lock/>\n"
- " <nc:lock-owner-type>0</nc:lock-owner-type>\n"
- " <nc:lock-owner>john</nc:lock-owner>\n"
- " <nc:lock-owner-displayname>John Doe</nc:lock-owner-displayname>\n"
- " <nc:lock-owner-editor>john</nc:lock-owner-editor>\n"
- " <nc:lock-time>1650619678</nc:lock-time>\n"
- " <nc:lock-timeout>300</nc:lock-timeout>\n"
- " <nc:lock-token>files_lock/310997d7-0aae-4e48-97e1-eeb6be6e2202</nc:lock-token>\n"
- "</d:prop>\n");
-
- FakeFolder fakeFolder{FileInfo{}};
- QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState());
-
- fakeFolder.setServerOverride([replyData] (FakeQNAM::Operation op, const QNetworkRequest &request, QIODevice *) {
- QNetworkReply *reply = nullptr;
- if (op == QNetworkAccessManager::CustomOperation && request.attribute(QNetworkRequest::CustomVerbAttribute).toString() == QStringLiteral("LOCK")) {
- reply = new FakeErrorReply(op, request, nullptr, LockedHttpErrorCode, replyData);
- } else if (op == QNetworkAccessManager::CustomOperation && request.attribute(QNetworkRequest::CustomVerbAttribute).toString() == QStringLiteral("UNLOCK")) {
- reply = new FakeErrorReply(op, request, nullptr, PreconditionFailedHttpErrorCode, replyData);
- }
-
- return reply;
- });
-
- fakeFolder.localModifier().insert(testFileName);
-
- QVERIFY(fakeFolder.syncOnce());
-
- auto job = new OCC::LockFileJob(fakeFolder.account(), &fakeFolder.syncJournal(), QStringLiteral("/") + testFileName, OCC::SyncFileItem::LockStatus::LockedItem);
-
- QSignalSpy jobSuccess(job, &OCC::LockFileJob::finishedWithoutError);
- QSignalSpy jobFailure(job, &OCC::LockFileJob::finishedWithError);
-
- job->start();
-
- QVERIFY(jobFailure.wait());
- QCOMPARE(jobSuccess.count(), 0);
- }
-
- void testLockFileJob_lockFile_jobError()
- {
- const auto testFileName = QStringLiteral("file.txt");
- static constexpr auto InternalServerErrorHttpErrorCode = 500;
-
- FakeFolder fakeFolder{FileInfo{}};
- QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState());
-
- fakeFolder.setServerOverride([] (FakeQNAM::Operation op, const QNetworkRequest &request, QIODevice *) {
- QNetworkReply *reply = nullptr;
- if (op == QNetworkAccessManager::CustomOperation && request.attribute(QNetworkRequest::CustomVerbAttribute).toString() == QStringLiteral("LOCK")) {
- reply = new FakeErrorReply(op, request, nullptr, InternalServerErrorHttpErrorCode, {});
- } else if (op == QNetworkAccessManager::CustomOperation && request.attribute(QNetworkRequest::CustomVerbAttribute).toString() == QStringLiteral("UNLOCK")) {
- reply = new FakeErrorReply(op, request, nullptr, InternalServerErrorHttpErrorCode, {});
- }
-
- return reply;
- });
-
- fakeFolder.localModifier().insert(QStringLiteral("file.txt"));
-
- QVERIFY(fakeFolder.syncOnce());
-
- auto lockFileJob = new OCC::LockFileJob(fakeFolder.account(), &fakeFolder.syncJournal(), QStringLiteral("/") + testFileName, OCC::SyncFileItem::LockStatus::LockedItem);
-
- QSignalSpy lockFileJobSuccess(lockFileJob, &OCC::LockFileJob::finishedWithoutError);
- QSignalSpy lockFileJobFailure(lockFileJob, &OCC::LockFileJob::finishedWithError);
-
- lockFileJob->start();
-
- QVERIFY(lockFileJobFailure.wait());
- QCOMPARE(lockFileJobSuccess.count(), 0);
-
- QVERIFY(fakeFolder.syncOnce());
-
- auto unlockFileJob = new OCC::LockFileJob(fakeFolder.account(), &fakeFolder.syncJournal(), QStringLiteral("/") + testFileName, OCC::SyncFileItem::LockStatus::UnlockedItem);
-
- QSignalSpy unlockFileJobSuccess(unlockFileJob, &OCC::LockFileJob::finishedWithoutError);
- QSignalSpy unlockFileJobFailure(unlockFileJob, &OCC::LockFileJob::finishedWithError);
-
- unlockFileJob->start();
-
- QVERIFY(unlockFileJobFailure.wait());
- QCOMPARE(unlockFileJobSuccess.count(), 0);
-
- QVERIFY(fakeFolder.syncOnce());
- }
-};
-
-QTEST_MAIN(TestLockFileJobs)
-#include "testlockfilejobs.moc"