feat: account deletion request and active-user check

This commit is contained in:
2026-10-26 02:11:44 +01:00
parent 83bb5d9847
commit 0b5d18c4ee
27 changed files with 577 additions and 151 deletions

View File

@@ -215,3 +215,41 @@ async fn a_remote_block_publishes_its_event_after_the_k_ap_write() {
assert_eq!(blocked, 1);
assert_eq!(queued(&pool, "ActorBlocked").await, 1);
}
/// A token outlives the account that owns it, so every authenticated route
/// must re-check the account: a deleted user gets exactly what an anonymous
/// caller gets.
#[tokio::test]
async fn a_deleted_users_token_is_rejected() {
let (router, pool) = support::server().await;
let alice = support::register(&router, "alice", "alice@example.com").await;
let bearer = |token: &str| {
axum::http::Request::builder()
.uri("/api/v1/diary/export?format=json")
.header("authorization", format!("Bearer {token}"))
.body(axum::body::Body::empty())
.unwrap()
};
let (status, _, body) = support::send(&router, bearer(&alice.token)).await;
assert_eq!(status, 200, "token works while the account is live: {body}");
let (status, _, _) =
support::send(&router, support::get("/diary/export", Some(&alice.cookie))).await;
assert_eq!(status, 200, "cookie works while the account is live");
sqlx::query("UPDATE users SET deleted_at = '2026-01-01T00:00:00Z' WHERE id = ?")
.bind(&alice.user_id)
.execute(&pool)
.await
.unwrap();
let (status, _, body) = support::send(&router, bearer(&alice.token)).await;
assert_eq!(status, 401, "json route: {body}");
let (anon_status, anon_headers, _) =
support::send(&router, support::get("/diary/export", None)).await;
let (status, headers, _) =
support::send(&router, support::get("/diary/export", Some(&alice.cookie))).await;
assert_eq!(status, anon_status, "classic owner page");
assert_eq!(headers.get("location"), anon_headers.get("location"));
assert_eq!(headers.get("location").unwrap(), "/login");
}