diff options
| author | DanConwayDev <DanConwayDev@protonmail.com> | 2024-06-25 09:06:47 +0100 |
|---|---|---|
| committer | DanConwayDev <DanConwayDev@protonmail.com> | 2024-06-25 09:06:47 +0100 |
| commit | b63bfc9a34657c5767c507deb7c059e24dd22779 (patch) | |
| tree | 462be1e29e6f21c5e0d75458e4966f574389451c /src/repo_ref.rs | |
| parent | 20d201740f0ace8437cf595476a52f9e42407724 (diff) | |
refactor: replace keys with signer
so that nip46 bunker signing can be added
Diffstat (limited to 'src/repo_ref.rs')
| -rw-r--r-- | src/repo_ref.rs | 257 |
1 files changed, 133 insertions, 124 deletions
diff --git a/src/repo_ref.rs b/src/repo_ref.rs index 7016257..2b0d024 100644 --- a/src/repo_ref.rs +++ b/src/repo_ref.rs | |||
| @@ -2,6 +2,7 @@ use std::{fs::File, io::BufReader, str::FromStr}; | |||
| 2 | 2 | ||
| 3 | use anyhow::{bail, Context, Result}; | 3 | use anyhow::{bail, Context, Result}; |
| 4 | use nostr::{nips::nip19::Nip19, FromBech32, PublicKey, Tag, TagStandard, ToBech32}; | 4 | use nostr::{nips::nip19::Nip19, FromBech32, PublicKey, Tag, TagStandard, ToBech32}; |
| 5 | use nostr_sdk::NostrSigner; | ||
| 5 | use serde::{Deserialize, Serialize}; | 6 | use serde::{Deserialize, Serialize}; |
| 6 | 7 | ||
| 7 | #[cfg(not(test))] | 8 | #[cfg(not(test))] |
| @@ -93,66 +94,67 @@ impl TryFrom<nostr::Event> for RepoRef { | |||
| 93 | pub static REPO_REF_KIND: u16 = 30_617; | 94 | pub static REPO_REF_KIND: u16 = 30_617; |
| 94 | 95 | ||
| 95 | impl RepoRef { | 96 | impl RepoRef { |
| 96 | pub fn to_event(&self, keys: &nostr::Keys) -> Result<nostr::Event> { | 97 | pub async fn to_event(&self, signer: &NostrSigner) -> Result<nostr::Event> { |
| 97 | nostr_sdk::EventBuilder::new( | 98 | signer |
| 98 | nostr::event::Kind::Custom(REPO_REF_KIND), | 99 | .sign_event_builder(nostr_sdk::EventBuilder::new( |
| 99 | "", | 100 | nostr::event::Kind::Custom(REPO_REF_KIND), |
| 100 | [ | 101 | "", |
| 101 | vec![ | 102 | [ |
| 102 | Tag::identifier(if self.identifier.to_string().is_empty() { | 103 | vec![ |
| 103 | // fiatjaf thought a random string. its not in the draft nip. | 104 | Tag::identifier(if self.identifier.to_string().is_empty() { |
| 104 | // thread_rng() | 105 | // fiatjaf thought a random string. its not in the draft nip. |
| 105 | // .sample_iter(&Alphanumeric) | 106 | // thread_rng() |
| 106 | // .take(15) | 107 | // .sample_iter(&Alphanumeric) |
| 107 | // .map(char::from) | 108 | // .take(15) |
| 108 | // .collect() | 109 | // .map(char::from) |
| 109 | 110 | // .collect() | |
| 110 | // an identifier based on first commit is better so that users dont | 111 | |
| 111 | // accidentally create two seperate identifiers for the same repo | 112 | // an identifier based on first commit is better so that users dont |
| 112 | // there is a hesitancy to use the commit id | 113 | // accidentally create two seperate identifiers for the same repo |
| 113 | // in another conversaion with fiatjaf he suggested the first 6 character of | 114 | // there is a hesitancy to use the commit id |
| 114 | // the commit id | 115 | // in another conversaion with fiatjaf he suggested the first 6 |
| 115 | // here we are using 7 which is the standard for shorthand commit id | 116 | // character of the commit id |
| 116 | self.root_commit.to_string()[..7].to_string() | 117 | // here we are using 7 which is the standard for shorthand commit id |
| 117 | } else { | 118 | self.root_commit.to_string()[..7].to_string() |
| 118 | self.identifier.to_string() | 119 | } else { |
| 119 | }), | 120 | self.identifier.to_string() |
| 120 | Tag::custom( | 121 | }), |
| 121 | nostr::TagKind::Custom(std::borrow::Cow::Borrowed("r")), | 122 | Tag::custom( |
| 122 | vec![self.root_commit.to_string(), "euc".to_string()], | 123 | nostr::TagKind::Custom(std::borrow::Cow::Borrowed("r")), |
| 123 | ), | 124 | vec![self.root_commit.to_string(), "euc".to_string()], |
| 124 | Tag::from_standardized(TagStandard::Name(self.name.clone())), | 125 | ), |
| 125 | Tag::from_standardized(TagStandard::Description(self.description.clone())), | 126 | Tag::from_standardized(TagStandard::Name(self.name.clone())), |
| 126 | Tag::custom( | 127 | Tag::from_standardized(TagStandard::Description(self.description.clone())), |
| 127 | nostr::TagKind::Custom(std::borrow::Cow::Borrowed("clone")), | 128 | Tag::custom( |
| 128 | self.git_server.clone(), | 129 | nostr::TagKind::Custom(std::borrow::Cow::Borrowed("clone")), |
| 129 | ), | 130 | self.git_server.clone(), |
| 130 | Tag::custom( | 131 | ), |
| 131 | nostr::TagKind::Custom(std::borrow::Cow::Borrowed("web")), | 132 | Tag::custom( |
| 132 | self.web.clone(), | 133 | nostr::TagKind::Custom(std::borrow::Cow::Borrowed("web")), |
| 133 | ), | 134 | self.web.clone(), |
| 134 | Tag::custom( | 135 | ), |
| 135 | nostr::TagKind::Custom(std::borrow::Cow::Borrowed("relays")), | 136 | Tag::custom( |
| 136 | self.relays.clone(), | 137 | nostr::TagKind::Custom(std::borrow::Cow::Borrowed("relays")), |
| 137 | ), | 138 | self.relays.clone(), |
| 138 | Tag::custom( | 139 | ), |
| 139 | nostr::TagKind::Custom(std::borrow::Cow::Borrowed("maintainers")), | 140 | Tag::custom( |
| 140 | self.maintainers | 141 | nostr::TagKind::Custom(std::borrow::Cow::Borrowed("maintainers")), |
| 141 | .iter() | 142 | self.maintainers |
| 142 | .map(std::string::ToString::to_string) | 143 | .iter() |
| 143 | .collect::<Vec<String>>(), | 144 | .map(std::string::ToString::to_string) |
| 144 | ), | 145 | .collect::<Vec<String>>(), |
| 145 | Tag::custom( | 146 | ), |
| 146 | nostr::TagKind::Custom(std::borrow::Cow::Borrowed("alt")), | 147 | Tag::custom( |
| 147 | vec![format!("git repository: {}", self.name.clone())], | 148 | nostr::TagKind::Custom(std::borrow::Cow::Borrowed("alt")), |
| 148 | ), | 149 | vec![format!("git repository: {}", self.name.clone())], |
| 149 | ], | 150 | ), |
| 150 | // code languages and hashtags | 151 | ], |
| 151 | ] | 152 | // code languages and hashtags |
| 152 | .concat(), | 153 | ] |
| 153 | ) | 154 | .concat(), |
| 154 | .to_event(keys) | 155 | )) |
| 155 | .context("failed to create repository reference event") | 156 | .await |
| 157 | .context("failed to create repository reference event") | ||
| 156 | } | 158 | } |
| 157 | } | 159 | } |
| 158 | 160 | ||
| @@ -308,7 +310,7 @@ mod tests { | |||
| 308 | 310 | ||
| 309 | use super::*; | 311 | use super::*; |
| 310 | 312 | ||
| 311 | fn create() -> nostr::Event { | 313 | async fn create() -> nostr::Event { |
| 312 | RepoRef { | 314 | RepoRef { |
| 313 | identifier: "123412341".to_string(), | 315 | identifier: "123412341".to_string(), |
| 314 | name: "test name".to_string(), | 316 | name: "test name".to_string(), |
| @@ -322,34 +324,38 @@ mod tests { | |||
| 322 | relays: vec!["ws://relay1.io".to_string(), "ws://relay2.io".to_string()], | 324 | relays: vec!["ws://relay1.io".to_string(), "ws://relay2.io".to_string()], |
| 323 | maintainers: vec![TEST_KEY_1_KEYS.public_key(), TEST_KEY_2_KEYS.public_key()], | 325 | maintainers: vec![TEST_KEY_1_KEYS.public_key(), TEST_KEY_2_KEYS.public_key()], |
| 324 | } | 326 | } |
| 325 | .to_event(&TEST_KEY_1_KEYS) | 327 | .to_event(&TEST_KEY_1_SIGNER) |
| 328 | .await | ||
| 326 | .unwrap() | 329 | .unwrap() |
| 327 | } | 330 | } |
| 328 | mod try_from { | 331 | mod try_from { |
| 329 | use super::*; | 332 | use super::*; |
| 330 | 333 | ||
| 331 | #[test] | 334 | #[tokio::test] |
| 332 | fn identifier() { | 335 | async fn identifier() { |
| 333 | assert_eq!(RepoRef::try_from(create()).unwrap().identifier, "123412341",) | 336 | assert_eq!( |
| 337 | RepoRef::try_from(create().await).unwrap().identifier, | ||
| 338 | "123412341", | ||
| 339 | ) | ||
| 334 | } | 340 | } |
| 335 | 341 | ||
| 336 | #[test] | 342 | #[tokio::test] |
| 337 | fn name() { | 343 | async fn name() { |
| 338 | assert_eq!(RepoRef::try_from(create()).unwrap().name, "test name",) | 344 | assert_eq!(RepoRef::try_from(create().await).unwrap().name, "test name",) |
| 339 | } | 345 | } |
| 340 | 346 | ||
| 341 | #[test] | 347 | #[tokio::test] |
| 342 | fn description() { | 348 | async fn description() { |
| 343 | assert_eq!( | 349 | assert_eq!( |
| 344 | RepoRef::try_from(create()).unwrap().description, | 350 | RepoRef::try_from(create().await).unwrap().description, |
| 345 | "test description", | 351 | "test description", |
| 346 | ) | 352 | ) |
| 347 | } | 353 | } |
| 348 | 354 | ||
| 349 | #[test] | 355 | #[tokio::test] |
| 350 | fn root_commit_is_r_tag() { | 356 | async fn root_commit_is_r_tag() { |
| 351 | assert_eq!( | 357 | assert_eq!( |
| 352 | RepoRef::try_from(create()).unwrap().root_commit, | 358 | RepoRef::try_from(create().await).unwrap().root_commit, |
| 353 | "5e664e5a7845cd1373c79f580ca4fe29ab5b34d2", | 359 | "5e664e5a7845cd1373c79f580ca4fe29ab5b34d2", |
| 354 | ) | 360 | ) |
| 355 | } | 361 | } |
| @@ -358,42 +364,43 @@ mod tests { | |||
| 358 | use nostr::JsonUtil; | 364 | use nostr::JsonUtil; |
| 359 | 365 | ||
| 360 | use super::*; | 366 | use super::*; |
| 361 | fn create_with_incorrect_first_commit_ref(s: &str) -> nostr::Event { | 367 | async fn create_with_incorrect_first_commit_ref(s: &str) -> nostr::Event { |
| 362 | nostr::Event::from_json( | 368 | nostr::Event::from_json( |
| 363 | create() | 369 | create() |
| 370 | .await | ||
| 364 | .as_json() | 371 | .as_json() |
| 365 | .replace("5e664e5a7845cd1373c79f580ca4fe29ab5b34d2", s), | 372 | .replace("5e664e5a7845cd1373c79f580ca4fe29ab5b34d2", s), |
| 366 | ) | 373 | ) |
| 367 | .unwrap() | 374 | .unwrap() |
| 368 | } | 375 | } |
| 369 | 376 | ||
| 370 | #[test] | 377 | #[tokio::test] |
| 371 | fn less_than_40_characters() { | 378 | async fn less_than_40_characters() { |
| 372 | let s = "5e664e5a7845cd1373"; | 379 | let s = "5e664e5a7845cd1373"; |
| 373 | assert_eq!( | 380 | assert_eq!( |
| 374 | RepoRef::try_from(create_with_incorrect_first_commit_ref(s)) | 381 | RepoRef::try_from(create_with_incorrect_first_commit_ref(s).await) |
| 375 | .unwrap() | 382 | .unwrap() |
| 376 | .root_commit, | 383 | .root_commit, |
| 377 | "", | 384 | "", |
| 378 | ) | 385 | ) |
| 379 | } | 386 | } |
| 380 | 387 | ||
| 381 | #[test] | 388 | #[tokio::test] |
| 382 | fn more_than_40_characters() { | 389 | async fn more_than_40_characters() { |
| 383 | let s = "5e664e5a7845cd1373c79f580ca4fe29ab5b34d2111111111"; | 390 | let s = "5e664e5a7845cd1373c79f580ca4fe29ab5b34d2111111111"; |
| 384 | assert_eq!( | 391 | assert_eq!( |
| 385 | RepoRef::try_from(create_with_incorrect_first_commit_ref(s)) | 392 | RepoRef::try_from(create_with_incorrect_first_commit_ref(s).await) |
| 386 | .unwrap() | 393 | .unwrap() |
| 387 | .root_commit, | 394 | .root_commit, |
| 388 | "", | 395 | "", |
| 389 | ) | 396 | ) |
| 390 | } | 397 | } |
| 391 | 398 | ||
| 392 | #[test] | 399 | #[tokio::test] |
| 393 | fn not_hex_characters() { | 400 | async fn not_hex_characters() { |
| 394 | let s = "xxx64e5a7845cd1373c79f580ca4fe29ab5b34d2"; | 401 | let s = "xxx64e5a7845cd1373c79f580ca4fe29ab5b34d2"; |
| 395 | assert_eq!( | 402 | assert_eq!( |
| 396 | RepoRef::try_from(create_with_incorrect_first_commit_ref(s)) | 403 | RepoRef::try_from(create_with_incorrect_first_commit_ref(s).await) |
| 397 | .unwrap() | 404 | .unwrap() |
| 398 | .root_commit, | 405 | .root_commit, |
| 399 | "", | 406 | "", |
| @@ -401,18 +408,18 @@ mod tests { | |||
| 401 | } | 408 | } |
| 402 | } | 409 | } |
| 403 | 410 | ||
| 404 | #[test] | 411 | #[tokio::test] |
| 405 | fn git_server() { | 412 | async fn git_server() { |
| 406 | assert_eq!( | 413 | assert_eq!( |
| 407 | RepoRef::try_from(create()).unwrap().git_server, | 414 | RepoRef::try_from(create().await).unwrap().git_server, |
| 408 | vec!["https://localhost:1000"], | 415 | vec!["https://localhost:1000"], |
| 409 | ) | 416 | ) |
| 410 | } | 417 | } |
| 411 | 418 | ||
| 412 | #[test] | 419 | #[tokio::test] |
| 413 | fn web() { | 420 | async fn web() { |
| 414 | assert_eq!( | 421 | assert_eq!( |
| 415 | RepoRef::try_from(create()).unwrap().web, | 422 | RepoRef::try_from(create().await).unwrap().web, |
| 416 | vec![ | 423 | vec![ |
| 417 | "https://exampleproject.xyz".to_string(), | 424 | "https://exampleproject.xyz".to_string(), |
| 418 | "https://gitworkshop.dev/123".to_string() | 425 | "https://gitworkshop.dev/123".to_string() |
| @@ -420,18 +427,18 @@ mod tests { | |||
| 420 | ) | 427 | ) |
| 421 | } | 428 | } |
| 422 | 429 | ||
| 423 | #[test] | 430 | #[tokio::test] |
| 424 | fn relays() { | 431 | async fn relays() { |
| 425 | assert_eq!( | 432 | assert_eq!( |
| 426 | RepoRef::try_from(create()).unwrap().relays, | 433 | RepoRef::try_from(create().await).unwrap().relays, |
| 427 | vec!["ws://relay1.io".to_string(), "ws://relay2.io".to_string()], | 434 | vec!["ws://relay1.io".to_string(), "ws://relay2.io".to_string()], |
| 428 | ) | 435 | ) |
| 429 | } | 436 | } |
| 430 | 437 | ||
| 431 | #[test] | 438 | #[tokio::test] |
| 432 | fn maintainers() { | 439 | async fn maintainers() { |
| 433 | assert_eq!( | 440 | assert_eq!( |
| 434 | RepoRef::try_from(create()).unwrap().maintainers, | 441 | RepoRef::try_from(create().await).unwrap().maintainers, |
| 435 | vec![TEST_KEY_1_KEYS.public_key(), TEST_KEY_2_KEYS.public_key()], | 442 | vec![TEST_KEY_1_KEYS.public_key(), TEST_KEY_2_KEYS.public_key()], |
| 436 | ) | 443 | ) |
| 437 | } | 444 | } |
| @@ -442,57 +449,59 @@ mod tests { | |||
| 442 | mod tags { | 449 | mod tags { |
| 443 | use super::*; | 450 | use super::*; |
| 444 | 451 | ||
| 445 | #[test] | 452 | #[tokio::test] |
| 446 | fn identifier() { | 453 | async fn identifier() { |
| 447 | assert!( | 454 | assert!( |
| 448 | create() | 455 | create() |
| 456 | .await | ||
| 449 | .tags | 457 | .tags |
| 450 | .iter() | 458 | .iter() |
| 451 | .any(|t| t.as_vec()[0].eq("d") && t.as_vec()[1].eq("123412341")) | 459 | .any(|t| t.as_vec()[0].eq("d") && t.as_vec()[1].eq("123412341")) |
| 452 | ) | 460 | ) |
| 453 | } | 461 | } |
| 454 | 462 | ||
| 455 | #[test] | 463 | #[tokio::test] |
| 456 | fn name() { | 464 | async fn name() { |
| 457 | assert!( | 465 | assert!( |
| 458 | create() | 466 | create() |
| 467 | .await | ||
| 459 | .tags | 468 | .tags |
| 460 | .iter() | 469 | .iter() |
| 461 | .any(|t| t.as_vec()[0].eq("name") && t.as_vec()[1].eq("test name")) | 470 | .any(|t| t.as_vec()[0].eq("name") && t.as_vec()[1].eq("test name")) |
| 462 | ) | 471 | ) |
| 463 | } | 472 | } |
| 464 | 473 | ||
| 465 | #[test] | 474 | #[tokio::test] |
| 466 | fn alt() { | 475 | async fn alt() { |
| 467 | assert!( | 476 | assert!( |
| 468 | create().tags.iter().any(|t| t.as_vec()[0].eq("alt") | 477 | create().await.tags.iter().any(|t| t.as_vec()[0].eq("alt") |
| 469 | && t.as_vec()[1].eq("git repository: test name")) | 478 | && t.as_vec()[1].eq("git repository: test name")) |
| 470 | ) | 479 | ) |
| 471 | } | 480 | } |
| 472 | 481 | ||
| 473 | #[test] | 482 | #[tokio::test] |
| 474 | fn description() { | 483 | async fn description() { |
| 475 | assert!(create().tags.iter().any( | 484 | assert!(create().await.tags.iter().any( |
| 476 | |t| t.as_vec()[0].eq("description") && t.as_vec()[1].eq("test description") | 485 | |t| t.as_vec()[0].eq("description") && t.as_vec()[1].eq("test description") |
| 477 | )) | 486 | )) |
| 478 | } | 487 | } |
| 479 | 488 | ||
| 480 | #[test] | 489 | #[tokio::test] |
| 481 | fn root_commit_as_reference() { | 490 | async fn root_commit_as_reference() { |
| 482 | assert!(create().tags.iter().any(|t| t.as_vec()[0].eq("r") | 491 | assert!(create().await.tags.iter().any(|t| t.as_vec()[0].eq("r") |
| 483 | && t.as_vec()[1].eq("5e664e5a7845cd1373c79f580ca4fe29ab5b34d2"))) | 492 | && t.as_vec()[1].eq("5e664e5a7845cd1373c79f580ca4fe29ab5b34d2"))) |
| 484 | } | 493 | } |
| 485 | 494 | ||
| 486 | #[test] | 495 | #[tokio::test] |
| 487 | fn git_server() { | 496 | async fn git_server() { |
| 488 | assert!(create().tags.iter().any( | 497 | assert!(create().await.tags.iter().any( |
| 489 | |t| t.as_vec()[0].eq("clone") && t.as_vec()[1].eq("https://localhost:1000") | 498 | |t| t.as_vec()[0].eq("clone") && t.as_vec()[1].eq("https://localhost:1000") |
| 490 | )) | 499 | )) |
| 491 | } | 500 | } |
| 492 | 501 | ||
| 493 | #[test] | 502 | #[tokio::test] |
| 494 | fn relays() { | 503 | async fn relays() { |
| 495 | let event = create(); | 504 | let event = create().await; |
| 496 | let relays_tag: &nostr::Tag = event | 505 | let relays_tag: &nostr::Tag = event |
| 497 | .tags | 506 | .tags |
| 498 | .iter() | 507 | .iter() |
| @@ -503,9 +512,9 @@ mod tests { | |||
| 503 | assert_eq!(relays_tag.as_vec()[2], "ws://relay2.io"); | 512 | assert_eq!(relays_tag.as_vec()[2], "ws://relay2.io"); |
| 504 | } | 513 | } |
| 505 | 514 | ||
| 506 | #[test] | 515 | #[tokio::test] |
| 507 | fn web() { | 516 | async fn web() { |
| 508 | let event = create(); | 517 | let event = create().await; |
| 509 | let web_tag: &nostr::Tag = | 518 | let web_tag: &nostr::Tag = |
| 510 | event.tags.iter().find(|t| t.as_vec()[0].eq("web")).unwrap(); | 519 | event.tags.iter().find(|t| t.as_vec()[0].eq("web")).unwrap(); |
| 511 | assert_eq!(web_tag.as_vec().len(), 3); | 520 | assert_eq!(web_tag.as_vec().len(), 3); |
| @@ -513,9 +522,9 @@ mod tests { | |||
| 513 | assert_eq!(web_tag.as_vec()[2], "https://gitworkshop.dev/123"); | 522 | assert_eq!(web_tag.as_vec()[2], "https://gitworkshop.dev/123"); |
| 514 | } | 523 | } |
| 515 | 524 | ||
| 516 | #[test] | 525 | #[tokio::test] |
| 517 | fn maintainers() { | 526 | async fn maintainers() { |
| 518 | let event = create(); | 527 | let event = create().await; |
| 519 | let maintainers_tag: &nostr::Tag = event | 528 | let maintainers_tag: &nostr::Tag = event |
| 520 | .tags | 529 | .tags |
| 521 | .iter() | 530 | .iter() |
| @@ -532,9 +541,9 @@ mod tests { | |||
| 532 | ); | 541 | ); |
| 533 | } | 542 | } |
| 534 | 543 | ||
| 535 | #[test] | 544 | #[tokio::test] |
| 536 | fn no_other_tags() { | 545 | async fn no_other_tags() { |
| 537 | assert_eq!(create().tags.len(), 9) | 546 | assert_eq!(create().await.tags.len(), 9) |
| 538 | } | 547 | } |
| 539 | } | 548 | } |
| 540 | } | 549 | } |