This commit is contained in:
2026-07-14 23:07:48 +02:00
parent b7c48ce7f3
commit 8afa694aed
7 changed files with 119 additions and 34 deletions
+42
View File
@@ -331,6 +331,48 @@ impl EventBus {
}) })
} }
// todo : Undocumented
pub fn on_async_with<T, C, F, Fut>(&self, topic: &str, context: C, handler: F) -> JoinHandle<()>
where
T: Any + Send + Sync + Clone + 'static,
C: Clone + Send + Sync + 'static,
F: Fn(C, T) -> Fut + Send + Sync + 'static,
Fut: Future<Output = ()> + Send + 'static,
{
let mut rx = self.get_or_create_sender(topic).subscribe();
let topic_owned = topic.to_string();
debug!(topic, "Async subscriber registered");
tokio::spawn(async move {
loop {
match rx.recv().await {
Ok(evt) => {
if let Some(typed) = evt.downcast_ref::<T>() {
trace!(topic = topic_owned, "Async handler invoked");
handler(context.clone(), typed.clone()).await;
}
}
Err(broadcast::error::RecvError::Lagged(n)) => {
warn!(
topic = topic_owned,
skipped = n,
"Subscriber lagged, messages dropped"
);
}
Err(broadcast::error::RecvError::Closed) => {
debug!(
topic = topic_owned,
"Channel closed, async subscriber exiting"
);
break;
}
}
}
})
}
// ───────────────────────────────────────────────────────────────────────── // ─────────────────────────────────────────────────────────────────────────
// Subscription — low-level access (advanced use cases) // Subscription — low-level access (advanced use cases)
// ───────────────────────────────────────────────────────────────────────── // ─────────────────────────────────────────────────────────────────────────
+19 -2
View File
@@ -1,7 +1,8 @@
use crate::domain::events::server::ServerCreatedEvent;
use crate::repositories::Repositories; use crate::repositories::Repositories;
use event_bus::EventBus; use event_bus::EventBus;
use std::sync::Arc; use std::sync::Arc;
use uuid::Uuid;
// list of all events : // list of all events :
// server_user_created // server_user_created
// server_user_deleted // server_user_deleted
@@ -42,5 +43,21 @@ impl PermissionSyncService {
} }
} }
pub fn listen(&self) {} pub async fn start_listen_event(&self) {
// todo : compléter la liste de permission avec le déclenchement des évènements
self.event_bus.on_async_with(
"server_created",
self.repositories.clone(),
move |repositories, payload: ServerCreatedEvent| {
Self::sync_server_permissions(repositories, payload.server.id)
},
);
}
async fn sync_server_permissions(repositories: Arc<Repositories>, server_id: Uuid) {
let _ = repositories
.computed_permission
.full_sync_server(server_id)
.await;
}
} }
+13 -10
View File
@@ -1,17 +1,20 @@
use crate::models::prelude::Channel; use crate::models::channel;
use uuid::Uuid; use uuid::Uuid;
pub struct ChannelCreated { #[derive(Debug, Clone)]
server_id: Uuid, pub struct ChannelCreatedEvent {
channel: Channel, pub server_id: Uuid,
pub channel: channel::Model,
} }
pub struct ChannelUpdated { #[derive(Debug, Clone)]
server_id: Uuid, pub struct ChannelUpdatedEvent {
channel: Channel, pub server_id: Uuid,
pub channel: channel::Model,
} }
pub struct ChannelDeleted { #[derive(Debug, Clone)]
server_id: Uuid, pub struct ChannelDeletedEvent {
channel: Channel, pub server_id: Uuid,
pub channel: channel::Model,
} }
+16 -13
View File
@@ -1,20 +1,23 @@
use crate::models::prelude::Message; use crate::models::message;
use uuid::Uuid; use uuid::Uuid;
pub struct MessageCreated { #[derive(Debug, Clone)]
server_id: Option<Uuid>, pub struct MessageCreatedEvent {
channel_id: Uuid, pub server_id: Option<Uuid>,
message: Message, pub channel_id: Uuid,
pub message: message::Model,
} }
pub struct MessageUpdated { #[derive(Debug, Clone)]
server_id: Option<Uuid>, pub struct MessageUpdatedEvent {
channel_id: Uuid, pub server_id: Option<Uuid>,
message: Message, pub channel_id: Uuid,
pub message: message::Model,
} }
pub struct MessageDeleted { #[derive(Debug, Clone)]
server_id: Option<Uuid>, pub struct MessageDeletedEvent {
channel_id: Uuid, pub server_id: Option<Uuid>,
message: Message, pub channel_id: Uuid,
pub message: message::Model,
} }
+10 -7
View File
@@ -1,13 +1,16 @@
use crate::models::prelude::Server; use crate::models::server;
pub struct ServerCreated { #[derive(Debug, Clone)]
server: Server, pub struct ServerCreatedEvent {
pub server: server::Model,
} }
pub struct ServerUpdated { #[derive(Debug, Clone)]
server: Server, pub struct ServerUpdatedEvent {
pub server: server::Model,
} }
pub struct ServerDeleted { #[derive(Debug, Clone)]
server: Server, pub struct ServerDeletedEvent {
pub server: server::Model,
} }
+8 -1
View File
@@ -7,11 +7,17 @@ use crate::repositories::{AnyResult, RepositoryContext};
use sea_orm::{ColumnTrait, EntityTrait, QueryFilter, QuerySelect, Set, TransactionTrait}; use sea_orm::{ColumnTrait, EntityTrait, QueryFilter, QuerySelect, Set, TransactionTrait};
use std::collections::HashMap; use std::collections::HashMap;
use std::sync::Arc; use std::sync::{Arc, OnceLock};
use tokio::sync::Mutex;
use uuid::Uuid; use uuid::Uuid;
use crate::models::computed_permission::PermissionScopeType; use crate::models::computed_permission::PermissionScopeType;
static SYNC_LOCK: OnceLock<Mutex<()>> = OnceLock::new();
fn _sync_lock() -> &'static Mutex<()> {
SYNC_LOCK.get_or_init(Mutex::default)
}
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub struct ComputedPermissionRepository { pub struct ComputedPermissionRepository {
pub context: Arc<RepositoryContext>, pub context: Arc<RepositoryContext>,
@@ -50,6 +56,7 @@ impl ComputedPermissionRepository {
/// - permissions de canal accordées aux rôles de l'utilisateur ; /// - permissions de canal accordées aux rôles de l'utilisateur ;
/// - permissions directes de l'utilisateur dans les canaux. /// - permissions directes de l'utilisateur dans les canaux.
pub async fn full_sync_user(&self, user_id: Uuid, server_id: Uuid) -> AnyResult<()> { pub async fn full_sync_user(&self, user_id: Uuid, server_id: Uuid) -> AnyResult<()> {
let _guard = _sync_lock().lock().await;
// --------------------------------------------------------------------- // ---------------------------------------------------------------------
// Rôles de l'utilisateur // Rôles de l'utilisateur
// --------------------------------------------------------------------- // ---------------------------------------------------------------------
+11 -1
View File
@@ -2,7 +2,7 @@ use super::types::{ServerExplorerItem, ServerTree};
use super::{AnyResult, RepositoryContext}; use super::{AnyResult, RepositoryContext};
use crate::models::{category, channel, role, server, server_user}; use crate::models::{category, channel, role, server, server_user};
use sea_orm::prelude::*; use sea_orm::prelude::*;
use sea_orm::{ActiveModelTrait, Set}; use sea_orm::{ActiveModelTrait, QuerySelect, Set};
use std::sync::Arc; use std::sync::Arc;
use uuid::Uuid; use uuid::Uuid;
@@ -72,6 +72,16 @@ impl ServerRepository {
.insert(&self.context.db) .insert(&self.context.db)
.await?; .await?;
let role_id: Uuid = role::Entity::find()
.filter(role::Column::ServerId.eq(server_id))
.filter(role::Column::IsDefault.eq(true))
.select_only()
.column(role::Column::Id)
.into_tuple::<Uuid>()
.one(&self.context.db)
.await?
.ok_or_else(|| anyhow::anyhow!("Rôle par défaut introuvable"))?;
self.context self.context
.events .events
.emit("server_user_created", (server_id, user_id)); .emit("server_user_created", (server_id, user_id));