From 8e70347330f9b88971ec525298de1df51d8a2ba0 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Wed, 16 Apr 2025 14:54:58 +0100 Subject: [PATCH] Iterate Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- src/i18n/strings/en_EN.json | 9 ++++--- src/store.ts | 50 +++++++++++++++++++++++++++++++------ 2 files changed, 48 insertions(+), 11 deletions(-) diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index 22538512..1c2dc8cb 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -64,9 +64,12 @@ }, "store": { "error": { - "title": "Failed to load configuration", - "unsupported_backend_override": "TODO", - "unknown_backend_override": "TODO" + "title": "Failed to load database", + "unsupported_backend_override": "The encrypted database is corrupted, unable to access your system keyring.", + "unsupported_backend_override_details": "Please check the logs for more details.", + "unknown_backend_override": "Your system has an unsupported keyring meaning the database cannot be opened.", + "unknown_backend_override_details": "Please check the logs for more details.", + "clear_data_cta": "Clear data" } } } diff --git a/src/store.ts b/src/store.ts index 1691ab3b..834ff0fc 100644 --- a/src/store.ts +++ b/src/store.ts @@ -17,6 +17,7 @@ limitations under the License. import ElectronStore from "electron-store"; import keytar from "keytar-forked"; import { app, safeStorage, dialog, type SafeStorage } from "electron"; +import { clearAllUserData, clearSensitiveDirectories, relaunchApp } from "@standardnotes/electron-clear-data"; import { _t } from "./language-helper.js"; @@ -26,20 +27,29 @@ import { _t } from "./language-helper.js"; const KEYTAR_SERVICE = "element.io"; const LEGACY_KEYTAR_SERVICE = "riot.im"; -type SafeStorageBackend = ReturnType; +type SafeStorageBackend = ReturnType | "system"; /** * Map of safeStorage backends to their command line arguments. * kwallet6 cannot be specified via command line * https://www.electronjs.org/docs/latest/api/safe-storage#safestoragegetselectedstoragebackend-linux */ -const safeStorageBackendMap: Omit, "unknown" | "kwallet6"> = { +const safeStorageBackendMap: Omit, "unknown" | "kwallet6" | "system"> = { basic_text: "basic", gnome_libsecret: "gnome-libsecret", kwallet: "kwallet", kwallet5: "kwallet5", }; +async function clearDataAndRelaunch(): Promise { + global.store?.clear(); + global.mainWindow?.webContents.session.flushStorageData(); + await global.mainWindow?.webContents.session.clearStorageData(); + clearAllUserData(); + clearSensitiveDirectories(); + relaunchApp(); +} + /** * JSON-backed store for settings which need to be accessible by the main process. * Secrets are stored within the `safeStorage` object, encrypted with safeStorage. @@ -115,7 +125,19 @@ class Store extends ElectronStore<{ } else { // This case should never happen, but could due to a downgrade or a modified store. dialog.showErrorBox(_t("store|error|title"), _t("store|error|unsupported_backend_override")); - throw new Error("safeStorage backend override is not supported"); + const response = dialog.showMessageBoxSync({ + title: _t("store|error|title"), + message: _t("store|error|unsupported_backend_override"), + detail: _t("store|error|unsupported_backend_override_details"), + type: "question", + buttons: [_t("common|no"), _t("store|error|clear_data_cta")], + defaultId: 0, + cancelId: 0, + }); + if (response === 0) { + throw new Error("safeStorage backend override is not supported"); + } + void clearDataAndRelaunch(); } } } @@ -129,7 +151,7 @@ class Store extends ElectronStore<{ await this.safeStorageReadyPromise; } - private getSecretStorageKey = (key: string) => `safeStorage.${key}` as const; + private getSecretStorageKey = (key: string) => `safeStorage.${key.replaceAll(".", "-")}` as const; private async prepareSafeStorage(): Promise { await app.whenReady(); @@ -142,7 +164,12 @@ class Store extends ElectronStore<{ if (selectedSafeStorageBackend === "unknown") { // This should never happen but good to be safe - dialog.showErrorBox(_t("store|error|title"), _t("store|error|unknown_backend_override")); + await dialog.showMessageBox({ + title: _t("store|error|title"), + message: _t("store|error|unknown_backend_override"), + detail: _t("store|error|unknown_backend_override_details"), + type: "error", + }); throw new Error("safeStorage backend unknown"); } @@ -166,7 +193,7 @@ class Store extends ElectronStore<{ } // Store the backend used for the safeStorage data so we can detect if it changes - this.set("safeStorageBackend", selectedSafeStorageBackend); + this.recordSafeStorageBackend(selectedSafeStorageBackend); safeStorageBackend = selectedSafeStorageBackend; } else if (safeStorageBackend !== selectedSafeStorageBackend) { console.warn(`safeStorage backend changed from ${safeStorageBackend} to ${selectedSafeStorageBackend}`); @@ -219,16 +246,23 @@ class Store extends ElectronStore<{ await this.migrateSecrets(); } + private recordSafeStorageBackend(backend: SafeStorageBackend): void { + this.set("safeStorageBackend", backend); + } + + private get isPlaintext(): boolean { + return this.get("safeStorageBackend") === "basic_text"; + } + /** * Migrates keytar data to safeStorage, * deletes data from legacy keytar but keeps it in the new keytar for downgrade compatibility. - * @throws if safeStorage is not available. TODO */ private async migrateSecrets(): Promise { if (this.has("safeStorage")) return; // already migrated console.info("Store migration: started"); - if (process.platform === "linux" && safeStorage.getSelectedStorageBackend() === "basic_text") { + if (process.platform === "linux" && this.isPlaintext) { console.warn("Store migration: safeStorage is using basic text encryption"); }