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