use crate::domain::dto::message::{CreateMessageRequest, MessageQueryParams, MessageResponse, UpdateMessageRequest}; use crate::core::state::AppState; use crate::http::context::CurrentUser; use crate::http::error::HTTPError; use crate::routes::message::mapper; use axum::{ extract::{Path, Query, State}, http::StatusCode, Json, }; use uuid::Uuid; /// Liste tous les messages #[utoipa::path( get, path = "/messages", responses( (status = 200, description = "Liste des messages récupérée avec succès", body = [MessageResponse]), (status = 500, description = "Erreur interne du serveur") ), params( MessageQueryParams ), tag = "Messages" )] pub async fn get_all( State(state): State, Query(filters): Query, ) -> Result>, HTTPError> { let params = mapper::query_params_to_message_filter(filters); let messages = state.repositories.message.filter(params).await?; Ok(Json( messages .into_iter() .map(mapper::message_model_to_message_response) .collect(), )) } /// Récupère un message par son ID #[utoipa::path( get, path = "/messages/{id}", responses( (status = 200, description = "Message trouvé", body = MessageResponse), (status = 404, description = "Message non trouvé"), (status = 500, description = "Erreur interne du serveur") ), params( ("id" = Uuid, Path, description = "ID du message") ), tag = "Messages" )] pub async fn get_by_id( State(state): State, Path(id): Path, ) -> Result, HTTPError> { let message = state .repositories .message .get_by_id(id) .await? .ok_or(HTTPError::NotFound)?; Ok(Json(mapper::message_model_to_message_response(message))) } /// Crée un nouveau message #[utoipa::path( post, path = "/messages", request_body = CreateMessageRequest, responses( (status = 201, description = "Message créé avec succès", body = MessageResponse), (status = 400, description = "Données invalides (canal non trouvé)"), (status = 500, description = "Erreur interne du serveur") ), tag = "Messages", security( ("bearerAuth" = []) ) )] pub async fn create( user: CurrentUser, State(state): State, Json(payload): Json, ) -> Result<(StatusCode, Json), HTTPError> { // Vérifier que le canal existe state .repositories .channel .get_by_id(payload.channel_id) .await? .ok_or(HTTPError::BadRequest("Channel not found".to_string()))?; // Optionnel: vérifier reply_to_id if let Some(reply_id) = payload.reply_to_id { state .repositories .message .get_by_id(reply_id) .await? .ok_or(HTTPError::BadRequest( "Parent message not found".to_string(), ))?; } let active_model = mapper::create_request_to_am(user.id, payload); let message = state.repositories.message.create(active_model).await?; Ok(( StatusCode::CREATED, Json(mapper::message_model_to_message_response(message)), )) } /// Met à jour un message existant #[utoipa::path( put, path = "/messages/{id}", request_body = UpdateMessageRequest, responses( (status = 200, description = "Message mis à jour avec succès", body = MessageResponse), (status = 403, description = "Interdit (pas l'auteur)"), (status = 404, description = "Message non trouvé"), (status = 500, description = "Erreur interne du serveur") ), params( ("id" = Uuid, Path, description = "ID du message") ), tag = "Messages", security( ("bearerAuth" = []) ) )] pub async fn update( user: CurrentUser, State(state): State, Path(id): Path, Json(payload): Json, ) -> Result, HTTPError> { // Vérifier l'existence let message = state .repositories .message .get_by_id(id) .await? .ok_or(HTTPError::NotFound)?; // Vérifier que l'utilisateur est l'auteur if message.user_id != user.id && !user.is_superuser { return Err(HTTPError::Forbidden); } let active_model = mapper::update_request_to_am(message, payload); let message = state.repositories.message.update(active_model).await?; Ok(Json(mapper::message_model_to_message_response(message))) } /// Supprime un message #[utoipa::path( delete, path = "/messages/{id}", responses( (status = 204, description = "Message supprimé avec succès"), (status = 403, description = "Interdit (pas l'auteur ou admin)"), (status = 404, description = "Message non trouvé"), (status = 500, description = "Erreur interne du serveur") ), params( ("id" = Uuid, Path, description = "ID du message") ), tag = "Messages", security( ("bearerAuth" = []) ) )] pub async fn delete( user: CurrentUser, State(state): State, Path(id): Path, ) -> Result { // Vérifier l'existence pour l'autorisation let message = state .repositories .message .get_by_id(id) .await? .ok_or(HTTPError::NotFound)?; // Autoriser si auteur ou superuser if message.user_id != user.id && !user.is_superuser { return Err(HTTPError::Forbidden); } if state.repositories.message.delete(id).await? { Ok(StatusCode::NO_CONTENT) } else { Err(HTTPError::NotFound) } }