api/routes/modules/assignments/tickets/delete.rs
1//! Ticket deletion handler.
2//!
3//! Provides an endpoint to delete an existing ticket for an assignment.
4//!
5//! Only the user who owns the ticket can delete it. The endpoint validates
6//! that the user has permission before performing the deletion.
7
8use crate::{auth::AuthUser, response::ApiResponse};
9use axum::{
10 extract::{Path, State},
11 http::StatusCode,
12 response::{IntoResponse, Json},
13 Extension,
14};
15use db::models::tickets::Model as TicketModel;
16use util::state::AppState;
17
18use crate::routes::modules::assignments::tickets::common::is_valid;
19
20/// Deletes an existing ticket.
21///
22/// **Endpoint:** `DELETE /modules/{module_id}/assignments/{assignment_id}/tickets/{ticket_id}`
23/// **Permissions:** Only the ticket owner can delete their ticket.
24///
25/// ### Path parameters
26/// - `module_id` → ID of the module (used for permission check)
27/// - `assignment_id` → ID of the assignment (unused in handler, kept for route consistency)
28/// - `ticket_id` → ID of the ticket to be deleted
29///
30/// ### Responses
31/// - `200 OK` → Ticket deleted successfully
32/// ```json
33/// {
34/// "success": true,
35/// "data": {},
36/// "message": "Ticket deleted successfully"
37/// }
38/// ```
39/// - `403 Forbidden` → User does not have permission to delete this ticket
40/// ```json
41/// {
42/// "success": false,
43/// "data": null,
44/// "message": "Forbidden"
45/// }
46/// ```
47/// - `500 Internal Server Error` → Failed to delete the ticket
48/// ```json
49/// {
50/// "success": false,
51/// "data": null,
52/// "message": "Failed to delete ticket"
53/// }
54/// ```
55pub async fn delete_ticket(
56 State(app_state): State<AppState>,
57 Path((module_id, _, ticket_id)): Path<(i64, i64, i64)>,
58 Extension(AuthUser(claims)): Extension<AuthUser>,
59) -> impl IntoResponse {
60 let db = app_state.db();
61 let user_id = claims.sub;
62
63 if !is_valid(user_id, ticket_id, module_id,claims.admin, db).await {
64 return (StatusCode::FORBIDDEN, Json(ApiResponse::<()>::error("Forbidden"))).into_response();
65 }
66
67 match TicketModel::delete(db, ticket_id).await {
68 Ok(_) => (
69 StatusCode::OK,
70 Json(ApiResponse::<()>::success((), "Ticket deleted successfully")),
71 )
72 .into_response(),
73 Err(_) => (
74 StatusCode::INTERNAL_SERVER_ERROR,
75 Json(ApiResponse::<()>::error("Failed to delete ticket")),
76 )
77 .into_response(),
78 }
79}