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