diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/login.rs | 89 |
1 files changed, 60 insertions, 29 deletions
diff --git a/src/login.rs b/src/login.rs index 218a079..38babaa 100644 --- a/src/login.rs +++ b/src/login.rs | |||
| @@ -1,7 +1,10 @@ | |||
| 1 | use std::{fs::create_dir_all, str::FromStr, time::Duration}; | 1 | use std::{fs::create_dir_all, str::FromStr, time::Duration}; |
| 2 | 2 | ||
| 3 | use anyhow::{bail, Context, Result}; | 3 | use anyhow::{bail, Context, Result}; |
| 4 | use nostr::{nips::nip46::NostrConnectURI, PublicKey}; | 4 | use nostr::{ |
| 5 | nips::{nip05::get_nip46, nip46::NostrConnectURI}, | ||
| 6 | PublicKey, | ||
| 7 | }; | ||
| 5 | use nostr_database::Order; | 8 | use nostr_database::Order; |
| 6 | use nostr_sdk::{ | 9 | use nostr_sdk::{ |
| 7 | Alphabet, FromBech32, JsonUtil, Keys, Kind, NostrDatabase, NostrSigner, SingleLetterTag, | 10 | Alphabet, FromBech32, JsonUtil, Keys, Kind, NostrDatabase, NostrSigner, SingleLetterTag, |
| @@ -348,41 +351,45 @@ async fn fresh_login( | |||
| 348 | ) -> Result<(NostrSigner, UserRef)> { | 351 | ) -> Result<(NostrSigner, UserRef)> { |
| 349 | let mut public_key: Option<PublicKey> = None; | 352 | let mut public_key: Option<PublicKey> = None; |
| 350 | // prompt for nsec | 353 | // prompt for nsec |
| 351 | let mut prompt = "login with bunker uri / nsec"; | 354 | let mut prompt = "login with nostr address / nsec"; |
| 352 | let signer = loop { | 355 | let signer = loop { |
| 353 | let input = Interactor::default() | 356 | let input = Interactor::default() |
| 354 | .input(PromptInputParms::default().with_prompt(prompt)) | 357 | .input(PromptInputParms::default().with_prompt(prompt)) |
| 355 | .context("failed to get nsec input from interactor")?; | 358 | .context("failed to get nsec input from interactor")?; |
| 356 | match nostr::Keys::from_str(&input) { | 359 | if let Ok(keys) = nostr::Keys::from_str(&input) { |
| 357 | Ok(key) => { | 360 | if let Err(error) = save_keys(git_repo, &keys, always_save) { |
| 358 | if let Err(error) = save_keys(git_repo, &key, always_save) { | 361 | println!("{error}"); |
| 362 | } | ||
| 363 | break NostrSigner::Keys(keys); | ||
| 364 | } | ||
| 365 | let uri = if let Ok(uri) = NostrConnectURI::parse(&input) { | ||
| 366 | uri | ||
| 367 | } else if input.contains('@') { | ||
| 368 | if let Ok(uri) = fetch_nip46_uri_from_nip05(&input).await { | ||
| 369 | uri | ||
| 370 | } else { | ||
| 371 | prompt = "failed. try again with nostr address / bunker uri / nsec"; | ||
| 372 | continue; | ||
| 373 | } | ||
| 374 | } else { | ||
| 375 | prompt = "invalid. try again with nostr address / bunker uri / nsec"; | ||
| 376 | continue; | ||
| 377 | }; | ||
| 378 | let app_key = Keys::generate().secret_key()?.to_secret_hex(); | ||
| 379 | match get_nip46_signer_from_uri_and_key(&uri.to_string(), &app_key).await { | ||
| 380 | Ok(signer) => { | ||
| 381 | let pub_key = fetch_public_key(&signer).await?; | ||
| 382 | if let Err(error) = | ||
| 383 | save_bunker(git_repo, &pub_key, &uri.to_string(), &app_key, always_save) | ||
| 384 | { | ||
| 359 | println!("{error}"); | 385 | println!("{error}"); |
| 360 | } | 386 | } |
| 361 | break NostrSigner::Keys(key); | 387 | public_key = Some(pub_key); |
| 388 | break signer; | ||
| 389 | } | ||
| 390 | Err(_) => { | ||
| 391 | prompt = "failed. try again with nostr address / bunker uri / nsec"; | ||
| 362 | } | 392 | } |
| 363 | Err(_) => match NostrConnectURI::parse(&input) { | ||
| 364 | Ok(_) => { | ||
| 365 | let app_key = Keys::generate().secret_key()?.to_secret_hex(); | ||
| 366 | match get_nip46_signer_from_uri_and_key(&input, &app_key).await { | ||
| 367 | Ok(signer) => { | ||
| 368 | let pub_key = fetch_public_key(&signer).await?; | ||
| 369 | if let Err(error) = | ||
| 370 | save_bunker(git_repo, &pub_key, &input, &app_key, always_save) | ||
| 371 | { | ||
| 372 | println!("{error}"); | ||
| 373 | } | ||
| 374 | public_key = Some(pub_key); | ||
| 375 | break signer; | ||
| 376 | } | ||
| 377 | Err(_) => { | ||
| 378 | prompt = "invalid. try again with nostr address / nsec"; | ||
| 379 | } | ||
| 380 | } | ||
| 381 | } | ||
| 382 | Err(_) => { | ||
| 383 | prompt = "invalid. try again with nostr address / nsec"; | ||
| 384 | } | ||
| 385 | }, | ||
| 386 | } | 393 | } |
| 387 | }; | 394 | }; |
| 388 | let public_key = if let Some(public_key) = public_key { | 395 | let public_key = if let Some(public_key) = public_key { |
| @@ -396,6 +403,30 @@ async fn fresh_login( | |||
| 396 | Ok((signer, user_ref)) | 403 | Ok((signer, user_ref)) |
| 397 | } | 404 | } |
| 398 | 405 | ||
| 406 | pub async fn fetch_nip46_uri_from_nip05(nip05: &str) -> Result<NostrConnectURI> { | ||
| 407 | let term = console::Term::stderr(); | ||
| 408 | term.write_line("contacting login service provider...")?; | ||
| 409 | let res = get_nip46(&nip05, None).await; | ||
| 410 | term.clear_last_lines(1)?; | ||
| 411 | match res { | ||
| 412 | Ok((signer_public_key, relays)) => { | ||
| 413 | if relays.is_empty() { | ||
| 414 | println!("nip05 provider isn't configured for remote login"); | ||
| 415 | bail!("nip05 provider isn't configured for remote login") | ||
| 416 | } | ||
| 417 | Ok(NostrConnectURI::Bunker { | ||
| 418 | signer_public_key, | ||
| 419 | relays, | ||
| 420 | secret: None, | ||
| 421 | }) | ||
| 422 | } | ||
| 423 | Err(error) => { | ||
| 424 | println!("error contacting login service provider: {error}"); | ||
| 425 | Err(error).context("error contacting login service provider") | ||
| 426 | } | ||
| 427 | } | ||
| 428 | } | ||
| 429 | |||
| 399 | fn save_bunker( | 430 | fn save_bunker( |
| 400 | git_repo: &Repo, | 431 | git_repo: &Repo, |
| 401 | public_key: &PublicKey, | 432 | public_key: &PublicKey, |