Files
oxspeak_server/src/services/channel.rs
T
2026-08-02 10:13:49 +02:00

295 lines
9.7 KiB
Rust

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<ServicesContext>,
}
impl ChannelService {
pub fn new(service_context: Arc<ServicesContext>) -> Self {
Self { service_context }
}
pub async fn create_channel(
&self,
payload: CreateChannelRequest,
) -> Result<channel::Model, anyhow::Error> {
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<channel::Model, 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 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<bool, anyhow::Error> {
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(())
}
}