upleb.uk

Public git repos — served from a NIP-34 GRASP relay at git.upleb.uk

summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/login.rs89
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 @@
1use std::{fs::create_dir_all, str::FromStr, time::Duration}; 1use std::{fs::create_dir_all, str::FromStr, time::Duration};
2 2
3use anyhow::{bail, Context, Result}; 3use anyhow::{bail, Context, Result};
4use nostr::{nips::nip46::NostrConnectURI, PublicKey}; 4use nostr::{
5 nips::{nip05::get_nip46, nip46::NostrConnectURI},
6 PublicKey,
7};
5use nostr_database::Order; 8use nostr_database::Order;
6use nostr_sdk::{ 9use 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
406pub 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
399fn save_bunker( 430fn save_bunker(
400 git_repo: &Repo, 431 git_repo: &Repo,
401 public_key: &PublicKey, 432 public_key: &PublicKey,