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}