Move the encrypt folder logic in a reusable job class
authorKevin Ottens <kevin.ottens@nextcloud.com>
Wed, 17 Jun 2020 17:08:59 +0000 (19:08 +0200)
committerKevin Ottens <kevin.ottens@nextcloud.com>
Tue, 30 Jun 2020 09:29:08 +0000 (11:29 +0200)
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 <kevin.ottens@nextcloud.com>
src/gui/accountsettings.cpp
src/gui/accountsettings.h
src/libsync/CMakeLists.txt
src/libsync/encryptfolderjob.cpp [new file with mode: 0644]
src/libsync/encryptfolderjob.h [new file with mode: 0644]

index db94e9048f4e7b9118d910835f57e4364a52eb48..59452288529e3877a5d5e5862d8da34264b8bb9d 100644 (file)
@@ -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<EncryptFolderJob*>(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());
index 68ddd01bb5eb453b47a5942c17fcdff8fe96d12a..a67994279dc26035ecb22e20eaee3ad7c9e5b352 100644 (file)
@@ -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,
index ac3e99bd4eb172ccc8b4827088a2f791cb4d7b43..146e0910ab1b014f4b4972ce356303f4659b86c2 100644 (file)
@@ -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 (file)
index 0000000..6d8bf5e
--- /dev/null
@@ -0,0 +1,127 @@
+/*
+ * Copyright (C) by Kevin Ottens <kevin.ottens@nextcloud.com>
+ *
+ * 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 <QLoggingCategory>
+
+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 (file)
index 0000000..142e253
--- /dev/null
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) by Kevin Ottens <kevin.ottens@nextcloud.com>
+ *
+ * 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 <QObject>
+
+#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;
+};
+}