FileKeyStorage -> AccountStorage

Signed-off-by: kernelkind <kernelkind@gmail.com>
This commit is contained in:
kernelkind
2025-03-17 19:36:23 -04:00
parent d9f92ef54f
commit 6003ef5aec
5 changed files with 45 additions and 45 deletions

View File

@@ -1,7 +1,7 @@
use tracing::{debug, error, info}; use tracing::{debug, error, info};
use crate::{ use crate::{
FileKeyStorage, MuteFun, Muted, RelaySpec, SingleUnkIdAction, UnknownIds, UserAccount, AccountStorage, MuteFun, Muted, RelaySpec, SingleUnkIdAction, UnknownIds, UserAccount,
}; };
use enostr::{ClientMessage, FilledKeypair, Keypair, Pubkey, RelayPool}; use enostr::{ClientMessage, FilledKeypair, Keypair, Pubkey, RelayPool};
use nostrdb::{Filter, Ndb, Note, NoteBuilder, NoteKey, Subscription, Transaction}; use nostrdb::{Filter, Ndb, Note, NoteBuilder, NoteKey, Subscription, Transaction};
@@ -308,7 +308,7 @@ pub struct AccountData {
pub struct Accounts { pub struct Accounts {
currently_selected_account: Option<usize>, currently_selected_account: Option<usize>,
accounts: Vec<UserAccount>, accounts: Vec<UserAccount>,
key_store: Option<FileKeyStorage>, key_store: Option<AccountStorage>,
account_data: BTreeMap<[u8; 32], AccountData>, account_data: BTreeMap<[u8; 32], AccountData>,
forced_relays: BTreeSet<RelaySpec>, forced_relays: BTreeSet<RelaySpec>,
bootstrap_relays: BTreeSet<RelaySpec>, bootstrap_relays: BTreeSet<RelaySpec>,
@@ -316,10 +316,10 @@ pub struct Accounts {
} }
impl Accounts { impl Accounts {
pub fn new(key_store: Option<FileKeyStorage>, forced_relays: Vec<String>) -> Self { pub fn new(key_store: Option<AccountStorage>, forced_relays: Vec<String>) -> Self {
let accounts = match &key_store { let accounts = match &key_store {
Some(keystore) => match keystore.get_keys() { Some(keystore) => match keystore.get_accounts() {
Ok(k) => k.into_iter().map(|key| UserAccount { key }).collect(), Ok(k) => k,
Err(e) => { Err(e) => {
tracing::error!("could not get keys: {e}"); tracing::error!("could not get keys: {e}");
Vec::new() Vec::new()
@@ -434,22 +434,22 @@ impl Accounts {
} }
#[must_use = "UnknownIdAction's must be handled. Use .process_unknown_id_action()"] #[must_use = "UnknownIdAction's must be handled. Use .process_unknown_id_action()"]
pub fn add_account(&mut self, account: Keypair) -> AddAccountAction { pub fn add_account(&mut self, key: Keypair) -> AddAccountAction {
let pubkey = account.pubkey; let pubkey = key.pubkey;
let switch_to_index = if let Some(contains_acc) = self.contains_account(pubkey.bytes()) { let switch_to_index = if let Some(contains_acc) = self.contains_account(pubkey.bytes()) {
if account.secret_key.is_some() && !contains_acc.has_nsec { if key.secret_key.is_some() && !contains_acc.has_nsec {
info!( info!(
"user provided nsec, but we already have npub {}. Upgrading to nsec", "user provided nsec, but we already have npub {}. Upgrading to nsec",
pubkey pubkey
); );
if let Some(key_store) = &self.key_store { if let Some(key_store) = &self.key_store {
if let Err(e) = key_store.add_key(&account) { if let Err(e) = key_store.write_account(&UserAccount::new(key.clone())) {
tracing::error!("Could not add key for {:?}: {e}", account.pubkey); tracing::error!("Could not add key for {:?}: {e}", key.pubkey);
} }
} }
self.accounts[contains_acc.index].key = account; self.accounts[contains_acc.index].key = key;
} else { } else {
info!("already have account, not adding {}", pubkey); info!("already have account, not adding {}", pubkey);
} }
@@ -457,11 +457,11 @@ impl Accounts {
} else { } else {
info!("adding new account {}", pubkey); info!("adding new account {}", pubkey);
if let Some(key_store) = &self.key_store { if let Some(key_store) = &self.key_store {
if let Err(e) = key_store.add_key(&account) { if let Err(e) = key_store.write_account(&UserAccount::new(key.clone())) {
tracing::error!("Could not add key for {:?}: {e}", account.pubkey); tracing::error!("Could not add key for {:?}: {e}", key.pubkey);
} }
} }
self.accounts.push(UserAccount::new(account)); self.accounts.push(UserAccount::new(key));
self.accounts.len() - 1 self.accounts.len() - 1
}; };
@@ -821,7 +821,7 @@ enum RelayAction {
Remove, Remove,
} }
fn get_selected_index(accounts: &[UserAccount], keystore: &FileKeyStorage) -> Option<usize> { fn get_selected_index(accounts: &[UserAccount], keystore: &AccountStorage) -> Option<usize> {
match keystore.get_selected_key() { match keystore.get_selected_key() {
Ok(Some(pubkey)) => { Ok(Some(pubkey)) => {
return accounts return accounts

View File

@@ -1,6 +1,6 @@
use crate::persist::{AppSizeHandler, ZoomHandler}; use crate::persist::{AppSizeHandler, ZoomHandler};
use crate::{ use crate::{
Accounts, AppContext, Args, DataPath, DataPathType, Directory, FileKeyStorage, Images, AccountStorage, Accounts, AppContext, Args, DataPath, DataPathType, Directory, Images,
NoteCache, RelayDebugView, ThemeHandler, UnknownIds, NoteCache, RelayDebugView, ThemeHandler, UnknownIds,
}; };
use egui::ThemePreference; use egui::ThemePreference;
@@ -149,7 +149,7 @@ impl Notedeck {
let keystore = if parsed_args.use_keystore { let keystore = if parsed_args.use_keystore {
let keys_path = path.path(DataPathType::Keys); let keys_path = path.path(DataPathType::Keys);
let selected_key_path = path.path(DataPathType::SelectedKey); let selected_key_path = path.path(DataPathType::SelectedKey);
Some(FileKeyStorage::new( Some(AccountStorage::new(
Directory::new(keys_path), Directory::new(keys_path),
Directory::new(selected_key_path), Directory::new(selected_key_path),
)) ))

View File

@@ -44,7 +44,7 @@ pub use persist::*;
pub use relay_debug::RelayDebugView; pub use relay_debug::RelayDebugView;
pub use relayspec::RelaySpec; pub use relayspec::RelaySpec;
pub use result::Result; pub use result::Result;
pub use storage::{DataPath, DataPathType, Directory, FileKeyStorage}; pub use storage::{AccountStorage, DataPath, DataPathType, Directory};
pub use style::NotedeckTextStyle; pub use style::NotedeckTextStyle;
pub use theme::ColorTheme; pub use theme::ColorTheme;
pub use time::time_ago_since; pub use time::time_ago_since;

View File

@@ -1,4 +1,4 @@
use crate::Result; use crate::{Result, UserAccount};
use enostr::{Keypair, Pubkey, SerializableKeypair}; use enostr::{Keypair, Pubkey, SerializableKeypair};
use tokenator::{TokenParser, TokenSerializable, TokenWriter}; use tokenator::{TokenParser, TokenSerializable, TokenWriter};
@@ -8,41 +8,42 @@ static SELECTED_PUBKEY_FILE_NAME: &str = "selected_pubkey";
/// An OS agnostic file key storage implementation /// An OS agnostic file key storage implementation
#[derive(Debug, PartialEq)] #[derive(Debug, PartialEq)]
pub struct FileKeyStorage { pub struct AccountStorage {
keys_directory: Directory, accounts_directory: Directory,
selected_key_directory: Directory, selected_key_directory: Directory,
} }
impl FileKeyStorage { impl AccountStorage {
pub fn new(keys_directory: Directory, selected_key_directory: Directory) -> Self { pub fn new(accounts_directory: Directory, selected_key_directory: Directory) -> Self {
Self { Self {
keys_directory, accounts_directory,
selected_key_directory, selected_key_directory,
} }
} }
pub fn add_key(&self, key: &Keypair) -> Result<()> { pub fn write_account(&self, account: &UserAccount) -> Result<()> {
let mut writer = TokenWriter::new("\t"); let mut writer = TokenWriter::new("\t");
key.serialize_tokens(&mut writer); account.serialize_tokens(&mut writer);
write_file( write_file(
&self.keys_directory.file_path, &self.accounts_directory.file_path,
key.pubkey.hex(), account.key.pubkey.hex(),
writer.str(), writer.str(),
) )
} }
pub fn get_keys(&self) -> Result<Vec<Keypair>> { pub fn get_accounts(&self) -> Result<Vec<UserAccount>> {
let keys = self let keys = self
.keys_directory .accounts_directory
.get_files()? .get_files()?
.values() .values()
.filter_map(|str_key| deserialize_kp(str_key).ok()) .filter_map(|str_key| deserialize_kp(str_key).ok())
.map(UserAccount::new)
.collect(); .collect();
Ok(keys) Ok(keys)
} }
pub fn remove_key(&self, key: &Keypair) -> Result<()> { pub fn remove_key(&self, key: &Keypair) -> Result<()> {
delete_file(&self.keys_directory.file_path, key.pubkey.hex()) delete_file(&self.accounts_directory.file_path, key.pubkey.hex())
} }
pub fn get_selected_key(&self) -> Result<Option<Pubkey>> { pub fn get_selected_key(&self) -> Result<Option<Pubkey>> {
@@ -97,14 +98,13 @@ mod tests {
use super::Result; use super::Result;
use super::*; use super::*;
use enostr::Keypair;
static CREATE_TMP_DIR: fn() -> Result<PathBuf> = static CREATE_TMP_DIR: fn() -> Result<PathBuf> =
|| Ok(tempfile::TempDir::new()?.path().to_path_buf()); || Ok(tempfile::TempDir::new()?.path().to_path_buf());
impl FileKeyStorage { impl AccountStorage {
fn mock() -> Result<Self> { fn mock() -> Result<Self> {
Ok(Self { Ok(Self {
keys_directory: Directory::new(CREATE_TMP_DIR()?), accounts_directory: Directory::new(CREATE_TMP_DIR()?),
selected_key_directory: Directory::new(CREATE_TMP_DIR()?), selected_key_directory: Directory::new(CREATE_TMP_DIR()?),
}) })
} }
@@ -113,17 +113,17 @@ mod tests {
#[test] #[test]
fn test_basic() { fn test_basic() {
let kp = enostr::FullKeypair::generate().to_keypair(); let kp = enostr::FullKeypair::generate().to_keypair();
let storage = FileKeyStorage::mock().unwrap(); let storage = AccountStorage::mock().unwrap();
let resp = storage.add_key(&kp); let resp = storage.write_account(&UserAccount::new(kp.clone()));
assert!(resp.is_ok()); assert!(resp.is_ok());
assert_num_storage(&storage.get_keys(), 1); assert_num_storage(&storage.get_accounts(), 1);
assert!(storage.remove_key(&kp).is_ok()); assert!(storage.remove_key(&kp).is_ok());
assert_num_storage(&storage.get_keys(), 0); assert_num_storage(&storage.get_accounts(), 0);
} }
fn assert_num_storage(keys_response: &Result<Vec<Keypair>>, n: usize) { fn assert_num_storage(keys_response: &Result<Vec<UserAccount>>, n: usize) {
match keys_response { match keys_response {
Ok(keys) => { Ok(keys) => {
assert_eq!(keys.len(), n); assert_eq!(keys.len(), n);
@@ -138,9 +138,9 @@ mod tests {
fn test_select_key() { fn test_select_key() {
let kp = enostr::FullKeypair::generate().to_keypair(); let kp = enostr::FullKeypair::generate().to_keypair();
let storage = FileKeyStorage::mock().unwrap(); let storage = AccountStorage::mock().unwrap();
let _ = storage.add_key(&kp); let _ = storage.write_account(&UserAccount::new(kp.clone()));
assert_num_storage(&storage.get_keys(), 1); assert_num_storage(&storage.get_accounts(), 1);
let resp = storage.select_key(Some(kp.pubkey)); let resp = storage.select_key(Some(kp.pubkey));
assert!(resp.is_ok()); assert!(resp.is_ok());
@@ -152,7 +152,7 @@ mod tests {
#[test] #[test]
fn test_get_selected_key_when_no_file() { fn test_get_selected_key_when_no_file() {
let storage = FileKeyStorage::mock().unwrap(); let storage = AccountStorage::mock().unwrap();
// Should return Ok(None) when no key has been selected // Should return Ok(None) when no key has been selected
match storage.get_selected_key() { match storage.get_selected_key() {

View File

@@ -1,5 +1,5 @@
mod file_key_storage; mod account_storage;
mod file_storage; mod file_storage;
pub use file_key_storage::FileKeyStorage; pub use account_storage::AccountStorage;
pub use file_storage::{delete_file, write_file, DataPath, DataPathType, Directory}; pub use file_storage::{delete_file, write_file, DataPath, DataPathType, Directory};