From: Kevin Ottens Date: Wed, 17 Jun 2020 17:08:59 +0000 (+0200) Subject: Move the encrypt folder logic in a reusable job class X-Git-Tag: archive/raspbian/3.16.7-1_deb13u1+rpi1~1^2~222^2^2~130^2~11 X-Git-Url: https://dgit.raspbian.org/?a=commitdiff_plain;h=74978a23fbf12fc9e914137ff5981d427f508350;p=nextcloud-desktop.git Move the encrypt folder logic in a reusable job class This way this whole logic isn't stuck into the settings dialog anymore. Also cleaned up the unused "decrypt folder" logic. Signed-off-by: Kevin Ottens --- diff --git a/src/gui/accountsettings.cpp b/src/gui/accountsettings.cpp index db94e9048..594522885 100644 --- a/src/gui/accountsettings.cpp +++ b/src/gui/accountsettings.cpp @@ -33,7 +33,7 @@ #include "creds/httpcredentialsgui.h" #include "tooltipupdater.h" #include "filesystem.h" -#include "clientsideencryptionjobs.h" +#include "encryptfolderjob.h" #include "syncresult.h" #include "ignorelisttablewidget.h" @@ -223,6 +223,17 @@ void AccountSettings::slotNewMnemonicGenerated() _ui->encryptionMessage->show(); } +void AccountSettings::slotEncryptFolderFinished(int status) +{ + qCInfo(lcAccountSettings) << "Current folder encryption status code:" << status; + auto job = qobject_cast(sender()); + Q_ASSERT(job); + if (!job->errorString().isEmpty()) { + QMessageBox::warning(nullptr, "Warning", job->errorString()); + } + job->deleteLater(); +} + QString AccountSettings::selectedFolderAlias() const { QModelIndex selected = _ui->_folderList->selectionModel()->currentIndex(); @@ -261,98 +272,6 @@ void AccountSettings::slotShowMnemonic(const QString &mnemonic) { AccountManager::instance()->displayMnemonic(mnemonic); } -void AccountSettings::slotEncryptionFlagSuccess(const QByteArray& fileId) -{ - if (auto info = _model->infoForFileId(fileId)) { - accountsState()->account()->e2e()->setFolderEncryptedStatus(info->_path, true); - } else { - qCInfo(lcAccountSettings()) << "Could not get information from the current folder."; - } - auto lockJob = new LockEncryptFolderApiJob(accountsState()->account(), fileId); - connect(lockJob, &LockEncryptFolderApiJob::success, - this, &AccountSettings::slotLockForEncryptionSuccess); - connect(lockJob, &LockEncryptFolderApiJob::error, - this, &AccountSettings::slotLockForEncryptionError); - lockJob->start(); -} - -void AccountSettings::slotEncryptionFlagError(const QByteArray& fileId, int httpErrorCode) -{ - Q_UNUSED(fileId); - Q_UNUSED(httpErrorCode); - qDebug() << "Error on the encryption flag"; -} - -void AccountSettings::slotLockForEncryptionSuccess(const QByteArray& fileId, const QByteArray &token) -{ - accountsState()->account()->e2e()->setTokenForFolder(fileId, token); - - FolderMetadata emptyMetadata(accountsState()->account()); - auto encryptedMetadata = emptyMetadata.encryptedMetadata(); - if (encryptedMetadata.isEmpty()) { - //TODO: Mark the folder as unencrypted as the metadata generation failed. - QMessageBox::warning(nullptr, "Warning", - "Could not generate the metadata for encryption, Unlocking the folder. \n" - "This can be an issue with your OpenSSL libraries, please note that OpenSSL 1.1 is \n" - "not compatible with Nextcloud yet." - ); - return; - } - auto storeMetadataJob = new StoreMetaDataApiJob(accountsState()->account(), fileId, emptyMetadata.encryptedMetadata()); - connect(storeMetadataJob, &StoreMetaDataApiJob::success, - this, &AccountSettings::slotUploadMetadataSuccess); - connect(storeMetadataJob, &StoreMetaDataApiJob::error, - this, &AccountSettings::slotUpdateMetadataError); - - storeMetadataJob->start(); -} - -void AccountSettings::slotUploadMetadataSuccess(const QByteArray& folderId) -{ - const auto token = accountsState()->account()->e2e()->tokenForFolder(folderId); - auto unlockJob = new UnlockEncryptFolderApiJob(accountsState()->account(), folderId, token); - connect(unlockJob, &UnlockEncryptFolderApiJob::success, - this, &AccountSettings::slotUnlockFolderSuccess); - connect(unlockJob, &UnlockEncryptFolderApiJob::error, - this, &AccountSettings::slotUnlockFolderError); - unlockJob->start(); -} - -void AccountSettings::slotUpdateMetadataError(const QByteArray& folderId, int httpReturnCode) -{ - Q_UNUSED(httpReturnCode); - - const auto token = accountsState()->account()->e2e()->tokenForFolder(folderId); - auto unlockJob = new UnlockEncryptFolderApiJob(accountsState()->account(), folderId, token); - connect(unlockJob, &UnlockEncryptFolderApiJob::success, - this, &AccountSettings::slotUnlockFolderSuccess); - connect(unlockJob, &UnlockEncryptFolderApiJob::error, - this, &AccountSettings::slotUnlockFolderError); - unlockJob->start(); -} - -void AccountSettings::slotLockForEncryptionError(const QByteArray& fileId, int httpErrorCode) -{ - Q_UNUSED(fileId); - Q_UNUSED(httpErrorCode); - - qCInfo(lcAccountSettings()) << "Locking error" << httpErrorCode; -} - -void AccountSettings::slotUnlockFolderError(const QByteArray& fileId, int httpErrorCode) -{ - Q_UNUSED(fileId); - Q_UNUSED(httpErrorCode); - - qCInfo(lcAccountSettings()) << "Unlocking error!"; -} -void AccountSettings::slotUnlockFolderSuccess(const QByteArray& fileId) -{ - Q_UNUSED(fileId); - - qCInfo(lcAccountSettings()) << "Unlocking success!"; -} - bool AccountSettings::canEncryptOrDecrypt (const FolderStatusModel::SubFolderInfo* info) { if (info->_folder->syncResult().status() != SyncResult::Status::Success) { QMessageBox msgBox; @@ -381,117 +300,11 @@ void AccountSettings::slotMarkSubfolderEncrypted(const FolderStatusModel::SubFol return; } - auto job = new OCC::SetEncryptionFlagApiJob(accountsState()->account(), folderInfo->_fileId); - connect(job, &OCC::SetEncryptionFlagApiJob::success, this, &AccountSettings::slotEncryptionFlagSuccess); - connect(job, &OCC::SetEncryptionFlagApiJob::error, this, &AccountSettings::slotEncryptionFlagError); + auto job = new OCC::EncryptFolderJob(accountsState()->account(), folderInfo->_path, folderInfo->_fileId, this); + connect(job, &OCC::EncryptFolderJob::finished, this, &AccountSettings::slotEncryptFolderFinished); job->start(); } - -// Order: -// 1 - Lock folder, -// 2 - Delete Metadata, -// 3 - Unlock Folder, -// 4 - Mark as Decrypted. - - -void AccountSettings::slotMarkSubfolderDecrypted(const FolderStatusModel::SubFolderInfo* folderInfo) -{ - if (!canEncryptOrDecrypt(folderInfo)) { - return; - } - - qDebug() << "Starting to mark as decrypted"; - qDebug() << "Locking the folder"; - auto lockJob = new LockEncryptFolderApiJob(accountsState()->account(), folderInfo->_fileId); - connect(lockJob, &LockEncryptFolderApiJob::success, - this, &AccountSettings::slotLockForDecryptionSuccess); - connect(lockJob, &LockEncryptFolderApiJob::error, - this, &AccountSettings::slotLockForDecryptionError); - lockJob->start(); -} - -void AccountSettings::slotLockForDecryptionSuccess(const QByteArray& fileId, const QByteArray& token) -{ - qDebug() << "Locking success, trying to delete the metadata"; - accountsState()->account()->e2e()->setTokenForFolder(fileId, token); - auto job = new DeleteMetadataApiJob(accountsState()->account(), fileId); - connect(job, &DeleteMetadataApiJob::success, - this, &AccountSettings::slotDeleteMetadataSuccess); - connect(job, &DeleteMetadataApiJob::error, - this, &AccountSettings::slotDeleteMetadataError); - job->start(); -} - -void AccountSettings::slotDeleteMetadataSuccess(const QByteArray& fileId) -{ - qDebug() << "Metadata successfully deleted, unlocking the folder"; - auto token = accountsState()->account()->e2e()->tokenForFolder(fileId); - auto job = new UnlockEncryptFolderApiJob(accountsState()->account(), fileId, token); - connect(job, &UnlockEncryptFolderApiJob::success, - this, &AccountSettings::slotUnlockForDecryptionSuccess); - connect(job, &UnlockEncryptFolderApiJob::error, - this, &AccountSettings::slotUnlockForDecryptionError); - job->start(); -} - -void AccountSettings::slotUnlockForDecryptionSuccess(const QByteArray& fileId) -{ - qDebug() << "Unlocked the folder successfully, removing the encrypted bit."; - auto job = new OCC::DeleteApiJob(accountsState()->account(), - "ocs/v2.php/apps/end_to_end_encryption/api/v1/encrypted/" + QString(fileId)); - - // This Delete ApiJob is different than all other jobs used here, sigh. - connect(job, &OCC::DeleteApiJob::result, [this, &fileId](int httpResponse) { - if (httpResponse == 200) { - slotDecryptionFlagSuccess(fileId); - } else { - slotDecryptionFlagError(fileId, httpResponse); - } - }); - job->start(); -} - -void AccountSettings::slotDecryptionFlagSuccess(const QByteArray& fileId) -{ - if (auto info = _model->infoForFileId(fileId)) { - accountsState()->account()->e2e()->setFolderEncryptedStatus(info->_path, false); - } else { - qCInfo(lcAccountSettings()) << "Could not get information for the current path."; - } -} - -void AccountSettings::slotDecryptionFlagError(const QByteArray& fileId, int httpReturnCode) -{ - Q_UNUSED(fileId); - Q_UNUSED(httpReturnCode); - - qDebug() << "Error Setting the Decryption Flag"; -} - -void AccountSettings::slotUnlockForDecryptionError(const QByteArray& fileId, int httpReturnCode) -{ - Q_UNUSED(fileId); - Q_UNUSED(httpReturnCode); - - qDebug() << "Error unlocking folder after decryption"; -} - -void AccountSettings::slotDeleteMetadataError(const QByteArray& fileId, int httpReturnCode) -{ - Q_UNUSED(fileId); - Q_UNUSED(httpReturnCode); - - qDebug() << "Error deleting the metadata"; -} -void AccountSettings::slotLockForDecryptionError(const QByteArray& fileId, int httpReturnCode) -{ - Q_UNUSED(fileId); - Q_UNUSED(httpReturnCode); - - qDebug() << "Error Locking for decryption"; -} - void AccountSettings::slotEditCurrentIgnoredFiles() { Folder *f = FolderMan::instance()->folder(selectedFolderAlias()); diff --git a/src/gui/accountsettings.h b/src/gui/accountsettings.h index 68ddd01bb..a67994279 100644 --- a/src/gui/accountsettings.h +++ b/src/gui/accountsettings.h @@ -92,7 +92,6 @@ protected slots: void slotOpenAccountWizard(); void refreshSelectiveSyncStatus(); void slotMarkSubfolderEncrypted(const FolderStatusModel::SubFolderInfo* folderInfo); - void slotMarkSubfolderDecrypted(const FolderStatusModel::SubFolderInfo* folderInfo); void slotSubfolderContextMenuRequested(const QModelIndex& idx, const QPoint& point); void slotCustomContextMenuRequested(const QPoint &); void slotFolderListClicked(const QModelIndex &indx); @@ -102,25 +101,7 @@ protected slots: // Encryption Related Stuff. void slotShowMnemonic(const QString &mnemonic); void slotNewMnemonicGenerated(); - - void slotEncryptionFlagSuccess(const QByteArray &folderId); - void slotEncryptionFlagError(const QByteArray &folderId, int httpReturnCode); - void slotLockForEncryptionSuccess(const QByteArray& folderId, const QByteArray& token); - void slotLockForEncryptionError(const QByteArray &folderId, int httpReturnCode); - void slotUnlockFolderSuccess(const QByteArray& folderId); - void slotUnlockFolderError(const QByteArray& folderId, int httpReturnCode); - void slotUploadMetadataSuccess(const QByteArray& folderId); - void slotUpdateMetadataError(const QByteArray& folderId, int httpReturnCode); - - // Remove Encryption Bit. - void slotLockForDecryptionSuccess(const QByteArray& folderId, const QByteArray& token); - void slotLockForDecryptionError(const QByteArray& folderId, int httpReturnCode); - void slotDeleteMetadataSuccess(const QByteArray& folderId); - void slotDeleteMetadataError(const QByteArray& folderId, int httpReturnCode); - void slotUnlockForDecryptionSuccess(const QByteArray& folderId); - void slotUnlockForDecryptionError(const QByteArray& folderId, int httpReturnCode); - void slotDecryptionFlagSuccess(const QByteArray& folderId); - void slotDecryptionFlagError(const QByteArray& folderId, int httpReturnCode); + void slotEncryptFolderFinished(int status); private: void showConnectionLabel(const QString &message, diff --git a/src/libsync/CMakeLists.txt b/src/libsync/CMakeLists.txt index ac3e99bd4..146e0910a 100644 --- a/src/libsync/CMakeLists.txt +++ b/src/libsync/CMakeLists.txt @@ -27,6 +27,7 @@ set(libsync_SRCS clientproxy.cpp cookiejar.cpp discoveryphase.cpp + encryptfolderjob.cpp filesystem.cpp logger.cpp accessmanager.cpp diff --git a/src/libsync/encryptfolderjob.cpp b/src/libsync/encryptfolderjob.cpp new file mode 100644 index 000000000..6d8bf5e9f --- /dev/null +++ b/src/libsync/encryptfolderjob.cpp @@ -0,0 +1,127 @@ +/* + * Copyright (C) by Kevin Ottens + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +#include "encryptfolderjob.h" + +#include "clientsideencryptionjobs.h" + +#include + +namespace OCC { + +Q_LOGGING_CATEGORY(lcEncryptFolderJob, "nextcloud.sync.propagator.encryptfolder", QtInfoMsg) + +EncryptFolderJob::EncryptFolderJob(const AccountPtr &account, const QString &path, const QByteArray &fileId, QObject *parent) + : QObject(parent) + , _account(account) + , _path(path) + , _fileId(fileId) +{ +} + +void EncryptFolderJob::start() +{ + auto job = new OCC::SetEncryptionFlagApiJob(_account, _fileId, this); + connect(job, &OCC::SetEncryptionFlagApiJob::success, this, &EncryptFolderJob::slotEncryptionFlagSuccess); + connect(job, &OCC::SetEncryptionFlagApiJob::error, this, &EncryptFolderJob::slotEncryptionFlagError); + job->start(); +} + +QString EncryptFolderJob::errorString() const +{ + return _errorString; +} + +void EncryptFolderJob::slotEncryptionFlagSuccess(const QByteArray &fileId) +{ + _account->e2e()->setFolderEncryptedStatus(_path, true); + + auto lockJob = new LockEncryptFolderApiJob(_account, fileId, this); + connect(lockJob, &LockEncryptFolderApiJob::success, + this, &EncryptFolderJob::slotLockForEncryptionSuccess); + connect(lockJob, &LockEncryptFolderApiJob::error, + this, &EncryptFolderJob::slotLockForEncryptionError); + lockJob->start(); +} + +void EncryptFolderJob::slotEncryptionFlagError(const QByteArray &fileId, int httpErrorCode) +{ + qDebug() << "Error on the encryption flag of" << fileId << "HTTP code:" << httpErrorCode; + emit finished(Error); +} + +void EncryptFolderJob::slotLockForEncryptionSuccess(const QByteArray &fileId, const QByteArray &token) +{ + _account->e2e()->setTokenForFolder(fileId, token); + + FolderMetadata emptyMetadata(_account); + auto encryptedMetadata = emptyMetadata.encryptedMetadata(); + if (encryptedMetadata.isEmpty()) { + //TODO: Mark the folder as unencrypted as the metadata generation failed. + _errorString = tr("Could not generate the metadata for encryption, Unlocking the folder. \n" + "This can be an issue with your OpenSSL libraries."); + emit finished(Error); + return; + } + + auto storeMetadataJob = new StoreMetaDataApiJob(_account, fileId, emptyMetadata.encryptedMetadata(), this); + connect(storeMetadataJob, &StoreMetaDataApiJob::success, + this, &EncryptFolderJob::slotUploadMetadataSuccess); + connect(storeMetadataJob, &StoreMetaDataApiJob::error, + this, &EncryptFolderJob::slotUpdateMetadataError); + storeMetadataJob->start(); +} + +void EncryptFolderJob::slotUploadMetadataSuccess(const QByteArray &folderId) +{ + const auto token = _account->e2e()->tokenForFolder(folderId); + auto unlockJob = new UnlockEncryptFolderApiJob(_account, folderId, token, this); + connect(unlockJob, &UnlockEncryptFolderApiJob::success, + this, &EncryptFolderJob::slotUnlockFolderSuccess); + connect(unlockJob, &UnlockEncryptFolderApiJob::error, + this, &EncryptFolderJob::slotUnlockFolderError); + unlockJob->start(); +} + +void EncryptFolderJob::slotUpdateMetadataError(const QByteArray &folderId, int httpReturnCode) +{ + Q_UNUSED(httpReturnCode); + + const auto token = _account->e2e()->tokenForFolder(folderId); + auto unlockJob = new UnlockEncryptFolderApiJob(_account, folderId, token, this); + connect(unlockJob, &UnlockEncryptFolderApiJob::success, + this, &EncryptFolderJob::slotUnlockFolderSuccess); + connect(unlockJob, &UnlockEncryptFolderApiJob::error, + this, &EncryptFolderJob::slotUnlockFolderError); + unlockJob->start(); +} + +void EncryptFolderJob::slotLockForEncryptionError(const QByteArray &fileId, int httpErrorCode) +{ + qCInfo(lcEncryptFolderJob()) << "Locking error for" << fileId << "HTTP code:" << httpErrorCode; + emit finished(Error); +} + +void EncryptFolderJob::slotUnlockFolderError(const QByteArray &fileId, int httpErrorCode) +{ + qCInfo(lcEncryptFolderJob()) << "Unlocking error for" << fileId << "HTTP code:" << httpErrorCode; + emit finished(Error); +} +void EncryptFolderJob::slotUnlockFolderSuccess(const QByteArray &fileId) +{ + qCInfo(lcEncryptFolderJob()) << "Unlocking success for" << fileId; + emit finished(Success); +} + +} diff --git a/src/libsync/encryptfolderjob.h b/src/libsync/encryptfolderjob.h new file mode 100644 index 000000000..142e25345 --- /dev/null +++ b/src/libsync/encryptfolderjob.h @@ -0,0 +1,56 @@ +/* + * Copyright (C) by Kevin Ottens + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ +#pragma once + +#include + +#include "account.h" + +namespace OCC { + +class OWNCLOUDSYNC_EXPORT EncryptFolderJob : public QObject +{ + Q_OBJECT +public: + enum Status { + Success = 0, + Error, + }; + Q_ENUM(Status) + + explicit EncryptFolderJob(const AccountPtr &account, const QString &path, const QByteArray &fileId, QObject *parent = nullptr); + void start(); + + QString errorString() const; + +signals: + void finished(int status); + +private slots: + void slotEncryptionFlagSuccess(const QByteArray &folderId); + void slotEncryptionFlagError(const QByteArray &folderId, int httpReturnCode); + void slotLockForEncryptionSuccess(const QByteArray &folderId, const QByteArray &token); + void slotLockForEncryptionError(const QByteArray &folderId, int httpReturnCode); + void slotUnlockFolderSuccess(const QByteArray &folderId); + void slotUnlockFolderError(const QByteArray &folderId, int httpReturnCode); + void slotUploadMetadataSuccess(const QByteArray &folderId); + void slotUpdateMetadataError(const QByteArray &folderId, int httpReturnCode); + +private: + AccountPtr _account; + QString _path; + QByteArray _fileId; + QString _errorString; +}; +}