this repo has no description
1use crate::auth::BearerAuthAdmin;
2use crate::state::AppState;
3use axum::{
4 Json,
5 extract::State,
6 http::StatusCode,
7 response::{IntoResponse, Response},
8};
9use serde::Deserialize;
10use serde_json::json;
11use tracing::{error, warn};
12
13#[derive(Deserialize)]
14pub struct DeleteAccountInput {
15 pub did: String,
16}
17
18pub async fn delete_account(
19 State(state): State<AppState>,
20 _auth: BearerAuthAdmin,
21 Json(input): Json<DeleteAccountInput>,
22) -> Response {
23 let did = input.did.trim();
24 if did.is_empty() {
25 return (
26 StatusCode::BAD_REQUEST,
27 Json(json!({"error": "InvalidRequest", "message": "did is required"})),
28 )
29 .into_response();
30 }
31 let user = sqlx::query!("SELECT id, handle FROM users WHERE did = $1", did)
32 .fetch_optional(&state.db)
33 .await;
34 let (user_id, handle) = match user {
35 Ok(Some(row)) => (row.id, row.handle),
36 Ok(None) => {
37 return (
38 StatusCode::NOT_FOUND,
39 Json(json!({"error": "AccountNotFound", "message": "Account not found"})),
40 )
41 .into_response();
42 }
43 Err(e) => {
44 error!("DB error in delete_account: {:?}", e);
45 return (
46 StatusCode::INTERNAL_SERVER_ERROR,
47 Json(json!({"error": "InternalError"})),
48 )
49 .into_response();
50 }
51 };
52 let mut tx = match state.db.begin().await {
53 Ok(tx) => tx,
54 Err(e) => {
55 error!("Failed to begin transaction for account deletion: {:?}", e);
56 return (
57 StatusCode::INTERNAL_SERVER_ERROR,
58 Json(json!({"error": "InternalError"})),
59 )
60 .into_response();
61 }
62 };
63 if let Err(e) = sqlx::query!("DELETE FROM session_tokens WHERE did = $1", did)
64 .execute(&mut *tx)
65 .await
66 {
67 error!("Failed to delete session tokens for {}: {:?}", did, e);
68 return (
69 StatusCode::INTERNAL_SERVER_ERROR,
70 Json(json!({"error": "InternalError", "message": "Failed to delete session tokens"})),
71 )
72 .into_response();
73 }
74 if let Err(e) = sqlx::query!("DELETE FROM used_refresh_tokens WHERE session_id IN (SELECT id FROM session_tokens WHERE did = $1)", did)
75 .execute(&mut *tx)
76 .await
77 {
78 error!("Failed to delete used refresh tokens for {}: {:?}", did, e);
79 }
80 if let Err(e) = sqlx::query!("DELETE FROM records WHERE repo_id = $1", user_id)
81 .execute(&mut *tx)
82 .await
83 {
84 error!("Failed to delete records for user {}: {:?}", user_id, e);
85 return (
86 StatusCode::INTERNAL_SERVER_ERROR,
87 Json(json!({"error": "InternalError", "message": "Failed to delete records"})),
88 )
89 .into_response();
90 }
91 if let Err(e) = sqlx::query!("DELETE FROM repos WHERE user_id = $1", user_id)
92 .execute(&mut *tx)
93 .await
94 {
95 error!("Failed to delete repos for user {}: {:?}", user_id, e);
96 return (
97 StatusCode::INTERNAL_SERVER_ERROR,
98 Json(json!({"error": "InternalError", "message": "Failed to delete repos"})),
99 )
100 .into_response();
101 }
102 if let Err(e) = sqlx::query!("DELETE FROM blobs WHERE created_by_user = $1", user_id)
103 .execute(&mut *tx)
104 .await
105 {
106 error!("Failed to delete blobs for user {}: {:?}", user_id, e);
107 return (
108 StatusCode::INTERNAL_SERVER_ERROR,
109 Json(json!({"error": "InternalError", "message": "Failed to delete blobs"})),
110 )
111 .into_response();
112 }
113 if let Err(e) = sqlx::query!("DELETE FROM app_passwords WHERE user_id = $1", user_id)
114 .execute(&mut *tx)
115 .await
116 {
117 error!(
118 "Failed to delete app passwords for user {}: {:?}",
119 user_id, e
120 );
121 return (
122 StatusCode::INTERNAL_SERVER_ERROR,
123 Json(json!({"error": "InternalError", "message": "Failed to delete app passwords"})),
124 )
125 .into_response();
126 }
127 if let Err(e) = sqlx::query!(
128 "DELETE FROM invite_code_uses WHERE used_by_user = $1",
129 user_id
130 )
131 .execute(&mut *tx)
132 .await
133 {
134 error!(
135 "Failed to delete invite code uses for user {}: {:?}",
136 user_id, e
137 );
138 }
139 if let Err(e) = sqlx::query!(
140 "DELETE FROM invite_codes WHERE created_by_user = $1",
141 user_id
142 )
143 .execute(&mut *tx)
144 .await
145 {
146 error!(
147 "Failed to delete invite codes for user {}: {:?}",
148 user_id, e
149 );
150 }
151 if let Err(e) = sqlx::query!("DELETE FROM user_keys WHERE user_id = $1", user_id)
152 .execute(&mut *tx)
153 .await
154 {
155 error!("Failed to delete user keys for user {}: {:?}", user_id, e);
156 return (
157 StatusCode::INTERNAL_SERVER_ERROR,
158 Json(json!({"error": "InternalError", "message": "Failed to delete user keys"})),
159 )
160 .into_response();
161 }
162 if let Err(e) = sqlx::query!("DELETE FROM users WHERE id = $1", user_id)
163 .execute(&mut *tx)
164 .await
165 {
166 error!("Failed to delete user {}: {:?}", user_id, e);
167 return (
168 StatusCode::INTERNAL_SERVER_ERROR,
169 Json(json!({"error": "InternalError", "message": "Failed to delete user"})),
170 )
171 .into_response();
172 }
173 if let Err(e) = tx.commit().await {
174 error!("Failed to commit account deletion transaction: {:?}", e);
175 return (
176 StatusCode::INTERNAL_SERVER_ERROR,
177 Json(json!({"error": "InternalError", "message": "Failed to commit deletion"})),
178 )
179 .into_response();
180 }
181 if let Err(e) =
182 crate::api::repo::record::sequence_account_event(&state, did, false, Some("deleted")).await
183 {
184 warn!(
185 "Failed to sequence account deletion event for {}: {}",
186 did, e
187 );
188 }
189 let _ = state.cache.delete(&format!("handle:{}", handle)).await;
190 (StatusCode::OK, Json(json!({}))).into_response()
191}