diff --git a/src/modules/features/SettingDialogue/PaneRemoteConfig.ts b/src/modules/features/SettingDialogue/PaneRemoteConfig.ts index 6c4b21e..e609e39 100644 --- a/src/modules/features/SettingDialogue/PaneRemoteConfig.ts +++ b/src/modules/features/SettingDialogue/PaneRemoteConfig.ts @@ -32,6 +32,7 @@ import SetupRemote from "../SetupWizard/dialogs/SetupRemote.svelte"; import SetupRemoteCouchDB from "../SetupWizard/dialogs/SetupRemoteCouchDB.svelte"; import SetupRemoteBucket from "../SetupWizard/dialogs/SetupRemoteBucket.svelte"; import SetupRemoteP2P from "../SetupWizard/dialogs/SetupRemoteP2P.svelte"; +import { syncActivatedRemoteSettings } from "./remoteConfigBuffer.ts"; function getSettingsFromEditingSettings(editingSettings: AllSettings): ObsidianLiveSyncSettings { const workObj = { ...editingSettings } as ObsidianLiveSyncSettings; @@ -183,6 +184,11 @@ export function paneRemoteConfig( }, true); if (synchroniseActiveRemote) { + // Keep both buffers aligned with the newly activated remote before saving any remaining dirty keys. + syncActivatedRemoteSettings(this.editingSettings, this.core.settings); + if (this.initialSettings) { + syncActivatedRemoteSettings(this.initialSettings, this.core.settings); + } await this.saveAllDirtySettings(); } diff --git a/src/modules/features/SettingDialogue/remoteConfigBuffer.ts b/src/modules/features/SettingDialogue/remoteConfigBuffer.ts new file mode 100644 index 0000000..be23e0d --- /dev/null +++ b/src/modules/features/SettingDialogue/remoteConfigBuffer.ts @@ -0,0 +1,17 @@ +import { pickBucketSyncSettings, pickCouchDBSyncSettings, pickP2PSyncSettings } from "@lib/common/utils.ts"; +import type { ObsidianLiveSyncSettings } from "@lib/common/types.ts"; + +// Keep the setting dialogue buffer aligned with the current core settings before persisting other dirty keys. +// This also clears stale dirty values left from editing a different remote type before switching active remotes. +export function syncActivatedRemoteSettings( + target: Partial, + source: ObsidianLiveSyncSettings +): void { + Object.assign(target, { + remoteType: source.remoteType, + activeConfigurationId: source.activeConfigurationId, + ...pickBucketSyncSettings(source), + ...pickCouchDBSyncSettings(source), + ...pickP2PSyncSettings(source), + }); +} diff --git a/src/modules/features/SettingDialogue/remoteConfigBuffer.unit.spec.ts b/src/modules/features/SettingDialogue/remoteConfigBuffer.unit.spec.ts new file mode 100644 index 0000000..224c7ce --- /dev/null +++ b/src/modules/features/SettingDialogue/remoteConfigBuffer.unit.spec.ts @@ -0,0 +1,83 @@ +import { describe, expect, it } from "vitest"; +import { DEFAULT_SETTINGS, REMOTE_COUCHDB, REMOTE_MINIO } from "../../../lib/src/common/types"; +import { syncActivatedRemoteSettings } from "./remoteConfigBuffer"; + +describe("syncActivatedRemoteSettings", () => { + it("should copy active MinIO credentials into the editing buffer", () => { + const target = { + ...DEFAULT_SETTINGS, + remoteType: REMOTE_COUCHDB, + activeConfigurationId: "old-remote", + accessKey: "", + secretKey: "", + endpoint: "", + bucket: "", + region: "", + encrypt: true, + }; + const source = { + ...DEFAULT_SETTINGS, + remoteType: REMOTE_MINIO, + activeConfigurationId: "remote-s3", + accessKey: "access", + secretKey: "secret", + endpoint: "https://minio.example.test", + bucket: "vault", + region: "sz-hq", + bucketPrefix: "folder/", + useCustomRequestHandler: false, + forcePathStyle: true, + bucketCustomHeaders: "", + }; + + syncActivatedRemoteSettings(target, source); + + expect(target.remoteType).toBe(REMOTE_MINIO); + expect(target.activeConfigurationId).toBe("remote-s3"); + expect(target.accessKey).toBe("access"); + expect(target.secretKey).toBe("secret"); + expect(target.endpoint).toBe("https://minio.example.test"); + expect(target.bucket).toBe("vault"); + expect(target.region).toBe("sz-hq"); + expect(target.bucketPrefix).toBe("folder/"); + expect(target.encrypt).toBe(true); + }); + + it("should clear stale dirty values from a different remote type", () => { + const target = { + ...DEFAULT_SETTINGS, + remoteType: REMOTE_MINIO, + activeConfigurationId: "remote-s3", + accessKey: "access", + secretKey: "secret", + endpoint: "https://minio.example.test", + bucket: "vault", + region: "sz-hq", + couchDB_URI: "https://edited.invalid", + couchDB_USER: "edited-user", + couchDB_PASSWORD: "edited-pass", + couchDB_DBNAME: "edited-db", + }; + const source = { + ...DEFAULT_SETTINGS, + remoteType: REMOTE_MINIO, + activeConfigurationId: "remote-s3", + accessKey: "access", + secretKey: "secret", + endpoint: "https://minio.example.test", + bucket: "vault", + region: "sz-hq", + couchDB_URI: "https://current.example.test", + couchDB_USER: "current-user", + couchDB_PASSWORD: "current-pass", + couchDB_DBNAME: "current-db", + }; + + syncActivatedRemoteSettings(target, source); + + expect(target.couchDB_URI).toBe("https://current.example.test"); + expect(target.couchDB_USER).toBe("current-user"); + expect(target.couchDB_PASSWORD).toBe("current-pass"); + expect(target.couchDB_DBNAME).toBe("current-db"); + }); +}); diff --git a/updates.md b/updates.md index 208a73a..24634a3 100644 --- a/updates.md +++ b/updates.md @@ -3,6 +3,12 @@ Since 19th July, 2025 (beta1 in 0.25.0-beta1, 13th July, 2025) The head note of 0.25 is now in [updates_old.md](https://github.com/vrtmrz/obsidian-livesync/blob/main/updates_old.md). Because 0.25 got a lot of updates, thankfully, compatibility is kept and we do not need breaking changes! In other words, when get enough stabled. The next version will be v1.0.0. Even though it my hope. +## unreleased + +### Fixed + +- No longer credentials are broken during object storage configuration (related: #852). + ## 0.25.57 9th April, 2026