this repo has no description
1mod common; 2use reqwest::StatusCode; 3use serde_json::{Value, json}; 4use sqlx::PgPool; 5 6async fn get_pool() -> PgPool { 7 let conn_str = common::get_db_connection_string().await; 8 sqlx::postgres::PgPoolOptions::new() 9 .max_connections(5) 10 .connect(&conn_str) 11 .await 12 .expect("Failed to connect to test database") 13} 14 15async fn create_verified_account( 16 client: &reqwest::Client, 17 base_url: &str, 18 handle: &str, 19 email: &str, 20) -> String { 21 let res = client 22 .post(format!( 23 "{}/xrpc/com.atproto.server.createAccount", 24 base_url 25 )) 26 .json(&json!({ 27 "handle": handle, 28 "email": email, 29 "password": "password" 30 })) 31 .send() 32 .await 33 .expect("Failed to create account"); 34 assert_eq!(res.status(), StatusCode::OK); 35 let body: Value = res.json().await.expect("Invalid JSON"); 36 let did = body["did"].as_str().expect("No did"); 37 common::verify_new_account(client, did).await 38} 39 40#[tokio::test] 41async fn test_email_update_flow_success() { 42 let client = common::client(); 43 let base_url = common::base_url().await; 44 let pool = get_pool().await; 45 let handle = format!("emailup_{}", uuid::Uuid::new_v4()); 46 let email = format!("{}@example.com", handle); 47 let access_jwt = create_verified_account(&client, &base_url, &handle, &email).await; 48 let new_email = format!("new_{}@example.com", handle); 49 let res = client 50 .post(format!( 51 "{}/xrpc/com.atproto.server.requestEmailUpdate", 52 base_url 53 )) 54 .bearer_auth(&access_jwt) 55 .json(&json!({"email": new_email})) 56 .send() 57 .await 58 .expect("Failed to request email update"); 59 assert_eq!(res.status(), StatusCode::OK); 60 let body: Value = res.json().await.expect("Invalid JSON"); 61 assert_eq!(body["tokenRequired"], true); 62 let user = sqlx::query!( 63 "SELECT email_pending_verification, email_confirmation_code, email FROM users WHERE handle = $1", 64 handle 65 ) 66 .fetch_one(&pool) 67 .await 68 .expect("User not found"); 69 assert_eq!( 70 user.email_pending_verification.as_deref(), 71 Some(new_email.as_str()) 72 ); 73 assert!(user.email_confirmation_code.is_some()); 74 let code = user.email_confirmation_code.unwrap(); 75 let res = client 76 .post(format!("{}/xrpc/com.atproto.server.confirmEmail", base_url)) 77 .bearer_auth(&access_jwt) 78 .json(&json!({ 79 "email": new_email, 80 "token": code 81 })) 82 .send() 83 .await 84 .expect("Failed to confirm email"); 85 assert_eq!(res.status(), StatusCode::OK); 86 let user = sqlx::query!( 87 "SELECT email, email_pending_verification, email_confirmation_code FROM users WHERE handle = $1", 88 handle 89 ) 90 .fetch_one(&pool) 91 .await 92 .expect("User not found"); 93 assert_eq!(user.email, Some(new_email)); 94 assert!(user.email_pending_verification.is_none()); 95 assert!(user.email_confirmation_code.is_none()); 96} 97 98#[tokio::test] 99async fn test_request_email_update_taken_email() { 100 let client = common::client(); 101 let base_url = common::base_url().await; 102 let handle1 = format!("emailup_taken1_{}", uuid::Uuid::new_v4()); 103 let email1 = format!("{}@example.com", handle1); 104 let _ = create_verified_account(&client, &base_url, &handle1, &email1).await; 105 let handle2 = format!("emailup_taken2_{}", uuid::Uuid::new_v4()); 106 let email2 = format!("{}@example.com", handle2); 107 let access_jwt2 = create_verified_account(&client, &base_url, &handle2, &email2).await; 108 let res = client 109 .post(format!( 110 "{}/xrpc/com.atproto.server.requestEmailUpdate", 111 base_url 112 )) 113 .bearer_auth(&access_jwt2) 114 .json(&json!({"email": email1})) 115 .send() 116 .await 117 .expect("Failed to request email update"); 118 assert_eq!(res.status(), StatusCode::BAD_REQUEST); 119 let body: Value = res.json().await.expect("Invalid JSON"); 120 assert_eq!(body["error"], "EmailTaken"); 121} 122 123#[tokio::test] 124async fn test_confirm_email_invalid_token() { 125 let client = common::client(); 126 let base_url = common::base_url().await; 127 let handle = format!("emailup_inv_{}", uuid::Uuid::new_v4()); 128 let email = format!("{}@example.com", handle); 129 let access_jwt = create_verified_account(&client, &base_url, &handle, &email).await; 130 let new_email = format!("new_{}@example.com", handle); 131 let res = client 132 .post(format!( 133 "{}/xrpc/com.atproto.server.requestEmailUpdate", 134 base_url 135 )) 136 .bearer_auth(&access_jwt) 137 .json(&json!({"email": new_email})) 138 .send() 139 .await 140 .expect("Failed to request email update"); 141 assert_eq!(res.status(), StatusCode::OK); 142 let res = client 143 .post(format!("{}/xrpc/com.atproto.server.confirmEmail", base_url)) 144 .bearer_auth(&access_jwt) 145 .json(&json!({ 146 "email": new_email, 147 "token": "wrong-token" 148 })) 149 .send() 150 .await 151 .expect("Failed to confirm email"); 152 assert_eq!(res.status(), StatusCode::BAD_REQUEST); 153 let body: Value = res.json().await.expect("Invalid JSON"); 154 assert_eq!(body["error"], "InvalidToken"); 155} 156 157#[tokio::test] 158async fn test_confirm_email_wrong_email() { 159 let client = common::client(); 160 let base_url = common::base_url().await; 161 let pool = get_pool().await; 162 let handle = format!("emailup_wrong_{}", uuid::Uuid::new_v4()); 163 let email = format!("{}@example.com", handle); 164 let access_jwt = create_verified_account(&client, &base_url, &handle, &email).await; 165 let new_email = format!("new_{}@example.com", handle); 166 let res = client 167 .post(format!( 168 "{}/xrpc/com.atproto.server.requestEmailUpdate", 169 base_url 170 )) 171 .bearer_auth(&access_jwt) 172 .json(&json!({"email": new_email})) 173 .send() 174 .await 175 .expect("Failed to request email update"); 176 assert_eq!(res.status(), StatusCode::OK); 177 let user = sqlx::query!( 178 "SELECT email_confirmation_code FROM users WHERE handle = $1", 179 handle 180 ) 181 .fetch_one(&pool) 182 .await 183 .expect("User not found"); 184 let code = user.email_confirmation_code.unwrap(); 185 let res = client 186 .post(format!("{}/xrpc/com.atproto.server.confirmEmail", base_url)) 187 .bearer_auth(&access_jwt) 188 .json(&json!({ 189 "email": "another_random@example.com", 190 "token": code 191 })) 192 .send() 193 .await 194 .expect("Failed to confirm email"); 195 assert_eq!(res.status(), StatusCode::BAD_REQUEST); 196 let body: Value = res.json().await.expect("Invalid JSON"); 197 assert_eq!(body["message"], "Email does not match pending update"); 198} 199 200#[tokio::test] 201async fn test_update_email_success_no_token_required() { 202 let client = common::client(); 203 let base_url = common::base_url().await; 204 let pool = get_pool().await; 205 let handle = format!("emailup_direct_{}", uuid::Uuid::new_v4()); 206 let email = format!("{}@example.com", handle); 207 let access_jwt = create_verified_account(&client, &base_url, &handle, &email).await; 208 let new_email = format!("direct_{}@example.com", handle); 209 let res = client 210 .post(format!("{}/xrpc/com.atproto.server.updateEmail", base_url)) 211 .bearer_auth(&access_jwt) 212 .json(&json!({ "email": new_email })) 213 .send() 214 .await 215 .expect("Failed to update email"); 216 assert_eq!(res.status(), StatusCode::OK); 217 let user = sqlx::query!("SELECT email FROM users WHERE handle = $1", handle) 218 .fetch_one(&pool) 219 .await 220 .expect("User not found"); 221 assert_eq!(user.email, Some(new_email)); 222} 223 224#[tokio::test] 225async fn test_update_email_same_email_noop() { 226 let client = common::client(); 227 let base_url = common::base_url().await; 228 let handle = format!("emailup_same_{}", uuid::Uuid::new_v4()); 229 let email = format!("{}@example.com", handle); 230 let access_jwt = create_verified_account(&client, &base_url, &handle, &email).await; 231 let res = client 232 .post(format!("{}/xrpc/com.atproto.server.updateEmail", base_url)) 233 .bearer_auth(&access_jwt) 234 .json(&json!({ "email": email })) 235 .send() 236 .await 237 .expect("Failed to update email"); 238 assert_eq!( 239 res.status(), 240 StatusCode::OK, 241 "Updating to same email should succeed as no-op" 242 ); 243} 244 245#[tokio::test] 246async fn test_update_email_requires_token_after_pending() { 247 let client = common::client(); 248 let base_url = common::base_url().await; 249 let handle = format!("emailup_token_{}", uuid::Uuid::new_v4()); 250 let email = format!("{}@example.com", handle); 251 let access_jwt = create_verified_account(&client, &base_url, &handle, &email).await; 252 let new_email = format!("pending_{}@example.com", handle); 253 let res = client 254 .post(format!( 255 "{}/xrpc/com.atproto.server.requestEmailUpdate", 256 base_url 257 )) 258 .bearer_auth(&access_jwt) 259 .json(&json!({"email": new_email})) 260 .send() 261 .await 262 .expect("Failed to request email update"); 263 assert_eq!(res.status(), StatusCode::OK); 264 let res = client 265 .post(format!("{}/xrpc/com.atproto.server.updateEmail", base_url)) 266 .bearer_auth(&access_jwt) 267 .json(&json!({ "email": new_email })) 268 .send() 269 .await 270 .expect("Failed to attempt email update"); 271 assert_eq!(res.status(), StatusCode::BAD_REQUEST); 272 let body: Value = res.json().await.expect("Invalid JSON"); 273 assert_eq!(body["error"], "TokenRequired"); 274} 275 276#[tokio::test] 277async fn test_update_email_with_valid_token() { 278 let client = common::client(); 279 let base_url = common::base_url().await; 280 let pool = get_pool().await; 281 let handle = format!("emailup_valid_{}", uuid::Uuid::new_v4()); 282 let email = format!("{}@example.com", handle); 283 let access_jwt = create_verified_account(&client, &base_url, &handle, &email).await; 284 let new_email = format!("valid_{}@example.com", handle); 285 let res = client 286 .post(format!( 287 "{}/xrpc/com.atproto.server.requestEmailUpdate", 288 base_url 289 )) 290 .bearer_auth(&access_jwt) 291 .json(&json!({"email": new_email})) 292 .send() 293 .await 294 .expect("Failed to request email update"); 295 assert_eq!(res.status(), StatusCode::OK); 296 let user = sqlx::query!( 297 "SELECT email_confirmation_code FROM users WHERE handle = $1", 298 handle 299 ) 300 .fetch_one(&pool) 301 .await 302 .expect("User not found"); 303 let code = user.email_confirmation_code.unwrap(); 304 let res = client 305 .post(format!("{}/xrpc/com.atproto.server.updateEmail", base_url)) 306 .bearer_auth(&access_jwt) 307 .json(&json!({ 308 "email": new_email, 309 "token": code 310 })) 311 .send() 312 .await 313 .expect("Failed to update email"); 314 assert_eq!(res.status(), StatusCode::OK); 315 let user = sqlx::query!( 316 "SELECT email, email_pending_verification FROM users WHERE handle = $1", 317 handle 318 ) 319 .fetch_one(&pool) 320 .await 321 .expect("User not found"); 322 assert_eq!(user.email, Some(new_email)); 323 assert!(user.email_pending_verification.is_none()); 324} 325 326#[tokio::test] 327async fn test_update_email_invalid_token() { 328 let client = common::client(); 329 let base_url = common::base_url().await; 330 let handle = format!("emailup_badtok_{}", uuid::Uuid::new_v4()); 331 let email = format!("{}@example.com", handle); 332 let access_jwt = create_verified_account(&client, &base_url, &handle, &email).await; 333 let new_email = format!("badtok_{}@example.com", handle); 334 let res = client 335 .post(format!( 336 "{}/xrpc/com.atproto.server.requestEmailUpdate", 337 base_url 338 )) 339 .bearer_auth(&access_jwt) 340 .json(&json!({"email": new_email})) 341 .send() 342 .await 343 .expect("Failed to request email update"); 344 assert_eq!(res.status(), StatusCode::OK); 345 let res = client 346 .post(format!("{}/xrpc/com.atproto.server.updateEmail", base_url)) 347 .bearer_auth(&access_jwt) 348 .json(&json!({ 349 "email": new_email, 350 "token": "wrong-token-12345" 351 })) 352 .send() 353 .await 354 .expect("Failed to attempt email update"); 355 assert_eq!(res.status(), StatusCode::BAD_REQUEST); 356 let body: Value = res.json().await.expect("Invalid JSON"); 357 assert_eq!(body["error"], "InvalidToken"); 358} 359 360#[tokio::test] 361async fn test_update_email_already_taken() { 362 let client = common::client(); 363 let base_url = common::base_url().await; 364 let handle1 = format!("emailup_dup1_{}", uuid::Uuid::new_v4()); 365 let email1 = format!("{}@example.com", handle1); 366 let _ = create_verified_account(&client, &base_url, &handle1, &email1).await; 367 let handle2 = format!("emailup_dup2_{}", uuid::Uuid::new_v4()); 368 let email2 = format!("{}@example.com", handle2); 369 let access_jwt2 = create_verified_account(&client, &base_url, &handle2, &email2).await; 370 let res = client 371 .post(format!("{}/xrpc/com.atproto.server.updateEmail", base_url)) 372 .bearer_auth(&access_jwt2) 373 .json(&json!({ "email": email1 })) 374 .send() 375 .await 376 .expect("Failed to attempt email update"); 377 assert_eq!(res.status(), StatusCode::BAD_REQUEST); 378 let body: Value = res.json().await.expect("Invalid JSON"); 379 assert!( 380 body["message"].as_str().unwrap().contains("already in use") 381 || body["error"] == "InvalidRequest" 382 ); 383} 384 385#[tokio::test] 386async fn test_update_email_no_auth() { 387 let client = common::client(); 388 let base_url = common::base_url().await; 389 let res = client 390 .post(format!("{}/xrpc/com.atproto.server.updateEmail", base_url)) 391 .json(&json!({ "email": "test@example.com" })) 392 .send() 393 .await 394 .expect("Failed to send request"); 395 assert_eq!(res.status(), StatusCode::UNAUTHORIZED); 396 let body: Value = res.json().await.expect("Invalid JSON"); 397 assert_eq!(body["error"], "AuthenticationRequired"); 398} 399 400#[tokio::test] 401async fn test_update_email_invalid_format() { 402 let client = common::client(); 403 let base_url = common::base_url().await; 404 let handle = format!("emailup_fmt_{}", uuid::Uuid::new_v4()); 405 let email = format!("{}@example.com", handle); 406 let access_jwt = create_verified_account(&client, &base_url, &handle, &email).await; 407 let res = client 408 .post(format!("{}/xrpc/com.atproto.server.updateEmail", base_url)) 409 .bearer_auth(&access_jwt) 410 .json(&json!({ "email": "not-an-email" })) 411 .send() 412 .await 413 .expect("Failed to send request"); 414 assert_eq!(res.status(), StatusCode::BAD_REQUEST); 415 let body: Value = res.json().await.expect("Invalid JSON"); 416 assert_eq!(body["error"], "InvalidEmail"); 417}