fix: refresh Security Seed before replication

Reason:
- A client that remains open during a remote database rebuild can retain the previous Security Seed and upload documents encrypted with the wrong key.

Changes:
- Fetch the remote Security Seed at every replication preflight instead of reusing the process cache.
- Add a regression test and an unreleased change note for issue #1018.
This commit is contained in:
Ouyang Xingyuan
2026-07-14 18:15:40 +08:00
parent 056d89aa4d
commit 45657ba39c
3 changed files with 54 additions and 1 deletions
@@ -0,0 +1,48 @@
import { describe, expect, it, vi } from "vitest";
import { ModuleReplicator } from "./ModuleReplicator";
describe("ModuleReplicator", () => {
it("refreshes the remote Security Seed before replication", async () => {
const ensurePBKDF2Salt = vi.fn(async () => true);
let beforeReplicate: ((showMessage: boolean) => Promise<boolean>) | undefined;
const addHandler = vi.fn((handler: (showMessage: boolean) => Promise<boolean>, priority?: number) => {
if (priority === 20) {
beforeReplicate = handler;
}
});
const services = {
API: { isOnline: true },
replicator: {
onReplicatorInitialised: { addHandler: vi.fn() },
getActiveReplicator: () => ({ ensurePBKDF2Salt }),
},
setting: { currentSettings: () => ({}) },
databaseEvents: { onDatabaseInitialised: { addHandler: vi.fn() } },
appLifecycle: { onSettingLoaded: { addHandler: vi.fn() } },
replication: {
parseSynchroniseResult: { addHandler: vi.fn() },
onBeforeReplicate: { addHandler },
onReplicationFailed: { addHandler: vi.fn() },
},
};
const module = {
_unresolvedErrorManager: {
showError: vi.fn(),
clearError: vi.fn(),
},
_onReplicatorInitialised: vi.fn(),
_everyOnDatabaseInitialized: vi.fn(),
_everyOnloadAfterLoadSettings: vi.fn(),
_parseReplicationResult: vi.fn(),
_everyBeforeReplicate: vi.fn(),
onReplicationFailed: vi.fn(),
};
ModuleReplicator.prototype.onBindFunction.call(module, {} as never, services as never);
expect(beforeReplicate).toBeDefined();
await beforeReplicate!(false);
expect(ensurePBKDF2Salt).toHaveBeenCalledWith({}, false, false);
});
});