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, require_object_filters};
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 let object_filters = require_object_filters(model_admin.as_ref(), user.as_ref())?;
71
72 let user_id = auth.user_id().unwrap_or("unknown").to_string();
73
74 let result = db
75 .delete_with_filters::<AdminRecord>(table_name, pk_field, &id, object_filters)
76 .await
77 .map_server_fn_error();
78
79 let affected = match result {
81 Err(e) => {
82 audit::log_delete(&user_id, &model_name, &id, false);
83 return Err(e);
84 }
85 Ok(n) => n,
86 };
87
88 if affected == 0 {
91 audit::log_delete(&user_id, &model_name, &id, false);
92 return Err(ServerFnError::server(
93 404,
94 format!("{} not found", model_name),
95 ));
96 }
97
98 audit::log_delete(&user_id, &model_name, &id, true);
99
100 Ok(MutationResponse {
101 success: true,
102 message: format!("{} deleted successfully", model_name),
103 affected: Some(affected),
104 data: None,
105 })
106}
107
108#[server_fn]
137pub async fn bulk_delete_records(
138 model_name: String,
139 request: crate::adapters::BulkDeleteRequest,
140 #[inject] site: Depends<AdminSiteKey, AdminSite>,
141 #[inject] db: Depends<AdminDatabaseKey, AdminDatabase>,
142 #[inject] http_request: ServerFnRequest,
143 #[inject] AdminAuthenticatedUser(user): AdminAuthenticatedUser,
144) -> Result<crate::adapters::BulkDeleteResponse, ServerFnError> {
145 require_csrf_token(&request.csrf_token, &http_request.inner().headers)?;
147
148 let auth = AdminAuth::from_request(&http_request);
150 let model_admin = site.get_model_admin(&model_name).map_server_fn_error()?;
151 auth.require_model_permission(model_admin.as_ref(), user.as_ref(), ModelPermission::Delete)
152 .await?;
153
154 let table_name = model_admin.table_name();
155 let pk_field = model_admin.pk_field();
156 let object_filters = require_object_filters(model_admin.as_ref(), user.as_ref())?;
157
158 let user_id = auth.user_id().unwrap_or("unknown").to_string();
159
160 let ids = request.ids;
161 if ids.len() > MAX_BULK_DELETE_IDS {
162 return Err(ServerFnError::application(format!(
163 "Too many IDs for bulk delete: {} exceeds maximum of {}",
164 ids.len(),
165 MAX_BULK_DELETE_IDS
166 )));
167 }
168
169 let result = db
170 .bulk_delete_with_filters::<AdminRecord>(table_name, pk_field, ids.clone(), object_filters)
171 .await
172 .map_server_fn_error();
173
174 let success = result.is_ok();
175 let affected_count = result.as_ref().copied().unwrap_or(0);
176 audit::log_bulk_delete(&user_id, &model_name, &ids, affected_count, success);
177
178 let affected = result?;
179
180 Ok(BulkDeleteResponse {
181 success: affected > 0,
182 deleted: affected,
183 message: format!("Deleted {} {} items", affected, model_name),
184 })
185}