This commit is contained in:
2026-08-29 14:05:43 +02:00
parent 5e97e9c223
commit 88ad3c389f
15 changed files with 423 additions and 109 deletions
+79 -20
View File
@@ -13,11 +13,18 @@ use axum::{
extract::{Path, Query, State},
http::StatusCode,
};
use uuid::Uuid;
use sea_orm::{ColumnTrait, EntityTrait, QueryFilter};
use uuid::Uuid;
pub(crate) async fn can_access(state: &AppState, channel_id: Uuid, user_id: Uuid) -> Result<bool, HTTPError> {
let Some(channel) = channel::Entity::find_by_id(channel_id).one(&state.db).await? else {
pub(crate) async fn can_access(
state: &AppState,
channel_id: Uuid,
user_id: Uuid,
) -> Result<bool, HTTPError> {
let Some(channel) = channel::Entity::find_by_id(channel_id)
.one(&state.db)
.await?
else {
return Ok(false);
};
if channel.channel_type != channel::ChannelType::DM {
@@ -26,7 +33,9 @@ pub(crate) async fn can_access(state: &AppState, channel_id: Uuid, user_id: Uuid
Ok(channel_user::Entity::find()
.filter(channel_user::Column::ChannelId.eq(channel_id))
.filter(channel_user::Column::UserId.eq(user_id))
.one(&state.db).await?.is_some())
.one(&state.db)
.await?
.is_some())
}
/// Liste une fenêtre paginée de messages
@@ -67,7 +76,11 @@ pub async fn get_all(
.message_reaction
.grouped_for_messages(&message_ids)
.await?;
let mut attachments = state.repositories.message.attachments_for_messages(&message_ids).await?;
let mut attachments = state
.repositories
.message
.attachments_for_messages(&message_ids)
.await?;
let oldest_id = page.messages.first().map(|message| message.id);
let newest_id = page.messages.last().map(|message| message.id);
@@ -124,11 +137,20 @@ pub async fn get_by_id(
.await?
.remove(&id)
.unwrap_or_default();
let attachments = state.repositories.message.attachments_for_messages(&[id]).await?.remove(&id).unwrap_or_default();
let attachments = state
.repositories
.message
.attachments_for_messages(&[id])
.await?
.remove(&id)
.unwrap_or_default();
Ok(Json(
mapper::message_model_to_message_response_with_data(message, None, reactions, attachments),
))
Ok(Json(mapper::message_model_to_message_response_with_data(
message,
None,
reactions,
attachments,
)))
}
/// Crée un nouveau message
@@ -163,7 +185,9 @@ pub async fn create(
}
if payload.content.trim().is_empty() && payload.file_ids.is_empty() {
return Err(HTTPError::BadRequest("content or at least one file is required".into()));
return Err(HTTPError::BadRequest(
"content or at least one file is required".into(),
));
}
// Optionnel: vérifier reply_to_id
@@ -181,10 +205,22 @@ pub async fn create(
let message = state
.services
.message
.create_message_with_attachments(payload.channel_id, user.id, payload.content, payload.file_ids, payload.reply_to_id)
.create_message_with_attachments(
payload.channel_id,
user.id,
payload.content,
payload.file_ids,
payload.reply_to_id,
)
.await
.map_err(|error| HTTPError::BadRequest(error.to_string()))?;
let attachments = state.repositories.message.attachments_for_messages(&[message.id]).await?.remove(&message.id).unwrap_or_default();
let attachments = state
.repositories
.message
.attachments_for_messages(&[message.id])
.await?
.remove(&message.id)
.unwrap_or_default();
Ok((
StatusCode::CREATED,
Json(mapper::message_model_to_message_response_with_data(
@@ -247,10 +283,19 @@ pub async fn update(
.await?
.remove(&id)
.unwrap_or_default();
let attachments = state.repositories.message.attachments_for_messages(&[id]).await?.remove(&id).unwrap_or_default();
Ok(Json(
mapper::message_model_to_message_response_with_data(message, None, reactions, attachments),
))
let attachments = state
.repositories
.message
.attachments_for_messages(&[id])
.await?
.remove(&id)
.unwrap_or_default();
Ok(Json(mapper::message_model_to_message_response_with_data(
message,
None,
reactions,
attachments,
)))
}
#[utoipa::path(
@@ -273,8 +318,15 @@ pub async fn add_reaction(
Path(message_id): Path<Uuid>,
Json(payload): Json<CreateReactionRequest>,
) -> Result<(StatusCode, Json<ReactionResponse>), HTTPError> {
let message = state.repositories.message.get_by_id(message_id).await?.ok_or(HTTPError::NotFound)?;
if !can_access(&state, message.channel_id, user.id).await? { return Err(HTTPError::Forbidden); }
let message = state
.repositories
.message
.get_by_id(message_id)
.await?
.ok_or(HTTPError::NotFound)?;
if !can_access(&state, message.channel_id, user.id).await? {
return Err(HTTPError::Forbidden);
}
let (reaction, created) = state
.services
.message_reaction
@@ -312,8 +364,15 @@ pub async fn remove_reaction(
Path((message_id, emoji_id)): Path<(Uuid, Uuid)>,
Query(query): Query<DeleteReactionQuery>,
) -> Result<StatusCode, HTTPError> {
let message = state.repositories.message.get_by_id(message_id).await?.ok_or(HTTPError::NotFound)?;
if !can_access(&state, message.channel_id, user.id).await? { return Err(HTTPError::Forbidden); }
let message = state
.repositories
.message
.get_by_id(message_id)
.await?
.ok_or(HTTPError::NotFound)?;
if !can_access(&state, message.channel_id, user.id).await? {
return Err(HTTPError::Forbidden);
}
state
.services
.message_reaction