From 4b51f2ebeb1861cfb951c9674724c52134e5af63 Mon Sep 17 00:00:00 2001 From: Shibo Lyu Date: Fri, 9 May 2025 01:28:37 +0800 Subject: [PATCH] feat: Add account export functionality for identity backup --- src/lib/accounts/manager.svelte.ts | 13 +++- .../settings/privacy-security/+page.svelte | 12 +++- .../ChangePasswordDialog.svelte | 4 ++ .../ExportIdentityKeyDialog.svelte | 69 +++++++++++++++++++ 4 files changed, 96 insertions(+), 2 deletions(-) create mode 100644 src/routes/(app)/settings/privacy-security/ExportIdentityKeyDialog.svelte diff --git a/src/lib/accounts/manager.svelte.ts b/src/lib/accounts/manager.svelte.ts index 63099e8..1349068 100644 --- a/src/lib/accounts/manager.svelte.ts +++ b/src/lib/accounts/manager.svelte.ts @@ -5,7 +5,7 @@ import { type BlahProfile } from '@blah-im/core/identity'; import { type IdentityDB, openIdentityDB } from './identityDB'; -import { BlahKeyPair } from '@blah-im/core/crypto'; +import { BlahKeyPair, type EncodedBlahKeyPair } from '@blah-im/core/crypto'; import { browser } from '$app/environment'; export type Account = BlahIdentityDescription & { @@ -106,6 +106,17 @@ class AccountManager { await this.loadAccounts(); } + async exportAccountIDKeyPair(accountOrIdKeyId: Account | string): Promise { + if (!this.keyDB) throw new Error('Account manager not initialized'); + + const idKeyId = + typeof accountOrIdKeyId === 'string' ? accountOrIdKeyId : accountOrIdKeyId.id_key; + const accountCreds = await this.keyDB.fetchAccount(idKeyId); + const encodedIdKeyPair = accountCreds?.encodedIdKeyPair; + if (!encodedIdKeyPair) throw new Error('No encoded ID key pair found'); + return encodedIdKeyPair; + } + async changePassword( accountOrIdKeyId: Account | string, oldPassword: string, diff --git a/src/routes/(app)/settings/privacy-security/+page.svelte b/src/routes/(app)/settings/privacy-security/+page.svelte index 912ff8e..711e7fa 100644 --- a/src/routes/(app)/settings/privacy-security/+page.svelte +++ b/src/routes/(app)/settings/privacy-security/+page.svelte @@ -5,8 +5,10 @@ import PageHeader from '$lib/components/PageHeader.svelte'; import { DocumentDuplicate, Key } from 'svelte-hero-icons'; import ChangePasswordDialog from './ChangePasswordDialog.svelte'; + import ExportIdentityKeyDialog from './ExportIdentityKeyDialog.svelte'; let showChangePasswordDialog = $state(false); + let showExportIdentityDialog = $state(false); @@ -21,8 +23,16 @@ - Backup Account + (showExportIdentityDialog = true)}>Generate Identity Backup File + {#snippet footer()} +

+ In case you don't have any other full-access-enabled devices, this file, combining + with your current password, can be imported on Blah apps to regain + full access. +

+ {/snippet}
+ diff --git a/src/routes/(app)/settings/privacy-security/ChangePasswordDialog.svelte b/src/routes/(app)/settings/privacy-security/ChangePasswordDialog.svelte index ae9bf93..95475fb 100644 --- a/src/routes/(app)/settings/privacy-security/ChangePasswordDialog.svelte +++ b/src/routes/(app)/settings/privacy-security/ChangePasswordDialog.svelte @@ -190,6 +190,10 @@

Remember to change it on all other devices to which you granted full access.

+

+ If you keeps backups of your identity, please update your backup file so it is encrypted + with the new password. +

{/if} diff --git a/src/routes/(app)/settings/privacy-security/ExportIdentityKeyDialog.svelte b/src/routes/(app)/settings/privacy-security/ExportIdentityKeyDialog.svelte new file mode 100644 index 0000000..3017877 --- /dev/null +++ b/src/routes/(app)/settings/privacy-security/ExportIdentityKeyDialog.svelte @@ -0,0 +1,69 @@ + + + + +

Export Identity Backup

+
+ +
+

+ This will generate a backup file containing your encrypted identity keys. You'll need your + current password to use this backup later. +

+ + + +

+ Keep this file in a secure location. Anyone with this file and your password will have + full access to your account. +

+
+