upleb.uk

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

summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Cargo.lock24
-rw-r--r--Cargo.toml10
-rw-r--r--src/login.rs89
-rw-r--r--test_utils/Cargo.toml4
-rw-r--r--tests/login.rs5
5 files changed, 78 insertions, 54 deletions
diff --git a/Cargo.lock b/Cargo.lock
index a5a8fa0..474adbb 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -1822,8 +1822,7 @@ checksum = "61807f77802ff30975e01f4f071c8ba10c022052f98b3294119f3e615d13e5be"
1822[[package]] 1822[[package]]
1823name = "nostr" 1823name = "nostr"
1824version = "0.32.1" 1824version = "0.32.1"
1825source = "registry+https://github.com/rust-lang/crates.io-index" 1825source = "git+https://github.com/DanConwayDev/nostr?branch=v0.32-get-nip46-from-nip05-address#429f3c1396f05bf08793f60ed1d92d7bc02ea438"
1826checksum = "f7948938314ee0392f378ab1a5d58b4707f2207550bc410b1629a80a4f28af7d"
1827dependencies = [ 1826dependencies = [
1828 "aes 0.8.4", 1827 "aes 0.8.4",
1829 "base64 0.21.7", 1828 "base64 0.21.7",
@@ -1852,8 +1851,7 @@ dependencies = [
1852[[package]] 1851[[package]]
1853name = "nostr-database" 1852name = "nostr-database"
1854version = "0.32.0" 1853version = "0.32.0"
1855source = "registry+https://github.com/rust-lang/crates.io-index" 1854source = "git+https://github.com/DanConwayDev/nostr?branch=v0.32-get-nip46-from-nip05-address#429f3c1396f05bf08793f60ed1d92d7bc02ea438"
1856checksum = "a88a72f92fbd5d2514db36e07a864646f1c1f44931c4a5ea195f6961029af4b3"
1857dependencies = [ 1855dependencies = [
1858 "async-trait", 1856 "async-trait",
1859 "flatbuffers", 1857 "flatbuffers",
@@ -1867,8 +1865,7 @@ dependencies = [
1867[[package]] 1865[[package]]
1868name = "nostr-relay-pool" 1866name = "nostr-relay-pool"
1869version = "0.32.0" 1867version = "0.32.0"
1870source = "registry+https://github.com/rust-lang/crates.io-index" 1868source = "git+https://github.com/DanConwayDev/nostr?branch=v0.32-get-nip46-from-nip05-address#429f3c1396f05bf08793f60ed1d92d7bc02ea438"
1871checksum = "d7b7bf72b02a24ccc7cf87033fa5ddfd57001c7d8c2e757321a7ca7a6df39876"
1872dependencies = [ 1869dependencies = [
1873 "async-utility", 1870 "async-utility",
1874 "async-wsocket", 1871 "async-wsocket",
@@ -1883,8 +1880,7 @@ dependencies = [
1883[[package]] 1880[[package]]
1884name = "nostr-sdk" 1881name = "nostr-sdk"
1885version = "0.32.0" 1882version = "0.32.0"
1886source = "registry+https://github.com/rust-lang/crates.io-index" 1883source = "git+https://github.com/DanConwayDev/nostr?branch=v0.32-get-nip46-from-nip05-address#429f3c1396f05bf08793f60ed1d92d7bc02ea438"
1887checksum = "005915a59ee6401f23ba510c3a9ac4a07b457f80dfe1dc05cd2c8fdbde439246"
1888dependencies = [ 1884dependencies = [
1889 "async-utility", 1885 "async-utility",
1890 "atomic-destructor", 1886 "atomic-destructor",
@@ -1903,8 +1899,7 @@ dependencies = [
1903[[package]] 1899[[package]]
1904name = "nostr-signer" 1900name = "nostr-signer"
1905version = "0.32.0" 1901version = "0.32.0"
1906source = "registry+https://github.com/rust-lang/crates.io-index" 1902source = "git+https://github.com/DanConwayDev/nostr?branch=v0.32-get-nip46-from-nip05-address#429f3c1396f05bf08793f60ed1d92d7bc02ea438"
1907checksum = "525574dc32fa07d64d04a6c72b534d97455b1ad954c29753c820c834c94e3704"
1908dependencies = [ 1903dependencies = [
1909 "async-utility", 1904 "async-utility",
1910 "nostr", 1905 "nostr",
@@ -1917,8 +1912,7 @@ dependencies = [
1917[[package]] 1912[[package]]
1918name = "nostr-sqlite" 1913name = "nostr-sqlite"
1919version = "0.32.0" 1914version = "0.32.0"
1920source = "registry+https://github.com/rust-lang/crates.io-index" 1915source = "git+https://github.com/DanConwayDev/nostr?branch=v0.32-get-nip46-from-nip05-address#429f3c1396f05bf08793f60ed1d92d7bc02ea438"
1921checksum = "418555707a30105f738b3a54a1ae13ffca5e7ec10b4d27a8c20bedde636233c3"
1922dependencies = [ 1916dependencies = [
1923 "async-trait", 1917 "async-trait",
1924 "nostr", 1918 "nostr",
@@ -1932,8 +1926,7 @@ dependencies = [
1932[[package]] 1926[[package]]
1933name = "nostr-zapper" 1927name = "nostr-zapper"
1934version = "0.32.0" 1928version = "0.32.0"
1935source = "registry+https://github.com/rust-lang/crates.io-index" 1929source = "git+https://github.com/DanConwayDev/nostr?branch=v0.32-get-nip46-from-nip05-address#429f3c1396f05bf08793f60ed1d92d7bc02ea438"
1936checksum = "430c2527c0efd2e7f1a421b0c7df01a03b334a79c60c39cc7a1ca684f720f2bf"
1937dependencies = [ 1930dependencies = [
1938 "async-trait", 1931 "async-trait",
1939 "nostr", 1932 "nostr",
@@ -2034,8 +2027,7 @@ checksum = "830b246a0e5f20af87141b25c173cd1b609bd7779a4617d6ec582abaf90870f3"
2034[[package]] 2027[[package]]
2035name = "nwc" 2028name = "nwc"
2036version = "0.32.0" 2029version = "0.32.0"
2037source = "registry+https://github.com/rust-lang/crates.io-index" 2030source = "git+https://github.com/DanConwayDev/nostr?branch=v0.32-get-nip46-from-nip05-address#429f3c1396f05bf08793f60ed1d92d7bc02ea438"
2038checksum = "c6fb91e4be3f6b872fc23c7714bbb500a58a1d59f458eb6eb9dd249fbec42fc2"
2039dependencies = [ 2031dependencies = [
2040 "async-utility", 2032 "async-utility",
2041 "nostr", 2033 "nostr",
diff --git a/Cargo.toml b/Cargo.toml
index d41d870..a0e2d00 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -23,11 +23,11 @@ futures = "0.3.28"
23git2 = "0.18.1" 23git2 = "0.18.1"
24indicatif = "0.17.7" 24indicatif = "0.17.7"
25keyring = "2.0.5" 25keyring = "2.0.5"
26nostr = "0.32.0" 26nostr = { git = "https://github.com/DanConwayDev/nostr", branch= "v0.32-get-nip46-from-nip05-address" }
27nostr-database = "0.32.0" 27nostr-database = { git = "https://github.com/DanConwayDev/nostr", branch= "v0.32-get-nip46-from-nip05-address" }
28nostr-sdk = "0.32.0" 28nostr-sdk = { git = "https://github.com/DanConwayDev/nostr", branch= "v0.32-get-nip46-from-nip05-address" }
29nostr-signer = "0.32.0" 29nostr-signer = { git = "https://github.com/DanConwayDev/nostr", branch= "v0.32-get-nip46-from-nip05-address" }
30nostr-sqlite = "0.32.0" 30nostr-sqlite = { git = "https://github.com/DanConwayDev/nostr", branch= "v0.32-get-nip46-from-nip05-address" }
31passwords = "3.1.13" 31passwords = "3.1.13"
32scrypt = "0.11.0" 32scrypt = "0.11.0"
33serde = { version = "1.0.181", features = ["derive"] } 33serde = { version = "1.0.181", features = ["derive"] }
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,
diff --git a/test_utils/Cargo.toml b/test_utils/Cargo.toml
index 43f3629..92f4dfd 100644
--- a/test_utils/Cargo.toml
+++ b/test_utils/Cargo.toml
@@ -9,8 +9,8 @@ assert_cmd = "2.0.12"
9dialoguer = "0.10.4" 9dialoguer = "0.10.4"
10directories = "5.0.1" 10directories = "5.0.1"
11git2 = "0.18.1" 11git2 = "0.18.1"
12nostr = "0.32.0" 12nostr = { git = "https://github.com/DanConwayDev/nostr", branch= "v0.32-get-nip46-from-nip05-address" }
13nostr-sdk = "0.32.0" 13nostr-sdk = { git = "https://github.com/DanConwayDev/nostr", branch= "v0.32-get-nip46-from-nip05-address" }
14once_cell = "1.18.0" 14once_cell = "1.18.0"
15rand = "0.8" 15rand = "0.8"
16rexpect = { git = "https://github.com/rust-cli/rexpect.git", rev = "9eb61dd" } 16rexpect = { git = "https://github.com/rust-cli/rexpect.git", rev = "9eb61dd" }
diff --git a/tests/login.rs b/tests/login.rs
index 9da2a0e..4cc2dbe 100644
--- a/tests/login.rs
+++ b/tests/login.rs
@@ -3,7 +3,7 @@ use git::GitTestRepo;
3use serial_test::serial; 3use serial_test::serial;
4use test_utils::*; 4use test_utils::*;
5 5
6static EXPECTED_NSEC_PROMPT: &str = "login with bunker uri / nsec"; 6static EXPECTED_NSEC_PROMPT: &str = "login with nostr address / nsec";
7static EXPECTED_LOCAL_REPOSITORY_PROMPT: &str = "just for this repository?"; 7static EXPECTED_LOCAL_REPOSITORY_PROMPT: &str = "just for this repository?";
8static EXPECTED_REQUIRE_PASSWORD_PROMPT: &str = "require password?"; 8static EXPECTED_REQUIRE_PASSWORD_PROMPT: &str = "require password?";
9static EXPECTED_SET_PASSWORD_PROMPT: &str = "encrypt with password"; 9static EXPECTED_SET_PASSWORD_PROMPT: &str = "encrypt with password";
@@ -909,7 +909,8 @@ mod with_offline_flag {
909 909
910 #[test] 910 #[test]
911 fn prompts_for_nsec_until_valid() -> Result<()> { 911 fn prompts_for_nsec_until_valid() -> Result<()> {
912 let invalid_nsec_response = "invalid. try again with nostr address / nsec"; 912 let invalid_nsec_response =
913 "invalid. try again with nostr address / bunker uri / nsec";
913 914
914 let test_repo = GitTestRepo::default(); 915 let test_repo = GitTestRepo::default();
915 let mut p = CliTester::new_from_dir(&test_repo.dir, ["login", "--offline"]); 916 let mut p = CliTester::new_from_dir(&test_repo.dir, ["login", "--offline"]);