This commit is contained in:
2026-07-28 08:56:14 +02:00
parent 96ffe27040
commit 066074dcd4
13 changed files with 151 additions and 85 deletions
@@ -5,19 +5,30 @@ sessionId: session-260713-161459-1v9e
# Requirements # Requirements
### Objectif ### Objectif
Créer dans `src/domain/` les payloads explicites correspondant à **tous les événements actuellement émis par `src/repositories/`**, afin quils soient réutilisables par plusieurs endpoints et consommateurs sans dépendre des modèles SeaORM, des repositories ou des DTO Gateway.
Créer dans `src/domain/` les payloads explicites correspondant à **tous les événements actuellement émis par
`src/repositories/`**, afin quils soient réutilisables par plusieurs endpoints et consommateurs sans dépendre des
modèles SeaORM, des repositories ou des DTO Gateway.
### Inclus ### Inclus
- Remplacer les payloads implicites des 20 émissions recensées dans `category.rs`, `channel.rs`, `group.rs`, `message.rs`, `server.rs` et `user.rs` par des contrats de domaine dédiés.
- Remplacer les payloads implicites des 20 émissions recensées dans `category.rs`, `channel.rs`, `role`, `message.rs`,
`server.rs` et `user.rs` par des contrats de domaine dédiés.
- Couvrir les événements de création, mise à jour, suppression et changement utilisateur/serveur existants. - Couvrir les événements de création, mise à jour, suppression et changement utilisateur/serveur existants.
- Prévoir des payloads dédiés pour les données complètes des créations/mises à jour et pour les identifiants nécessaires aux suppressions ; ne pas utiliser de tuple anonyme. - Prévoir des payloads dédiés pour les données complètes des créations/mises à jour et pour les identifiants nécessaires
- Conserver les contrats de permissions déjà demandés : `ServerUserChanged`, `RoleUserChanged`, `ServerRolePermissionChanged`, `ServerUserPermissionChanged`, `ChannelRolePermissionChanged` et `ChannelUserPermissionChanged`. aux suppressions ; ne pas utiliser de tuple anonyme.
- Ajouter les contrats CRUD pour les ressources `Category`, `Channel`, `Group`, `Message`, `Server` et `User`, ainsi que les payloads didentifiants de suppression et le payload `UserChanged` si nécessaire pour `user_changed`. - Conserver les contrats de permissions déjà demandés : `ServerUserChanged`, `RoleUserChanged`,
- Utiliser `Uuid` et des noms explicites (`category_id`, `channel_id`, `group_id`/`role_id`, `message_id`, `server_id`, `user_id`) plutôt que `id` lorsque le domaine est connu. `ServerRolePermissionChanged`, `ServerUserPermissionChanged`, `ChannelRolePermissionChanged` et
`ChannelUserPermissionChanged`.
- Ajouter les contrats CRUD pour les ressources `Category`, `Channel`, `Group`, `Message`, `Server` et `User`, ainsi que
les payloads didentifiants de suppression et le payload `UserChanged` si nécessaire pour `user_changed`.
- Utiliser `Uuid` et des noms explicites (`category_id`, `channel_id`, `group_id`/`role_id`, `message_id`, `server_id`,
`user_id`) plutôt que `id` lorsque le domaine est connu.
- Dériver `Clone` et `Debug` sur chaque struct, avec une composition compatible avec `Send + Sync + 'static`. - Dériver `Clone` et `Debug` sur chaque struct, avec une composition compatible avec `Send + Sync + 'static`.
- Exposer les contrats depuis `crate::domain` pour une utilisation multi-endpoint. - Exposer les contrats depuis `crate::domain` pour une utilisation multi-endpoint.
### Exclus ### Exclus
- Aucun branchement des nouveaux types dans les repositories et aucune modification de `Repositories`. - Aucun branchement des nouveaux types dans les repositories et aucune modification de `Repositories`.
- Aucun changement de nom de topic, de logique CRUD, dordre mutation puis émission ou de comportement de suppression. - Aucun changement de nom de topic, de logique CRUD, dordre mutation puis émission ou de comportement de suppression.
- Aucun abonnement ou traitement dans `src/core/permission_sync.rs`. - Aucun abonnement ou traitement dans `src/core/permission_sync.rs`.
@@ -27,22 +38,36 @@ Créer dans `src/domain/` les payloads explicites correspondant à **tous les é
# Technical Design # Technical Design
### Contexte actuel ### Contexte actuel
- Les 20 appels `EventBus::emit` sont répartis entre six repositories ; `computed_permission.rs` ne produit actuellement aucun événement.
- Les créations et mises à jour transmettent des modèles SeaORM, tandis que les suppressions transmettent généralement un `Uuid`; `server_user_created` transmet un tuple `(server_id, user_id)`. - Les 20 appels `EventBus::emit` sont répartis entre six repositories ; `computed_permission.rs` ne produit actuellement
- `message_deleted` et `user_deleted` vérifient déjà `rows_affected` avant émission, alors que dautres suppressions devront conserver leur comportement actuel dans cette étape. aucun événement.
- `src/routes/gateway/mod.rs` consomme certains événements de canal avec ses propres modèles ; les contrats de domaine resteront indépendants. - Les créations et mises à jour transmettent des modèles SeaORM, tandis que les suppressions transmettent généralement
un `Uuid`; `server_user_created` transmet un tuple `(server_id, user_id)`.
- `message_deleted` et `user_deleted` vérifient déjà `rows_affected` avant émission, alors que dautres suppressions
devront conserver leur comportement actuel dans cette étape.
- `src/routes/gateway/mod.rs` consomme certains événements de canal avec ses propres modèles ; les contrats de domaine
resteront indépendants.
### Organisation proposée ### Organisation proposée
- Ajouter `src/domain/mod.rs` et un sous-module par famille émettrice : - Ajouter `src/domain/mod.rs` et un sous-module par famille émettrice :
- `category.rs`, `channel.rs`, `group.rs`, `message.rs`, `server.rs` et `user.rs` pour les événements CRUD et les changements de relation. - `category.rs`, `channel.rs`, `role`, `message.rs`, `server.rs` et `user.rs` pour les événements CRUD et les
- `server_role_permission.rs`, `server_user_permission.rs`, `channel_role_permission.rs` et `channel_user_permission.rs` pour les contrats de permissions. changements de relation.
- Définir dans chaque module les payloads spécifiques nécessaires aux topics de sa famille, par exemple `CategoryChanged`/`CategoryDeleted`, `ChannelChanged`/`ChannelDeleted`, `MessageChanged`/`MessageDeleted`, `ServerChanged`/`ServerDeleted` et `UserChanged`/`UserDeleted`. - `server_role_permission.rs`, `server_user_permission.rs`, `channel_role_permission.rs` et
- Utiliser des structs distinctes lorsque les événements de création/mise à jour transportent plusieurs propriétés et lorsquune suppression ne nécessite que lidentifiant ; le contenu exact doit refléter les informations actuellement véhiculées par les modèles, sans importer SeaORM dans `domain`. `channel_user_permission.rs` pour les contrats de permissions.
- Conserver `ServerUserChanged` et `RoleUserChanged` comme contrats relationnels identifiés, avec les champs `server_id`, `role_id` et `user_id`. - Définir dans chaque module les payloads spécifiques nécessaires aux topics de sa famille, par exemple
`CategoryChanged`/`CategoryDeleted`, `ChannelChanged`/`ChannelDeleted`, `MessageChanged`/`MessageDeleted`,
`ServerChanged`/`ServerDeleted` et `UserChanged`/`UserDeleted`.
- Utiliser des structs distinctes lorsque les événements de création/mise à jour transportent plusieurs propriétés et
lorsquune suppression ne nécessite que lidentifiant ; le contenu exact doit refléter les informations actuellement
véhiculées par les modèles, sans importer SeaORM dans `domain`.
- Conserver `ServerUserChanged` et `RoleUserChanged` comme contrats relationnels identifiés, avec les champs
`server_id`, `role_id` et `user_id`.
- Réexporter sélectivement tous les contrats depuis `crate::domain`; ajouter `pub mod domain;` dans `src/lib.rs`. - Réexporter sélectivement tous les contrats depuis `crate::domain`; ajouter `pub mod domain;` dans `src/lib.rs`.
- Ne modifier ni `src/repositories/mod.rs`, ni `src/core/permission_sync.rs`, ni les routes Gateway. - Ne modifier ni `src/repositories/mod.rs`, ni `src/core/permission_sync.rs`, ni les routes Gateway.
### Contrats de données ### Contrats de données
Tous les contrats suivent ce style : Tous les contrats suivent ce style :
```rust ```rust
@@ -59,32 +84,46 @@ pub struct ChannelDeleted {
pub channel_id: Uuid, pub channel_id: Uuid,
} }
``` ```
Les payloads de ressource complète reprennent explicitement les champs utiles du modèle courant ; les payloads de suppression reprennent lidentifiant nommé de la ressource. Les six contrats de permissions utilisent respectivement `server_id`, `role_id`, `channel_id` et `user_id` selon leur responsabilité, sans bitmask implicite ni modèle persisté.
Les payloads de ressource complète reprennent explicitement les champs utiles du modèle courant ; les payloads de
suppression reprennent lidentifiant nommé de la ressource. Les six contrats de permissions utilisent respectivement
`server_id`, `role_id`, `channel_id` et `user_id` selon leur responsabilité, sans bitmask implicite ni modèle persisté.
### Risques et garde-fous ### Risques et garde-fous
- Les contrats CRUD devront être suffisamment complets pour ne pas perdre dinformation lors du futur branchement des repositories ; la liste de champs sera vérifiée contre `src/models/*.rs`.
- Le changement ultérieur des payloads de topics de canal pourra nécessiter une adaptation du Gateway ; cette intégration est explicitement exclue. - Les contrats CRUD devront être suffisamment complets pour ne pas perdre dinformation lors du futur branchement des
- Les payloads ne doivent pas être centralisés dans `repositories` ni dépendre de SeaORM, afin de rester utilisables par plusieurs endpoints. repositories ; la liste de champs sera vérifiée contre `src/models/*.rs`.
- Le changement ultérieur des payloads de topics de canal pourra nécessiter une adaptation du Gateway ; cette
intégration est explicitement exclue.
- Les payloads ne doivent pas être centralisés dans `repositories` ni dépendre de SeaORM, afin de rester utilisables par
plusieurs endpoints.
# Testing # Testing
### Validation ### Validation
- Ajouter des assertions ou tests de compilation pour instancier chaque contrat public et accéder à tous ses champs. - Ajouter des assertions ou tests de compilation pour instancier chaque contrat public et accéder à tous ses champs.
- Vérifier les familles couvrant chaque émission : `category_*`, `channel_*`, `group_*`, `message_*`, `server_*` et `user_*`, y compris les suppressions et `server_user_created`. - Vérifier les familles couvrant chaque émission : `category_*`, `channel_*`, `group_*`, `message_*`, `server_*` et
`user_*`, y compris les suppressions et `server_user_created`.
- Vérifier `Clone`, `Debug`, `Send`, `Sync` et `'static` pour tous les payloads. - Vérifier `Clone`, `Debug`, `Send`, `Sync` et `'static` pour tous les payloads.
- Vérifier les imports via `crate::domain::{...}` et exécuter `cargo check` ainsi que les tests ciblés. - Vérifier les imports via `crate::domain::{...}` et exécuter `cargo check` ainsi que les tests ciblés.
### Limites de validation ### Limites de validation
Les émissions réelles, les changements de topics, la consommation par `PermissionSyncService`, les recalculs de permissions et lintégration Gateway restent hors périmètre ; le demandeur réalisera leur branchement ultérieurement.
Les émissions réelles, les changements de topics, la consommation par `PermissionSyncService`, les recalculs de
permissions et lintégration Gateway restent hors périmètre ; le demandeur réalisera leur branchement ultérieurement.
### ✓ Step 1: Recenser les émissions et les modèles ### ✓ Step 1: Recenser les émissions et les modèles
- Vérifier les topics et les champs actuellement transmis par chaque repository. - Vérifier les topics et les champs actuellement transmis par chaque repository.
- Vérifier les modèles correspondants pour définir les contrats complets. - Vérifier les modèles correspondants pour définir les contrats complets.
### ✓ Step 2: Créer les modules et payloads de domaine ### ✓ Step 2: Créer les modules et payloads de domaine
- Ajouter les modules `src/domain/` et les structs CRUD, relationnelles et de permissions. - Ajouter les modules `src/domain/` et les structs CRUD, relationnelles et de permissions.
- Exposer les contrats depuis `crate::domain` sans modifier les repositories. - Exposer les contrats depuis `crate::domain` sans modifier les repositories.
### ✓ Step 3: Ajouter la validation des contrats ### ✓ Step 3: Ajouter la validation des contrats
- Ajouter des assertions de compilation couvrant les structs et leurs champs. - Ajouter des assertions de compilation couvrant les structs et leurs champs.
- Exécuter `cargo check` et les tests ciblés. - Exécuter `cargo check` et les tests ciblés.
+4 -4
View File
@@ -3,8 +3,8 @@ pub type AnyResult<T> = anyhow::Result<T>;
use crate::repositories::category::CategoryRepository; use crate::repositories::category::CategoryRepository;
use crate::repositories::channel::ChannelRepository; use crate::repositories::channel::ChannelRepository;
use crate::repositories::computed_permission::ComputedPermissionRepository; use crate::repositories::computed_permission::ComputedPermissionRepository;
use crate::repositories::group::GroupRepository;
use crate::repositories::message::MessageRepository; use crate::repositories::message::MessageRepository;
use crate::repositories::role::RoleRepository;
use crate::repositories::server::ServerRepository; use crate::repositories::server::ServerRepository;
use crate::repositories::server_item_order::ServerItemOrderRepository; use crate::repositories::server_item_order::ServerItemOrderRepository;
use crate::repositories::user::UserRepository; use crate::repositories::user::UserRepository;
@@ -15,8 +15,8 @@ use std::sync::Arc;
mod category; mod category;
mod channel; mod channel;
mod computed_permission; mod computed_permission;
mod group;
mod message; mod message;
mod role;
mod server; mod server;
mod server_item_order; mod server_item_order;
pub mod types; pub mod types;
@@ -33,7 +33,7 @@ pub struct Repositories {
pub server: ServerRepository, pub server: ServerRepository,
pub category: CategoryRepository, pub category: CategoryRepository,
pub channel: ChannelRepository, pub channel: ChannelRepository,
pub group: GroupRepository, pub role: RoleRepository,
pub message: MessageRepository, pub message: MessageRepository,
pub user: UserRepository, pub user: UserRepository,
pub computed_permission: ComputedPermissionRepository, pub computed_permission: ComputedPermissionRepository,
@@ -54,7 +54,7 @@ impl Repositories {
channel: ChannelRepository { channel: ChannelRepository {
context: context.clone(), context: context.clone(),
}, },
group: GroupRepository { role: RoleRepository {
context: context.clone(), context: context.clone(),
}, },
message: MessageRepository { message: MessageRepository {
@@ -1,15 +1,15 @@
use crate::models::role; use crate::models::{role, role_user};
use crate::repositories::{AnyResult, RepositoryContext}; use crate::repositories::{AnyResult, RepositoryContext};
use sea_orm::{ActiveModelTrait, ColumnTrait, EntityTrait, QueryFilter}; use sea_orm::{ActiveModelTrait, ColumnTrait, EntityTrait, QueryFilter, Set};
use std::sync::Arc; use std::sync::Arc;
use uuid::Uuid; use uuid::Uuid;
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub struct GroupRepository { pub struct RoleRepository {
pub context: Arc<RepositoryContext>, pub context: Arc<RepositoryContext>,
} }
impl GroupRepository { impl RoleRepository {
pub async fn get_all_by_server(&self, server_id: Uuid) -> AnyResult<Vec<role::Model>> { pub async fn get_all_by_server(&self, server_id: Uuid) -> AnyResult<Vec<role::Model>> {
Ok(role::Entity::find() Ok(role::Entity::find()
.filter(role::Column::ServerId.eq(server_id)) .filter(role::Column::ServerId.eq(server_id))
@@ -17,6 +17,28 @@ impl GroupRepository {
.await?) .await?)
} }
pub async fn get_default_by_server(&self, server_id: Uuid) -> AnyResult<Option<role::Model>> {
Ok(role::Entity::find()
.filter(role::Column::ServerId.eq(server_id))
.filter(role::Column::IsDefault.eq(true))
.one(&self.context.db)
.await?)
}
pub async fn add_to_default(&self, user_id: Uuid, server_id: Uuid) -> AnyResult<()> {
let default_role = self.get_default_by_server(server_id).await?;
if let Some(default_role) = default_role {
role_user::ActiveModel {
role_id: Set(default_role.id),
user_id: Set(user_id),
..Default::default()
}
.insert(&self.context.db)
.await?;
}
Ok(())
}
pub async fn get_all(&self) -> AnyResult<Vec<role::Model>> { pub async fn get_all(&self) -> AnyResult<Vec<role::Model>> {
Ok(role::Entity::find().all(&self.context.db).await?) Ok(role::Entity::find().all(&self.context.db).await?)
} }
+10 -5
View File
@@ -52,11 +52,16 @@ pub async fn join(
*init_token_lock = None; *init_token_lock = None;
} }
state tokio::try_join!(
.repositories state
.server .repositories
.add_user(state.default_server.id, user.id) .server
.await?; .add_user(state.default_server.id, user.id),
state
.repositories
.role
.add_to_default(user.id, state.default_server.id)
)?;
Ok(StatusCode::CREATED) Ok(StatusCode::CREATED)
} }
+4 -4
View File
@@ -1,6 +1,6 @@
use crate::http::middleware;
use crate::http::OxRouter; use crate::http::OxRouter;
use axum::{middleware as axum_middleware, Router}; use crate::http::middleware;
use axum::{Router, middleware as axum_middleware};
use utoipa::OpenApi; use utoipa::OpenApi;
use utoipa_swagger_ui::SwaggerUi; use utoipa_swagger_ui::SwaggerUi;
@@ -10,9 +10,9 @@ pub mod category;
pub mod channel; pub mod channel;
pub mod core; pub mod core;
pub mod gateway; pub mod gateway;
pub mod group;
pub mod message; pub mod message;
pub mod openapi; pub mod openapi;
pub mod role;
pub mod server; pub mod server;
pub mod user; pub mod user;
@@ -22,7 +22,7 @@ pub fn router() -> OxRouter {
.merge(server::routes::router()) .merge(server::routes::router())
.merge(category::routes::router()) .merge(category::routes::router())
.merge(channel::routes::router()) .merge(channel::routes::router())
.merge(group::routes::router()) .merge(role::routes::router())
.merge(message::routes::router()) .merge(message::routes::router())
.merge(user::routes::router()) .merge(user::routes::router())
.layer(axum_middleware::from_fn(middleware::require_auth)); .layer(axum_middleware::from_fn(middleware::require_auth));
+9 -9
View File
@@ -30,11 +30,11 @@ use utoipa::{Modify, OpenApi};
channel::handlers::create, channel::handlers::create,
channel::handlers::update, channel::handlers::update,
channel::handlers::delete, channel::handlers::delete,
group::handlers::get_all, role::handlers::get_all,
group::handlers::get_by_id, role::handlers::get_by_id,
group::handlers::create, role::handlers::create,
group::handlers::update, role::handlers::update,
group::handlers::delete, role::handlers::delete,
message::handlers::get_all, message::handlers::get_all,
message::handlers::get_by_id, message::handlers::get_by_id,
message::handlers::create, message::handlers::create,
@@ -59,9 +59,9 @@ use utoipa::{Modify, OpenApi};
channel::dto::ChannelResponse, channel::dto::ChannelResponse,
channel::dto::CreateChannelRequest, channel::dto::CreateChannelRequest,
channel::dto::UpdateChannelRequest, channel::dto::UpdateChannelRequest,
group::dto::GroupResponse, role::dto::RoleResponse,
group::dto::CreateGroupRequest, role::dto::CreateRoleRequest,
group::dto::UpdateGroupRequest, role::dto::UpdateRoleRequest,
message::dto::MessageResponse, message::dto::MessageResponse,
message::dto::CreateMessageRequest, message::dto::CreateMessageRequest,
message::dto::UpdateMessageRequest, message::dto::UpdateMessageRequest,
@@ -76,7 +76,7 @@ use utoipa::{Modify, OpenApi};
(name = "Servers", description = "Gestion des serveurs"), (name = "Servers", description = "Gestion des serveurs"),
(name = "Categories", description = "Gestion des catégories"), (name = "Categories", description = "Gestion des catégories"),
(name = "Channels", description = "Gestion des salons"), (name = "Channels", description = "Gestion des salons"),
(name = "Groups", description = "Gestion des groupes"), (name = "roles", description = "Gestion des rolees"),
(name = "Messages", description = "Gestion des messages"), (name = "Messages", description = "Gestion des messages"),
(name = "Core", description = "Endpoints de base (enregistrement, etc.)"), (name = "Core", description = "Endpoints de base (enregistrement, etc.)"),
) )
@@ -4,7 +4,7 @@ use utoipa::ToSchema;
use uuid::Uuid; use uuid::Uuid;
#[derive(Debug, Serialize, Deserialize, ToSchema)] #[derive(Debug, Serialize, Deserialize, ToSchema)]
pub struct CreateGroupRequest { pub struct CreateRoleRequest {
pub server_id: Uuid, pub server_id: Uuid,
#[schema(example = "Modérateurs")] #[schema(example = "Modérateurs")]
pub name: String, pub name: String,
@@ -13,14 +13,14 @@ pub struct CreateGroupRequest {
} }
#[derive(Debug, Serialize, Deserialize, ToSchema)] #[derive(Debug, Serialize, Deserialize, ToSchema)]
pub struct UpdateGroupRequest { pub struct UpdateRoleRequest {
#[schema(example = "Modérateurs (MAJ)")] #[schema(example = "Modérateurs (MAJ)")]
pub name: String, pub name: String,
pub is_default: bool, pub is_default: bool,
} }
#[derive(Debug, Serialize, Deserialize, ToSchema)] #[derive(Debug, Serialize, Deserialize, ToSchema)]
pub struct GroupResponse { pub struct RoleResponse {
pub id: Uuid, pub id: Uuid,
pub server_id: Uuid, pub server_id: Uuid,
pub name: String, pub name: String,
@@ -1,12 +1,12 @@
use crate::core::state::AppState; use crate::core::state::AppState;
use crate::http::context::Superuser; use crate::http::context::Superuser;
use crate::http::error::HTTPError; use crate::http::error::HTTPError;
use crate::routes::group::dto::{CreateGroupRequest, GroupResponse, UpdateGroupRequest}; use crate::routes::role::dto::{CreateRoleRequest, RoleResponse, UpdateRoleRequest};
use crate::routes::group::mapper; use crate::routes::role::mapper;
use axum::{ use axum::{
Json,
extract::{Path, State}, extract::{Path, State},
http::StatusCode, http::StatusCode,
Json,
}; };
use uuid::Uuid; use uuid::Uuid;
@@ -15,13 +15,13 @@ use uuid::Uuid;
get, get,
path = "/groups", path = "/groups",
responses( responses(
(status = 200, description = "Liste des groupes récupérée avec succès", body = [GroupResponse]), (status = 200, description = "Liste des groupes récupérée avec succès", body = [RoleResponse]),
(status = 500, description = "Erreur interne du serveur") (status = 500, description = "Erreur interne du serveur")
), ),
tag = "Groups" tag = "Roles"
)] )]
pub async fn get_all(State(state): State<AppState>) -> Result<Json<Vec<GroupResponse>>, HTTPError> { pub async fn get_all(State(state): State<AppState>) -> Result<Json<Vec<RoleResponse>>, HTTPError> {
let groups = state.repositories.group.get_all().await?; let groups = state.repositories.role.get_all().await?;
Ok(Json( Ok(Json(
groups groups
.into_iter() .into_iter()
@@ -35,22 +35,22 @@ pub async fn get_all(State(state): State<AppState>) -> Result<Json<Vec<GroupResp
get, get,
path = "/groups/{id}", path = "/groups/{id}",
responses( responses(
(status = 200, description = "Groupe trouvé", body = GroupResponse), (status = 200, description = "Rolee trouvé", body = RoleResponse),
(status = 404, description = "Groupe non trouvé"), (status = 404, description = "Rolee non trouvé"),
(status = 500, description = "Erreur interne du serveur") (status = 500, description = "Erreur interne du serveur")
), ),
params( params(
("id" = Uuid, Path, description = "ID du groupe") ("id" = Uuid, Path, description = "ID du groupe")
), ),
tag = "Groups" tag = "Roles"
)] )]
pub async fn get_by_id( pub async fn get_by_id(
State(state): State<AppState>, State(state): State<AppState>,
Path(id): Path<Uuid>, Path(id): Path<Uuid>,
) -> Result<Json<GroupResponse>, HTTPError> { ) -> Result<Json<RoleResponse>, HTTPError> {
let group = state let group = state
.repositories .repositories
.group .role
.get_by_id(id) .get_by_id(id)
.await? .await?
.ok_or(HTTPError::NotFound)?; .ok_or(HTTPError::NotFound)?;
@@ -62,13 +62,13 @@ pub async fn get_by_id(
#[utoipa::path( #[utoipa::path(
post, post,
path = "/groups", path = "/groups",
request_body = CreateGroupRequest, request_body = CreateRoleRequest,
responses( responses(
(status = 201, description = "Groupe créé avec succès", body = GroupResponse), (status = 201, description = "Role créé avec succès", body = RoleResponse),
(status = 404, description = "Serveur non trouvé"), (status = 404, description = "Serveur non trouvé"),
(status = 500, description = "Erreur interne du serveur") (status = 500, description = "Erreur interne du serveur")
), ),
tag = "Groups", tag = "Roles",
security( security(
("bearerAuth" = []) ("bearerAuth" = [])
) )
@@ -76,8 +76,8 @@ pub async fn get_by_id(
pub async fn create( pub async fn create(
_admin: Superuser, _admin: Superuser,
State(state): State<AppState>, State(state): State<AppState>,
Json(payload): Json<CreateGroupRequest>, Json(payload): Json<CreateRoleRequest>,
) -> Result<(StatusCode, Json<GroupResponse>), HTTPError> { ) -> Result<(StatusCode, Json<RoleResponse>), HTTPError> {
// Vérifier que le serveur existe // Vérifier que le serveur existe
state state
.repositories .repositories
@@ -87,7 +87,7 @@ pub async fn create(
.ok_or(HTTPError::BadRequest("Server not found".to_string()))?; .ok_or(HTTPError::BadRequest("Server not found".to_string()))?;
let active_model = mapper::create_request_to_am(payload); let active_model = mapper::create_request_to_am(payload);
let group = state.repositories.group.create(active_model).await?; let group = state.repositories.role.create(active_model).await?;
Ok(( Ok((
StatusCode::CREATED, StatusCode::CREATED,
Json(mapper::group_model_to_group_response(group)), Json(mapper::group_model_to_group_response(group)),
@@ -98,16 +98,16 @@ pub async fn create(
#[utoipa::path( #[utoipa::path(
put, put,
path = "/groups/{id}", path = "/groups/{id}",
request_body = UpdateGroupRequest, request_body = UpdateRoleRequest,
responses( responses(
(status = 200, description = "Groupe mis à jour avec succès", body = GroupResponse), (status = 200, description = "Role mis à jour avec succès", body = RoleResponse),
(status = 404, description = "Groupe non trouvé"), (status = 404, description = "Role non trouvé"),
(status = 500, description = "Erreur interne du serveur") (status = 500, description = "Erreur interne du serveur")
), ),
params( params(
("id" = Uuid, Path, description = "ID du groupe") ("id" = Uuid, Path, description = "ID du groupe")
), ),
tag = "Groups", tag = "Roles",
security( security(
("bearerAuth" = []) ("bearerAuth" = [])
) )
@@ -116,18 +116,18 @@ pub async fn update(
_admin: Superuser, _admin: Superuser,
State(state): State<AppState>, State(state): State<AppState>,
Path(id): Path<Uuid>, Path(id): Path<Uuid>,
Json(payload): Json<UpdateGroupRequest>, Json(payload): Json<UpdateRoleRequest>,
) -> Result<Json<GroupResponse>, HTTPError> { ) -> Result<Json<RoleResponse>, HTTPError> {
// Vérifier l'existence // Vérifier l'existence
let group = state let group = state
.repositories .repositories
.group .role
.get_by_id(id) .get_by_id(id)
.await? .await?
.ok_or(HTTPError::NotFound)?; .ok_or(HTTPError::NotFound)?;
let active_model = mapper::update_request_to_am(group.id, group.server_id, payload); let active_model = mapper::update_request_to_am(group.id, group.server_id, payload);
let group = state.repositories.group.update(active_model).await?; let group = state.repositories.role.update(active_model).await?;
Ok(Json(mapper::group_model_to_group_response(group))) Ok(Json(mapper::group_model_to_group_response(group)))
} }
@@ -137,14 +137,14 @@ pub async fn update(
delete, delete,
path = "/groups/{id}", path = "/groups/{id}",
responses( responses(
(status = 204, description = "Groupe supprimé avec succès"), (status = 204, description = "Role supprimé avec succès"),
(status = 404, description = "Groupe non trouvé"), (status = 404, description = "Role non trouvé"),
(status = 500, description = "Erreur interne du serveur") (status = 500, description = "Erreur interne du serveur")
), ),
params( params(
("id" = Uuid, Path, description = "ID du groupe") ("id" = Uuid, Path, description = "ID du groupe")
), ),
tag = "Groups", tag = "Roles",
security( security(
("bearerAuth" = []) ("bearerAuth" = [])
) )
@@ -154,7 +154,7 @@ pub async fn delete(
State(state): State<AppState>, State(state): State<AppState>,
Path(id): Path<Uuid>, Path(id): Path<Uuid>,
) -> Result<StatusCode, HTTPError> { ) -> Result<StatusCode, HTTPError> {
if state.repositories.group.delete(id).await? { if state.repositories.role.delete(id).await? {
Ok(StatusCode::NO_CONTENT) Ok(StatusCode::NO_CONTENT)
} else { } else {
Err(HTTPError::NotFound) Err(HTTPError::NotFound)
@@ -1,10 +1,10 @@
use crate::models::role; use crate::models::role;
use crate::routes::group::dto::{CreateGroupRequest, GroupResponse, UpdateGroupRequest}; use crate::routes::role::dto::{CreateRoleRequest, RoleResponse, UpdateRoleRequest};
use sea_orm::Set; use sea_orm::Set;
use uuid::Uuid; use uuid::Uuid;
pub fn group_model_to_group_response(model: role::Model) -> GroupResponse { pub fn group_model_to_group_response(model: role::Model) -> RoleResponse {
GroupResponse { RoleResponse {
id: model.id, id: model.id,
server_id: model.server_id, server_id: model.server_id,
name: model.name, name: model.name,
@@ -13,7 +13,7 @@ pub fn group_model_to_group_response(model: role::Model) -> GroupResponse {
} }
} }
pub fn create_request_to_am(req: CreateGroupRequest) -> role::ActiveModel { pub fn create_request_to_am(req: CreateRoleRequest) -> role::ActiveModel {
role::ActiveModel { role::ActiveModel {
id: Set(Uuid::new_v4()), id: Set(Uuid::new_v4()),
server_id: Set(req.server_id), server_id: Set(req.server_id),
@@ -26,7 +26,7 @@ pub fn create_request_to_am(req: CreateGroupRequest) -> role::ActiveModel {
pub fn update_request_to_am( pub fn update_request_to_am(
id: Uuid, id: Uuid,
server_id: Uuid, server_id: Uuid,
req: UpdateGroupRequest, req: UpdateRoleRequest,
) -> role::ActiveModel { ) -> role::ActiveModel {
role::ActiveModel { role::ActiveModel {
id: Set(id), id: Set(id),