Skip to content

Commit

Permalink
Add test for deleting encrypted files
Browse files Browse the repository at this point in the history
Signed-off-by: Claudio Cambra <[email protected]>
  • Loading branch information
claucambra committed Dec 9, 2022
1 parent 2cba9f3 commit db6284c
Show file tree
Hide file tree
Showing 4 changed files with 115 additions and 3 deletions.
4 changes: 2 additions & 2 deletions src/gui/folder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1338,7 +1338,7 @@ void Folder::removeLocalE2eFiles()
const auto currentSyncPaused = syncPaused();
setSyncPaused(true);

qCDebug(lcFolder) << "About to remove: " << e2eFiles;
qCInfo(lcFolder) << "About to remove: " << e2eFiles;

for (const auto &e2eFilePath : qAsConst(e2eFiles)) {
if (!_journal.deleteFileRecord(e2eFilePath, true)) {
Expand All @@ -1347,7 +1347,7 @@ void Folder::removeLocalE2eFiles()
continue;
}

qCDebug(lcFolder) << "Removing local copy of" << e2eFilePath;
qCInfo(lcFolder) << "Removing local copy of" << e2eFilePath;

const auto fullPath = QString(path() + e2eFilePath);
const QFileInfo pathInfo(fullPath);
Expand Down
14 changes: 14 additions & 0 deletions test/syncenginetestutils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,10 @@ void DiskFileModifier::modifyLockState([[maybe_unused]] const QString &relativeP
{
}

void DiskFileModifier::setE2EE([[maybe_unused]] const QString &relativePath, [[maybe_unused]] const bool enable)
{
}

FileInfo FileInfo::A12_B12_C12_S12()
{
FileInfo fi { QString {}, {
Expand Down Expand Up @@ -213,6 +217,13 @@ void FileInfo::modifyLockState(const QString &relativePath, LockState lockState,
file->lockTimeout = lockTimeout;
}

void FileInfo::setE2EE(const QString &relativePath, const bool enable)
{
FileInfo *file = findInvalidatingEtags(relativePath);
Q_ASSERT(file);
file->isEncrypted = enable;
}

FileInfo *FileInfo::find(PathComponents pathComponents, const bool invalidateEtags)
{
if (pathComponents.isEmpty()) {
Expand Down Expand Up @@ -366,6 +377,7 @@ FakePropfindReply::FakePropfindReply(FileInfo &remoteRootFileInfo, QNetworkAcces
xml.writeTextElement(ncUri, QStringLiteral("lock-owner-editor"), fileInfo.lockOwnerId);
xml.writeTextElement(ncUri, QStringLiteral("lock-time"), QString::number(fileInfo.lockTime));
xml.writeTextElement(ncUri, QStringLiteral("lock-timeout"), QString::number(fileInfo.lockTimeout));
xml.writeTextElement(ncUri, QStringLiteral("is-encrypted"), fileInfo.isEncrypted ? QString::number(1) : QString::number(0));
buffer.write(fileInfo.extraDavProperties);
xml.writeEndElement(); // prop
xml.writeTextElement(davUri, QStringLiteral("status"), QStringLiteral("HTTP/1.1 200 OK"));
Expand Down Expand Up @@ -1000,11 +1012,13 @@ QNetworkReply *FakeQNAM::createRequest(QNetworkAccessManager::Operation op, cons
newRequest.setRawHeader("X-Request-ID", OCC::AccessManager::generateRequestId());
auto contentType = request.header(QNetworkRequest::ContentTypeHeader).toString();
if (_override) {
qDebug() << "Using override!";
if (auto _reply = _override(op, newRequest, outgoingData)) {
reply = _reply;
}
}
if (!reply) {
qDebug() << newRequest.url();
reply = overrideReplyWithError(getFilePathFromUrl(newRequest.url()), op, newRequest);
}
if (!reply) {
Expand Down
5 changes: 5 additions & 0 deletions test/syncenginetestutils.h
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ class FileModifier
virtual void rename(const QString &relativePath, const QString &relativeDestinationDirectory) = 0;
virtual void setModTime(const QString &relativePath, const QDateTime &modTime) = 0;
virtual void modifyLockState(const QString &relativePath, LockState lockState, int lockType, const QString &lockOwner, const QString &lockOwnerId, const QString &lockEditorId, quint64 lockTime, quint64 lockTimeout) = 0;
virtual void setE2EE(const QString &relativepath, const bool enabled) = 0;
};

class DiskFileModifier : public FileModifier
Expand All @@ -106,6 +107,7 @@ class DiskFileModifier : public FileModifier
void rename(const QString &from, const QString &to) override;
void setModTime(const QString &relativePath, const QDateTime &modTime) override;
void modifyLockState(const QString &relativePath, LockState lockState, int lockType, const QString &lockOwner, const QString &lockOwnerId, const QString &lockEditorId, quint64 lockTime, quint64 lockTimeout) override;
void setE2EE(const QString &relativepath, const bool enabled) override;
};

class FileInfo : public FileModifier
Expand Down Expand Up @@ -140,6 +142,8 @@ class FileInfo : public FileModifier

void modifyLockState(const QString &relativePath, LockState lockState, int lockType, const QString &lockOwner, const QString &lockOwnerId, const QString &lockEditorId, quint64 lockTime, quint64 lockTimeout) override;

void setE2EE(const QString &relativepath, const bool enabled) override;

FileInfo *find(PathComponents pathComponents, const bool invalidateEtags = false);

FileInfo *createDir(const QString &relativePath);
Expand Down Expand Up @@ -180,6 +184,7 @@ class FileInfo : public FileModifier
QString lockEditorId;
quint64 lockTime = 0;
quint64 lockTimeout = 0;
bool isEncrypted = false;

// Sorted by name to be able to compare trees
QMap<QString, FileInfo> children;
Expand Down
95 changes: 94 additions & 1 deletion test/testfolderman.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#include <QTemporaryDir>
#include <QtTest>

#include "QtTest/qtestcase.h"
#include "common/utility.h"
#include "folderman.h"
#include "account.h"
Expand All @@ -20,6 +21,14 @@

using namespace OCC;

bool itemDidCompleteSuccessfully(const ItemCompletedSpy &spy, const QString &path)
{
if (auto item = spy.findItem(path)) {
return item->_status == SyncFileItem::Success;
}
return false;
}

class TestFolderMan: public QObject
{
Q_OBJECT
Expand Down Expand Up @@ -311,7 +320,91 @@ private slots:
QCOMPARE(folderman->findGoodPathForNewSyncFolder(dirPath + "/ownCloud2", url),
QString(dirPath + "/ownCloud22"));
}

void testDeleteEncryptedFiles()
{
FakeFolder fakeFolder{FileInfo::A12_B12_C12_S12()};
QCOMPARE(fakeFolder.currentLocalState().children.count(), 4);

ItemCompletedSpy completeSpy(fakeFolder);
fakeFolder.localModifier().mkdir("encrypted");
fakeFolder.localModifier().setE2EE("encrypted", true);
fakeFolder.remoteModifier().mkdir("encrypted");
fakeFolder.remoteModifier().setE2EE("encrypted", true);

const auto fakeFileInfo = fakeFolder.remoteModifier().find("encrypted");
QVERIFY(fakeFileInfo);
QCOMPARE(fakeFolder.currentLocalState().children.count(), 5);

const auto fakeFileId = fakeFileInfo->fileId;
const auto fakeQnam = new FakeQNAM({});
// Let's avoid the null filename assert in the default FakeQNAM request creation
const auto fakeQnamOverride = [this, fakeFileId](const QNetworkAccessManager::Operation op, const QNetworkRequest &req, QIODevice *device) {
Q_UNUSED(device)
QNetworkReply *reply = nullptr;

const auto reqUrl = req.url();
const auto reqRawPath = reqUrl.path();
const auto reqPath = reqRawPath.startsWith("/owncloud/") ? reqRawPath.mid(10) : reqRawPath;

if (reqPath.startsWith(QStringLiteral("ocs/v2.php/apps/end_to_end_encryption/api/v1/meta-data/"))) {
const auto splitUrlPath = reqPath.split('/');
const auto fileId = splitUrlPath.last();

const QUrlQuery urlQuery(req.url());
const auto formatParam = urlQuery.queryItemValue(QStringLiteral("format"));

if(fileId == fakeFileId && formatParam == QStringLiteral("json")) {
reply = new FakePayloadReply(op, req, QJsonDocument().toJson(), this);
}
}
return reply;
};
fakeFolder.setServerOverride(fakeQnamOverride);
fakeQnam->setOverride(fakeQnamOverride);

const auto account = Account::create();
const auto capabilities = QVariantMap {
{QStringLiteral("end-to-end-encryption"), QVariantMap {
{QStringLiteral("enabled"), true},
{QStringLiteral("api-version"), QString::number(2.0)},
}},
};
account->setCapabilities(capabilities);
account->setCredentials(new FakeCredentials{fakeQnam});
account->setUrl(QUrl(("owncloud://somehost/owncloud")));
const auto accountState = new FakeAccountState(account);
QVERIFY(accountState->isConnected());

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

const auto folder = FolderMan::instance()->addFolder(accountState, folderDefinition(fakeFolder.localPath()));
QVERIFY(folder);
QSignalSpy folderSyncDone(folder, &Folder::syncFinished);

QDir dir(folder->path() + QStringLiteral("encrypted"));
QVERIFY(dir.exists());
QVERIFY(fakeFolder.remoteModifier().find("encrypted"));
QVERIFY(fakeFolder.currentLocalState().find("encrypted"));
QCOMPARE(fakeFolder.currentLocalState().children.count(), 5);

// Rather than go through the pain of trying to replicate the E2EE response from
// the server, let's just manually set the encryption bool in the folder journal
SyncJournalFileRecord rec;
QVERIFY(folder->journalDb()->getFileRecord(QStringLiteral("encrypted"), &rec));
rec._isE2eEncrypted = true;
rec._path = QStringLiteral("encrypted").toUtf8();
QVERIFY(folder->journalDb()->setFileRecord(rec));
FolderMan::instance()->removeE2eFiles(account);

QVERIFY(folderSyncDone.wait());

QVERIFY(fakeFolder.currentRemoteState().find("encrypted"));
QVERIFY(!fakeFolder.currentLocalState().find("encrypted"));
QCOMPARE(fakeFolder.currentLocalState().children.count(), 4);
}
};

QTEST_GUILESS_MAIN(TestFolderMan)
QTEST_MAIN(TestFolderMan)
#include "testfolderman.moc"

0 comments on commit db6284c

Please sign in to comment.