upleb.uk

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

summaryrefslogtreecommitdiff
path: root/grasp-audit/src/client.rs
diff options
context:
space:
mode:
authorDanConwayDev <DanConwayDev@protonmail.com>2025-11-26 08:45:16 +0000
committerDanConwayDev <DanConwayDev@protonmail.com>2025-11-26 09:56:44 +0000
commita6edb42dfc653b6826b59b7f296e0d0c4ee74557 (patch)
tree4355445d8d51672cbf1dd86af0a4bd2ffcde1a7a /grasp-audit/src/client.rs
parent30411a938d072a59d68815c975735d40366ad874 (diff)
fix: parsing maintainers from announcement event
Diffstat (limited to 'grasp-audit/src/client.rs')
-rw-r--r--grasp-audit/src/client.rs125
1 files changed, 125 insertions, 0 deletions
diff --git a/grasp-audit/src/client.rs b/grasp-audit/src/client.rs
index 35aaccd..b2a4e38 100644
--- a/grasp-audit/src/client.rs
+++ b/grasp-audit/src/client.rs
@@ -286,6 +286,80 @@ impl AuditClient {
286 Ok(event) 286 Ok(event)
287 } 287 }
288 288
289 /// Create a NIP-34 repository announcement event with maintainers
290 ///
291 /// This helper creates a properly formatted NIP-34 announcement that will be
292 /// accepted by GRASP relays (which require events to list the relay in clone/relays tags).
293 /// This variant also includes a maintainers tag for push authorization testing.
294 ///
295 /// # Arguments
296 /// * `test_name` - Name of the test (used to create unique repo identifier)
297 /// * `maintainer_pubkeys` - Hex pubkeys of maintainers who can push to the repository
298 ///
299 /// # Returns
300 /// A built and signed Event ready to be sent to the relay
301 pub async fn create_repo_announcement_with_maintainers(
302 &self,
303 test_name: &str,
304 maintainer_pubkeys: &[String],
305 ) -> Result<Event> {
306 // Get relay URL from client
307 let relay_url = self
308 .client
309 .relays()
310 .await
311 .keys()
312 .next()
313 .ok_or_else(|| anyhow!("No relay connected"))?
314 .to_string();
315
316 // Convert WebSocket URL to HTTP URL for clone tag
317 let http_url = relay_url
318 .replace("ws://", "http://")
319 .replace("wss://", "https://");
320
321 // Create unique repository identifier using UUID for consistency
322 let repo_id = format!("{}-{}", test_name, &uuid::Uuid::new_v4().to_string()[..8]);
323
324 // Get npub for clone URL
325 let npub = self
326 .public_key()
327 .to_bech32()
328 .map_err(|e| anyhow!("Failed to convert public key to bech32 npub format: {}", e))?;
329
330 // Build kind 30617 repository announcement with maintainers tag
331 let event = self
332 .event_builder(
333 Kind::GitRepoAnnouncement,
334 format!("Test repository for {}", test_name),
335 )
336 .tag(Tag::identifier(&repo_id))
337 .tag(Tag::custom(
338 TagKind::custom("name"),
339 vec![format!("{} Test Repository", test_name)],
340 ))
341 .tag(Tag::custom(
342 TagKind::custom("description"),
343 vec![format!("Repository for {} testing", test_name)],
344 ))
345 .tag(Tag::custom(
346 TagKind::custom("clone"),
347 vec![format!("{}/{}/{}.git", http_url, npub, repo_id)],
348 ))
349 .tag(Tag::custom(
350 TagKind::custom("relays"),
351 vec![relay_url.clone()],
352 ))
353 .tag(Tag::custom(
354 TagKind::custom("maintainers"),
355 maintainer_pubkeys.to_vec(),
356 ))
357 .build(self.keys())
358 .map_err(|e| anyhow!("Failed to build repository announcement event: {}", e))?;
359
360 Ok(event)
361 }
362
289 /// Create an issue (kind 1621) that references a repository 363 /// Create an issue (kind 1621) that references a repository
290 /// 364 ///
291 /// # Arguments 365 /// # Arguments
@@ -456,4 +530,55 @@ mod tests {
456 "Missing custom tag value" 530 "Missing custom tag value"
457 ); 531 );
458 } 532 }
533
534 #[tokio::test]
535 async fn test_create_repo_announcement_with_maintainers() {
536 let config = AuditConfig::ci();
537 let client = AuditClient::new_test(config);
538
539 // Create test maintainer pubkeys (hex format)
540 let maintainer_pubkeys = vec![
541 "a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2".to_string(),
542 "b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3".to_string(),
543 ];
544
545 // Note: We can't test create_repo_announcement_with_maintainers directly in unit tests
546 // because it requires a connected relay. Instead, we test the underlying event building
547 // with maintainers tag to verify the tag format is correct.
548
549 // Build an event with maintainers tag directly to test the tag format
550 let event = client
551 .event_builder(
552 Kind::GitRepoAnnouncement,
553 "Test repository",
554 )
555 .tag(Tag::identifier("test-repo"))
556 .tag(Tag::custom(
557 TagKind::custom("maintainers"),
558 maintainer_pubkeys.clone(),
559 ))
560 .build(client.keys())
561 .unwrap();
562
563 // Verify the maintainers tag is present and correctly formatted
564 let maintainers_tag = event
565 .tags
566 .iter()
567 .find(|t| t.kind() == TagKind::custom("maintainers"));
568
569 assert!(
570 maintainers_tag.is_some(),
571 "Missing 'maintainers' tag in event"
572 );
573
574 // Verify the tag contains the maintainer pubkeys
575 let tag = maintainers_tag.unwrap();
576 let tag_vec: Vec<String> = tag.clone().to_vec();
577
578 // First element is "maintainers", rest are the pubkeys
579 assert_eq!(tag_vec[0], "maintainers");
580 assert_eq!(tag_vec.len(), 3, "Expected 3 elements: tag name + 2 pubkeys");
581 assert_eq!(tag_vec[1], maintainer_pubkeys[0]);
582 assert_eq!(tag_vec[2], maintainer_pubkeys[1]);
583 }
459} 584}