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