upleb.uk

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

summaryrefslogtreecommitdiff
path: root/src/repo_ref.rs
diff options
context:
space:
mode:
authorDanConwayDev <DanConwayDev@protonmail.com>2024-06-25 09:06:47 +0100
committerDanConwayDev <DanConwayDev@protonmail.com>2024-06-25 09:06:47 +0100
commitb63bfc9a34657c5767c507deb7c059e24dd22779 (patch)
tree462be1e29e6f21c5e0d75458e4966f574389451c /src/repo_ref.rs
parent20d201740f0ace8437cf595476a52f9e42407724 (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.rs257
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
3use anyhow::{bail, Context, Result}; 3use anyhow::{bail, Context, Result};
4use nostr::{nips::nip19::Nip19, FromBech32, PublicKey, Tag, TagStandard, ToBech32}; 4use nostr::{nips::nip19::Nip19, FromBech32, PublicKey, Tag, TagStandard, ToBech32};
5use nostr_sdk::NostrSigner;
5use serde::{Deserialize, Serialize}; 6use serde::{Deserialize, Serialize};
6 7
7#[cfg(not(test))] 8#[cfg(not(test))]
@@ -93,66 +94,67 @@ impl TryFrom<nostr::Event> for RepoRef {
93pub static REPO_REF_KIND: u16 = 30_617; 94pub static REPO_REF_KIND: u16 = 30_617;
94 95
95impl RepoRef { 96impl 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 }