reinhardt_admin/server/
delete.rs1#[cfg(server)]
6use super::admin_auth::AdminAuthenticatedUser;
7use crate::adapters::{AdminDatabase, AdminRecord, AdminSite, BulkDeleteResponse};
8#[cfg(server)]
9use crate::core::{AdminDatabaseKey, AdminSiteKey};
10use crate::types::MutationResponse;
11#[cfg(server)]
12use reinhardt_di::Depends;
13#[cfg(server)]
14use reinhardt_pages::server_fn::ServerFnRequest;
15use reinhardt_pages::server_fn::{ServerFnError, server_fn};
16
17#[cfg(server)]
18use super::audit;
19#[cfg(server)]
20use super::error::{AdminAuth, MapServerFnError, ModelPermission};
21#[cfg(server)]
22use super::limits::MAX_BULK_DELETE_IDS;
23#[cfg(server)]
24use super::security::require_csrf_token;
25
26#[server_fn]
50pub async fn delete_record(
51 model_name: String,
52 id: String,
53 csrf_token: String,
54 #[inject] site: Depends<AdminSiteKey, AdminSite>,
55 #[inject] db: Depends<AdminDatabaseKey, AdminDatabase>,
56 #[inject] http_request: ServerFnRequest,
57 #[inject] AdminAuthenticatedUser(user): AdminAuthenticatedUser,
58) -> Result<crate::types::MutationResponse, ServerFnError> {
59 require_csrf_token(&csrf_token, &http_request.inner().headers)?;
61
62 let auth = AdminAuth::from_request(&http_request);
64 let model_admin = site.get_model_admin(&model_name).map_server_fn_error()?;
65 auth.require_model_permission(model_admin.as_ref(), user.as_ref(), ModelPermission::Delete)
66 .await?;
67
68 let table_name = model_admin.table_name();
69 let pk_field = model_admin.pk_field();
70
71 let user_id = auth.user_id().unwrap_or("unknown").to_string();
72
73 let result = db
74 .delete::<AdminRecord>(table_name, pk_field, &id)
75 .await
76 .map_server_fn_error();
77
78 let affected = match result {
80 Err(e) => {
81 audit::log_delete(&user_id, &model_name, &id, false);
82 return Err(e);
83 }
84 Ok(n) => n,
85 };
86
87 if affected == 0 {
90 audit::log_delete(&user_id, &model_name, &id, false);
91 return Err(ServerFnError::server(
92 404,
93 format!("{} not found", model_name),
94 ));
95 }
96
97 audit::log_delete(&user_id, &model_name, &id, true);
98
99 Ok(MutationResponse {
100 success: true,
101 message: format!("{} deleted successfully", model_name),
102 affected: Some(affected),
103 data: None,
104 })
105}
106
107#[server_fn]
136pub async fn bulk_delete_records(
137 model_name: String,
138 request: crate::adapters::BulkDeleteRequest,
139 #[inject] site: Depends<AdminSiteKey, AdminSite>,
140 #[inject] db: Depends<AdminDatabaseKey, AdminDatabase>,
141 #[inject] http_request: ServerFnRequest,
142 #[inject] AdminAuthenticatedUser(user): AdminAuthenticatedUser,
143) -> Result<crate::adapters::BulkDeleteResponse, ServerFnError> {
144 require_csrf_token(&request.csrf_token, &http_request.inner().headers)?;
146
147 let auth = AdminAuth::from_request(&http_request);
149 let model_admin = site.get_model_admin(&model_name).map_server_fn_error()?;
150 auth.require_model_permission(model_admin.as_ref(), user.as_ref(), ModelPermission::Delete)
151 .await?;
152
153 let table_name = model_admin.table_name();
154 let pk_field = model_admin.pk_field();
155
156 let user_id = auth.user_id().unwrap_or("unknown").to_string();
157
158 let ids = request.ids;
159 if ids.len() > MAX_BULK_DELETE_IDS {
160 return Err(ServerFnError::application(format!(
161 "Too many IDs for bulk delete: {} exceeds maximum of {}",
162 ids.len(),
163 MAX_BULK_DELETE_IDS
164 )));
165 }
166
167 let result = db
168 .bulk_delete::<AdminRecord>(table_name, pk_field, ids.clone())
169 .await
170 .map_server_fn_error();
171
172 let success = result.is_ok();
173 let affected_count = result.as_ref().copied().unwrap_or(0);
174 audit::log_bulk_delete(&user_id, &model_name, &ids, affected_count, success);
175
176 let affected = result?;
177
178 Ok(BulkDeleteResponse {
179 success: affected > 0,
180 deleted: affected,
181 message: format!("Deleted {} {} items", affected, model_name),
182 })
183}