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