notedeck

One damus client to rule them all
git clone git://jb55.com/notedeck
Log | Files | Refs | README | LICENSE

commit 1e05fa551d878dd5dbe89cea446f384aa1ff4dba
parent 69b651bbc5ebf6251f4dd4c3923f056894f4e488
Author: kernelkind <kernelkind@gmail.com>
Date:   Sat, 15 Mar 2025 15:06:40 -0400

simplify key storage

Signed-off-by: kernelkind <kernelkind@gmail.com>

Diffstat:
Mcrates/notedeck/src/accounts.rs | 66++++++++++++++++++++++++++++++++++++++++++++++++------------------
Mcrates/notedeck/src/app.rs | 6+++---
Mcrates/notedeck/src/lib.rs | 4+---
Mcrates/notedeck/src/storage/file_key_storage.rs | 59++++++++++++++---------------------------------------------
Dcrates/notedeck/src/storage/key_storage_impl.rs | 73-------------------------------------------------------------------------
Mcrates/notedeck/src/storage/mod.rs | 3---
6 files changed, 66 insertions(+), 145 deletions(-)

diff --git a/crates/notedeck/src/accounts.rs b/crates/notedeck/src/accounts.rs @@ -1,8 +1,7 @@ use tracing::{debug, error, info}; use crate::{ - KeyStorageResponse, KeyStorageType, MuteFun, Muted, RelaySpec, SingleUnkIdAction, UnknownIds, - UserAccount, + FileKeyStorage, MuteFun, Muted, RelaySpec, SingleUnkIdAction, UnknownIds, UserAccount, }; use enostr::{ClientMessage, FilledKeypair, Keypair, RelayPool}; use nostrdb::{Filter, Ndb, Note, NoteBuilder, NoteKey, Subscription, Transaction}; @@ -309,7 +308,7 @@ pub struct AccountData { pub struct Accounts { currently_selected_account: Option<usize>, accounts: Vec<UserAccount>, - key_store: KeyStorageType, + key_store: Option<FileKeyStorage>, account_data: BTreeMap<[u8; 32], AccountData>, forced_relays: BTreeSet<RelaySpec>, bootstrap_relays: BTreeSet<RelaySpec>, @@ -317,14 +316,24 @@ pub struct Accounts { } impl Accounts { - pub fn new(key_store: KeyStorageType, forced_relays: Vec<String>) -> Self { - let accounts = if let KeyStorageResponse::ReceivedResult(res) = key_store.get_keys() { - res.unwrap_or_default() + pub fn new(key_store: Option<FileKeyStorage>, forced_relays: Vec<String>) -> Self { + let accounts = match &key_store { + Some(keystore) => match keystore.get_keys() { + Ok(k) => k, + Err(e) => { + tracing::error!("could not get keys: {e}"); + Vec::new() + } + }, + None => Vec::new(), + }; + + let currently_selected_account = if let Some(key_store) = &key_store { + get_selected_index(&accounts, key_store) } else { - Vec::new() + None }; - let currently_selected_account = get_selected_index(&accounts, &key_store); let account_data = BTreeMap::new(); let forced_relays: BTreeSet<RelaySpec> = forced_relays .into_iter() @@ -367,7 +376,12 @@ impl Accounts { pub fn remove_account(&mut self, index: usize) { if let Some(account) = self.accounts.get(index) { - let _ = self.key_store.remove_key(account); + if let Some(key_store) = &self.key_store { + if let Err(e) = key_store.remove_key(account) { + tracing::error!("Could not remove account at index {index}: {e}"); + } + } + self.accounts.remove(index); if let Some(selected_index) = self.currently_selected_account { @@ -426,7 +440,12 @@ impl Accounts { "user provided nsec, but we already have npub {}. Upgrading to nsec", pubkey ); - let _ = self.key_store.add_key(&account); + + if let Some(key_store) = &self.key_store { + if let Err(e) = key_store.add_key(&account) { + tracing::error!("Could not add key for {:?}: {e}", account.pubkey); + } + } self.accounts[contains_acc.index] = account; } else { @@ -435,7 +454,11 @@ impl Accounts { contains_acc.index } else { info!("adding new account {}", pubkey); - let _ = self.key_store.add_key(&account); + if let Some(key_store) = &self.key_store { + if let Err(e) = key_store.add_key(&account) { + tracing::error!("Could not add key for {:?}: {e}", account.pubkey); + } + } self.accounts.push(account); self.accounts.len() - 1 }; @@ -493,13 +516,21 @@ impl Accounts { pub fn select_account(&mut self, index: usize) { if let Some(account) = self.accounts.get(index) { self.currently_selected_account = Some(index); - self.key_store.select_key(Some(account.pubkey)); + if let Some(key_store) = &self.key_store { + if let Err(e) = key_store.select_key(Some(account.pubkey)) { + tracing::error!("Could not select key {:?}: {e}", account.pubkey); + } + } } } pub fn clear_selected_account(&mut self) { self.currently_selected_account = None; - self.key_store.select_key(None); + if let Some(key_store) = &self.key_store { + if let Err(e) = key_store.select_key(None) { + tracing::error!("Could not select None key: {e}"); + } + } } pub fn mutefun(&self) -> Box<MuteFun> { @@ -794,14 +825,13 @@ enum RelayAction { Remove, } -fn get_selected_index(accounts: &[UserAccount], keystore: &KeyStorageType) -> Option<usize> { +fn get_selected_index(accounts: &[UserAccount], keystore: &FileKeyStorage) -> Option<usize> { match keystore.get_selected_key() { - KeyStorageResponse::ReceivedResult(Ok(Some(pubkey))) => { + Ok(Some(pubkey)) => { return accounts.iter().position(|account| account.pubkey == pubkey); } - - KeyStorageResponse::ReceivedResult(Err(e)) => error!("Error getting selected key: {}", e), - KeyStorageResponse::Waiting | KeyStorageResponse::ReceivedResult(Ok(None)) => {} + Ok(None) => {} + Err(e) => error!("Error getting selected key: {}", e), }; None diff --git a/crates/notedeck/src/app.rs b/crates/notedeck/src/app.rs @@ -1,7 +1,7 @@ use crate::persist::{AppSizeHandler, ZoomHandler}; use crate::{ Accounts, AppContext, Args, DataPath, DataPathType, Directory, FileKeyStorage, Images, - KeyStorageType, NoteCache, RelayDebugView, ThemeHandler, UnknownIds, + NoteCache, RelayDebugView, ThemeHandler, UnknownIds, }; use egui::ThemePreference; use egui_winit::clipboard::Clipboard; @@ -149,12 +149,12 @@ impl Notedeck { let keystore = if parsed_args.use_keystore { let keys_path = path.path(DataPathType::Keys); let selected_key_path = path.path(DataPathType::SelectedKey); - KeyStorageType::FileSystem(FileKeyStorage::new( + Some(FileKeyStorage::new( Directory::new(keys_path), Directory::new(selected_key_path), )) } else { - KeyStorageType::None + None }; let mut accounts = Accounts::new(keystore, parsed_args.relays.clone()); diff --git a/crates/notedeck/src/lib.rs b/crates/notedeck/src/lib.rs @@ -44,9 +44,7 @@ pub use persist::*; pub use relay_debug::RelayDebugView; pub use relayspec::RelaySpec; pub use result::Result; -pub use storage::{ - DataPath, DataPathType, Directory, FileKeyStorage, KeyStorageResponse, KeyStorageType, -}; +pub use storage::{DataPath, DataPathType, Directory, FileKeyStorage}; pub use style::NotedeckTextStyle; pub use theme::ColorTheme; pub use time::time_ago_since; diff --git a/crates/notedeck/src/storage/file_key_storage.rs b/crates/notedeck/src/storage/file_key_storage.rs @@ -1,10 +1,7 @@ use crate::Result; use enostr::{Keypair, Pubkey, SerializableKeypair}; -use super::{ - file_storage::{delete_file, write_file, Directory}, - key_storage_impl::KeyStorageResponse, -}; +use super::file_storage::{delete_file, write_file, Directory}; static SELECTED_PUBKEY_FILE_NAME: &str = "selected_pubkey"; @@ -23,7 +20,7 @@ impl FileKeyStorage { } } - fn add_key_internal(&self, key: &Keypair) -> Result<()> { + pub fn add_key(&self, key: &Keypair) -> Result<()> { write_file( &self.keys_directory.file_path, key.pubkey.hex(), @@ -31,7 +28,7 @@ impl FileKeyStorage { ) } - fn get_keys_internal(&self) -> Result<Vec<Keypair>> { + pub fn get_keys(&self) -> Result<Vec<Keypair>> { let keys = self .keys_directory .get_files()? @@ -42,11 +39,11 @@ impl FileKeyStorage { Ok(keys) } - fn remove_key_internal(&self, key: &Keypair) -> Result<()> { + pub fn remove_key(&self, key: &Keypair) -> Result<()> { delete_file(&self.keys_directory.file_path, key.pubkey.hex()) } - fn get_selected_pubkey(&self) -> Result<Option<Pubkey>> { + pub fn get_selected_key(&self) -> Result<Option<Pubkey>> { match self .selected_key_directory .get_file(SELECTED_PUBKEY_FILE_NAME.to_owned()) @@ -57,7 +54,7 @@ impl FileKeyStorage { } } - fn select_pubkey(&self, pubkey: Option<Pubkey>) -> Result<()> { + pub fn select_key(&self, pubkey: Option<Pubkey>) -> Result<()> { if let Some(pubkey) = pubkey { write_file( &self.selected_key_directory.file_path, @@ -80,28 +77,6 @@ impl FileKeyStorage { } } -impl FileKeyStorage { - pub fn get_keys(&self) -> KeyStorageResponse<Vec<enostr::Keypair>> { - KeyStorageResponse::ReceivedResult(self.get_keys_internal()) - } - - pub fn add_key(&self, key: &enostr::Keypair) -> KeyStorageResponse<()> { - KeyStorageResponse::ReceivedResult(self.add_key_internal(key)) - } - - pub fn remove_key(&self, key: &enostr::Keypair) -> KeyStorageResponse<()> { - KeyStorageResponse::ReceivedResult(self.remove_key_internal(key)) - } - - pub fn get_selected_key(&self) -> KeyStorageResponse<Option<Pubkey>> { - KeyStorageResponse::ReceivedResult(self.get_selected_pubkey()) - } - - pub fn select_key(&self, key: Option<Pubkey>) -> KeyStorageResponse<()> { - KeyStorageResponse::ReceivedResult(self.select_pubkey(key)) - } -} - #[cfg(test)] mod tests { use std::path::PathBuf; @@ -128,27 +103,21 @@ mod tests { let storage = FileKeyStorage::mock().unwrap(); let resp = storage.add_key(&kp); - assert_eq!(resp, KeyStorageResponse::ReceivedResult(Ok(()))); + assert!(resp.is_ok()); assert_num_storage(&storage.get_keys(), 1); - assert_eq!( - storage.remove_key(&kp), - KeyStorageResponse::ReceivedResult(Ok(())) - ); + assert!(storage.remove_key(&kp).is_ok()); assert_num_storage(&storage.get_keys(), 0); } - fn assert_num_storage(keys_response: &KeyStorageResponse<Vec<Keypair>>, n: usize) { + fn assert_num_storage(keys_response: &Result<Vec<Keypair>>, n: usize) { match keys_response { - KeyStorageResponse::ReceivedResult(Ok(keys)) => { + Ok(keys) => { assert_eq!(keys.len(), n); } - KeyStorageResponse::ReceivedResult(Err(_e)) => { + Err(_e) => { panic!("could not get keys"); } - KeyStorageResponse::Waiting => { - panic!("did not receive result"); - } } } @@ -160,10 +129,10 @@ mod tests { let _ = storage.add_key(&kp); assert_num_storage(&storage.get_keys(), 1); - let resp = storage.select_pubkey(Some(kp.pubkey)); + let resp = storage.select_key(Some(kp.pubkey)); assert!(resp.is_ok()); - let resp = storage.get_selected_pubkey(); + let resp = storage.get_selected_key(); assert!(resp.is_ok()); } @@ -174,7 +143,7 @@ mod tests { // Should return Ok(None) when no key has been selected match storage.get_selected_key() { - KeyStorageResponse::ReceivedResult(Ok(None)) => (), // This is what we expect + Ok(None) => (), // This is what we expect other => panic!("Expected Ok(None), got {:?}", other), } } diff --git a/crates/notedeck/src/storage/key_storage_impl.rs b/crates/notedeck/src/storage/key_storage_impl.rs @@ -1,73 +0,0 @@ -use enostr::{Keypair, Pubkey}; - -use super::file_key_storage::FileKeyStorage; -use crate::Result; - -#[derive(Debug, PartialEq)] -pub enum KeyStorageType { - None, - FileSystem(FileKeyStorage), -} - -#[allow(dead_code)] -#[derive(Debug)] -pub enum KeyStorageResponse<R> { - Waiting, - ReceivedResult(Result<R>), -} - -impl<R: PartialEq> PartialEq for KeyStorageResponse<R> { - fn eq(&self, other: &Self) -> bool { - match (self, other) { - (KeyStorageResponse::Waiting, KeyStorageResponse::Waiting) => true, - ( - KeyStorageResponse::ReceivedResult(Ok(r1)), - KeyStorageResponse::ReceivedResult(Ok(r2)), - ) => r1 == r2, - ( - KeyStorageResponse::ReceivedResult(Err(_)), - KeyStorageResponse::ReceivedResult(Err(_)), - ) => true, - _ => false, - } - } -} - -impl KeyStorageType { - pub fn get_keys(&self) -> KeyStorageResponse<Vec<Keypair>> { - match self { - Self::None => KeyStorageResponse::ReceivedResult(Ok(Vec::new())), - Self::FileSystem(f) => f.get_keys(), - } - } - - pub fn add_key(&self, key: &Keypair) -> KeyStorageResponse<()> { - let _ = key; - match self { - Self::None => KeyStorageResponse::ReceivedResult(Ok(())), - Self::FileSystem(f) => f.add_key(key), - } - } - - pub fn remove_key(&self, key: &Keypair) -> KeyStorageResponse<()> { - let _ = key; - match self { - Self::None => KeyStorageResponse::ReceivedResult(Ok(())), - Self::FileSystem(f) => f.remove_key(key), - } - } - - pub fn get_selected_key(&self) -> KeyStorageResponse<Option<Pubkey>> { - match self { - Self::None => KeyStorageResponse::ReceivedResult(Ok(None)), - Self::FileSystem(f) => f.get_selected_key(), - } - } - - pub fn select_key(&self, key: Option<Pubkey>) -> KeyStorageResponse<()> { - match self { - Self::None => KeyStorageResponse::ReceivedResult(Ok(())), - Self::FileSystem(f) => f.select_key(key), - } - } -} diff --git a/crates/notedeck/src/storage/mod.rs b/crates/notedeck/src/storage/mod.rs @@ -3,6 +3,3 @@ mod file_storage; pub use file_key_storage::FileKeyStorage; pub use file_storage::{delete_file, write_file, DataPath, DataPathType, Directory}; - -pub mod key_storage_impl; -pub use key_storage_impl::{KeyStorageResponse, KeyStorageType};