use crate::domain::dto::channel::{CreateChannelRequest, UpdateChannelRequest}; use crate::models::server_item_order::OrderedResourceType; use crate::models::{channel, role}; use crate::permissions::PermissionSet; use crate::services::ServicesContext; use crate::services::permission::PermissionService; use sea_orm::{ ActiveModelTrait, ColumnTrait, EntityTrait, QueryFilter, Set, TransactionTrait, }; use std::sync::Arc; use uuid::Uuid; #[derive(Debug, Clone)] pub struct ChannelService { service_context: Arc, } impl ChannelService { pub fn new(service_context: Arc) -> Self { Self { service_context } } pub async fn create_channel( &self, payload: CreateChannelRequest, ) -> Result { let db = &self.service_context.repositories.server.context.db; let event_bus = &self.service_context.event_bus; let server_order = self .service_context .services .get() .expect("services initialized") .server_order .clone(); let channel = db .transaction::<_, channel::Model, anyhow::Error>(|txn| { Box::pin(async move { // 1. Insertion du canal let active_model = channel::ActiveModel { server_id: Set(payload.server_id), category_id: Set(payload.category_id), channel_type: Set(payload.channel_type), name: Set(payload.name), ..Default::default() }; let channel = active_model.insert(txn).await?; // 2. Si server_id est présent, enregistrement de l'ordre d'affichage if let Some(server_id) = payload.server_id { server_order .append( txn, server_id, channel.id, OrderedResourceType::Channel, payload.category_id, ) .await?; // 3. Attribution des permissions par défaut au rôle par défaut if let Some(default_role) = role::Entity::find() .filter(role::Column::ServerId.eq(server_id)) .filter(role::Column::IsDefault.eq(true)) .one(txn) .await? { let default_channel_permissions = PermissionSet::DEFAULT.channel.bits() as i64; let role_perm = crate::models::channel_role_permission::ActiveModel { channel_id: Set(channel.id), role_id: Set(default_role.id), permissions: Set(default_channel_permissions), ..Default::default() }; role_perm.insert(txn).await?; } // 4. Refresh des permissions (Global pour l'instant) // TODO: Cibler/focaliser le spectre du recalcul (ex: uniquement les membres impactés ou le canal spécifique) PermissionService::sync_server_with_db(txn, server_id).await?; } Ok(channel) }) }) .await?; // Post-commit event emission event_bus.emit("channel_created", channel.clone()); Ok(channel) } pub async fn update_channel( &self, id: Uuid, payload: UpdateChannelRequest, ) -> Result { let db = &self.service_context.repositories.server.context.db; let event_bus = &self.service_context.event_bus; let txn = db.begin().await?; let existing = channel::Entity::find_by_id(id) .one(&txn) .await? .ok_or_else(|| anyhow::anyhow!("Channel not found"))?; let mut active: channel::ActiveModel = existing.into(); active.server_id = Set(payload.server_id); active.category_id = Set(payload.category_id); active.channel_type = Set(payload.channel_type); active.name = Set(payload.name); let channel = active.update(&txn).await?; self.service_context .services .get() .expect("services initialized") .server_order .sync( &txn, channel.id, OrderedResourceType::Channel, channel.server_id, channel.category_id, ) .await?; txn.commit().await?; event_bus.emit("channel_updated", channel.clone()); Ok(channel) } pub async fn delete_channel(&self, id: Uuid) -> Result { let db = &self.service_context.repositories.server.context.db; let event_bus = &self.service_context.event_bus; let txn = db.begin().await?; self.service_context .services .get() .expect("services initialized") .server_order .remove(&txn, id, OrderedResourceType::Channel) .await?; let res = channel::Entity::delete_by_id(id).exec(&txn).await?; let deleted = res.rows_affected > 0; txn.commit().await?; if deleted { event_bus.emit("channel_deleted", id); } Ok(deleted) } pub async fn set_user_permission( &self, channel_id: Uuid, user_id: Uuid, permissions: u64, ) -> Result<(), anyhow::Error> { let db = &self.service_context.repositories.server.context.db; let event_bus = &self.service_context.event_bus; let txn = db.begin().await?; let permission = crate::models::channel_user_permission::ActiveModel { channel_id: Set(channel_id), user_id: Set(user_id), permissions: Set(permissions as i64), ..Default::default() }; crate::models::channel_user_permission::Entity::insert(permission) .on_conflict( sea_orm::sea_query::OnConflict::columns([ crate::models::channel_user_permission::Column::ChannelId, crate::models::channel_user_permission::Column::UserId, ]) .update_columns([crate::models::channel_user_permission::Column::Permissions]) .to_owned(), ) .exec(&txn) .await?; txn.commit().await?; event_bus.emit( "channel_user_permission_created", (channel_id, user_id, permissions), ); Ok(()) } pub async fn remove_user_permission( &self, channel_id: Uuid, user_id: Uuid, ) -> Result<(), anyhow::Error> { let db = &self.service_context.repositories.server.context.db; let event_bus = &self.service_context.event_bus; let txn = db.begin().await?; crate::models::channel_user_permission::Entity::delete_many() .filter(crate::models::channel_user_permission::Column::ChannelId.eq(channel_id)) .filter(crate::models::channel_user_permission::Column::UserId.eq(user_id)) .exec(&txn) .await?; txn.commit().await?; event_bus.emit("channel_user_permission_deleted", (channel_id, user_id)); Ok(()) } pub async fn set_role_permission( &self, channel_id: Uuid, role_id: Uuid, permissions: u64, ) -> Result<(), anyhow::Error> { let db = &self.service_context.repositories.server.context.db; let event_bus = &self.service_context.event_bus; let txn = db.begin().await?; let permission = crate::models::channel_role_permission::ActiveModel { channel_id: Set(channel_id), role_id: Set(role_id), permissions: Set(permissions as i64), ..Default::default() }; crate::models::channel_role_permission::Entity::insert(permission) .on_conflict( sea_orm::sea_query::OnConflict::columns([ crate::models::channel_role_permission::Column::ChannelId, crate::models::channel_role_permission::Column::RoleId, ]) .update_columns([crate::models::channel_role_permission::Column::Permissions]) .to_owned(), ) .exec(&txn) .await?; txn.commit().await?; event_bus.emit( "channel_role_permission_created", (channel_id, role_id, permissions), ); Ok(()) } pub async fn remove_role_permission( &self, channel_id: Uuid, role_id: Uuid, ) -> Result<(), anyhow::Error> { let db = &self.service_context.repositories.server.context.db; let event_bus = &self.service_context.event_bus; let txn = db.begin().await?; crate::models::channel_role_permission::Entity::delete_many() .filter(crate::models::channel_role_permission::Column::ChannelId.eq(channel_id)) .filter(crate::models::channel_role_permission::Column::RoleId.eq(role_id)) .exec(&txn) .await?; txn.commit().await?; event_bus.emit("channel_role_permission_deleted", (channel_id, role_id)); Ok(()) } }