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