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