Skip to content

Commit

Permalink
Merge pull request #5978 from nextcloud/bugfix/lockUnlockVirtualFiles
Browse files Browse the repository at this point in the history
update read-only status of virtual files when needed for lock state
  • Loading branch information
mgallien authored Aug 21, 2023
2 parents 0bcc772 + a7c1639 commit 5183455
Show file tree
Hide file tree
Showing 4 changed files with 129 additions and 0 deletions.
12 changes: 12 additions & 0 deletions src/libsync/syncengine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -389,6 +389,18 @@ void OCC::SyncEngine::slotItemDiscovered(const OCC::SyncFileItemPtr &item)
modificationHappened = true;
}

if (item->_type == CSyncEnums::ItemTypeVirtualFile) {
if (item->_locked == SyncFileItem::LockStatus::LockedItem && (item->_lockOwnerType != SyncFileItem::LockOwnerType::UserLock || item->_lockOwnerId != account()->davUser())) {
qCDebug(lcEngine()) << filePath << "file is locked: making it read only";
FileSystem::setFileReadOnly(filePath, true);
} else {
qCDebug(lcEngine()) << filePath << "file is not locked: making it"
<< ((!item->_remotePerm.isNull() && !item->_remotePerm.hasPermission(RemotePermissions::CanWrite)) ? "read only"
: "read write");
FileSystem::setFileReadOnlyWeak(filePath, (!item->_remotePerm.isNull() && !item->_remotePerm.hasPermission(RemotePermissions::CanWrite)));
}
}

// Update on-disk virtual file metadata
if (modificationHappened && item->_type == ItemTypeVirtualFile) {
auto r = _syncOptions._vfs->updateMetadata(filePath, item->_modtime, item->_size, item->_fileId);
Expand Down
39 changes: 39 additions & 0 deletions test/testlockfile.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -631,6 +631,45 @@ private slots:
auto expectedState = fakeFolder.currentLocalState();
QCOMPARE(fakeFolder.currentRemoteState(), expectedState);
}

void testLockFile_lockedFileReadOnly_afterSync()
{
FakeFolder fakeFolder{ FileInfo::A12_B12_C12_S12() };
QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState());

ItemCompletedSpy completeSpy(fakeFolder);

completeSpy.clear();
QVERIFY(fakeFolder.syncOnce());

QCOMPARE(completeSpy.findItem(QStringLiteral("A/a1"))->_locked, OCC::SyncFileItem::LockStatus::UnlockedItem);
OCC::SyncJournalFileRecord fileRecordBefore;
QVERIFY(fakeFolder.syncJournal().getFileRecord(QStringLiteral("A/a1"), &fileRecordBefore));
QVERIFY(!fileRecordBefore._lockstate._locked);

QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState());

const auto localFileNotLocked = QFileInfo{fakeFolder.localPath() + u"A/a1"};
QVERIFY(localFileNotLocked.isWritable());

fakeFolder.remoteModifier().modifyLockState(QStringLiteral("A/a1"), FileModifier::LockState::FileLocked, 1, QStringLiteral("Nextcloud Office"), {}, QStringLiteral("richdocuments"), QDateTime::currentDateTime().toSecsSinceEpoch(), 1226);
fakeFolder.remoteModifier().setModTimeKeepEtag(QStringLiteral("A/a1"), QDateTime::currentDateTime());
fakeFolder.remoteModifier().appendByte(QStringLiteral("A/a1"));

completeSpy.clear();
QVERIFY(fakeFolder.syncOnce());

QCOMPARE(completeSpy.findItem(QStringLiteral("A/a1"))->_locked, OCC::SyncFileItem::LockStatus::LockedItem);
OCC::SyncJournalFileRecord fileRecordLocked;
QVERIFY(fakeFolder.syncJournal().getFileRecord(QStringLiteral("A/a1"), &fileRecordLocked));
QVERIFY(fileRecordLocked._lockstate._locked);

auto expectedState = fakeFolder.currentLocalState();
QCOMPARE(fakeFolder.currentRemoteState(), expectedState);

const auto localFileLocked = QFileInfo{fakeFolder.localPath() + u"A/a1"};
QVERIFY(!localFileLocked.isWritable());
}
};

QTEST_GUILESS_MAIN(TestLockFile)
Expand Down
39 changes: 39 additions & 0 deletions test/testsynccfapi.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1315,6 +1315,45 @@ private slots:

QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState());
}

void testLockFile_lockedFileReadOnly_afterSync()
{
FakeFolder fakeFolder{ FileInfo{} };
setupVfs(fakeFolder);

ItemCompletedSpy completeSpy(fakeFolder);

fakeFolder.remoteModifier().mkdir("A");
fakeFolder.remoteModifier().insert("A/a1");

completeSpy.clear();
QVERIFY(fakeFolder.syncOnce());

QCOMPARE(completeSpy.findItem(QStringLiteral("A/a1"))->_locked, OCC::SyncFileItem::LockStatus::UnlockedItem);
OCC::SyncJournalFileRecord fileRecordBefore;
QVERIFY(fakeFolder.syncJournal().getFileRecord(QStringLiteral("A/a1"), &fileRecordBefore));
QVERIFY(fileRecordBefore.isValid());
QVERIFY(!fileRecordBefore._lockstate._locked);

const auto localFileNotLocked = QFileInfo{fakeFolder.localPath() + u"A/a1"};
QVERIFY(localFileNotLocked.isWritable());

fakeFolder.remoteModifier().modifyLockState(QStringLiteral("A/a1"), FileModifier::LockState::FileLocked, 1, QStringLiteral("Nextcloud Office"), {}, QStringLiteral("richdocuments"), QDateTime::currentDateTime().toSecsSinceEpoch(), 1226);
fakeFolder.remoteModifier().setModTimeKeepEtag(QStringLiteral("A/a1"), QDateTime::currentDateTime());
fakeFolder.remoteModifier().appendByte(QStringLiteral("A/a1"));

completeSpy.clear();
QVERIFY(fakeFolder.syncOnce());

QCOMPARE(completeSpy.findItem(QStringLiteral("A/a1"))->_locked, OCC::SyncFileItem::LockStatus::LockedItem);
OCC::SyncJournalFileRecord fileRecordLocked;
QVERIFY(fakeFolder.syncJournal().getFileRecord(QStringLiteral("A/a1"), &fileRecordLocked));
QVERIFY(fileRecordLocked.isValid());
QVERIFY(fileRecordLocked._lockstate._locked);

const auto localFileLocked = QFileInfo{fakeFolder.localPath() + u"A/a1"};
QVERIFY(!localFileLocked.isWritable());
}
};

QTEST_GUILESS_MAIN(TestSyncCfApi)
Expand Down
39 changes: 39 additions & 0 deletions test/testsyncvirtualfiles.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1906,6 +1906,45 @@ private slots:

QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState());
}

void testLockFile_lockedFileReadOnly_afterSync()
{
FakeFolder fakeFolder{ FileInfo{} };
setupVfs(fakeFolder);

ItemCompletedSpy completeSpy(fakeFolder);

fakeFolder.remoteModifier().mkdir("A");
fakeFolder.remoteModifier().insert("A/a1");

completeSpy.clear();
QVERIFY(fakeFolder.syncOnce());

QCOMPARE(completeSpy.findItem(QStringLiteral("A/a1") + DVSUFFIX)->_locked, OCC::SyncFileItem::LockStatus::UnlockedItem);
OCC::SyncJournalFileRecord fileRecordBefore;
QVERIFY(fakeFolder.syncJournal().getFileRecord(QStringLiteral("A/a1") + DVSUFFIX, &fileRecordBefore));
QVERIFY(fileRecordBefore.isValid());
QVERIFY(!fileRecordBefore._lockstate._locked);

const auto localFileNotLocked = QFileInfo{fakeFolder.localPath() + u"A/a1" + DVSUFFIX};
QVERIFY(localFileNotLocked.isWritable());

fakeFolder.remoteModifier().modifyLockState(QStringLiteral("A/a1"), FileModifier::LockState::FileLocked, 1, QStringLiteral("Nextcloud Office"), {}, QStringLiteral("richdocuments"), QDateTime::currentDateTime().toSecsSinceEpoch(), 1226);
fakeFolder.remoteModifier().setModTimeKeepEtag(QStringLiteral("A/a1"), QDateTime::currentDateTime());
fakeFolder.remoteModifier().appendByte(QStringLiteral("A/a1"));

completeSpy.clear();
QVERIFY(fakeFolder.syncOnce());

QCOMPARE(completeSpy.findItem(QStringLiteral("A/a1") + DVSUFFIX)->_locked, OCC::SyncFileItem::LockStatus::LockedItem);
OCC::SyncJournalFileRecord fileRecordLocked;
QVERIFY(fakeFolder.syncJournal().getFileRecord(QStringLiteral("A/a1") + DVSUFFIX, &fileRecordLocked));
QVERIFY(fileRecordLocked.isValid());
QVERIFY(fileRecordLocked._lockstate._locked);

const auto localFileLocked = QFileInfo{fakeFolder.localPath() + u"A/a1" + DVSUFFIX};
QVERIFY(!localFileLocked.isWritable());
}
};

QTEST_GUILESS_MAIN(TestSyncVirtualFiles)
Expand Down

0 comments on commit 5183455

Please sign in to comment.