this repo has no description
at main 4.9 kB view raw
1use crate::api::EmptyResponse; 2use crate::api::error::ApiError; 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())) 51 .into_response(); 52 } 53 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()) 54 .execute(&mut *tx) 55 .await 56 { 57 error!("Failed to delete used refresh tokens for {}: {:?}", did, e); 58 } 59 if let Err(e) = sqlx::query!("DELETE FROM records WHERE repo_id = $1", user_id) 60 .execute(&mut *tx) 61 .await 62 { 63 error!("Failed to delete records for user {}: {:?}", user_id, e); 64 return ApiError::InternalError(Some("Failed to delete records".into())).into_response(); 65 } 66 if let Err(e) = sqlx::query!("DELETE FROM repos WHERE user_id = $1", user_id) 67 .execute(&mut *tx) 68 .await 69 { 70 error!("Failed to delete repos for user {}: {:?}", user_id, e); 71 return ApiError::InternalError(Some("Failed to delete repos".into())).into_response(); 72 } 73 if let Err(e) = sqlx::query!("DELETE FROM blobs WHERE created_by_user = $1", user_id) 74 .execute(&mut *tx) 75 .await 76 { 77 error!("Failed to delete blobs for user {}: {:?}", user_id, e); 78 return ApiError::InternalError(Some("Failed to delete blobs".into())).into_response(); 79 } 80 if let Err(e) = sqlx::query!("DELETE FROM app_passwords WHERE user_id = $1", user_id) 81 .execute(&mut *tx) 82 .await 83 { 84 error!( 85 "Failed to delete app passwords for user {}: {:?}", 86 user_id, e 87 ); 88 return ApiError::InternalError(Some("Failed to delete app passwords".into())) 89 .into_response(); 90 } 91 if let Err(e) = sqlx::query!( 92 "DELETE FROM invite_code_uses WHERE used_by_user = $1", 93 user_id 94 ) 95 .execute(&mut *tx) 96 .await 97 { 98 error!( 99 "Failed to delete invite code uses for user {}: {:?}", 100 user_id, e 101 ); 102 } 103 if let Err(e) = sqlx::query!( 104 "DELETE FROM invite_codes WHERE created_by_user = $1", 105 user_id 106 ) 107 .execute(&mut *tx) 108 .await 109 { 110 error!( 111 "Failed to delete invite codes for user {}: {:?}", 112 user_id, e 113 ); 114 } 115 if let Err(e) = sqlx::query!("DELETE FROM user_keys WHERE user_id = $1", user_id) 116 .execute(&mut *tx) 117 .await 118 { 119 error!("Failed to delete user keys for user {}: {:?}", user_id, e); 120 return ApiError::InternalError(Some("Failed to delete user keys".into())).into_response(); 121 } 122 if let Err(e) = sqlx::query!("DELETE FROM users WHERE id = $1", user_id) 123 .execute(&mut *tx) 124 .await 125 { 126 error!("Failed to delete user {}: {:?}", user_id, e); 127 return ApiError::InternalError(Some("Failed to delete user".into())).into_response(); 128 } 129 if let Err(e) = tx.commit().await { 130 error!("Failed to commit account deletion transaction: {:?}", e); 131 return ApiError::InternalError(Some("Failed to commit deletion".into())).into_response(); 132 } 133 if let Err(e) = 134 crate::api::repo::record::sequence_account_event(&state, did, false, Some("deleted")).await 135 { 136 warn!( 137 "Failed to sequence account deletion event for {}: {}", 138 did, e 139 ); 140 } 141 let _ = state.cache.delete(&format!("handle:{}", handle)).await; 142 EmptyResponse::ok().into_response() 143}