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