nextcloud-desktop/src/libsync/propagateremotedeleteencrypted.cpp
Kevin Ottens 0575d0e793 Stop unlocking from within PropagateRemoteDeleteEncrypted
We need to finish deleting the file before we can actually unlock. Also
the token will be necessary for the delete to succeed.

Signed-off-by: Kevin Ottens <kevin.ottens@nextcloud.com>
2020-07-09 16:22:54 +02:00

144 lines
5.3 KiB
C++

#include "propagateremotedeleteencrypted.h"
#include "clientsideencryptionjobs.h"
#include "clientsideencryption.h"
#include "owncloudpropagator.h"
#include <QLoggingCategory>
#include <QMimeDatabase>
#include <QFileInfo>
#include <QDir>
using namespace OCC;
Q_LOGGING_CATEGORY(PROPAGATE_REMOVE_ENCRYPTED, "nextcloud.sync.propagator.remove.encrypted")
PropagateRemoteDeleteEncrypted::PropagateRemoteDeleteEncrypted(OwncloudPropagator *propagator, SyncFileItemPtr item, QObject *parent)
: QObject(parent)
, _propagator(propagator)
, _item(item)
{
}
QByteArray PropagateRemoteDeleteEncrypted::folderToken()
{
return _folderToken;
}
void PropagateRemoteDeleteEncrypted::start()
{
Q_ASSERT(!_item->_encryptedFileName.isEmpty());
QFileInfo info(_item->_encryptedFileName);
qCDebug(PROPAGATE_REMOVE_ENCRYPTED) << "Folder is encrypted, let's get the Id from it.";
auto job = new LsColJob(_propagator->account(), info.path(), this);
job->setProperties({"resourcetype", "http://owncloud.org/ns:fileid"});
connect(job, &LsColJob::directoryListingSubfolders, this, &PropagateRemoteDeleteEncrypted::slotFolderEncryptedIdReceived);
connect(job, &LsColJob::finishedWithError, this, &PropagateRemoteDeleteEncrypted::taskFailed);
job->start();
}
void PropagateRemoteDeleteEncrypted::slotFolderEncryptedIdReceived(const QStringList &list)
{
qCDebug(PROPAGATE_REMOVE_ENCRYPTED) << "Received id of folder, trying to lock it so we can prepare the metadata";
auto job = qobject_cast<LsColJob *>(sender());
const ExtraFolderInfo folderInfo = job->_folderInfos.value(list.first());
slotTryLock(folderInfo.fileId);
}
void PropagateRemoteDeleteEncrypted::slotTryLock(const QByteArray &folderId)
{
auto lockJob = new LockEncryptFolderApiJob(_propagator->account(), folderId, this);
connect(lockJob, &LockEncryptFolderApiJob::success, this, &PropagateRemoteDeleteEncrypted::slotFolderLockedSuccessfully);
connect(lockJob, &LockEncryptFolderApiJob::error, this, &PropagateRemoteDeleteEncrypted::taskFailed);
lockJob->start();
}
void PropagateRemoteDeleteEncrypted::slotFolderLockedSuccessfully(const QByteArray &folderId, const QByteArray &token)
{
qCDebug(PROPAGATE_REMOVE_ENCRYPTED) << "Folder id" << folderId << "Locked Successfully for Upload, Fetching Metadata";
_folderLocked = true;
_folderToken = token;
_folderId = folderId;
auto job = new GetMetadataApiJob(_propagator->account(), _folderId);
connect(job, &GetMetadataApiJob::jsonReceived, this, &PropagateRemoteDeleteEncrypted::slotFolderEncryptedMetadataReceived);
connect(job, &GetMetadataApiJob::error, this, &PropagateRemoteDeleteEncrypted::taskFailed);
job->start();
}
void PropagateRemoteDeleteEncrypted::slotFolderEncryptedMetadataReceived(const QJsonDocument &json, int statusCode)
{
if (statusCode == 404) {
qCDebug(PROPAGATE_REMOVE_ENCRYPTED) << "Metadata not found, ignoring.";
emit finished(true);
return;
}
qCDebug(PROPAGATE_REMOVE_ENCRYPTED) << "Metadata Received, Preparing it for the new file.";
// Encrypt File!
FolderMetadata metadata(_propagator->account(), json.toJson(QJsonDocument::Compact), statusCode);
QFileInfo info(_propagator->_localDir + QDir::separator() + _item->_file);
const QString fileName = info.fileName();
// Find existing metadata for this file
bool found = false;
const QVector<EncryptedFile> files = metadata.files();
for (const EncryptedFile &file : files) {
if (file.originalFilename == fileName) {
metadata.removeEncryptedFile(file);
found = true;
break;
}
}
if (!found) {
// The removed file was not in the JSON so nothing else to do
emit finished(true);
return;
}
qCDebug(PROPAGATE_REMOVE_ENCRYPTED) << "Metadata updated, sending to the server.";
auto job = new UpdateMetadataApiJob(_propagator->account(),
_folderId,
metadata.encryptedMetadata(),
_folderToken);
connect(job, &UpdateMetadataApiJob::success, this, [this] { emit finished(true); });
connect(job, &UpdateMetadataApiJob::error, this, &PropagateRemoteDeleteEncrypted::taskFailed);
job->start();
}
void PropagateRemoteDeleteEncrypted::unlockFolder()
{
if (!_folderLocked) {
emit folderUnlocked();
return;
}
qCDebug(PROPAGATE_REMOVE_ENCRYPTED) << "Unlocking folder" << _folderId;
auto unlockJob = new UnlockEncryptFolderApiJob(_propagator->account(),
_folderId, _folderToken, this);
connect(unlockJob, &UnlockEncryptFolderApiJob::success, [this] {
qCDebug(PROPAGATE_REMOVE_ENCRYPTED) << "Folder successfully unlocked" << _folderId;
_folderLocked = false;
emit folderUnlocked();
});
connect(unlockJob, &UnlockEncryptFolderApiJob::error, this, &PropagateRemoteDeleteEncrypted::taskFailed);
unlockJob->start();
}
void PropagateRemoteDeleteEncrypted::taskFailed()
{
qCDebug(PROPAGATE_REMOVE_ENCRYPTED) << "Task failed of job" << sender();
if (_folderLocked) {
connect(this, &PropagateRemoteDeleteEncrypted::folderUnlocked, this, [this] { emit finished(false); });
unlockFolder();
} else {
emit finished(false);
}
}