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