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