this repo has no description
1mod common; 2 3use reqwest::StatusCode; 4use serde_json::{json, Value}; 5use sqlx::PgPool; 6 7async fn get_pool() -> PgPool { 8 let conn_str = common::get_db_connection_string().await; 9 sqlx::postgres::PgPoolOptions::new() 10 .max_connections(5) 11 .connect(&conn_str) 12 .await 13 .expect("Failed to connect to test database") 14} 15 16#[tokio::test] 17async fn test_reserve_signing_key_without_did() { 18 let client = common::client(); 19 let base_url = common::base_url().await; 20 21 let res = client 22 .post(format!( 23 "{}/xrpc/com.atproto.server.reserveSigningKey", 24 base_url 25 )) 26 .json(&json!({})) 27 .send() 28 .await 29 .expect("Failed to send request"); 30 31 assert_eq!(res.status(), StatusCode::OK); 32 let body: Value = res.json().await.expect("Response was not valid JSON"); 33 34 assert!(body["signingKey"].is_string()); 35 let signing_key = body["signingKey"].as_str().unwrap(); 36 assert!( 37 signing_key.starts_with("did:key:z"), 38 "Signing key should be in did:key format with multibase prefix" 39 ); 40} 41 42#[tokio::test] 43async fn test_reserve_signing_key_with_did() { 44 let client = common::client(); 45 let base_url = common::base_url().await; 46 let pool = get_pool().await; 47 48 let target_did = "did:plc:test123456"; 49 let res = client 50 .post(format!( 51 "{}/xrpc/com.atproto.server.reserveSigningKey", 52 base_url 53 )) 54 .json(&json!({ "did": target_did })) 55 .send() 56 .await 57 .expect("Failed to send request"); 58 59 assert_eq!(res.status(), StatusCode::OK); 60 let body: Value = res.json().await.expect("Response was not valid JSON"); 61 62 let signing_key = body["signingKey"].as_str().unwrap(); 63 assert!(signing_key.starts_with("did:key:z")); 64 65 let row = sqlx::query!( 66 "SELECT did, public_key_did_key FROM reserved_signing_keys WHERE public_key_did_key = $1", 67 signing_key 68 ) 69 .fetch_one(&pool) 70 .await 71 .expect("Reserved key not found in database"); 72 73 assert_eq!(row.did.as_deref(), Some(target_did)); 74 assert_eq!(row.public_key_did_key, signing_key); 75} 76 77#[tokio::test] 78async fn test_reserve_signing_key_stores_private_key() { 79 let client = common::client(); 80 let base_url = common::base_url().await; 81 let pool = get_pool().await; 82 83 let res = client 84 .post(format!( 85 "{}/xrpc/com.atproto.server.reserveSigningKey", 86 base_url 87 )) 88 .json(&json!({})) 89 .send() 90 .await 91 .expect("Failed to send request"); 92 93 assert_eq!(res.status(), StatusCode::OK); 94 let body: Value = res.json().await.expect("Response was not valid JSON"); 95 let signing_key = body["signingKey"].as_str().unwrap(); 96 97 let row = sqlx::query!( 98 "SELECT private_key_bytes, expires_at, used_at FROM reserved_signing_keys WHERE public_key_did_key = $1", 99 signing_key 100 ) 101 .fetch_one(&pool) 102 .await 103 .expect("Reserved key not found in database"); 104 105 assert_eq!(row.private_key_bytes.len(), 32, "Private key should be 32 bytes for secp256k1"); 106 assert!(row.used_at.is_none(), "Reserved key should not be marked as used yet"); 107 assert!(row.expires_at > chrono::Utc::now(), "Key should expire in the future"); 108} 109 110#[tokio::test] 111async fn test_reserve_signing_key_unique_keys() { 112 let client = common::client(); 113 let base_url = common::base_url().await; 114 115 let res1 = client 116 .post(format!( 117 "{}/xrpc/com.atproto.server.reserveSigningKey", 118 base_url 119 )) 120 .json(&json!({})) 121 .send() 122 .await 123 .expect("Failed to send request 1"); 124 assert_eq!(res1.status(), StatusCode::OK); 125 let body1: Value = res1.json().await.unwrap(); 126 let key1 = body1["signingKey"].as_str().unwrap(); 127 128 let res2 = client 129 .post(format!( 130 "{}/xrpc/com.atproto.server.reserveSigningKey", 131 base_url 132 )) 133 .json(&json!({})) 134 .send() 135 .await 136 .expect("Failed to send request 2"); 137 assert_eq!(res2.status(), StatusCode::OK); 138 let body2: Value = res2.json().await.unwrap(); 139 let key2 = body2["signingKey"].as_str().unwrap(); 140 141 assert_ne!(key1, key2, "Each call should generate a unique signing key"); 142} 143 144#[tokio::test] 145async fn test_reserve_signing_key_is_public() { 146 let client = common::client(); 147 let base_url = common::base_url().await; 148 149 let res = client 150 .post(format!( 151 "{}/xrpc/com.atproto.server.reserveSigningKey", 152 base_url 153 )) 154 .json(&json!({})) 155 .send() 156 .await 157 .expect("Failed to send request"); 158 159 assert_eq!( 160 res.status(), 161 StatusCode::OK, 162 "reserveSigningKey should work without authentication" 163 ); 164} 165 166#[tokio::test] 167async fn test_create_account_with_reserved_signing_key() { 168 let client = common::client(); 169 let base_url = common::base_url().await; 170 let pool = get_pool().await; 171 172 let res = client 173 .post(format!( 174 "{}/xrpc/com.atproto.server.reserveSigningKey", 175 base_url 176 )) 177 .json(&json!({})) 178 .send() 179 .await 180 .expect("Failed to reserve signing key"); 181 assert_eq!(res.status(), StatusCode::OK); 182 let body: Value = res.json().await.unwrap(); 183 let signing_key = body["signingKey"].as_str().unwrap(); 184 185 let handle = format!("reserved_key_user_{}", uuid::Uuid::new_v4()); 186 let res = client 187 .post(format!( 188 "{}/xrpc/com.atproto.server.createAccount", 189 base_url 190 )) 191 .json(&json!({ 192 "handle": handle, 193 "email": format!("{}@example.com", handle), 194 "password": "password", 195 "signingKey": signing_key 196 })) 197 .send() 198 .await 199 .expect("Failed to create account"); 200 201 assert_eq!(res.status(), StatusCode::OK); 202 let body: Value = res.json().await.unwrap(); 203 assert!(body["accessJwt"].is_string()); 204 assert!(body["did"].is_string()); 205 206 let reserved = sqlx::query!( 207 "SELECT used_at FROM reserved_signing_keys WHERE public_key_did_key = $1", 208 signing_key 209 ) 210 .fetch_one(&pool) 211 .await 212 .expect("Reserved key not found"); 213 assert!( 214 reserved.used_at.is_some(), 215 "Reserved key should be marked as used" 216 ); 217} 218 219#[tokio::test] 220async fn test_create_account_with_invalid_signing_key() { 221 let client = common::client(); 222 let base_url = common::base_url().await; 223 224 let handle = format!("bad_key_user_{}", uuid::Uuid::new_v4()); 225 let res = client 226 .post(format!( 227 "{}/xrpc/com.atproto.server.createAccount", 228 base_url 229 )) 230 .json(&json!({ 231 "handle": handle, 232 "email": format!("{}@example.com", handle), 233 "password": "password", 234 "signingKey": "did:key:zNonExistentKey12345" 235 })) 236 .send() 237 .await 238 .expect("Failed to send request"); 239 240 assert_eq!(res.status(), StatusCode::BAD_REQUEST); 241 let body: Value = res.json().await.unwrap(); 242 assert_eq!(body["error"], "InvalidSigningKey"); 243} 244 245#[tokio::test] 246async fn test_create_account_cannot_reuse_signing_key() { 247 let client = common::client(); 248 let base_url = common::base_url().await; 249 250 let res = client 251 .post(format!( 252 "{}/xrpc/com.atproto.server.reserveSigningKey", 253 base_url 254 )) 255 .json(&json!({})) 256 .send() 257 .await 258 .expect("Failed to reserve signing key"); 259 assert_eq!(res.status(), StatusCode::OK); 260 let body: Value = res.json().await.unwrap(); 261 let signing_key = body["signingKey"].as_str().unwrap(); 262 263 let handle1 = format!("reuse_key_user1_{}", uuid::Uuid::new_v4()); 264 let res = client 265 .post(format!( 266 "{}/xrpc/com.atproto.server.createAccount", 267 base_url 268 )) 269 .json(&json!({ 270 "handle": handle1, 271 "email": format!("{}@example.com", handle1), 272 "password": "password", 273 "signingKey": signing_key 274 })) 275 .send() 276 .await 277 .expect("Failed to create first account"); 278 assert_eq!(res.status(), StatusCode::OK); 279 280 let handle2 = format!("reuse_key_user2_{}", uuid::Uuid::new_v4()); 281 let res = client 282 .post(format!( 283 "{}/xrpc/com.atproto.server.createAccount", 284 base_url 285 )) 286 .json(&json!({ 287 "handle": handle2, 288 "email": format!("{}@example.com", handle2), 289 "password": "password", 290 "signingKey": signing_key 291 })) 292 .send() 293 .await 294 .expect("Failed to send second request"); 295 296 assert_eq!(res.status(), StatusCode::BAD_REQUEST); 297 let body: Value = res.json().await.unwrap(); 298 assert_eq!(body["error"], "InvalidSigningKey"); 299 assert!(body["message"] 300 .as_str() 301 .unwrap() 302 .contains("already used")); 303} 304 305#[tokio::test] 306async fn test_reserved_key_tokens_work() { 307 let client = common::client(); 308 let base_url = common::base_url().await; 309 310 let res = client 311 .post(format!( 312 "{}/xrpc/com.atproto.server.reserveSigningKey", 313 base_url 314 )) 315 .json(&json!({})) 316 .send() 317 .await 318 .expect("Failed to reserve signing key"); 319 assert_eq!(res.status(), StatusCode::OK); 320 let body: Value = res.json().await.unwrap(); 321 let signing_key = body["signingKey"].as_str().unwrap(); 322 323 let handle = format!("token_test_user_{}", uuid::Uuid::new_v4()); 324 let res = client 325 .post(format!( 326 "{}/xrpc/com.atproto.server.createAccount", 327 base_url 328 )) 329 .json(&json!({ 330 "handle": handle, 331 "email": format!("{}@example.com", handle), 332 "password": "password", 333 "signingKey": signing_key 334 })) 335 .send() 336 .await 337 .expect("Failed to create account"); 338 assert_eq!(res.status(), StatusCode::OK); 339 let body: Value = res.json().await.unwrap(); 340 let access_jwt = body["accessJwt"].as_str().unwrap(); 341 342 let res = client 343 .get(format!( 344 "{}/xrpc/com.atproto.server.getSession", 345 base_url 346 )) 347 .bearer_auth(access_jwt) 348 .send() 349 .await 350 .expect("Failed to get session"); 351 352 assert_eq!(res.status(), StatusCode::OK); 353 let body: Value = res.json().await.unwrap(); 354 assert_eq!(body["handle"], handle); 355}