forked from
lewis.moe/bspds-sandbox
PDS software with bells & whistles you didn’t even know you needed. will move this to its own account when ready.
1mod common;
2mod helpers;
3use common::*;
4use helpers::*;
5use reqwest::StatusCode;
6use serde_json::{Value, json};
7
8#[tokio::test]
9async fn test_list_sessions_returns_current_session() {
10 let client = client();
11 let (did, jwt) = setup_new_user("list-sessions").await;
12 let res = client
13 .get(format!("{}/xrpc/_account.listSessions", base_url().await))
14 .bearer_auth(&jwt)
15 .send()
16 .await
17 .expect("Failed to send request");
18 assert_eq!(res.status(), StatusCode::OK);
19 let body: Value = res.json().await.unwrap();
20 let sessions = body["sessions"]
21 .as_array()
22 .expect("sessions should be array");
23 assert!(!sessions.is_empty(), "Should have at least one session");
24 let current = sessions
25 .iter()
26 .find(|s| s["isCurrent"].as_bool() == Some(true));
27 assert!(current.is_some(), "Should have a current session marked");
28 let session = current.unwrap();
29 assert!(session["id"].as_str().is_some(), "Session should have id");
30 assert!(
31 session["createdAt"].as_str().is_some(),
32 "Session should have createdAt"
33 );
34 assert!(
35 session["expiresAt"].as_str().is_some(),
36 "Session should have expiresAt"
37 );
38 let _ = did;
39}
40
41#[tokio::test]
42async fn test_list_sessions_multiple_sessions() {
43 let client = client();
44 let ts = chrono::Utc::now().timestamp_millis();
45 let handle = format!("multi-list-{}.test", ts);
46 let email = format!("multi-list-{}@test.com", ts);
47 let password = "Testpass123!";
48 let create_payload = json!({
49 "handle": handle,
50 "email": email,
51 "password": password
52 });
53 let create_res = client
54 .post(format!(
55 "{}/xrpc/com.atproto.server.createAccount",
56 base_url().await
57 ))
58 .json(&create_payload)
59 .send()
60 .await
61 .expect("Failed to create account");
62 assert_eq!(create_res.status(), StatusCode::OK);
63 let create_body: Value = create_res.json().await.unwrap();
64 let did = create_body["did"].as_str().unwrap();
65 let jwt1 = verify_new_account(&client, did).await;
66 let login_payload = json!({
67 "identifier": handle,
68 "password": password
69 });
70 let login_res = client
71 .post(format!(
72 "{}/xrpc/com.atproto.server.createSession",
73 base_url().await
74 ))
75 .json(&login_payload)
76 .send()
77 .await
78 .expect("Failed to login");
79 assert_eq!(login_res.status(), StatusCode::OK);
80 let login_body: Value = login_res.json().await.unwrap();
81 let jwt2 = login_body["accessJwt"].as_str().unwrap();
82 let list_res = client
83 .get(format!("{}/xrpc/_account.listSessions", base_url().await))
84 .bearer_auth(jwt2)
85 .send()
86 .await
87 .expect("Failed to list sessions");
88 assert_eq!(list_res.status(), StatusCode::OK);
89 let list_body: Value = list_res.json().await.unwrap();
90 let sessions = list_body["sessions"].as_array().unwrap();
91 assert!(
92 sessions.len() >= 2,
93 "Should have at least 2 sessions, got {}",
94 sessions.len()
95 );
96 let _ = jwt1;
97}
98
99#[tokio::test]
100async fn test_list_sessions_requires_auth() {
101 let client = client();
102 let res = client
103 .get(format!("{}/xrpc/_account.listSessions", base_url().await))
104 .send()
105 .await
106 .expect("Failed to send request");
107 assert_eq!(res.status(), StatusCode::UNAUTHORIZED);
108}
109
110#[tokio::test]
111async fn test_revoke_session_success() {
112 let client = client();
113 let ts = chrono::Utc::now().timestamp_millis();
114 let handle = format!("revoke-sess-{}.test", ts);
115 let email = format!("revoke-sess-{}@test.com", ts);
116 let password = "Testpass123!";
117 let create_payload = json!({
118 "handle": handle,
119 "email": email,
120 "password": password
121 });
122 let create_res = client
123 .post(format!(
124 "{}/xrpc/com.atproto.server.createAccount",
125 base_url().await
126 ))
127 .json(&create_payload)
128 .send()
129 .await
130 .expect("Failed to create account");
131 assert_eq!(create_res.status(), StatusCode::OK);
132 let create_body: Value = create_res.json().await.unwrap();
133 let did = create_body["did"].as_str().unwrap();
134 let jwt1 = verify_new_account(&client, did).await;
135 let login_payload = json!({
136 "identifier": handle,
137 "password": password
138 });
139 let login_res = client
140 .post(format!(
141 "{}/xrpc/com.atproto.server.createSession",
142 base_url().await
143 ))
144 .json(&login_payload)
145 .send()
146 .await
147 .expect("Failed to login");
148 assert_eq!(login_res.status(), StatusCode::OK);
149 let login_body: Value = login_res.json().await.unwrap();
150 let jwt2 = login_body["accessJwt"].as_str().unwrap();
151 let list_res = client
152 .get(format!("{}/xrpc/_account.listSessions", base_url().await))
153 .bearer_auth(jwt2)
154 .send()
155 .await
156 .expect("Failed to list sessions");
157 let list_body: Value = list_res.json().await.unwrap();
158 let sessions = list_body["sessions"].as_array().unwrap();
159 let other_session = sessions
160 .iter()
161 .find(|s| s["isCurrent"].as_bool() != Some(true));
162 assert!(
163 other_session.is_some(),
164 "Should have another session to revoke"
165 );
166 let session_id = other_session.unwrap()["id"].as_str().unwrap();
167 let revoke_res = client
168 .post(format!("{}/xrpc/_account.revokeSession", base_url().await))
169 .bearer_auth(jwt2)
170 .json(&json!({"sessionId": session_id}))
171 .send()
172 .await
173 .expect("Failed to revoke session");
174 assert_eq!(revoke_res.status(), StatusCode::OK);
175 let list_after_res = client
176 .get(format!("{}/xrpc/_account.listSessions", base_url().await))
177 .bearer_auth(jwt2)
178 .send()
179 .await
180 .expect("Failed to list sessions after revoke");
181 let list_after_body: Value = list_after_res.json().await.unwrap();
182 let sessions_after = list_after_body["sessions"].as_array().unwrap();
183 let revoked_still_exists = sessions_after
184 .iter()
185 .any(|s| s["id"].as_str() == Some(session_id));
186 assert!(
187 !revoked_still_exists,
188 "Revoked session should not appear in list"
189 );
190 let _ = jwt1;
191}
192
193#[tokio::test]
194async fn test_revoke_session_invalid_id() {
195 let client = client();
196 let (_, jwt) = setup_new_user("revoke-invalid").await;
197 let res = client
198 .post(format!("{}/xrpc/_account.revokeSession", base_url().await))
199 .bearer_auth(&jwt)
200 .json(&json!({"sessionId": "not-a-number"}))
201 .send()
202 .await
203 .expect("Failed to send request");
204 assert_eq!(res.status(), StatusCode::BAD_REQUEST);
205}
206
207#[tokio::test]
208async fn test_revoke_session_not_found() {
209 let client = client();
210 let (_, jwt) = setup_new_user("revoke-notfound").await;
211 let res = client
212 .post(format!("{}/xrpc/_account.revokeSession", base_url().await))
213 .bearer_auth(&jwt)
214 .json(&json!({"sessionId": "jwt:999999999"}))
215 .send()
216 .await
217 .expect("Failed to send request");
218 assert_eq!(res.status(), StatusCode::NOT_FOUND);
219}
220
221#[tokio::test]
222async fn test_revoke_session_requires_auth() {
223 let client = client();
224 let res = client
225 .post(format!("{}/xrpc/_account.revokeSession", base_url().await))
226 .json(&json!({"sessionId": "1"}))
227 .send()
228 .await
229 .expect("Failed to send request");
230 assert_eq!(res.status(), StatusCode::UNAUTHORIZED);
231}