this repo has no description
1mod common; 2mod helpers; 3use reqwest::StatusCode; 4use serde_json::{json, Value}; 5use sqlx::PgPool; 6use helpers::verify_new_account; 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!(row.private_key_bytes.len(), 32, "Private key should be 32 bytes for secp256k1"); 95 assert!(row.used_at.is_none(), "Reserved key should not be marked as used yet"); 96 assert!(row.expires_at > chrono::Utc::now(), "Key should expire in the future"); 97} 98 99#[tokio::test] 100async fn test_reserve_signing_key_unique_keys() { 101 let client = common::client(); 102 let base_url = common::base_url().await; 103 let res1 = client 104 .post(format!( 105 "{}/xrpc/com.atproto.server.reserveSigningKey", 106 base_url 107 )) 108 .json(&json!({})) 109 .send() 110 .await 111 .expect("Failed to send request 1"); 112 assert_eq!(res1.status(), StatusCode::OK); 113 let body1: Value = res1.json().await.unwrap(); 114 let key1 = body1["signingKey"].as_str().unwrap(); 115 let res2 = 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 2"); 124 assert_eq!(res2.status(), StatusCode::OK); 125 let body2: Value = res2.json().await.unwrap(); 126 let key2 = body2["signingKey"].as_str().unwrap(); 127 assert_ne!(key1, key2, "Each call should generate a unique signing key"); 128} 129 130#[tokio::test] 131async fn test_reserve_signing_key_is_public() { 132 let client = common::client(); 133 let base_url = common::base_url().await; 134 let res = client 135 .post(format!( 136 "{}/xrpc/com.atproto.server.reserveSigningKey", 137 base_url 138 )) 139 .json(&json!({})) 140 .send() 141 .await 142 .expect("Failed to send request"); 143 assert_eq!( 144 res.status(), 145 StatusCode::OK, 146 "reserveSigningKey should work without authentication" 147 ); 148} 149 150#[tokio::test] 151async fn test_create_account_with_reserved_signing_key() { 152 let client = common::client(); 153 let base_url = common::base_url().await; 154 let pool = get_pool().await; 155 let res = client 156 .post(format!( 157 "{}/xrpc/com.atproto.server.reserveSigningKey", 158 base_url 159 )) 160 .json(&json!({})) 161 .send() 162 .await 163 .expect("Failed to reserve signing key"); 164 assert_eq!(res.status(), StatusCode::OK); 165 let body: Value = res.json().await.unwrap(); 166 let signing_key = body["signingKey"].as_str().unwrap(); 167 let handle = format!("reserved_key_user_{}", uuid::Uuid::new_v4()); 168 let res = client 169 .post(format!( 170 "{}/xrpc/com.atproto.server.createAccount", 171 base_url 172 )) 173 .json(&json!({ 174 "handle": handle, 175 "email": format!("{}@example.com", handle), 176 "password": "password", 177 "signingKey": signing_key 178 })) 179 .send() 180 .await 181 .expect("Failed to create account"); 182 assert_eq!(res.status(), StatusCode::OK); 183 let body: Value = res.json().await.unwrap(); 184 assert!(body["did"].is_string()); 185 let did = body["did"].as_str().unwrap(); 186 let access_jwt = verify_new_account(&client, did).await; 187 assert!(!access_jwt.is_empty()); 188 let reserved = sqlx::query!( 189 "SELECT used_at FROM reserved_signing_keys WHERE public_key_did_key = $1", 190 signing_key 191 ) 192 .fetch_one(&pool) 193 .await 194 .expect("Reserved key not found"); 195 assert!( 196 reserved.used_at.is_some(), 197 "Reserved key should be marked as used" 198 ); 199} 200 201#[tokio::test] 202async fn test_create_account_with_invalid_signing_key() { 203 let client = common::client(); 204 let base_url = common::base_url().await; 205 let handle = format!("bad_key_user_{}", uuid::Uuid::new_v4()); 206 let res = client 207 .post(format!( 208 "{}/xrpc/com.atproto.server.createAccount", 209 base_url 210 )) 211 .json(&json!({ 212 "handle": handle, 213 "email": format!("{}@example.com", handle), 214 "password": "password", 215 "signingKey": "did:key:zNonExistentKey12345" 216 })) 217 .send() 218 .await 219 .expect("Failed to send request"); 220 assert_eq!(res.status(), StatusCode::BAD_REQUEST); 221 let body: Value = res.json().await.unwrap(); 222 assert_eq!(body["error"], "InvalidSigningKey"); 223} 224 225#[tokio::test] 226async fn test_create_account_cannot_reuse_signing_key() { 227 let client = common::client(); 228 let base_url = common::base_url().await; 229 let res = client 230 .post(format!( 231 "{}/xrpc/com.atproto.server.reserveSigningKey", 232 base_url 233 )) 234 .json(&json!({})) 235 .send() 236 .await 237 .expect("Failed to reserve signing key"); 238 assert_eq!(res.status(), StatusCode::OK); 239 let body: Value = res.json().await.unwrap(); 240 let signing_key = body["signingKey"].as_str().unwrap(); 241 let handle1 = format!("reuse_key_user1_{}", uuid::Uuid::new_v4()); 242 let res = client 243 .post(format!( 244 "{}/xrpc/com.atproto.server.createAccount", 245 base_url 246 )) 247 .json(&json!({ 248 "handle": handle1, 249 "email": format!("{}@example.com", handle1), 250 "password": "password", 251 "signingKey": signing_key 252 })) 253 .send() 254 .await 255 .expect("Failed to create first account"); 256 assert_eq!(res.status(), StatusCode::OK); 257 let handle2 = format!("reuse_key_user2_{}", uuid::Uuid::new_v4()); 258 let res = client 259 .post(format!( 260 "{}/xrpc/com.atproto.server.createAccount", 261 base_url 262 )) 263 .json(&json!({ 264 "handle": handle2, 265 "email": format!("{}@example.com", handle2), 266 "password": "password", 267 "signingKey": signing_key 268 })) 269 .send() 270 .await 271 .expect("Failed to send second request"); 272 assert_eq!(res.status(), StatusCode::BAD_REQUEST); 273 let body: Value = res.json().await.unwrap(); 274 assert_eq!(body["error"], "InvalidSigningKey"); 275 assert!(body["message"] 276 .as_str() 277 .unwrap() 278 .contains("already used")); 279} 280 281#[tokio::test] 282async fn test_reserved_key_tokens_work() { 283 let client = common::client(); 284 let base_url = common::base_url().await; 285 let res = client 286 .post(format!( 287 "{}/xrpc/com.atproto.server.reserveSigningKey", 288 base_url 289 )) 290 .json(&json!({})) 291 .send() 292 .await 293 .expect("Failed to reserve signing key"); 294 assert_eq!(res.status(), StatusCode::OK); 295 let body: Value = res.json().await.unwrap(); 296 let signing_key = body["signingKey"].as_str().unwrap(); 297 let handle = format!("token_test_user_{}", uuid::Uuid::new_v4()); 298 let res = client 299 .post(format!( 300 "{}/xrpc/com.atproto.server.createAccount", 301 base_url 302 )) 303 .json(&json!({ 304 "handle": handle, 305 "email": format!("{}@example.com", handle), 306 "password": "password", 307 "signingKey": signing_key 308 })) 309 .send() 310 .await 311 .expect("Failed to create account"); 312 assert_eq!(res.status(), StatusCode::OK); 313 let body: Value = res.json().await.unwrap(); 314 let did = body["did"].as_str().unwrap(); 315 let access_jwt = verify_new_account(&client, did).await; 316 let res = client 317 .get(format!( 318 "{}/xrpc/com.atproto.server.getSession", 319 base_url 320 )) 321 .bearer_auth(&access_jwt) 322 .send() 323 .await 324 .expect("Failed to get session"); 325 assert_eq!(res.status(), StatusCode::OK); 326 let body: Value = res.json().await.unwrap(); 327 assert_eq!(body["handle"], handle); 328}