[network/ruqola] src: Add pending feature
Laurent Montel <[email protected]>
| Newsgroups | gmane.comp.kde.cvs |
|---|---|
| Message-ID | <[email protected]> |
Git commit 0e5fff9efa17b0e4f360326e8d5104ccaff84ed3 by Laurent Montel.
Committed on 03/08/2026 at 06:14.
Pushed by mlaurent into branch 'master'.
Add pending feature
M +3 -0 src/core/autotests/e2ekeymanagertest.cpp
M +10 -1 src/core/encryption/e2ekeymanager.cpp
M +2 -0 src/core/encryption/e2ekeymanager.h
M +13 -0 src/core/rocketchataccount.cpp
M +2 -0 src/core/rocketchataccount.h
M +3 -3 src/widgets/room/roomwidget.cpp
https://invent.kde.org/network/ruqola/-/commit/0e5fff9efa17b0e4f360326e8d5104ccaff84ed3
diff --git a/src/core/autotests/e2ekeymanagertest.cpp b/src/core/autotests/e2ekeymanagertest.cpp
index e4649899b7..4e44ff5f5b 100644
--- a/src/core/autotests/e2ekeymanagertest.cpp
+++ b/src/core/autotests/e2ekeymanagertest.cpp
@@ -32,6 +32,7 @@ void E2eKeyManagerTest::shouldHaveDefaultValues()
E2eKeyManager m(nullptr);
QCOMPARE(m.status(), E2eKeyManager::Status::Unknown);
QVERIFY(!m.keySaved());
+ QVERIFY(!m.hasPendingUploadFailure());
}
void E2eKeyManagerTest::shouldEmitDecodeSignalOnlyWhenNeeded()
@@ -171,11 +172,13 @@ void E2eKeyManagerTest::shouldKeepGenerationStateAndAllowRetryWhenUploadFails()
manager.verifyExistingKeyForTest(QJsonObject{});
QCOMPARE(manager.status(), E2eKeyManager::Status::NeedToGenerateKey);
QCOMPARE(uploadFailedSpy.count(), 1);
+ QVERIFY(manager.hasPendingUploadFailure());
// Retry should attempt another upload with the same pending generated key data.
QVERIFY(!manager.retryUploadGeneratedKey());
QCOMPARE(manager.status(), E2eKeyManager::Status::NeedToGenerateKey);
QCOMPARE(uploadFailedSpy.count(), 2);
+ QVERIFY(manager.hasPendingUploadFailure());
QVERIFY(account.localDatabaseManager()->e2EDatabase()->deleteKey(u"test-e2e-user-upload-retry"_s));
#endif
diff --git a/src/core/encryption/e2ekeymanager.cpp b/src/core/encryption/e2ekeymanager.cpp
index 33059b2615..f40138257f 100644
--- a/src/core/encryption/e2ekeymanager.cpp
+++ b/src/core/encryption/e2ekeymanager.cpp
@@ -106,7 +106,7 @@ void E2eKeyManager::postponeDecryption()
bool E2eKeyManager::retryUploadGeneratedKey()
{
#if USE_E2E_SUPPORT
- if (!mAccount || mPendingUploadPublicKey.isEmpty() || mPendingUploadPrivateKey.isEmpty()) {
+ if (!mAccount || !mPendingUploadFailed || mPendingUploadPublicKey.isEmpty() || mPendingUploadPrivateKey.isEmpty()) {
return false;
}
@@ -117,6 +117,11 @@ bool E2eKeyManager::retryUploadGeneratedKey()
#endif
}
+bool E2eKeyManager::hasPendingUploadFailure() const
+{
+ return mPendingUploadFailed;
+}
+
QString E2eKeyManager::generateRandomPassword() const
{
#if USE_E2E_SUPPORT
@@ -236,6 +241,7 @@ bool E2eKeyManager::startUploadGeneratedKey(const QByteArray &publicKey, const Q
mPendingUploadPublicKey = publicKey;
mPendingUploadPrivateKey = encryptedPrivateKey;
+ mPendingUploadFailed = false;
auto setJob = new RocketChatRestApi::SetUserPublicAndPrivateKeysJob(this);
mAccount->restApi()->initializeRestApiJob(setJob);
@@ -246,15 +252,18 @@ bool E2eKeyManager::startUploadGeneratedKey(const QByteArray &publicKey, const Q
setJob->setSetUserPublicAndPrivateKeysInfo(info);
connect(setJob, &RocketChatRestApi::SetUserPublicAndPrivateKeysJob::setUserPublicAndPrivateKeysDone, this, [this]() {
+ mPendingUploadFailed = false;
Q_EMIT uploadEncryptionKeyDone();
});
connect(setJob, &RocketChatRestApi::RestApiAbstractJob::failed, this, [this](const QString &, const QString &) {
+ mPendingUploadFailed = true;
setStatus(Status::NeedToGenerateKey);
Q_EMIT uploadEncryptionKeyFailed();
});
if (!setJob->start()) {
qCWarning(RUQOLA_ENCRYPTION_LOG) << "Unable to upload generated E2E keypair";
+ mPendingUploadFailed = true;
setStatus(Status::NeedToGenerateKey);
Q_EMIT uploadEncryptionKeyFailed();
return false;
diff --git a/src/core/encryption/e2ekeymanager.h b/src/core/encryption/e2ekeymanager.h
index 674c6e16bd..bc3bc965bb 100644
--- a/src/core/encryption/e2ekeymanager.h
+++ b/src/core/encryption/e2ekeymanager.h
@@ -28,6 +28,7 @@ public:
[[nodiscard]] bool decodeEncryptionKey(const QString &password);
void postponeDecryption();
[[nodiscard]] bool retryUploadGeneratedKey();
+ [[nodiscard]] bool hasPendingUploadFailure() const;
void fetchMyKeys();
@@ -60,5 +61,6 @@ private:
QByteArray mDecodedPrivateKey;
QByteArray mPendingUploadPublicKey;
QByteArray mPendingUploadPrivateKey;
+ bool mPendingUploadFailed = false;
RocketChatAccount *const mAccount;
};
diff --git a/src/core/rocketchataccount.cpp b/src/core/rocketchataccount.cpp
index d035639bd9..9f2c43f7d1 100644
--- a/src/core/rocketchataccount.cpp
+++ b/src/core/rocketchataccount.cpp
@@ -305,6 +305,8 @@ RocketChatAccount::RocketChatAccount(const QString &accountFileName, QObject *pa
connect(mE2eKeyManager, &E2eKeyManager::decodeEncryptionKeyDone, this, &RocketChatAccount::slotE2eDecodeKeyDone);
connect(mE2eKeyManager, &E2eKeyManager::failedDecodeEncryptionKey, this, &RocketChatAccount::slotE2eDecodeKeyFailed);
connect(mE2eKeyManager, &E2eKeyManager::decodeEncryptionKeyPostponed, this, &RocketChatAccount::slotE2eDecodeKeyPostponed);
+ connect(mE2eKeyManager, &E2eKeyManager::uploadEncryptionKeyDone, this, &RocketChatAccount::slotE2eUploadKeyDone);
+ connect(mE2eKeyManager, &E2eKeyManager::uploadEncryptionKeyFailed, this, &RocketChatAccount::slotE2eUploadKeyFailed);
connect(mMemoryManager, &MemoryManager::clearApplicationSettingsModelRequested, mAppsMarketPlaceModel, &AppsMarketPlaceModel::clear);
connect(mMemoryManager, &MemoryManager::cleanRoomHistoryRequested, mRoomModel, &RoomModel::cleanRoomHistory);
@@ -3358,6 +3360,17 @@ void RocketChatAccount::slotE2eDecodeKeyPostponed()
setE2EPasswordMustBeDecrypt(true);
}
+void RocketChatAccount::slotE2eUploadKeyDone()
+{
+ setE2EPasswordMustBeSave(false);
+}
+
+void RocketChatAccount::slotE2eUploadKeyFailed()
+{
+ setE2EPasswordMustBeSave(true);
+ Q_EMIT needToSaveE2EPassword();
+}
+
MemoryManager *RocketChatAccount::memoryManager() const
{
return mMemoryManager;
diff --git a/src/core/rocketchataccount.h b/src/core/rocketchataccount.h
index 529d25f0e8..bc1628846b 100644
--- a/src/core/rocketchataccount.h
+++ b/src/core/rocketchataccount.h
@@ -598,6 +598,8 @@ private:
LIBRUQOLACORE_NO_EXPORT void slotE2eDecodeKeyDone();
LIBRUQOLACORE_NO_EXPORT void slotE2eDecodeKeyFailed();
LIBRUQOLACORE_NO_EXPORT void slotE2eDecodeKeyPostponed();
+ LIBRUQOLACORE_NO_EXPORT void slotE2eUploadKeyDone();
+ LIBRUQOLACORE_NO_EXPORT void slotE2eUploadKeyFailed();
LIBRUQOLACORE_NO_EXPORT void slotDDpLoginStatusChanged();
LIBRUQOLACORE_NO_EXPORT void slotRESTLoginStatusChanged();
LIBRUQOLACORE_NO_EXPORT void slotRoomOpenChanged(const QByteArray &rid);
diff --git a/src/widgets/room/roomwidget.cpp b/src/widgets/room/roomwidget.cpp
index 2e1f3421cc..9786133fbe 100644
--- a/src/widgets/room/roomwidget.cpp
+++ b/src/widgets/room/roomwidget.cpp
@@ -294,9 +294,9 @@ void RoomWidget::slotGenerateNewPassword()
QPointer<E2eCopyPasswordDialog> dlg = new E2eCopyPasswordDialog(mCurrentRocketChatAccount, this);
if (dlg->exec()) {
mCurrentRocketChatAccount->settings()->setKeySaved(true);
- // Retry upload in case the initial key publication failed (e.g. temporary network/server issue).
- if (!mCurrentRocketChatAccount->e2eKeyManager()->retryUploadGeneratedKey()) {
- qCWarning(RUQOLAWIDGETS_LOG) << "Unable to retry uploading generated E2E key";
+ // Retry only after an actual upload failure, otherwise this is a no-op that creates noise.
+ if (mCurrentRocketChatAccount->e2eKeyManager()->hasPendingUploadFailure() && !mCurrentRocketChatAccount->e2eKeyManager()->retryUploadGeneratedKey()) {
+ qCWarning(RUQOLAWIDGETS_LOG) << "Unable to retry failed upload of generated E2E key";
}
// TODO save it in kwalletmanagers ?
}