this repo has no description
1use crate::api::error::ApiError; 2use crate::api::EmptyResponse; 3use crate::auth::BearerAuthAdmin; 4use crate::state::AppState; 5use crate::types::Did; 6use axum::{ 7 Json, 8 extract::State, 9 response::{IntoResponse, Response}, 10}; 11use serde::Deserialize; 12use tracing::{error, warn}; 13 14#[derive(Deserialize)] 15pub struct DeleteAccountInput { 16 pub did: Did, 17} 18 19pub async fn delete_account( 20 State(state): State<AppState>, 21 _auth: BearerAuthAdmin, 22 Json(input): Json<DeleteAccountInput>, 23) -> Response { 24 let did = &input.did; 25 let user = sqlx::query!("SELECT id, handle FROM users WHERE did = $1", did.as_str()) 26 .fetch_optional(&state.db) 27 .await; 28 let (user_id, handle) = match user { 29 Ok(Some(row)) => (row.id, row.handle), 30 Ok(None) => { 31 return ApiError::AccountNotFound.into_response(); 32 } 33 Err(e) => { 34 error!("DB error in delete_account: {:?}", e); 35 return ApiError::InternalError(None).into_response(); 36 } 37 }; 38 let mut tx = match state.db.begin().await { 39 Ok(tx) => tx, 40 Err(e) => { 41 error!("Failed to begin transaction for account deletion: {:?}", e); 42 return ApiError::InternalError(None).into_response(); 43 } 44 }; 45 if let Err(e) = sqlx::query!("DELETE FROM session_tokens WHERE did = $1", did.as_str()) 46 .execute(&mut *tx) 47 .await 48 { 49 error!("Failed to delete session tokens for {}: {:?}", did, e); 50 return ApiError::InternalError(Some("Failed to delete session tokens".into())).into_response(); 51 } 52 if let Err(e) = sqlx::query!("DELETE FROM used_refresh_tokens WHERE session_id IN (SELECT id FROM session_tokens WHERE did = $1)", did.as_str()) 53 .execute(&mut *tx) 54 .await 55 { 56 error!("Failed to delete used refresh tokens for {}: {:?}", did, e); 57 } 58 if let Err(e) = sqlx::query!("DELETE FROM records WHERE repo_id = $1", user_id) 59 .execute(&mut *tx) 60 .await 61 { 62 error!("Failed to delete records for user {}: {:?}", user_id, e); 63 return ApiError::InternalError(Some("Failed to delete records".into())).into_response(); 64 } 65 if let Err(e) = sqlx::query!("DELETE FROM repos WHERE user_id = $1", user_id) 66 .execute(&mut *tx) 67 .await 68 { 69 error!("Failed to delete repos for user {}: {:?}", user_id, e); 70 return ApiError::InternalError(Some("Failed to delete repos".into())).into_response(); 71 } 72 if let Err(e) = sqlx::query!("DELETE FROM blobs WHERE created_by_user = $1", user_id) 73 .execute(&mut *tx) 74 .await 75 { 76 error!("Failed to delete blobs for user {}: {:?}", user_id, e); 77 return ApiError::InternalError(Some("Failed to delete blobs".into())).into_response(); 78 } 79 if let Err(e) = sqlx::query!("DELETE FROM app_passwords WHERE user_id = $1", user_id) 80 .execute(&mut *tx) 81 .await 82 { 83 error!( 84 "Failed to delete app passwords for user {}: {:?}", 85 user_id, e 86 ); 87 return ApiError::InternalError(Some("Failed to delete app passwords".into())).into_response(); 88 } 89 if let Err(e) = sqlx::query!( 90 "DELETE FROM invite_code_uses WHERE used_by_user = $1", 91 user_id 92 ) 93 .execute(&mut *tx) 94 .await 95 { 96 error!( 97 "Failed to delete invite code uses for user {}: {:?}", 98 user_id, e 99 ); 100 } 101 if let Err(e) = sqlx::query!( 102 "DELETE FROM invite_codes WHERE created_by_user = $1", 103 user_id 104 ) 105 .execute(&mut *tx) 106 .await 107 { 108 error!( 109 "Failed to delete invite codes for user {}: {:?}", 110 user_id, e 111 ); 112 } 113 if let Err(e) = sqlx::query!("DELETE FROM user_keys WHERE user_id = $1", user_id) 114 .execute(&mut *tx) 115 .await 116 { 117 error!("Failed to delete user keys for user {}: {:?}", user_id, e); 118 return ApiError::InternalError(Some("Failed to delete user keys".into())).into_response(); 119 } 120 if let Err(e) = sqlx::query!("DELETE FROM users WHERE id = $1", user_id) 121 .execute(&mut *tx) 122 .await 123 { 124 error!("Failed to delete user {}: {:?}", user_id, e); 125 return ApiError::InternalError(Some("Failed to delete user".into())).into_response(); 126 } 127 if let Err(e) = tx.commit().await { 128 error!("Failed to commit account deletion transaction: {:?}", e); 129 return ApiError::InternalError(Some("Failed to commit deletion".into())).into_response(); 130 } 131 if let Err(e) = 132 crate::api::repo::record::sequence_account_event(&state, did.as_str(), false, Some("deleted")).await 133 { 134 warn!( 135 "Failed to sequence account deletion event for {}: {}", 136 did, e 137 ); 138 } 139 let _ = state.cache.delete(&format!("handle:{}", handle)).await; 140 EmptyResponse::ok().into_response() 141}