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