FileKeyStorage -> AccountStorage
Signed-off-by: kernelkind <kernelkind@gmail.com>
This commit is contained in:
@@ -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
|
||||||
|
|||||||
@@ -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),
|
||||||
))
|
))
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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() {
|
||||||
@@ -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};
|
||||||
|
|||||||
Reference in New Issue
Block a user