upleb.uk

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

summaryrefslogtreecommitdiff
path: root/tests/state_authorization.rs
diff options
context:
space:
mode:
authorDanConwayDev <DanConwayDev@protonmail.com>2026-01-09 19:58:41 +0000
committerDanConwayDev <DanConwayDev@protonmail.com>2026-01-09 19:58:41 +0000
commitb28a356cb41077ccee12a9c52f4ef2054e76cac6 (patch)
tree2a0867f1ab0216e86efa062aef90b2b8077e6fb9 /tests/state_authorization.rs
parent6dd9fcd5392891b0ddb7894e2c5cb40450eae00e (diff)
chore: cargo fmt
Diffstat (limited to 'tests/state_authorization.rs')
-rw-r--r--tests/state_authorization.rs242
1 files changed, 119 insertions, 123 deletions
diff --git a/tests/state_authorization.rs b/tests/state_authorization.rs
index a5dfa2d..d443005 100644
--- a/tests/state_authorization.rs
+++ b/tests/state_authorization.rs
@@ -13,30 +13,27 @@ use nostr_sdk::prelude::*;
13async fn test_reject_state_without_announcement() { 13async fn test_reject_state_without_announcement() {
14 // Start test relay 14 // Start test relay
15 let relay = TestRelay::start().await; 15 let relay = TestRelay::start().await;
16 16
17 // Create test keypair 17 // Create test keypair
18 let keys = Keys::generate(); 18 let keys = Keys::generate();
19 19
20 // Create a state event without any announcement 20 // Create a state event without any announcement
21 let state_event = EventBuilder::new( 21 let state_event = EventBuilder::new(Kind::RepoState, "")
22 Kind::RepoState, 22 .tags([
23 "", 23 Tag::custom(TagKind::custom("d"), ["test-repo"]),
24 ) 24 Tag::custom(TagKind::custom("refs/heads/main"), ["abc123"]),
25 .tags([ 25 ])
26 Tag::custom(TagKind::custom("d"), ["test-repo"]), 26 .sign_with_keys(&keys)
27 Tag::custom(TagKind::custom("refs/heads/main"), ["abc123"]), 27 .unwrap();
28 ]) 28
29 .sign_with_keys(&keys)
30 .unwrap();
31
32 // Connect to relay 29 // Connect to relay
33 let client = Client::default(); 30 let client = Client::default();
34 client.add_relay(relay.url()).await.unwrap(); 31 client.add_relay(relay.url()).await.unwrap();
35 client.connect().await; 32 client.connect().await;
36 33
37 // Try to send state event 34 // Try to send state event
38 let result = client.send_event(&state_event).await; 35 let result = client.send_event(&state_event).await;
39 36
40 // Should be rejected 37 // Should be rejected
41 match result { 38 match result {
42 Ok(output) => { 39 Ok(output) => {
@@ -45,22 +42,26 @@ async fn test_reject_state_without_announcement() {
45 "Event should be processed" 42 "Event should be processed"
46 ); 43 );
47 // Check if any relay rejected it 44 // Check if any relay rejected it
48 let rejected = output.failed.values().any(|err| { 45 let rejected = output
49 err.to_string().contains("no announcement exists") 46 .failed
50 }); 47 .values()
51 assert!(rejected, "Event should be rejected due to missing announcement"); 48 .any(|err| err.to_string().contains("no announcement exists"));
49 assert!(
50 rejected,
51 "Event should be rejected due to missing announcement"
52 );
52 } 53 }
53 Err(e) => { 54 Err(e) => {
54 // Also acceptable - relay rejected the event 55 // Also acceptable - relay rejected the event
55 assert!( 56 assert!(
56 e.to_string().contains("no announcement exists") || 57 e.to_string().contains("no announcement exists")
57 e.to_string().contains("rejected"), 58 || e.to_string().contains("rejected"),
58 "Error should indicate missing announcement: {}", 59 "Error should indicate missing announcement: {}",
59 e 60 e
60 ); 61 );
61 } 62 }
62 } 63 }
63 64
64 relay.stop().await; 65 relay.stop().await;
65} 66}
66 67
@@ -68,67 +69,67 @@ async fn test_reject_state_without_announcement() {
68async fn test_reject_state_from_unauthorized_author() { 69async fn test_reject_state_from_unauthorized_author() {
69 // Start test relay 70 // Start test relay
70 let relay = TestRelay::start().await; 71 let relay = TestRelay::start().await;
71 72
72 // Create two keypairs: one for announcement, one for unauthorized state 73 // Create two keypairs: one for announcement, one for unauthorized state
73 let announcement_keys = Keys::generate(); 74 let announcement_keys = Keys::generate();
74 let unauthorized_keys = Keys::generate(); 75 let unauthorized_keys = Keys::generate();
75 76
76 // Create announcement 77 // Create announcement
77 let announcement = EventBuilder::new( 78 let announcement = EventBuilder::new(Kind::GitRepoAnnouncement, "")
78 Kind::GitRepoAnnouncement, 79 .tags([
79 "", 80 Tag::custom(TagKind::custom("d"), ["test-repo"]),
80 ) 81 Tag::custom(
81 .tags([ 82 TagKind::custom("clone"),
82 Tag::custom(TagKind::custom("d"), ["test-repo"]), 83 [format!("https://{}/test.git", relay.domain())],
83 Tag::custom(TagKind::custom("clone"), [format!("https://{}/test.git", relay.domain())]), 84 ),
84 Tag::custom(TagKind::custom("relays"), [relay.url()]), 85 Tag::custom(TagKind::custom("relays"), [relay.url()]),
85 ]) 86 ])
86 .sign_with_keys(&announcement_keys) 87 .sign_with_keys(&announcement_keys)
87 .unwrap(); 88 .unwrap();
88 89
89 // Connect to relay 90 // Connect to relay
90 let client = Client::default(); 91 let client = Client::default();
91 client.add_relay(relay.url()).await.unwrap(); 92 client.add_relay(relay.url()).await.unwrap();
92 client.connect().await; 93 client.connect().await;
93 94
94 // Send announcement 95 // Send announcement
95 client.send_event(&announcement).await.unwrap(); 96 client.send_event(&announcement).await.unwrap();
96 97
97 // Wait for announcement to be processed 98 // Wait for announcement to be processed
98 tokio::time::sleep(tokio::time::Duration::from_millis(100)).await; 99 tokio::time::sleep(tokio::time::Duration::from_millis(100)).await;
99 100
100 // Try to send state event from unauthorized author 101 // Try to send state event from unauthorized author
101 let state_event = EventBuilder::new( 102 let state_event = EventBuilder::new(Kind::RepoState, "")
102 Kind::RepoState, 103 .tags([
103 "", 104 Tag::custom(TagKind::custom("d"), ["test-repo"]),
104 ) 105 Tag::custom(TagKind::custom("refs/heads/main"), ["abc123"]),
105 .tags([ 106 ])
106 Tag::custom(TagKind::custom("d"), ["test-repo"]), 107 .sign_with_keys(&unauthorized_keys)
107 Tag::custom(TagKind::custom("refs/heads/main"), ["abc123"]), 108 .unwrap();
108 ]) 109
109 .sign_with_keys(&unauthorized_keys)
110 .unwrap();
111
112 let result = client.send_event(&state_event).await; 110 let result = client.send_event(&state_event).await;
113 111
114 // Should be rejected 112 // Should be rejected
115 match result { 113 match result {
116 Ok(output) => { 114 Ok(output) => {
117 let rejected = output.failed.values().any(|err| { 115 let rejected = output
118 err.to_string().contains("not authorized") 116 .failed
119 }); 117 .values()
120 assert!(rejected, "Event should be rejected due to unauthorized author"); 118 .any(|err| err.to_string().contains("not authorized"));
119 assert!(
120 rejected,
121 "Event should be rejected due to unauthorized author"
122 );
121 } 123 }
122 Err(e) => { 124 Err(e) => {
123 assert!( 125 assert!(
124 e.to_string().contains("not authorized") || 126 e.to_string().contains("not authorized") || e.to_string().contains("rejected"),
125 e.to_string().contains("rejected"),
126 "Error should indicate unauthorized author: {}", 127 "Error should indicate unauthorized author: {}",
127 e 128 e
128 ); 129 );
129 } 130 }
130 } 131 }
131 132
132 relay.stop().await; 133 relay.stop().await;
133} 134}
134 135
@@ -136,48 +137,45 @@ async fn test_reject_state_from_unauthorized_author() {
136async fn test_accept_state_from_announcement_author() { 137async fn test_accept_state_from_announcement_author() {
137 // Start test relay 138 // Start test relay
138 let relay = TestRelay::start().await; 139 let relay = TestRelay::start().await;
139 140
140 // Create keypair 141 // Create keypair
141 let keys = Keys::generate(); 142 let keys = Keys::generate();
142 143
143 // Create announcement 144 // Create announcement
144 let announcement = EventBuilder::new( 145 let announcement = EventBuilder::new(Kind::GitRepoAnnouncement, "")
145 Kind::GitRepoAnnouncement, 146 .tags([
146 "", 147 Tag::custom(TagKind::custom("d"), ["test-repo"]),
147 ) 148 Tag::custom(
148 .tags([ 149 TagKind::custom("clone"),
149 Tag::custom(TagKind::custom("d"), ["test-repo"]), 150 [format!("https://{}/test.git", relay.domain())],
150 Tag::custom(TagKind::custom("clone"), [format!("https://{}/test.git", relay.domain())]), 151 ),
151 Tag::custom(TagKind::custom("relays"), [relay.url()]), 152 Tag::custom(TagKind::custom("relays"), [relay.url()]),
152 ]) 153 ])
153 .sign_with_keys(&keys) 154 .sign_with_keys(&keys)
154 .unwrap(); 155 .unwrap();
155 156
156 // Connect to relay 157 // Connect to relay
157 let client = Client::default(); 158 let client = Client::default();
158 client.add_relay(relay.url()).await.unwrap(); 159 client.add_relay(relay.url()).await.unwrap();
159 client.connect().await; 160 client.connect().await;
160 161
161 // Send announcement 162 // Send announcement
162 client.send_event(&announcement).await.unwrap(); 163 client.send_event(&announcement).await.unwrap();
163 164
164 // Wait for announcement to be processed 165 // Wait for announcement to be processed
165 tokio::time::sleep(tokio::time::Duration::from_millis(100)).await; 166 tokio::time::sleep(tokio::time::Duration::from_millis(100)).await;
166 167
167 // Send state event from same author (should be accepted or go to purgatory) 168 // Send state event from same author (should be accepted or go to purgatory)
168 let state_event = EventBuilder::new( 169 let state_event = EventBuilder::new(Kind::RepoState, "")
169 Kind::RepoState, 170 .tags([
170 "", 171 Tag::custom(TagKind::custom("d"), ["test-repo"]),
171 ) 172 Tag::custom(TagKind::custom("refs/heads/main"), ["abc123"]),
172 .tags([ 173 ])
173 Tag::custom(TagKind::custom("d"), ["test-repo"]), 174 .sign_with_keys(&keys)
174 Tag::custom(TagKind::custom("refs/heads/main"), ["abc123"]), 175 .unwrap();
175 ]) 176
176 .sign_with_keys(&keys)
177 .unwrap();
178
179 let result = client.send_event(&state_event).await; 177 let result = client.send_event(&state_event).await;
180 178
181 // Should be accepted or go to purgatory (not permanently rejected) 179 // Should be accepted or go to purgatory (not permanently rejected)
182 match result { 180 match result {
183 Ok(output) => { 181 Ok(output) => {
@@ -194,14 +192,13 @@ async fn test_accept_state_from_announcement_author() {
194 Err(e) => { 192 Err(e) => {
195 // Purgatory is acceptable 193 // Purgatory is acceptable
196 assert!( 194 assert!(
197 e.to_string().contains("purgatory") || 195 e.to_string().contains("purgatory") || e.to_string().contains("waiting for git"),
198 e.to_string().contains("waiting for git"),
199 "Error should be about purgatory, not authorization: {}", 196 "Error should be about purgatory, not authorization: {}",
200 e 197 e
201 ); 198 );
202 } 199 }
203 } 200 }
204 201
205 relay.stop().await; 202 relay.stop().await;
206} 203}
207 204
@@ -209,50 +206,50 @@ async fn test_accept_state_from_announcement_author() {
209async fn test_accept_state_from_maintainer() { 206async fn test_accept_state_from_maintainer() {
210 // Start test relay 207 // Start test relay
211 let relay = TestRelay::start().await; 208 let relay = TestRelay::start().await;
212 209
213 // Create two keypairs: owner and maintainer 210 // Create two keypairs: owner and maintainer
214 let owner_keys = Keys::generate(); 211 let owner_keys = Keys::generate();
215 let maintainer_keys = Keys::generate(); 212 let maintainer_keys = Keys::generate();
216 213
217 // Create announcement with maintainer 214 // Create announcement with maintainer
218 let announcement = EventBuilder::new( 215 let announcement = EventBuilder::new(Kind::GitRepoAnnouncement, "")
219 Kind::GitRepoAnnouncement, 216 .tags([
220 "", 217 Tag::custom(TagKind::custom("d"), ["test-repo"]),
221 ) 218 Tag::custom(
222 .tags([ 219 TagKind::custom("clone"),
223 Tag::custom(TagKind::custom("d"), ["test-repo"]), 220 [format!("https://{}/test.git", relay.domain())],
224 Tag::custom(TagKind::custom("clone"), [format!("https://{}/test.git", relay.domain())]), 221 ),
225 Tag::custom(TagKind::custom("relays"), [relay.url()]), 222 Tag::custom(TagKind::custom("relays"), [relay.url()]),
226 Tag::custom(TagKind::custom("maintainers"), [maintainer_keys.public_key().to_hex()]), 223 Tag::custom(
227 ]) 224 TagKind::custom("maintainers"),
228 .sign_with_keys(&owner_keys) 225 [maintainer_keys.public_key().to_hex()],
229 .unwrap(); 226 ),
230 227 ])
228 .sign_with_keys(&owner_keys)
229 .unwrap();
230
231 // Connect to relay 231 // Connect to relay
232 let client = Client::default(); 232 let client = Client::default();
233 client.add_relay(relay.url()).await.unwrap(); 233 client.add_relay(relay.url()).await.unwrap();
234 client.connect().await; 234 client.connect().await;
235 235
236 // Send announcement 236 // Send announcement
237 client.send_event(&announcement).await.unwrap(); 237 client.send_event(&announcement).await.unwrap();
238 238
239 // Wait for announcement to be processed 239 // Wait for announcement to be processed
240 tokio::time::sleep(tokio::time::Duration::from_millis(100)).await; 240 tokio::time::sleep(tokio::time::Duration::from_millis(100)).await;
241 241
242 // Send state event from maintainer 242 // Send state event from maintainer
243 let state_event = EventBuilder::new( 243 let state_event = EventBuilder::new(Kind::RepoState, "")
244 Kind::RepoState, 244 .tags([
245 "", 245 Tag::custom(TagKind::custom("d"), ["test-repo"]),
246 ) 246 Tag::custom(TagKind::custom("refs/heads/main"), ["abc123"]),
247 .tags([ 247 ])
248 Tag::custom(TagKind::custom("d"), ["test-repo"]), 248 .sign_with_keys(&maintainer_keys)
249 Tag::custom(TagKind::custom("refs/heads/main"), ["abc123"]), 249 .unwrap();
250 ]) 250
251 .sign_with_keys(&maintainer_keys)
252 .unwrap();
253
254 let result = client.send_event(&state_event).await; 251 let result = client.send_event(&state_event).await;
255 252
256 // Should be accepted or go to purgatory (not permanently rejected) 253 // Should be accepted or go to purgatory (not permanently rejected)
257 match result { 254 match result {
258 Ok(output) => { 255 Ok(output) => {
@@ -268,13 +265,12 @@ async fn test_accept_state_from_maintainer() {
268 Err(e) => { 265 Err(e) => {
269 // Purgatory is acceptable 266 // Purgatory is acceptable
270 assert!( 267 assert!(
271 e.to_string().contains("purgatory") || 268 e.to_string().contains("purgatory") || e.to_string().contains("waiting for git"),
272 e.to_string().contains("waiting for git"),
273 "Error should be about purgatory, not authorization: {}", 269 "Error should be about purgatory, not authorization: {}",
274 e 270 e
275 ); 271 );
276 } 272 }
277 } 273 }
278 274
279 relay.stop().await; 275 relay.stop().await;
280} 276}