From 2c35f45765307c26ac7c5d61ca22ce6dc01f3b2d Mon Sep 17 00:00:00 2001 From: Zeedif Date: Wed, 26 Aug 2026 20:45:44 -0600 Subject: [PATCH] =?UTF-8?q?fix(setup-wizard):=20address=20review=20?= =?UTF-8?q?=E2=80=94=20icon,=20CSS=20scope,=20E2E=20coverage?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Use a plain emoji glyph for the password visibility toggle instead of embedded SVG paths, matching the same pragmatic approach already used for the browser build's menu icons in this codebase. - Scope the wider label width to the E2EE dialogue instead of changing it for every InputRow in every Svelte dialogue. - Extend the existing CouchDB manual setup E2E workflow to assert the passphrase and Obfuscate Properties fields are hidden until encryption is enabled, then appear, and that the passphrase value survives toggling its visibility. --- .../dialogs/SetupRemoteE2EE.svelte | 158 ++++++++++-------- .../services/LiveSyncUI/DialogHost.svelte | 2 +- .../LiveSyncUI/components/Password.svelte | 35 +--- .../scripts/couchdb-manual-setup-workflow.ts | 38 ++++- 4 files changed, 126 insertions(+), 107 deletions(-) diff --git a/src/modules/features/SetupWizard/dialogs/SetupRemoteE2EE.svelte b/src/modules/features/SetupWizard/dialogs/SetupRemoteE2EE.svelte index 0c6c00a1..7340f31d 100644 --- a/src/modules/features/SetupWizard/dialogs/SetupRemoteE2EE.svelte +++ b/src/modules/features/SetupWizard/dialogs/SetupRemoteE2EE.svelte @@ -48,80 +48,94 @@ } - -{translateMessage("Please configure your end-to-end encryption settings.")} - - - - - {translateMessage( - "Enabling end-to-end encryption ensures that your data is encrypted on your device before being sent to the remote server. This means that even if someone gains access to the server, they won't be able to read your data without the passphrase. Make sure to remember your passphrase, as it will be required to decrypt your data on other devices." - )} -
- {translateMessage( - "Also, please note that if you are using Peer-to-Peer synchronization, this configuration will be used when you switch to other methods and connect to a remote server in the future." - )} -
-{#if encryptionSettings.encrypt} - - +
+ + {translateMessage("Please configure your end-to-end encryption settings.")} + + + + {translateMessage( + "Enabling end-to-end encryption ensures that your data is encrypted on your device before being sent to the remote server. This means that even if someone gains access to the server, they won't be able to read your data without the passphrase. Make sure to remember your passphrase, as it will be required to decrypt your data on other devices." + )} +
+ {translateMessage( + "Also, please note that if you are using Peer-to-Peer synchronization, this configuration will be used when you switch to other methods and connect to a remote server in the future." + )} +
+ {#if encryptionSettings.encrypt} + + + + + {translateMessage( + "This setting must be the same even when connecting to multiple synchronisation destinations." + )} + + + + + + {translateMessage( + "Obfuscating properties (e.g., path of file, size, creation and modification dates) adds an additional layer of security by making it harder to identify the structure and names of your files and folders on the remote server. This helps protect your privacy and makes it more difficult for unauthorized users to infer information about your data." + )} + + {/if} + + + + + + + {translateMessage( + "In most cases, you should stick with the default algorithm (${algorithm}), This setting is only required if you have an existing Vault encrypted in a different format.", + { algorithm: E2EEAlgorithmNames[DEFAULT_SETTINGS.E2EEAlgorithm] } + )} + + + {translateMessage( + "Changing the encryption algorithm will prevent access to any data previously encrypted with a different algorithm. Ensure that all your devices are configured to use the same algorithm to maintain access to your data." + )} + + + - {translateMessage( - "This setting must be the same even when connecting to multiple synchronisation destinations." - )} +

+ {translateMessage( + "Please be aware that the End-to-End Encryption passphrase is not validated until the synchronisation process actually commences. This is a security measure designed to protect your data." + )} +

+

+ {translateMessage( + "Therefore, we ask that you exercise extreme caution when configuring server information manually. If an incorrect passphrase is entered, the data on the server will become corrupted." + )}

+ {translateMessage("Please understand that this is intended behaviour.")} +

- - - - - {translateMessage( - "Obfuscating properties (e.g., path of file, size, creation and modification dates) adds an additional layer of security by making it harder to identify the structure and names of your files and folders on the remote server. This helps protect your privacy and makes it more difficult for unauthorized users to infer information about your data." - )} - -{/if} - - - - - - {translateMessage( - "In most cases, you should stick with the default algorithm (${algorithm}), This setting is only required if you have an existing Vault encrypted in a different format.", - { algorithm: E2EEAlgorithmNames[DEFAULT_SETTINGS.E2EEAlgorithm] } - )} - - - {translateMessage( - "Changing the encryption algorithm will prevent access to any data previously encrypted with a different algorithm. Ensure that all your devices are configured to use the same algorithm to maintain access to your data." - )} - - + + commit()} /> + setResult(TYPE_CANCELLED)} /> + +
- -

- {translateMessage( - "Please be aware that the End-to-End Encryption passphrase is not validated until the synchronisation process actually commences. This is a security measure designed to protect your data." - )} -

-

- {translateMessage( - "Therefore, we ask that you exercise extreme caution when configuring server information manually. If an incorrect passphrase is entered, the data on the server will become corrupted." - )}

- {translateMessage("Please understand that this is intended behaviour.")} -

-
- - - commit()} /> - setResult(TYPE_CANCELLED)} /> - + diff --git a/src/modules/services/LiveSyncUI/DialogHost.svelte b/src/modules/services/LiveSyncUI/DialogHost.svelte index c71c257a..6265c7bf 100644 --- a/src/modules/services/LiveSyncUI/DialogHost.svelte +++ b/src/modules/services/LiveSyncUI/DialogHost.svelte @@ -110,7 +110,7 @@ .dialog-host :global(label > span) { display: block; - min-width: 8em; + width: 8em; } .dialog-host :global(.note), diff --git a/src/modules/services/LiveSyncUI/components/Password.svelte b/src/modules/services/LiveSyncUI/components/Password.svelte index b3be8c80..1a674ee8 100644 --- a/src/modules/services/LiveSyncUI/components/Password.svelte +++ b/src/modules/services/LiveSyncUI/components/Password.svelte @@ -41,37 +41,7 @@ {disabled} onclick={() => (showPassword = !showPassword)} > - {#if showPassword} - - - - - - - {:else} - - - - - {/if} + 👁️ diff --git a/test/e2e-obsidian/scripts/couchdb-manual-setup-workflow.ts b/test/e2e-obsidian/scripts/couchdb-manual-setup-workflow.ts index ef44ae87..fc832bd1 100644 --- a/test/e2e-obsidian/scripts/couchdb-manual-setup-workflow.ts +++ b/test/e2e-obsidian/scripts/couchdb-manual-setup-workflow.ts @@ -117,19 +117,55 @@ async function enterManualCouchDBSettings(port: number, couchDb: CouchDbConfig, const encryption = modalByTitle(page, "End-to-End Encryption"); await encryption.waitFor({ state: "visible", timeout: uiTimeoutMs }); + assertEqual( + await encryption.locator('input[name="e2ee-passphrase"]').count(), + 0, + "The passphrase field was present before end-to-end encryption was enabled." + ); + assertEqual( + await encryption.locator("label.row").filter({ hasText: "Obfuscate Properties" }).count(), + 0, + "The Obfuscate Properties row was present before end-to-end encryption was enabled." + ); await encryption .locator("label.row") .filter({ hasText: "End-to-End Encryption" }) .locator('input[type="checkbox"]') .first() .check({ timeout: uiTimeoutMs }); + const passphraseInput = encryption.locator('input[name="e2ee-passphrase"]'); + await passphraseInput.waitFor({ state: "visible", timeout: uiTimeoutMs }); await encryption .locator("label.row") .filter({ hasText: "Obfuscate Properties" }) .locator('input[type="checkbox"]') .first() .check({ timeout: uiTimeoutMs }); - await encryption.locator('input[name="e2ee-passphrase"]').fill(randomBytes(24).toString("base64url")); + const passphraseValue = randomBytes(24).toString("base64url"); + await passphraseInput.fill(passphraseValue); + const passwordToggle = encryption.locator("button.sls-password-toggle"); + await passwordToggle.click({ timeout: uiTimeoutMs }); + assertEqual( + await passphraseInput.getAttribute("type"), + "text", + "Toggling visibility did not reveal the passphrase." + ); + assertEqual( + await passphraseInput.inputValue(), + passphraseValue, + "Toggling visibility changed the passphrase value." + ); + await passwordToggle.click({ timeout: uiTimeoutMs }); + assertEqual( + await passphraseInput.getAttribute("type"), + "password", + "Toggling visibility again did not re-mask the passphrase." + ); + assertEqual( + await passphraseInput.inputValue(), + passphraseValue, + "Re-masking the passphrase changed its value." + ); }); screenshots.push(await captureGuideDialogue(port, "guide-couchdb-manual-encryption.png", "End-to-End Encryption")); await withObsidianPage(port, async (page) => {