mirror of
https://github.com/block/buzz.git
synced 2026-08-18 06:50:31 +02:00
fix: replace non-existent REST endpoints with real relay surface in e2e_relay tests
Tests assumed HTTP REST endpoints (/api/events, /api/users/{pubkey}/profile,
/api/users/me/channel-add-policy) that the relay does not serve. The relay
router only exposes /events, /query, /count, and a few other paths.
Three fix patterns applied:
- POST /api/events → POST /events (the relay's actual HTTP bridge)
- GET /api/users/{pubkey}/profile → POST /query with kind:0 filter
- PUT /api/users/me/channel-add-policy → submit kind:10100 event via POST /events
Also fixed self-add test that hit nostr crate's default p-tag stripping
(EventBuilder removes p tags matching the signer unless allow_self_tagging
is called), and added a 1s sleep in kind0_nip05_sync to ensure the
replacement event gets a strictly newer created_at timestamp.
Co-authored-by: Will Pfleger <pfleger.will@gmail.com>
Signed-off-by: Will Pfleger <pfleger.will@gmail.com>
This commit is contained in:
co-authored by
Will Pfleger
parent
7e53066dac
commit
c17c4df1e1
@@ -39,7 +39,7 @@ fn relay_http_url() -> String {
|
||||
.to_string()
|
||||
}
|
||||
|
||||
/// Create a real channel via a signed kind:9007 event submitted to POST /api/events.
|
||||
/// Create a real channel via a signed kind:9007 event submitted to POST /events.
|
||||
async fn create_test_channel(keys: &Keys) -> String {
|
||||
let client = reqwest::Client::new();
|
||||
let pubkey_hex = keys.public_key().to_hex();
|
||||
@@ -57,7 +57,7 @@ async fn create_test_channel(keys: &Keys) -> String {
|
||||
.unwrap();
|
||||
|
||||
let resp = client
|
||||
.post(format!("{}/api/events", relay_http_url()))
|
||||
.post(format!("{}/events", relay_http_url()))
|
||||
.header("X-Pubkey", &pubkey_hex)
|
||||
.header("Content-Type", "application/json")
|
||||
.body(serde_json::to_string(&event).unwrap())
|
||||
@@ -714,24 +714,38 @@ async fn test_kind0_nip05_sync() {
|
||||
// Give the relay a moment to process the side effect.
|
||||
tokio::time::sleep(Duration::from_millis(300)).await;
|
||||
|
||||
// Step 2: Verify the profile has the NIP-05 handle via REST GET.
|
||||
// Step 2: Verify the kind:0 content was stored via POST /query.
|
||||
let http_client = reqwest::Client::new();
|
||||
let filters = serde_json::json!([{
|
||||
"kinds": [0],
|
||||
"authors": [&pubkey_hex],
|
||||
"limit": 1,
|
||||
}]);
|
||||
let profile_resp = http_client
|
||||
.get(format!("{}/api/users/{}/profile", http, pubkey_hex))
|
||||
.post(format!("{}/query", http))
|
||||
.header("X-Pubkey", &pubkey_hex)
|
||||
.header("Content-Type", "application/json")
|
||||
.body(serde_json::to_string(&filters).unwrap())
|
||||
.send()
|
||||
.await
|
||||
.expect("GET profile");
|
||||
assert_eq!(
|
||||
profile_resp.status(),
|
||||
200,
|
||||
"profile should exist after kind:0"
|
||||
.expect("query kind:0");
|
||||
assert!(
|
||||
profile_resp.status().is_success(),
|
||||
"kind:0 query failed: {}",
|
||||
profile_resp.status()
|
||||
);
|
||||
let profile: serde_json::Value = profile_resp.json().await.expect("profile json");
|
||||
let events: Vec<serde_json::Value> = profile_resp.json().await.expect("kind:0 json");
|
||||
assert!(
|
||||
!events.is_empty(),
|
||||
"kind:0 event should exist after publishing"
|
||||
);
|
||||
let kind0_stored: serde_json::Value =
|
||||
serde_json::from_str(events[0]["content"].as_str().unwrap_or("{}"))
|
||||
.expect("parse kind:0 content");
|
||||
assert_eq!(
|
||||
profile["nip05_handle"].as_str(),
|
||||
kind0_stored["nip05"].as_str(),
|
||||
Some(valid_handle.as_str()),
|
||||
"nip05_handle should be synced from kind:0"
|
||||
"nip05 should be stored in kind:0 content"
|
||||
);
|
||||
|
||||
// Step 3: Verify NIP-05 resolves via /.well-known/nostr.json.
|
||||
@@ -753,6 +767,8 @@ async fn test_kind0_nip05_sync() {
|
||||
);
|
||||
|
||||
// Step 4: Publish another kind:0 with an off-domain nip05 (should be cleared).
|
||||
// Sleep to ensure a strictly newer created_at (second-level granularity).
|
||||
tokio::time::sleep(Duration::from_secs(1)).await;
|
||||
let off_domain_content = serde_json::json!({
|
||||
"display_name": "Kind0 Test User",
|
||||
"nip05": format!("{}@evil.com", unique_name),
|
||||
@@ -775,23 +791,9 @@ async fn test_kind0_nip05_sync() {
|
||||
|
||||
tokio::time::sleep(Duration::from_millis(300)).await;
|
||||
|
||||
// Step 5: Verify the handle was CLEARED (not set to the off-domain value).
|
||||
let profile_resp2 = http_client
|
||||
.get(format!("{}/api/users/{}/profile", http, pubkey_hex))
|
||||
.header("X-Pubkey", &pubkey_hex)
|
||||
.send()
|
||||
.await
|
||||
.expect("GET profile after off-domain kind:0");
|
||||
assert_eq!(profile_resp2.status(), 200);
|
||||
let profile2: serde_json::Value = profile_resp2.json().await.expect("profile json");
|
||||
let handle_after = profile2["nip05_handle"].as_str().unwrap_or("");
|
||||
assert!(
|
||||
handle_after.is_empty() || handle_after == "null",
|
||||
"nip05_handle should be cleared after off-domain kind:0, got: {:?}",
|
||||
profile2["nip05_handle"]
|
||||
);
|
||||
|
||||
// Step 6: Confirm NIP-05 no longer resolves.
|
||||
// Step 5: Verify the handle was CLEARED — NIP-05 should no longer resolve
|
||||
// after the off-domain kind:0 was accepted. The relay's side effect clears
|
||||
// the nip05_handle in the users table when the domain doesn't match.
|
||||
let nip05_resp2 = http_client
|
||||
.get(format!(
|
||||
"{}/.well-known/nostr.json?name={}",
|
||||
@@ -856,19 +858,27 @@ async fn test_nip29_put_user_nobody_blocks() {
|
||||
let agent_keys = Keys::generate();
|
||||
let agent_pubkey_hex = agent_keys.public_key().to_hex();
|
||||
|
||||
// Set agent's channel_add_policy to "nobody" via REST.
|
||||
// Set agent's channel_add_policy to "nobody" via kind:10100 event.
|
||||
let http_client = reqwest::Client::new();
|
||||
let policy_event = EventBuilder::new(
|
||||
Kind::Custom(10100),
|
||||
serde_json::json!({ "channel_add_policy": "nobody" }).to_string(),
|
||||
)
|
||||
.sign_with_keys(&agent_keys)
|
||||
.expect("sign kind:10100");
|
||||
let resp = http_client
|
||||
.put(format!(
|
||||
"{}/api/users/me/channel-add-policy",
|
||||
relay_http_url()
|
||||
))
|
||||
.post(format!("{}/events", relay_http_url()))
|
||||
.header("X-Pubkey", &agent_pubkey_hex)
|
||||
.json(&serde_json::json!({ "channel_add_policy": "nobody" }))
|
||||
.header("Content-Type", "application/json")
|
||||
.body(serde_json::to_string(&policy_event).unwrap())
|
||||
.send()
|
||||
.await
|
||||
.expect("set policy request");
|
||||
assert_eq!(resp.status(), 200, "set policy failed");
|
||||
assert!(
|
||||
resp.status().is_success(),
|
||||
"set policy failed: {}",
|
||||
resp.status()
|
||||
);
|
||||
|
||||
// Create a channel owned by channel_owner (not the agent).
|
||||
let channel_id = create_test_channel(&channel_owner_keys).await;
|
||||
@@ -910,19 +920,27 @@ async fn test_nip29_put_user_self_add_bypasses_policy() {
|
||||
let agent_keys = Keys::generate();
|
||||
let agent_pubkey_hex = agent_keys.public_key().to_hex();
|
||||
|
||||
// Set agent's channel_add_policy to "nobody" via REST.
|
||||
// Set agent's channel_add_policy to "nobody" via kind:10100 event.
|
||||
let http_client = reqwest::Client::new();
|
||||
let policy_event = EventBuilder::new(
|
||||
Kind::Custom(10100),
|
||||
serde_json::json!({ "channel_add_policy": "nobody" }).to_string(),
|
||||
)
|
||||
.sign_with_keys(&agent_keys)
|
||||
.expect("sign kind:10100");
|
||||
let resp = http_client
|
||||
.put(format!(
|
||||
"{}/api/users/me/channel-add-policy",
|
||||
relay_http_url()
|
||||
))
|
||||
.post(format!("{}/events", relay_http_url()))
|
||||
.header("X-Pubkey", &agent_pubkey_hex)
|
||||
.json(&serde_json::json!({ "channel_add_policy": "nobody" }))
|
||||
.header("Content-Type", "application/json")
|
||||
.body(serde_json::to_string(&policy_event).unwrap())
|
||||
.send()
|
||||
.await
|
||||
.expect("set policy request");
|
||||
assert_eq!(resp.status(), 200, "set policy failed");
|
||||
assert!(
|
||||
resp.status().is_success(),
|
||||
"set policy failed: {}",
|
||||
resp.status()
|
||||
);
|
||||
|
||||
// Create a channel where the agent is the owner.
|
||||
let channel_id = create_test_channel(&agent_keys).await;
|
||||
@@ -936,6 +954,7 @@ async fn test_nip29_put_user_self_add_bypasses_policy() {
|
||||
let h_tag = nostr::Tag::parse(["h", &channel_id]).expect("h tag");
|
||||
let p_tag = nostr::Tag::parse(["p", &agent_pubkey_hex]).expect("p tag");
|
||||
let event = nostr::EventBuilder::new(Kind::Custom(9000), "")
|
||||
.allow_self_tagging()
|
||||
.tags([h_tag, p_tag])
|
||||
.sign_with_keys(&agent_keys)
|
||||
.expect("sign kind 9000");
|
||||
@@ -961,19 +980,27 @@ async fn test_nip29_put_user_owner_only_blocks() {
|
||||
let agent_keys = Keys::generate();
|
||||
let agent_pubkey_hex = agent_keys.public_key().to_hex();
|
||||
|
||||
// Set agent's channel_add_policy to "owner_only" via REST.
|
||||
// Set agent's channel_add_policy to "owner_only" via kind:10100 event.
|
||||
let http_client = reqwest::Client::new();
|
||||
let policy_event = EventBuilder::new(
|
||||
Kind::Custom(10100),
|
||||
serde_json::json!({ "channel_add_policy": "owner_only" }).to_string(),
|
||||
)
|
||||
.sign_with_keys(&agent_keys)
|
||||
.expect("sign kind:10100");
|
||||
let resp = http_client
|
||||
.put(format!(
|
||||
"{}/api/users/me/channel-add-policy",
|
||||
relay_http_url()
|
||||
))
|
||||
.post(format!("{}/events", relay_http_url()))
|
||||
.header("X-Pubkey", &agent_pubkey_hex)
|
||||
.json(&serde_json::json!({ "channel_add_policy": "owner_only" }))
|
||||
.header("Content-Type", "application/json")
|
||||
.body(serde_json::to_string(&policy_event).unwrap())
|
||||
.send()
|
||||
.await
|
||||
.expect("set policy request");
|
||||
assert_eq!(resp.status(), 200, "set policy failed");
|
||||
assert!(
|
||||
resp.status().is_success(),
|
||||
"set policy failed: {}",
|
||||
resp.status()
|
||||
);
|
||||
|
||||
// Create a channel owned by channel_owner (not the agent).
|
||||
let channel_id = create_test_channel(&channel_owner_keys).await;
|
||||
@@ -1274,7 +1301,7 @@ async fn test_membership_notification_emitted_on_add() {
|
||||
.sign_with_keys(&owner_keys)
|
||||
.unwrap();
|
||||
let resp = http_client
|
||||
.post(format!("{}/api/events", relay_http_url()))
|
||||
.post(format!("{}/events", relay_http_url()))
|
||||
.header("X-Pubkey", &owner_keys.public_key().to_hex())
|
||||
.header("Content-Type", "application/json")
|
||||
.body(serde_json::to_string(&add_event).unwrap())
|
||||
@@ -1546,7 +1573,7 @@ async fn test_membership_notification_emitted_on_remove() {
|
||||
.sign_with_keys(&owner_keys)
|
||||
.unwrap();
|
||||
let resp = http_client
|
||||
.post(format!("{}/api/events", relay_http_url()))
|
||||
.post(format!("{}/events", relay_http_url()))
|
||||
.header("X-Pubkey", &owner_pubkey_hex)
|
||||
.header("Content-Type", "application/json")
|
||||
.body(serde_json::to_string(&add_event).unwrap())
|
||||
@@ -1585,7 +1612,7 @@ async fn test_membership_notification_emitted_on_remove() {
|
||||
.sign_with_keys(&owner_keys)
|
||||
.unwrap();
|
||||
let resp = http_client
|
||||
.post(format!("{}/api/events", relay_http_url()))
|
||||
.post(format!("{}/events", relay_http_url()))
|
||||
.header("X-Pubkey", &owner_pubkey_hex)
|
||||
.header("Content-Type", "application/json")
|
||||
.body(serde_json::to_string(&remove_event).unwrap())
|
||||
|
||||
Reference in New Issue
Block a user