use crate::core::state::AppState; use crate::domain::dto::server::{ CreateServerRequest, ServerResponse, ServerRolePermissionResponse, ServerTreeResponse, ServerUserPermissionResponse, SetServerPermissionRequest, UpdateServerRequest, }; use crate::http::context::{CurrentUser, Superuser}; use crate::http::error::HTTPError; use crate::permissions::ServerPermission; use crate::routes::server::mapper; use axum::{ Json, extract::{Path, State}, http::StatusCode, }; use uuid::Uuid; async fn require_server_permission( state: &AppState, user: &CurrentUser, server_id: Uuid, permission: ServerPermission, ) -> Result<(), HTTPError> { if user.is_superuser { return Ok(()); } let granted = state .repositories .server .get_user_permission(server_id, user.id) .await? .map(|value| ServerPermission::from_bits_truncate(value.permissions as u64)) .unwrap_or_default(); if granted.contains(permission) { Ok(()) } else { Err(HTTPError::Forbidden) } } /// Liste tous les serveurs #[utoipa::path( get, path = "/servers", responses( (status = 200, description = "Liste des serveurs récupérée avec succès", body = [ServerResponse]), (status = 500, description = "Erreur interne du serveur") ), security(("bearerAuth" = [])), tag = "Servers" )] pub async fn get_all( user: CurrentUser, State(state): State, ) -> Result>, HTTPError> { let servers = state.repositories.server.get_all().await?; let unread_counts = state .repositories .read_state .unread_counts_by_server(user.id) .await?; Ok(Json( servers .into_iter() .map(|server| { let server_id = server.id; mapper::server_model_to_server_response_with_unread_count( server, unread_counts.get(&server_id).copied().unwrap_or(0), ) }) .collect(), )) } /// Récupère un serveur par son ID #[utoipa::path( get, path = "/servers/{id}", responses( (status = 200, description = "Serveur trouvé", body = ServerResponse), (status = 404, description = "Serveur non trouvé"), (status = 500, description = "Erreur interne du serveur") ), params( ("id" = Uuid, Path, description = "ID du serveur") ), tag = "Servers" )] pub async fn get_by_id( State(state): State, Path(id): Path, ) -> Result, HTTPError> { let server = state .repositories .server .get_by_id(id) .await? .ok_or(HTTPError::NotFound)?; Ok(Json(mapper::server_model_to_server_response(server))) } /// Crée un nouveau serveur #[utoipa::path( post, path = "/servers", request_body = CreateServerRequest, responses( (status = 201, description = "Serveur créé avec succès", body = ServerResponse), (status = 500, description = "Erreur interne du serveur") ), tag = "Servers", security( ("bearerAuth" = []) ) )] pub async fn create( _admin: Superuser, State(state): State, Json(payload): Json, ) -> Result<(StatusCode, Json), HTTPError> { let server = state .services .server .create_server(payload.name, payload.is_default) .await?; Ok(( StatusCode::CREATED, Json(mapper::server_model_to_server_response(server)), )) } /// Met à jour un serveur existant #[utoipa::path( put, path = "/servers/{id}", request_body = UpdateServerRequest, responses( (status = 200, description = "Serveur mis à jour avec succès", body = ServerResponse), (status = 404, description = "Serveur non trouvé"), (status = 500, description = "Erreur interne du serveur") ), params( ("id" = Uuid, Path, description = "ID du serveur") ), tag = "Servers", security( ("bearerAuth" = []) ) )] pub async fn update( user: CurrentUser, State(state): State, Path(id): Path, Json(payload): Json, ) -> Result, HTTPError> { // Vérifier l'existence let _server = state .repositories .server .get_by_id(id) .await? .ok_or(HTTPError::NotFound)?; require_server_permission(&state, &user, id, ServerPermission::MANAGE_SERVER).await?; let server = state .services .server .update_server(id, payload.name, payload.is_default) .await?; Ok(Json(mapper::server_model_to_server_response(server))) } /// Supprime un serveur #[utoipa::path( delete, path = "/servers/{id}", responses( (status = 204, description = "Serveur supprimé avec succès"), (status = 404, description = "Serveur non trouvé"), (status = 500, description = "Erreur interne du serveur") ), params( ("id" = Uuid, Path, description = "ID du serveur") ), tag = "Servers", security( ("bearerAuth" = []) ) )] pub async fn delete( _admin: Superuser, State(state): State, Path(id): Path, ) -> Result { if state.services.server.delete_server(id).await? { Ok(StatusCode::NO_CONTENT) } else { Err(HTTPError::NotFound) } } /// Récupère les permissions directes d'un utilisateur sur un serveur. #[utoipa::path( get, path = "/servers/{server_id}/permissions/users/{user_id}", params( ("server_id" = Uuid, Path, description = "ID du serveur"), ("user_id" = Uuid, Path, description = "ID de l'utilisateur") ), responses( (status = 200, body = ServerUserPermissionResponse), (status = 404, description = "Permission introuvable"), (status = 500, description = "Erreur interne du serveur") ), tag = "Server Permissions" )] pub async fn get_user_permission( State(state): State, Path((server_id, user_id)): Path<(Uuid, Uuid)>, ) -> Result, HTTPError> { let permission = state .repositories .server .get_user_permission(server_id, user_id) .await? .ok_or(HTTPError::NotFound)?; Ok(Json(mapper::server_user_permission_to_response(permission))) } /// Liste les permissions directes des utilisateurs d'un serveur. #[utoipa::path( get, path = "/servers/{server_id}/permissions/users", params(("server_id" = Uuid, Path, description = "ID du serveur")), responses((status = 200, body = [ServerUserPermissionResponse])), tag = "Server Permissions" )] pub async fn list_user_permissions( State(state): State, Path(server_id): Path, ) -> Result>, HTTPError> { state .repositories .server .get_by_id(server_id) .await? .ok_or(HTTPError::NotFound)?; let permissions = state .repositories .server .get_user_permissions(server_id) .await?; Ok(Json( permissions .into_iter() .map(mapper::server_user_permission_to_response) .collect(), )) } /// Définit ou remplace les permissions directes d'un utilisateur sur un serveur. #[utoipa::path( put, path = "/servers/{server_id}/permissions/users/{user_id}", request_body = SetServerPermissionRequest, params( ("server_id" = Uuid, Path, description = "ID du serveur"), ("user_id" = Uuid, Path, description = "ID de l'utilisateur") ), responses( (status = 200, body = ServerUserPermissionResponse), (status = 500, description = "Erreur interne du serveur") ), tag = "Server Permissions" )] pub async fn set_user_permission( user: CurrentUser, State(state): State, Path((server_id, user_id)): Path<(Uuid, Uuid)>, Json(payload): Json, ) -> Result, HTTPError> { require_server_permission(&state, &user, server_id, ServerPermission::MANAGE_MEMBERS).await?; state .repositories .server .get_user(server_id, user_id) .await? .ok_or(HTTPError::BadRequest( "User is not a member of this server".to_string(), ))?; state .repositories .server .set_user_permission(server_id, user_id, payload.permissions) .await?; state .event_bus .emit("server_user_permission_updated", (server_id, user_id)); let permission = state .repositories .server .get_user_permission(server_id, user_id) .await? .ok_or(HTTPError::NotFound)?; Ok(Json(mapper::server_user_permission_to_response(permission))) } /// Supprime les permissions directes d'un utilisateur sur un serveur. #[utoipa::path( delete, path = "/servers/{server_id}/permissions/users/{user_id}", params( ("server_id" = Uuid, Path, description = "ID du serveur"), ("user_id" = Uuid, Path, description = "ID de l'utilisateur") ), responses( (status = 204, description = "Permission supprimée"), (status = 404, description = "Permission introuvable"), (status = 500, description = "Erreur interne du serveur") ), tag = "Server Permissions" )] pub async fn remove_user_permission( user: CurrentUser, State(state): State, Path((server_id, user_id)): Path<(Uuid, Uuid)>, ) -> Result { require_server_permission(&state, &user, server_id, ServerPermission::MANAGE_MEMBERS).await?; if state .repositories .server .get_user_permission(server_id, user_id) .await? .is_none() { return Err(HTTPError::NotFound); } state .repositories .server .remove_user_permission(server_id, user_id) .await?; state .event_bus .emit("server_user_permission_updated", (server_id, user_id)); Ok(StatusCode::NO_CONTENT) } /// Récupère les permissions d'un rôle sur un serveur. #[utoipa::path( get, path = "/servers/{server_id}/permissions/roles/{role_id}", params( ("server_id" = Uuid, Path, description = "ID du serveur"), ("role_id" = Uuid, Path, description = "ID du rôle") ), responses( (status = 200, body = ServerRolePermissionResponse), (status = 404, description = "Permission introuvable"), (status = 500, description = "Erreur interne du serveur") ), tag = "Server Permissions" )] pub async fn get_role_permission( State(state): State, Path((server_id, role_id)): Path<(Uuid, Uuid)>, ) -> Result, HTTPError> { let permission = state .repositories .server .get_role_permission(server_id, role_id) .await? .ok_or(HTTPError::NotFound)?; Ok(Json(mapper::server_role_permission_to_response(permission))) } /// Définit ou remplace les permissions d'un rôle sur un serveur. #[utoipa::path( put, path = "/servers/{server_id}/permissions/roles/{role_id}", request_body = SetServerPermissionRequest, params( ("server_id" = Uuid, Path, description = "ID du serveur"), ("role_id" = Uuid, Path, description = "ID du rôle") ), responses( (status = 200, body = ServerRolePermissionResponse), (status = 500, description = "Erreur interne du serveur") ), tag = "Server Permissions" )] pub async fn set_role_permission( user: CurrentUser, State(state): State, Path((server_id, role_id)): Path<(Uuid, Uuid)>, Json(payload): Json, ) -> Result, HTTPError> { require_server_permission(&state, &user, server_id, ServerPermission::MANAGE_ROLES).await?; state .repositories .server .set_role_permission(server_id, role_id, payload.permissions) .await?; state .event_bus .emit("server_role_permission_updated", (role_id, server_id)); let permission = state .repositories .server .get_role_permission(server_id, role_id) .await? .ok_or(HTTPError::NotFound)?; Ok(Json(mapper::server_role_permission_to_response(permission))) } /// Supprime les permissions d'un rôle sur un serveur. #[utoipa::path( delete, path = "/servers/{server_id}/permissions/roles/{role_id}", params( ("server_id" = Uuid, Path, description = "ID du serveur"), ("role_id" = Uuid, Path, description = "ID du rôle") ), responses( (status = 204, description = "Permission supprimée"), (status = 404, description = "Permission introuvable"), (status = 500, description = "Erreur interne du serveur") ), tag = "Server Permissions" )] pub async fn remove_role_permission( user: CurrentUser, State(state): State, Path((server_id, role_id)): Path<(Uuid, Uuid)>, ) -> Result { require_server_permission(&state, &user, server_id, ServerPermission::MANAGE_ROLES).await?; if state .repositories .server .get_role_permission(server_id, role_id) .await? .is_none() { return Err(HTTPError::NotFound); } state .repositories .server .remove_role_permission(server_id, role_id) .await?; state .event_bus .emit("server_role_permission_updated", (role_id, server_id)); Ok(StatusCode::NO_CONTENT) } #[utoipa::path( get, path = "/servers/{server_id}/tree", responses( (status = 200, description = "Arborescence du serveur récupérée avec succès"), (status = 404, description = "Serveur introuvable"), (status = 500, description = "Erreur interne du serveur") ), params( ("server_id" = Uuid, Path, description = "ID du serveur") ), tag = "Servers" )] pub async fn get_tree( user: CurrentUser, State(state): State, Path(server_id): Path, ) -> Result, HTTPError> { // Vérifier l'existence du serveur state .repositories .server .get_by_id(server_id) .await? .ok_or(HTTPError::NotFound)?; let tree = state .repositories .server_tree .get_for_user(server_id, user.id) .await?; Ok(Json(mapper::build_server_tree( tree.orders, tree.channels, tree.categories, tree.unread_counts, ))) }