this repo has no description
1mod common; 2mod helpers; 3use common::*; 4use helpers::verify_new_account; 5use reqwest::StatusCode; 6use serde_json::{Value, json}; 7 8#[tokio::test] 9async fn test_server_basics() { 10 let client = client(); 11 let base = base_url().await; 12 let health = client.get(format!("{}/health", base)).send().await.unwrap(); 13 assert_eq!(health.status(), StatusCode::OK); 14 assert_eq!(health.text().await.unwrap(), "OK"); 15 let describe = client 16 .get(format!("{}/xrpc/com.atproto.server.describeServer", base)) 17 .send() 18 .await 19 .unwrap(); 20 assert_eq!(describe.status(), StatusCode::OK); 21 let body: Value = describe.json().await.unwrap(); 22 assert!(body.get("availableUserDomains").is_some()); 23} 24 25#[tokio::test] 26async fn test_account_and_session_lifecycle() { 27 let client = client(); 28 let base = base_url().await; 29 let handle = format!("u{}", &uuid::Uuid::new_v4().simple().to_string()[..12]); 30 let payload = json!({ "handle": handle, "email": format!("{}@example.com", handle), "password": "Testpass123!" }); 31 let create_res = client 32 .post(format!("{}/xrpc/com.atproto.server.createAccount", base)) 33 .json(&payload) 34 .send() 35 .await 36 .unwrap(); 37 assert_eq!(create_res.status(), StatusCode::OK); 38 let create_body: Value = create_res.json().await.unwrap(); 39 let did = create_body["did"].as_str().unwrap(); 40 let _ = verify_new_account(&client, did).await; 41 let login = client 42 .post(format!("{}/xrpc/com.atproto.server.createSession", base)) 43 .json(&json!({ "identifier": handle, "password": "Testpass123!" })) 44 .send() 45 .await 46 .unwrap(); 47 assert_eq!(login.status(), StatusCode::OK); 48 let login_body: Value = login.json().await.unwrap(); 49 let access_jwt = login_body["accessJwt"].as_str().unwrap().to_string(); 50 let refresh_jwt = login_body["refreshJwt"].as_str().unwrap().to_string(); 51 let refresh = client 52 .post(format!("{}/xrpc/com.atproto.server.refreshSession", base)) 53 .bearer_auth(&refresh_jwt) 54 .send() 55 .await 56 .unwrap(); 57 assert_eq!(refresh.status(), StatusCode::OK); 58 let refresh_body: Value = refresh.json().await.unwrap(); 59 assert!(refresh_body["accessJwt"].as_str().is_some()); 60 assert_ne!(refresh_body["accessJwt"].as_str().unwrap(), access_jwt); 61 assert_ne!(refresh_body["refreshJwt"].as_str().unwrap(), refresh_jwt); 62 let missing_id = client 63 .post(format!("{}/xrpc/com.atproto.server.createSession", base)) 64 .json(&json!({ "password": "Testpass123!" })) 65 .send() 66 .await 67 .unwrap(); 68 assert!( 69 missing_id.status() == StatusCode::BAD_REQUEST 70 || missing_id.status() == StatusCode::UNPROCESSABLE_ENTITY 71 ); 72 let invalid_handle = client.post(format!("{}/xrpc/com.atproto.server.createAccount", base)) 73 .json(&json!({ "handle": "invalid!handle.com", "email": "test@example.com", "password": "Testpass123!" })) 74 .send().await.unwrap(); 75 assert_eq!(invalid_handle.status(), StatusCode::BAD_REQUEST); 76 let unauth_session = client 77 .get(format!("{}/xrpc/com.atproto.server.getSession", base)) 78 .bearer_auth(AUTH_TOKEN) 79 .send() 80 .await 81 .unwrap(); 82 assert_eq!(unauth_session.status(), StatusCode::UNAUTHORIZED); 83 let delete_session = client 84 .post(format!("{}/xrpc/com.atproto.server.deleteSession", base)) 85 .bearer_auth(AUTH_TOKEN) 86 .send() 87 .await 88 .unwrap(); 89 assert_eq!(delete_session.status(), StatusCode::UNAUTHORIZED); 90} 91 92#[tokio::test] 93async fn test_service_auth() { 94 let client = client(); 95 let base = base_url().await; 96 let (access_jwt, did) = create_account_and_login(&client).await; 97 let res = client 98 .get(format!("{}/xrpc/com.atproto.server.getServiceAuth", base)) 99 .bearer_auth(&access_jwt) 100 .query(&[("aud", "did:web:example.com")]) 101 .send() 102 .await 103 .unwrap(); 104 assert_eq!(res.status(), StatusCode::OK); 105 let body: Value = res.json().await.unwrap(); 106 let token = body["token"].as_str().unwrap(); 107 let parts: Vec<&str> = token.split('.').collect(); 108 assert_eq!(parts.len(), 3, "Token should be a valid JWT"); 109 use base64::{Engine as _, engine::general_purpose::URL_SAFE_NO_PAD}; 110 let payload_bytes = URL_SAFE_NO_PAD.decode(parts[1]).unwrap(); 111 let claims: Value = serde_json::from_slice(&payload_bytes).unwrap(); 112 assert_eq!(claims["iss"], did); 113 assert_eq!(claims["sub"], did); 114 assert_eq!(claims["aud"], "did:web:example.com"); 115 let lxm_res = client 116 .get(format!("{}/xrpc/com.atproto.server.getServiceAuth", base)) 117 .bearer_auth(&access_jwt) 118 .query(&[ 119 ("aud", "did:web:example.com"), 120 ("lxm", "com.atproto.repo.getRecord"), 121 ]) 122 .send() 123 .await 124 .unwrap(); 125 assert_eq!(lxm_res.status(), StatusCode::OK); 126 let lxm_body: Value = lxm_res.json().await.unwrap(); 127 let lxm_token = lxm_body["token"].as_str().unwrap(); 128 let lxm_parts: Vec<&str> = lxm_token.split('.').collect(); 129 let lxm_payload = URL_SAFE_NO_PAD.decode(lxm_parts[1]).unwrap(); 130 let lxm_claims: Value = serde_json::from_slice(&lxm_payload).unwrap(); 131 assert_eq!(lxm_claims["lxm"], "com.atproto.repo.getRecord"); 132 let unauth = client 133 .get(format!("{}/xrpc/com.atproto.server.getServiceAuth", base)) 134 .query(&[("aud", "did:web:example.com")]) 135 .send() 136 .await 137 .unwrap(); 138 assert_eq!(unauth.status(), StatusCode::UNAUTHORIZED); 139 let missing_aud = client 140 .get(format!("{}/xrpc/com.atproto.server.getServiceAuth", base)) 141 .bearer_auth(&access_jwt) 142 .send() 143 .await 144 .unwrap(); 145 assert_eq!(missing_aud.status(), StatusCode::BAD_REQUEST); 146} 147 148#[tokio::test] 149async fn test_account_status_and_activation() { 150 let client = client(); 151 let base = base_url().await; 152 let (access_jwt, _) = create_account_and_login(&client).await; 153 let status = client 154 .get(format!( 155 "{}/xrpc/com.atproto.server.checkAccountStatus", 156 base 157 )) 158 .bearer_auth(&access_jwt) 159 .send() 160 .await 161 .unwrap(); 162 assert_eq!(status.status(), StatusCode::OK); 163 let body: Value = status.json().await.unwrap(); 164 assert_eq!(body["activated"], true); 165 assert_eq!(body["validDid"], true); 166 assert!(body["repoCommit"].is_string()); 167 assert!(body["repoRev"].is_string()); 168 assert!(body["indexedRecords"].is_number()); 169 let unauth_status = client 170 .get(format!( 171 "{}/xrpc/com.atproto.server.checkAccountStatus", 172 base 173 )) 174 .send() 175 .await 176 .unwrap(); 177 assert_eq!(unauth_status.status(), StatusCode::UNAUTHORIZED); 178 let activate = client 179 .post(format!("{}/xrpc/com.atproto.server.activateAccount", base)) 180 .bearer_auth(&access_jwt) 181 .send() 182 .await 183 .unwrap(); 184 assert_eq!(activate.status(), StatusCode::OK); 185 let unauth_activate = client 186 .post(format!("{}/xrpc/com.atproto.server.activateAccount", base)) 187 .send() 188 .await 189 .unwrap(); 190 assert_eq!(unauth_activate.status(), StatusCode::UNAUTHORIZED); 191 let deactivate = client 192 .post(format!( 193 "{}/xrpc/com.atproto.server.deactivateAccount", 194 base 195 )) 196 .bearer_auth(&access_jwt) 197 .json(&json!({})) 198 .send() 199 .await 200 .unwrap(); 201 assert_eq!(deactivate.status(), StatusCode::OK); 202}