mirror of
https://github.com/nextcloud/desktop.git
synced 2024-11-23 05:25:50 +03:00
Merge pull request #6347 from nextcloud/feature/filelocking-keep-user-lock
Feature/filelocking keep user lock
This commit is contained in:
commit
8bb36566c7
10 changed files with 70 additions and 24 deletions
|
@ -650,7 +650,8 @@ void EditLocallyJob::lockFile()
|
|||
_folderForFile->remotePathTrailingSlash(),
|
||||
_folderForFile->path(),
|
||||
_folderForFile->journalDb(),
|
||||
SyncFileItem::LockStatus::LockedItem);
|
||||
SyncFileItem::LockStatus::LockedItem,
|
||||
SyncFileItem::LockOwnerType::TokenLock);
|
||||
}
|
||||
|
||||
void EditLocallyJob::disconnectFolderSignals()
|
||||
|
|
|
@ -649,7 +649,7 @@ void Folder::slotFilesLockReleased(const QSet<QString> &files)
|
|||
}
|
||||
const auto canUnlockFile = isFileRecordValid
|
||||
&& rec._lockstate._locked
|
||||
&& rec._lockstate._lockOwnerType == static_cast<qint64>(SyncFileItem::LockOwnerType::UserLock)
|
||||
&& rec._lockstate._lockOwnerType == static_cast<qint64>(SyncFileItem::LockOwnerType::TokenLock)
|
||||
&& rec._lockstate._lockOwnerId == _accountState->account()->davUser();
|
||||
|
||||
if (!canUnlockFile) {
|
||||
|
@ -668,11 +668,13 @@ void Folder::slotFilesLockReleased(const QSet<QString> &files)
|
|||
disconnect(_officeFileLockReleaseUnlockFailure);
|
||||
qCWarning(lcFolder) << "Failed to unlock a file:" << remoteFilePath << message;
|
||||
});
|
||||
const auto lockOwnerType = static_cast<SyncFileItem::LockOwnerType>(rec._lockstate._lockOwnerType);
|
||||
_accountState->account()->setLockFileState(remoteFilePath,
|
||||
remotePathTrailingSlash(),
|
||||
path(),
|
||||
journalDb(),
|
||||
SyncFileItem::LockStatus::UnlockedItem);
|
||||
SyncFileItem::LockStatus::UnlockedItem,
|
||||
lockOwnerType);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -719,7 +721,8 @@ void Folder::slotLockedFilesFound(const QSet<QString> &files)
|
|||
remotePathTrailingSlash(),
|
||||
path(),
|
||||
journalDb(),
|
||||
SyncFileItem::LockStatus::LockedItem);
|
||||
SyncFileItem::LockStatus::LockedItem,
|
||||
SyncFileItem::LockOwnerType::TokenLock);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1091,11 +1091,18 @@ void SocketApi::setFileLock(const QString &localFile, const SyncFileItem::LockSt
|
|||
return;
|
||||
}
|
||||
|
||||
const auto record = fileData.journalRecord();
|
||||
if (static_cast<SyncFileItem::LockOwnerType>(record._lockstate._lockOwnerType) != SyncFileItem::LockOwnerType::UserLock) {
|
||||
qCDebug(lcSocketApi) << "Only user lock state or non-locked files can be affected manually!";
|
||||
return;
|
||||
}
|
||||
|
||||
shareFolder->accountState()->account()->setLockFileState(fileData.serverRelativePath,
|
||||
shareFolder->remotePathTrailingSlash(),
|
||||
shareFolder->path(),
|
||||
shareFolder->journalDb(),
|
||||
lockState);
|
||||
lockState,
|
||||
SyncFileItem::LockOwnerType::UserLock);
|
||||
|
||||
shareFolder->journalDb()->schedulePathForRemoteDiscovery(fileData.serverRelativePath);
|
||||
shareFolder->scheduleThisFolderSoon();
|
||||
|
|
|
@ -959,7 +959,8 @@ void Account::setLockFileState(const QString &serverRelativePath,
|
|||
const QString &remoteSyncPathWithTrailingSlash,
|
||||
const QString &localSyncPath,
|
||||
SyncJournalDb * const journal,
|
||||
const SyncFileItem::LockStatus lockStatus)
|
||||
const SyncFileItem::LockStatus lockStatus,
|
||||
const SyncFileItem::LockOwnerType lockOwnerType)
|
||||
{
|
||||
auto& lockStatusJobInProgress = _lockStatusChangeInprogress[serverRelativePath];
|
||||
if (lockStatusJobInProgress.contains(lockStatus)) {
|
||||
|
@ -967,7 +968,7 @@ void Account::setLockFileState(const QString &serverRelativePath,
|
|||
return;
|
||||
}
|
||||
lockStatusJobInProgress.push_back(lockStatus);
|
||||
auto job = std::make_unique<LockFileJob>(sharedFromThis(), journal, serverRelativePath, remoteSyncPathWithTrailingSlash, localSyncPath, lockStatus);
|
||||
auto job = std::make_unique<LockFileJob>(sharedFromThis(), journal, serverRelativePath, remoteSyncPathWithTrailingSlash, localSyncPath, lockStatus, lockOwnerType);
|
||||
connect(job.get(), &LockFileJob::finishedWithoutError, this, [this, serverRelativePath, lockStatus]() {
|
||||
removeLockStatusChangeInprogress(serverRelativePath, lockStatus);
|
||||
Q_EMIT lockFileSuccess();
|
||||
|
|
|
@ -316,7 +316,8 @@ public:
|
|||
const QString &remoteSyncPathWithTrailingSlash,
|
||||
const QString &localSyncPath,
|
||||
SyncJournalDb * const journal,
|
||||
const SyncFileItem::LockStatus lockStatus);
|
||||
const SyncFileItem::LockStatus lockStatus,
|
||||
const SyncFileItem::LockOwnerType lockOwnerType);
|
||||
|
||||
SyncFileItem::LockStatus fileLockStatus(SyncJournalDb * const journal,
|
||||
const QString &folderRelativePath) const;
|
||||
|
|
|
@ -254,6 +254,11 @@ bool Capabilities::filesLockAvailable() const
|
|||
return _capabilities["files"].toMap()["locking"].toByteArray() >= "1.0";
|
||||
}
|
||||
|
||||
bool Capabilities::filesLockTypeAvailable() const
|
||||
{
|
||||
return _capabilities["files"].toMap()["api-feature-lock-type"].toByteArray() >= "1.0";
|
||||
}
|
||||
|
||||
bool Capabilities::userStatus() const
|
||||
{
|
||||
if (!_capabilities.contains("user_status")) {
|
||||
|
|
|
@ -66,6 +66,7 @@ public:
|
|||
[[nodiscard]] bool chunkingNg() const;
|
||||
[[nodiscard]] bool bulkUpload() const;
|
||||
[[nodiscard]] bool filesLockAvailable() const;
|
||||
[[nodiscard]] bool filesLockTypeAvailable() const;
|
||||
[[nodiscard]] bool userStatus() const;
|
||||
[[nodiscard]] bool userStatusSupportsEmoji() const;
|
||||
[[nodiscard]] QColor serverColor() const;
|
||||
|
|
|
@ -31,10 +31,12 @@ LockFileJob::LockFileJob(const AccountPtr account,
|
|||
const QString &remoteSyncPathWithTrailingSlash,
|
||||
const QString &localSyncPath,
|
||||
const SyncFileItem::LockStatus requestedLockState,
|
||||
const SyncFileItem::LockOwnerType lockOwnerType,
|
||||
QObject *parent)
|
||||
: AbstractNetworkJob(account, path, parent)
|
||||
, _journal(journal)
|
||||
, _requestedLockState(requestedLockState)
|
||||
, _requestedLockOwnerType(lockOwnerType)
|
||||
, _remoteSyncPathWithTrailingSlash(remoteSyncPathWithTrailingSlash)
|
||||
, _localSyncPath(localSyncPath)
|
||||
{
|
||||
|
@ -48,7 +50,14 @@ void LockFileJob::start()
|
|||
qCInfo(lcLockFileJob()) << "start" << path() << _requestedLockState;
|
||||
|
||||
QNetworkRequest request;
|
||||
request.setRawHeader("X-User-Lock", "1");
|
||||
request.setRawHeader(QByteArrayLiteral("X-User-Lock"), QByteArrayLiteral("1"));
|
||||
if (_account->capabilities().filesLockTypeAvailable()) {
|
||||
if (_requestedLockOwnerType == SyncFileItem::LockOwnerType::UserLock) {
|
||||
request.setRawHeader(QByteArrayLiteral("X-User-Lock-Type"), ("0"));
|
||||
} else if (_requestedLockOwnerType == SyncFileItem::LockOwnerType::TokenLock) {
|
||||
request.setRawHeader(QByteArrayLiteral("X-User-Lock-Type"), ("2"));
|
||||
}
|
||||
}
|
||||
|
||||
QByteArray verb;
|
||||
switch(_requestedLockState)
|
||||
|
@ -174,7 +183,7 @@ SyncJournalFileRecord LockFileJob::handleReply()
|
|||
if (_journal->getFileRecord(relativePathInDb, &record) && record.isValid()) {
|
||||
setFileRecordLocked(record);
|
||||
if ((_lockStatus == SyncFileItem::LockStatus::LockedItem)
|
||||
&& (_lockOwnerType != SyncFileItem::LockOwnerType::UserLock || _userId != account()->davUser())) {
|
||||
&& (_lockOwnerType == SyncFileItem::LockOwnerType::AppLock || _userId != account()->davUser())) {
|
||||
FileSystem::setFileReadOnly(_localSyncPath + relativePathInDb, true);
|
||||
}
|
||||
const auto result = _journal->setFileRecord(record);
|
||||
|
@ -205,6 +214,8 @@ void LockFileJob::decodeStartElement(const QString &name,
|
|||
const auto convertedValue = valueText.toInt(&isValid);
|
||||
if (isValid) {
|
||||
_lockOwnerType = static_cast<SyncFileItem::LockOwnerType>(convertedValue);
|
||||
} else {
|
||||
_lockOwnerType = SyncFileItem::LockOwnerType::UserLock;
|
||||
}
|
||||
} else if (name == QStringLiteral("lock-owner-displayname")) {
|
||||
_userDisplayName = reader.readElementText();
|
||||
|
|
|
@ -25,6 +25,7 @@ public:
|
|||
const QString &remoteSyncPathWithTrailingSlash,
|
||||
const QString &localSyncPath,
|
||||
const SyncFileItem::LockStatus requestedLockState,
|
||||
const SyncFileItem::LockOwnerType lockOwnerType,
|
||||
QObject *parent = nullptr);
|
||||
void start() override;
|
||||
|
||||
|
@ -48,6 +49,7 @@ private:
|
|||
|
||||
SyncJournalDb* _journal = nullptr;
|
||||
SyncFileItem::LockStatus _requestedLockState = SyncFileItem::LockStatus::LockedItem;
|
||||
SyncFileItem::LockOwnerType _requestedLockOwnerType = SyncFileItem::LockOwnerType::UserLock;
|
||||
|
||||
SyncFileItem::LockStatus _lockStatus = SyncFileItem::LockStatus::UnlockedItem;
|
||||
SyncFileItem::LockOwnerType _lockOwnerType = SyncFileItem::LockOwnerType::UserLock;
|
||||
|
|
|
@ -40,7 +40,8 @@ private slots:
|
|||
QStringLiteral("/"),
|
||||
fakeFolder.localPath(),
|
||||
&fakeFolder.syncJournal(),
|
||||
OCC::SyncFileItem::LockStatus::LockedItem);
|
||||
OCC::SyncFileItem::LockStatus::LockedItem,
|
||||
OCC::SyncFileItem::LockOwnerType::UserLock);
|
||||
|
||||
QVERIFY(lockFileSuccessSpy.wait());
|
||||
QCOMPARE(lockFileErrorSpy.count(), 0);
|
||||
|
@ -85,7 +86,8 @@ private slots:
|
|||
QStringLiteral("/"),
|
||||
fakeFolder.localPath(),
|
||||
&fakeFolder.syncJournal(),
|
||||
OCC::SyncFileItem::LockStatus::LockedItem);
|
||||
OCC::SyncFileItem::LockStatus::LockedItem,
|
||||
OCC::SyncFileItem::LockOwnerType::UserLock);
|
||||
|
||||
QVERIFY(lockFileErrorSpy.wait());
|
||||
QCOMPARE(lockFileSuccessSpy.count(), 0);
|
||||
|
@ -109,7 +111,8 @@ private slots:
|
|||
QStringLiteral("/"),
|
||||
fakeFolder.localPath(),
|
||||
&fakeFolder.syncJournal(),
|
||||
OCC::SyncFileItem::LockStatus::LockedItem);
|
||||
OCC::SyncFileItem::LockStatus::LockedItem,
|
||||
OCC::SyncFileItem::LockOwnerType::UserLock);
|
||||
|
||||
QVERIFY(lockFileSuccessSpy.wait());
|
||||
QCOMPARE(lockFileErrorSpy.count(), 0);
|
||||
|
@ -136,7 +139,8 @@ private slots:
|
|||
QStringLiteral("/"),
|
||||
fakeFolder.localPath(),
|
||||
&fakeFolder.syncJournal(),
|
||||
OCC::SyncFileItem::LockStatus::LockedItem);
|
||||
OCC::SyncFileItem::LockStatus::LockedItem,
|
||||
OCC::SyncFileItem::LockOwnerType::UserLock);
|
||||
|
||||
QVERIFY(lockFileSuccessSpy.wait());
|
||||
QCOMPARE(lockFileErrorSpy.count(), 0);
|
||||
|
@ -160,7 +164,8 @@ private slots:
|
|||
QStringLiteral("/") + testFileName,
|
||||
QStringLiteral("/"),
|
||||
fakeFolder.localPath(),
|
||||
OCC::SyncFileItem::LockStatus::LockedItem);
|
||||
OCC::SyncFileItem::LockStatus::LockedItem,
|
||||
OCC::SyncFileItem::LockOwnerType::UserLock);
|
||||
|
||||
QSignalSpy jobSuccess(job, &OCC::LockFileJob::finishedWithoutError);
|
||||
QSignalSpy jobFailure(job, &OCC::LockFileJob::finishedWithError);
|
||||
|
@ -198,7 +203,8 @@ private slots:
|
|||
QStringLiteral("/") + testFileName,
|
||||
QStringLiteral("/"),
|
||||
fakeFolder.localPath(),
|
||||
OCC::SyncFileItem::LockStatus::LockedItem);
|
||||
OCC::SyncFileItem::LockStatus::LockedItem,
|
||||
OCC::SyncFileItem::LockOwnerType::UserLock);
|
||||
|
||||
QSignalSpy lockFileJobSuccess(lockFileJob, &OCC::LockFileJob::finishedWithoutError);
|
||||
QSignalSpy lockFileJobFailure(lockFileJob, &OCC::LockFileJob::finishedWithError);
|
||||
|
@ -215,7 +221,8 @@ private slots:
|
|||
QStringLiteral("/") + testFileName,
|
||||
QStringLiteral("/"),
|
||||
fakeFolder.localPath(),
|
||||
OCC::SyncFileItem::LockStatus::UnlockedItem);
|
||||
OCC::SyncFileItem::LockStatus::UnlockedItem,
|
||||
OCC::SyncFileItem::LockOwnerType::UserLock);
|
||||
|
||||
QSignalSpy unlockFileJobSuccess(unlockFileJob, &OCC::LockFileJob::finishedWithoutError);
|
||||
QSignalSpy unlockFileJobFailure(unlockFileJob, &OCC::LockFileJob::finishedWithError);
|
||||
|
@ -274,7 +281,8 @@ private slots:
|
|||
QStringLiteral("/") + testFileName,
|
||||
QStringLiteral("/"),
|
||||
fakeFolder.localPath(),
|
||||
OCC::SyncFileItem::LockStatus::LockedItem);
|
||||
OCC::SyncFileItem::LockStatus::LockedItem,
|
||||
OCC::SyncFileItem::LockOwnerType::UserLock);
|
||||
|
||||
QSignalSpy jobSuccess(job, &OCC::LockFileJob::finishedWithoutError);
|
||||
QSignalSpy jobFailure(job, &OCC::LockFileJob::finishedWithError);
|
||||
|
@ -327,7 +335,8 @@ private slots:
|
|||
QStringLiteral("/") + testFileName,
|
||||
QStringLiteral("/"),
|
||||
fakeFolder.localPath(),
|
||||
OCC::SyncFileItem::LockStatus::LockedItem);
|
||||
OCC::SyncFileItem::LockStatus::LockedItem,
|
||||
OCC::SyncFileItem::LockOwnerType::UserLock);
|
||||
|
||||
QSignalSpy jobSuccess(job, &OCC::LockFileJob::finishedWithoutError);
|
||||
QSignalSpy jobFailure(job, &OCC::LockFileJob::finishedWithError);
|
||||
|
@ -380,7 +389,8 @@ private slots:
|
|||
QStringLiteral("/") + testFileName,
|
||||
QStringLiteral("/"),
|
||||
fakeFolder.localPath(),
|
||||
OCC::SyncFileItem::LockStatus::UnlockedItem);
|
||||
OCC::SyncFileItem::LockStatus::UnlockedItem,
|
||||
OCC::SyncFileItem::LockOwnerType::UserLock);
|
||||
|
||||
QSignalSpy jobSuccess(job, &OCC::LockFileJob::finishedWithoutError);
|
||||
QSignalSpy jobFailure(job, &OCC::LockFileJob::finishedWithError);
|
||||
|
@ -431,7 +441,8 @@ private slots:
|
|||
QStringLiteral("/") + testFileName,
|
||||
QStringLiteral("/"),
|
||||
fakeFolder.localPath(),
|
||||
OCC::SyncFileItem::LockStatus::UnlockedItem);
|
||||
OCC::SyncFileItem::LockStatus::UnlockedItem,
|
||||
OCC::SyncFileItem::LockOwnerType::UserLock);
|
||||
|
||||
QSignalSpy jobSuccess(job, &OCC::LockFileJob::finishedWithoutError);
|
||||
QSignalSpy jobFailure(job, &OCC::LockFileJob::finishedWithError);
|
||||
|
@ -469,7 +480,8 @@ private slots:
|
|||
QStringLiteral("/") + testFileName,
|
||||
QStringLiteral("/"),
|
||||
fakeFolder.localPath(),
|
||||
OCC::SyncFileItem::LockStatus::LockedItem);
|
||||
OCC::SyncFileItem::LockStatus::LockedItem,
|
||||
OCC::SyncFileItem::LockOwnerType::UserLock);
|
||||
|
||||
QSignalSpy lockFileJobSuccess(lockFileJob, &OCC::LockFileJob::finishedWithoutError);
|
||||
QSignalSpy lockFileJobFailure(lockFileJob, &OCC::LockFileJob::finishedWithError);
|
||||
|
@ -486,7 +498,8 @@ private slots:
|
|||
QStringLiteral("/") + testFileName,
|
||||
QStringLiteral("/"),
|
||||
fakeFolder.localPath(),
|
||||
OCC::SyncFileItem::LockStatus::UnlockedItem);
|
||||
OCC::SyncFileItem::LockStatus::UnlockedItem,
|
||||
OCC::SyncFileItem::LockOwnerType::UserLock);
|
||||
|
||||
QSignalSpy unlockFileJobSuccess(unlockFileJob, &OCC::LockFileJob::finishedWithoutError);
|
||||
QSignalSpy unlockFileJobFailure(unlockFileJob, &OCC::LockFileJob::finishedWithError);
|
||||
|
@ -539,7 +552,8 @@ private slots:
|
|||
QStringLiteral("/") + testFileName,
|
||||
QStringLiteral("/"),
|
||||
fakeFolder.localPath(),
|
||||
OCC::SyncFileItem::LockStatus::UnlockedItem);
|
||||
OCC::SyncFileItem::LockStatus::UnlockedItem,
|
||||
OCC::SyncFileItem::LockOwnerType::UserLock);
|
||||
|
||||
QSignalSpy jobSuccess(job, &OCC::LockFileJob::finishedWithoutError);
|
||||
QSignalSpy jobFailure(job, &OCC::LockFileJob::finishedWithError);
|
||||
|
|
Loading…
Reference in a new issue