-
Notifications
You must be signed in to change notification settings - Fork 935
E2EE Desync folders on restart of application, computer or logout and back in to user account #9653
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
Caffe1neAdd1ct
wants to merge
17
commits into
nextcloud:master
Choose a base branch
from
Caffe1neAdd1ct:bugfix/gh-9345-e2e-accountsettings
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from 11 commits
Commits
Show all changes
17 commits
Select commit
Hold shift + click to select a range
d204214
feat(gh-9345): add E2E initialization state tracking
Caffe1neAdd1ct 0a9e82e
fix(gh-9345): prevent E2E folders from being blacklisted during startup
Caffe1neAdd1ct b64a9ed
fix(gh-9345): clear E2E restoration list on encryption reset
Caffe1neAdd1ct 30ea5ff
fix(gh-9345): ensure E2E state correctly transitions to Initialized
Caffe1neAdd1ct 4e8b46e
fix(gh-9345): defer E2E folders during initialization, distinguish fr…
Caffe1neAdd1ct 3b3847c
feat(gh-9345): add E2EFolderManager bridge for startup restoration
Caffe1neAdd1ct 66cca74
test(gh-9345): add E2EFolderManager tests and improve folder restorat…
Caffe1neAdd1ct 44623ac
fix(gh-9345): address all review feedback from PR 9379
Caffe1neAdd1ct 3ef9a14
fix(gh-9345): address PR feedback, clean test logs, handle capability…
Caffe1neAdd1ct 89e89d4
fix(gh-9345): clean up comments
Caffe1neAdd1ct 9067ac9
fix(gh-9345): remove maybe_unused and improved qverify asserts
Caffe1neAdd1ct 743aeb4
refactor(gh-9345): consolidate initialization state management
Caffe1neAdd1ct 6186298
fix(gh-9345): enhance E2E folder restoration tests and improve blackl…
Caffe1neAdd1ct 4321f21
fix(gh-9345): set initialization state to failed on unsuccessful init…
Caffe1neAdd1ct ed5abe1
fix(gh-9345): improve E2E folder restoration by handling sync termina…
Caffe1neAdd1ct b554564
fix(gh-9345): add initialization logging for E2E folder manager tests
Caffe1neAdd1ct 2c96643
Merge branch 'master' into bugfix/gh-9345-e2e-accountsettings
Caffe1neAdd1ct File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Some comments aren't visible on the classic Files Changed page.
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,139 @@ | ||
| // SPDX-FileCopyrightText: 2026 Nextcloud GmbH and Nextcloud contributors | ||
| // SPDX-License-Identifier: GPL-2.0-or-later | ||
|
|
||
| #include "e2eefoldermanager.h" | ||
| #include "accountmanager.h" | ||
| #include "clientsideencryption.h" | ||
| #include "folderman.h" | ||
| #include "folder.h" | ||
|
|
||
| #include <QLoggingCategory> | ||
|
|
||
| namespace OCC { | ||
|
|
||
| Q_LOGGING_CATEGORY(lcE2eFolderManager, "nextcloud.gui.e2efoldermanager", QtInfoMsg) | ||
|
|
||
| E2EFolderManager *E2EFolderManager::_instance = nullptr; | ||
|
|
||
| E2EFolderManager *E2EFolderManager::instance() | ||
| { | ||
| if (!_instance) { | ||
| _instance = new E2EFolderManager(); | ||
| } | ||
| return _instance; | ||
| } | ||
|
|
||
| E2EFolderManager::E2EFolderManager(QObject *parent) | ||
| : QObject(parent) | ||
| { | ||
| const auto accounts = AccountManager::instance()->accounts(); | ||
| for (const auto &accountState : accounts) { | ||
| if (accountState && accountState->account() && accountState->account()->e2e()) { | ||
| connectE2eSignals(accountState->account()); | ||
| } | ||
| } | ||
|
|
||
| connect(AccountManager::instance(), &AccountManager::accountAdded, | ||
| this, &E2EFolderManager::slotAccountAdded); | ||
| } | ||
|
|
||
| E2EFolderManager::~E2EFolderManager() | ||
| { | ||
| _instance = nullptr; | ||
| } | ||
|
|
||
| void E2EFolderManager::slotAccountAdded(AccountState *accountState) | ||
| { | ||
| if (accountState && accountState->account() && accountState->account()->e2e()) { | ||
| connectE2eSignals(accountState->account()); | ||
| } | ||
| } | ||
|
|
||
| void E2EFolderManager::connectE2eSignals(const AccountPtr &account) | ||
| { | ||
| if (!account || !account->e2e()) { | ||
| return; | ||
| } | ||
|
|
||
| connect(account->e2e(), &ClientSideEncryption::initializationFinished, | ||
| this, &E2EFolderManager::slotE2eInitializationFinished, Qt::UniqueConnection); | ||
|
|
||
| if (account->e2e()->isInitialized()) { | ||
| restoreE2eFoldersForAccount(account); | ||
| } | ||
| } | ||
|
|
||
| void E2EFolderManager::slotE2eInitializationFinished() | ||
| { | ||
| qCDebug(lcE2eFolderManager) << "E2E initialization finished, restoring blacklisted E2E folders"; | ||
|
|
||
| auto *e2e = qobject_cast<ClientSideEncryption *>(sender()); | ||
| if (!e2e) { | ||
| qCWarning(lcE2eFolderManager) << "slotE2eInitializationFinished called but sender is not ClientSideEncryption"; | ||
| return; | ||
| } | ||
|
|
||
| const auto accounts = AccountManager::instance()->accounts(); | ||
| for (const auto &accountState : accounts) { | ||
| if (accountState->account()->e2e() == e2e) { | ||
| restoreE2eFoldersForAccount(accountState->account()); | ||
| break; | ||
| } | ||
| } | ||
| } | ||
|
|
||
| void E2EFolderManager::restoreE2eFoldersForAccount(const AccountPtr &account) | ||
| { | ||
| if (!account || !account->e2e() || !account->e2e()->isInitialized()) { | ||
| qCDebug(lcE2eFolderManager) << "Cannot restore folders - account or E2E not ready"; | ||
| return; | ||
| } | ||
|
|
||
| qCDebug(lcE2eFolderManager) << "Restoring E2E folders for account:" << account->displayName(); | ||
|
|
||
| auto *folderMan = FolderMan::instance(); | ||
| const auto folders = folderMan->map(); | ||
|
|
||
| int foldersProcessed = 0; | ||
| for (const auto &folder : folders) { | ||
| if (folder->accountState()->account() != account) { | ||
| continue; | ||
| } | ||
|
|
||
| bool ok = false; | ||
| const auto foldersToRemoveFromBlacklist = folder->journalDb()->getSelectiveSyncList( | ||
| SyncJournalDb::SelectiveSyncE2eFoldersToRemoveFromBlacklist, &ok); | ||
|
|
||
| if (foldersToRemoveFromBlacklist.isEmpty()) { | ||
| continue; | ||
| } | ||
|
|
||
| qCDebug(lcE2eFolderManager) << "Found E2E folders to restore for" << folder->alias() | ||
| << ":" << foldersToRemoveFromBlacklist; | ||
|
|
||
| auto blackList = folder->journalDb()->getSelectiveSyncList(SyncJournalDb::SelectiveSyncBlackList, &ok); | ||
| qCDebug(lcE2eFolderManager) << "Current blacklist:" << blackList; | ||
|
|
||
| for (const auto &pathToRemoveFromBlackList : foldersToRemoveFromBlacklist) { | ||
| blackList.removeAll(pathToRemoveFromBlackList); | ||
| } | ||
|
|
||
| folder->journalDb()->setSelectiveSyncList(SyncJournalDb::SelectiveSyncBlackList, blackList); | ||
| folder->journalDb()->setSelectiveSyncList(SyncJournalDb::SelectiveSyncE2eFoldersToRemoveFromBlacklist, {}); | ||
|
|
||
| for (const auto &pathToRemoteDiscover : foldersToRemoveFromBlacklist) { | ||
| folder->journalDb()->schedulePathForRemoteDiscovery(pathToRemoteDiscover); | ||
| } | ||
|
|
||
| folderMan->scheduleFolder(folder); | ||
| ++foldersProcessed; | ||
| } | ||
|
|
||
| if (foldersProcessed > 0) { | ||
| qCDebug(lcE2eFolderManager) << "Restored E2E folders for" << foldersProcessed << "sync folders"; | ||
| } else { | ||
| qCDebug(lcE2eFolderManager) << "No E2E folders needed restoration"; | ||
| } | ||
| } | ||
|
|
||
| } // namespace OCC |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,43 @@ | ||
| // SPDX-FileCopyrightText: 2026 Nextcloud GmbH and Nextcloud contributors | ||
| // SPDX-License-Identifier: GPL-2.0-or-later | ||
|
|
||
| #pragma once | ||
|
|
||
| #include <QObject> | ||
| #include "account.h" | ||
| #include "accountmanager.h" | ||
|
|
||
| namespace OCC { | ||
|
|
||
| /** | ||
| * @brief Stateless bridge between E2E encryption and folder management | ||
| * | ||
| * This class acts as a mediator that: | ||
| * - Listens to E2E initialization signals from all accounts | ||
| * - Coordinates folder restoration when E2E becomes ready | ||
| * - Keeps E2E concerns separate from FolderMan's core responsibilities | ||
| * | ||
| * @ingroup gui | ||
| */ | ||
| class E2EFolderManager : public QObject | ||
| { | ||
| Q_OBJECT | ||
|
|
||
| public: | ||
| static E2EFolderManager *instance(); | ||
| ~E2EFolderManager() override; | ||
|
|
||
| private slots: | ||
| void slotE2eInitializationFinished(); | ||
| void slotAccountAdded(AccountState *accountState); | ||
|
|
||
| private: | ||
| E2EFolderManager(QObject *parent = nullptr); | ||
|
|
||
| void connectE2eSignals(const AccountPtr &account); | ||
| void restoreE2eFoldersForAccount(const AccountPtr &account); | ||
|
|
||
| static E2EFolderManager *_instance; | ||
| }; | ||
|
|
||
| } // namespace OCC |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.