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
This commit is contained in:
William Casarin
2024-11-27 09:19:34 -08:00

View File

@@ -1,7 +1,7 @@
use std::cmp::Ordering; use std::cmp::Ordering;
use enostr::{FilledKeypair, FullKeypair, Keypair}; use enostr::{FilledKeypair, FullKeypair, Keypair};
use nostrdb::Ndb; use nostrdb::{Ndb, Transaction};
use crate::{ use crate::{
column::Columns, column::Columns,
@@ -14,6 +14,7 @@ use crate::{
accounts::{AccountsView, AccountsViewResponse}, accounts::{AccountsView, AccountsViewResponse},
}, },
unknowns::SingleUnkIdAction, unknowns::SingleUnkIdAction,
unknowns::UnknownIds,
user_account::UserAccount, user_account::UserAccount,
}; };
use tracing::{error, info}; use tracing::{error, info};
@@ -138,27 +139,45 @@ impl Accounts {
} }
} }
pub fn has_account_pubkey(&self, pubkey: &[u8; 32]) -> bool { fn contains_account(&self, pubkey: &[u8; 32]) -> Option<ContainsAccount> {
for account in &self.accounts { for (index, account) in self.accounts.iter().enumerate() {
if account.pubkey.bytes() == pubkey { let has_pubkey = account.pubkey.bytes() == pubkey;
return true; 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()"] #[must_use = "UnknownIdAction's must be handled. Use .process_unknown_id_action()"]
pub fn add_account(&mut self, account: Keypair) -> SingleUnkIdAction { pub fn add_account(&mut self, account: Keypair) -> LoginAction {
if self.has_account_pubkey(account.pubkey.bytes()) { let pubkey = account.pubkey;
info!("already have account, not adding {}", account.pubkey); let switch_to_index = if let Some(contains_acc) = self.contains_account(pubkey.bytes()) {
return SingleUnkIdAction::pubkey(account.pubkey); 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); self.accounts[contains_acc.index] = account;
let pk = account.pubkey; } else {
self.accounts.push(account); info!("already have account, not adding {}", pubkey);
SingleUnkIdAction::pubkey(pk) }
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 { pub fn num_accounts(&self) -> usize {
@@ -217,12 +236,34 @@ pub fn process_login_view_response(
manager: &mut Accounts, manager: &mut Accounts,
response: AccountLoginResponse, response: AccountLoginResponse,
) -> SingleUnkIdAction { ) -> SingleUnkIdAction {
let r = match response { let login_action = match response {
AccountLoginResponse::CreateNew => { AccountLoginResponse::CreateNew => {
manager.add_account(FullKeypair::generate().to_keypair()) manager.add_account(FullKeypair::generate().to_keypair())
} }
AccountLoginResponse::LoginWith(keypair) => manager.add_account(keypair), AccountLoginResponse::LoginWith(keypair) => manager.add_account(keypair),
}; };
manager.select_account(manager.num_accounts() - 1); manager.select_account(login_action.switch_to_index);
r 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,
} }