commit 536f7579a90042871772801566032fe4f59bc336
parent 12743b446932bbc67e0d81e6345cbfb7e3bc6e6e
Author: William Casarin <jb55@jb55.com>
Date: Wed, 27 Nov 2024 09:19:34 -0800
Merge: user can upgrade their npub -> nsec #485
William Casarin (2):
refactor: make LoginAction a bit safer
kernelkind (1):
user can upgrade their npub -> nsec
Diffstat:
M | src/accounts/mod.rs | | | 77 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------------------ |
1 file changed, 59 insertions(+), 18 deletions(-)
diff --git a/src/accounts/mod.rs b/src/accounts/mod.rs
@@ -1,7 +1,7 @@
use std::cmp::Ordering;
use enostr::{FilledKeypair, FullKeypair, Keypair};
-use nostrdb::Ndb;
+use nostrdb::{Ndb, Transaction};
use crate::{
column::Columns,
@@ -14,6 +14,7 @@ use crate::{
accounts::{AccountsView, AccountsViewResponse},
},
unknowns::SingleUnkIdAction,
+ unknowns::UnknownIds,
user_account::UserAccount,
};
use tracing::{error, info};
@@ -138,27 +139,45 @@ impl Accounts {
}
}
- pub fn has_account_pubkey(&self, pubkey: &[u8; 32]) -> bool {
- for account in &self.accounts {
- if account.pubkey.bytes() == pubkey {
- return true;
+ fn contains_account(&self, pubkey: &[u8; 32]) -> Option<ContainsAccount> {
+ for (index, account) in self.accounts.iter().enumerate() {
+ let has_pubkey = account.pubkey.bytes() == pubkey;
+ let has_nsec = account.secret_key.is_some();
+ if has_pubkey {
+ return Some(ContainsAccount { has_nsec, index });
}
}
- false
+ None
}
#[must_use = "UnknownIdAction's must be handled. Use .process_unknown_id_action()"]
- pub fn add_account(&mut self, account: Keypair) -> SingleUnkIdAction {
- if self.has_account_pubkey(account.pubkey.bytes()) {
- info!("already have account, not adding {}", account.pubkey);
- return SingleUnkIdAction::pubkey(account.pubkey);
- }
+ pub fn add_account(&mut self, account: Keypair) -> LoginAction {
+ let pubkey = account.pubkey;
+ let switch_to_index = if let Some(contains_acc) = self.contains_account(pubkey.bytes()) {
+ if account.secret_key.is_some() && !contains_acc.has_nsec {
+ info!(
+ "user provided nsec, but we already have npub {}. Upgrading to nsec",
+ pubkey
+ );
+ let _ = self.key_store.add_key(&account);
- let _ = self.key_store.add_key(&account);
- let pk = account.pubkey;
- self.accounts.push(account);
- SingleUnkIdAction::pubkey(pk)
+ self.accounts[contains_acc.index] = account;
+ } else {
+ info!("already have account, not adding {}", pubkey);
+ }
+ contains_acc.index
+ } else {
+ info!("adding new account {}", pubkey);
+ let _ = self.key_store.add_key(&account);
+ self.accounts.push(account);
+ self.accounts.len() - 1
+ };
+
+ LoginAction {
+ unk: SingleUnkIdAction::pubkey(pubkey),
+ switch_to_index,
+ }
}
pub fn num_accounts(&self) -> usize {
@@ -217,12 +236,34 @@ pub fn process_login_view_response(
manager: &mut Accounts,
response: AccountLoginResponse,
) -> SingleUnkIdAction {
- let r = match response {
+ let login_action = match response {
AccountLoginResponse::CreateNew => {
manager.add_account(FullKeypair::generate().to_keypair())
}
AccountLoginResponse::LoginWith(keypair) => manager.add_account(keypair),
};
- manager.select_account(manager.num_accounts() - 1);
- r
+ manager.select_account(login_action.switch_to_index);
+ login_action.unk
+}
+
+#[must_use = "You must call process_login_action on this to handle unknown ids"]
+pub struct LoginAction {
+ unk: SingleUnkIdAction,
+ pub switch_to_index: usize,
+}
+
+impl LoginAction {
+ // Simple wrapper around processing the unknown action to expose too
+ // much internal logic. This allows us to have a must_use on our
+ // LoginAction type, otherwise the SingleUnkIdAction's must_use will
+ // be lost when returned in the login action
+ pub fn process_action(&mut self, ids: &mut UnknownIds, ndb: &Ndb, txn: &Transaction) {
+ self.unk.process_action(ids, ndb, txn);
+ }
+}
+
+#[derive(Default)]
+struct ContainsAccount {
+ pub has_nsec: bool,
+ pub index: usize,
}