360 lines
13 KiB
Rust
360 lines
13 KiB
Rust
use crate::domain::events::channel::{ChannelCreatedEvent, ChannelDeletedEvent};
|
|
use crate::domain::events::channel_permission::{
|
|
ChannelRolePermissionUpdatedEvent, ChannelUserPermissionCreatedEvent,
|
|
ChannelUserPermissionDeletedEvent, ChannelUserPermissionUpdatedEvent,
|
|
};
|
|
use crate::domain::events::role::{RoleUserCreatedEvent, RoleUserDeletedEvent};
|
|
use crate::domain::events::server::{
|
|
ServerCreatedEvent, ServerUserCreatedEvent, ServerUserDeletedEvent,
|
|
};
|
|
use crate::domain::events::server_permission::{
|
|
ServerRolePermissionUpdatedEvent, ServerUserPermissionUpdatedEvent,
|
|
};
|
|
use crate::domain::events::server_tree::ServerTreeInvalidatedEvent;
|
|
use crate::repositories::Repositories;
|
|
use crate::services::ServicesContext;
|
|
use event_bus::EventBus;
|
|
use std::sync::Arc;
|
|
use uuid::Uuid;
|
|
// list of all events :
|
|
// server_user_created
|
|
// server_user_deleted
|
|
//
|
|
// role_user_created
|
|
// role_user_deleted
|
|
//
|
|
// server_role_permission_created
|
|
// server_role_permission_updated
|
|
// server_role_permission_deleted
|
|
//
|
|
// server_user_permission_created
|
|
// server_user_permission_updated
|
|
// server_user_permission_deleted
|
|
//
|
|
// channel_role_permission_created
|
|
// channel_role_permission_updated
|
|
// channel_role_permission_deleted
|
|
//
|
|
// channel_user_permission_created
|
|
// channel_user_permission_updated
|
|
// channel_user_permission_deleted
|
|
//
|
|
// channel_created
|
|
// channel_deleted
|
|
// [Requête HTTP Admin]
|
|
// │
|
|
// ▼
|
|
// 1. Repositories (Ecriture BDD)
|
|
// │
|
|
// ▼ (Emit Event ex: server_role_permission_updated)
|
|
// 2. EventBus
|
|
// │
|
|
// ├────────────────────────────────────────┐
|
|
// ▼ ▼
|
|
// 3. PermissionSyncService (Async Task) [Réponse HTTP 200/204]
|
|
// │
|
|
// ├─► Recalcule computed_permission (full_sync_user)
|
|
// │
|
|
// └─► Emit Event "user_permissions_updated"
|
|
// │
|
|
// ▼
|
|
// 4. Gateway WebSocket
|
|
// │
|
|
// ▼ (Push WS)
|
|
// 5. Client Frontend (Vue 3 / Pinia)
|
|
|
|
#[derive(Debug, Clone)]
|
|
pub struct PermissionSyncService {
|
|
service_context: Arc<ServicesContext>,
|
|
}
|
|
|
|
impl PermissionSyncService {
|
|
fn invalidate_tree(event_bus: &Arc<EventBus>, server_id: Uuid, user_ids: Option<Vec<Uuid>>) {
|
|
event_bus.emit(ServerTreeInvalidatedEvent {
|
|
server_id,
|
|
user_ids,
|
|
});
|
|
}
|
|
|
|
pub fn new(service_context: Arc<ServicesContext>) -> Self {
|
|
Self { service_context }
|
|
}
|
|
|
|
/// Enregistre les listeners sur l'EventBus pour mettre à jour le cache
|
|
/// des permissions calculées lors des modifications de structure ou de droits.
|
|
pub async fn start_listen_event(&self) {
|
|
let repositories = self.service_context.repositories.clone();
|
|
let event_bus = self.service_context.event_bus.clone();
|
|
|
|
// ---------------------------------------------------------------------
|
|
// Événements Serveur & Membres Serveur
|
|
// ---------------------------------------------------------------------
|
|
let notify = event_bus.clone();
|
|
event_bus.on_async_with::<ServerCreatedEvent, _>(
|
|
repositories.clone(),
|
|
move |repositories, event| async move {
|
|
Self::sync_server(repositories, event.server.id).await;
|
|
},
|
|
);
|
|
|
|
event_bus.on_async_with::<ServerUserCreatedEvent, _>(
|
|
repositories.clone(),
|
|
move |repositories, event| {
|
|
let server_id = event.server_user.server_id;
|
|
let user_id = event.server_user.user_id;
|
|
let notify = notify.clone();
|
|
async move {
|
|
Self::sync_user(repositories, user_id, server_id).await;
|
|
Self::invalidate_tree(¬ify, server_id, Some(vec![user_id]));
|
|
}
|
|
},
|
|
);
|
|
|
|
let notify = event_bus.clone();
|
|
event_bus.on_async_with::<ServerUserDeletedEvent, _>(
|
|
repositories.clone(),
|
|
move |repositories, event| {
|
|
let server_id = event.server_user.server_id;
|
|
let user_id = event.server_user.user_id;
|
|
let notify = notify.clone();
|
|
async move {
|
|
Self::sync_user(repositories, user_id, server_id).await;
|
|
Self::invalidate_tree(¬ify, server_id, Some(vec![user_id]));
|
|
}
|
|
},
|
|
);
|
|
|
|
// ---------------------------------------------------------------------
|
|
// Événements Rôles & Membres de Rôle
|
|
// ---------------------------------------------------------------------
|
|
|
|
let notify = event_bus.clone();
|
|
event_bus.on_async_with::<RoleUserCreatedEvent, _>(
|
|
repositories.clone(),
|
|
move |repositories, event| {
|
|
let server_id = event.server_id;
|
|
let user_id = event.role_user.user_id;
|
|
let notify = notify.clone();
|
|
async move {
|
|
Self::sync_user(repositories, user_id, server_id).await;
|
|
Self::invalidate_tree(¬ify, server_id, Some(vec![user_id]));
|
|
}
|
|
},
|
|
);
|
|
|
|
let notify = event_bus.clone();
|
|
event_bus.on_async_with::<RoleUserDeletedEvent, _>(
|
|
repositories.clone(),
|
|
move |repositories, event| {
|
|
let server_id = event.server_id;
|
|
let user_id = event.role_user.user_id;
|
|
let notify = notify.clone();
|
|
async move {
|
|
Self::sync_user(repositories, user_id, server_id).await;
|
|
Self::invalidate_tree(¬ify, server_id, Some(vec![user_id]));
|
|
}
|
|
},
|
|
);
|
|
|
|
// ---------------------------------------------------------------------
|
|
// Overrides de Permissions Serveur
|
|
// ---------------------------------------------------------------------
|
|
|
|
let notify = event_bus.clone();
|
|
event_bus.on_async_with::<ServerRolePermissionUpdatedEvent, _>(
|
|
repositories.clone(),
|
|
move |repositories, event| {
|
|
let role_id = event.role_id;
|
|
let server_id = event.server_id;
|
|
let notify = notify.clone();
|
|
async move {
|
|
Self::sync_role_members(repositories, role_id, server_id).await;
|
|
Self::invalidate_tree(¬ify, server_id, None);
|
|
}
|
|
},
|
|
);
|
|
|
|
let notify = event_bus.clone();
|
|
event_bus.on_async_with::<ServerUserPermissionUpdatedEvent, _>(
|
|
repositories.clone(),
|
|
move |repositories, event| {
|
|
let server_id = event.server_id;
|
|
let user_id = event.user_id;
|
|
let notify = notify.clone();
|
|
async move {
|
|
Self::sync_user(repositories, user_id, server_id).await;
|
|
Self::invalidate_tree(¬ify, server_id, Some(vec![user_id]));
|
|
}
|
|
},
|
|
);
|
|
|
|
// ---------------------------------------------------------------------
|
|
// Événements Canaux & Overrides de Permissions Canaux
|
|
// ---------------------------------------------------------------------
|
|
|
|
let notify = event_bus.clone();
|
|
event_bus.on_async_with::<ChannelCreatedEvent, _>(
|
|
repositories.clone(),
|
|
move |repositories, event| {
|
|
let notify = notify.clone();
|
|
async move {
|
|
if let Some(server_id) = event.channel.server_id {
|
|
Self::sync_server(repositories, server_id).await;
|
|
Self::invalidate_tree(¬ify, server_id, None);
|
|
}
|
|
}
|
|
},
|
|
);
|
|
|
|
let notify = event_bus.clone();
|
|
event_bus.on_async_with::<ChannelDeletedEvent, _>(
|
|
repositories.clone(),
|
|
move |repositories, event| {
|
|
let notify = notify.clone();
|
|
async move {
|
|
if let Some(server_id) = event.channel.server_id {
|
|
Self::sync_server(repositories, server_id).await;
|
|
Self::invalidate_tree(¬ify, server_id, None);
|
|
}
|
|
}
|
|
},
|
|
);
|
|
|
|
let notify = event_bus.clone();
|
|
event_bus.on_async_with::<ChannelRolePermissionUpdatedEvent, _>(
|
|
repositories.clone(),
|
|
move |repositories, event| {
|
|
let role_id = event.role_id;
|
|
let server_id = event.server_id;
|
|
let notify = notify.clone();
|
|
async move {
|
|
Self::sync_role_members(repositories, role_id, server_id).await;
|
|
Self::invalidate_tree(¬ify, server_id, None);
|
|
}
|
|
},
|
|
);
|
|
|
|
let notify = event_bus.clone();
|
|
event_bus.on_async_with::<ChannelUserPermissionUpdatedEvent, _>(
|
|
repositories.clone(),
|
|
move |repositories, event| {
|
|
let user_id = event.user_id;
|
|
let notify = notify.clone();
|
|
async move {
|
|
if let Some(channel) = repositories
|
|
.channel
|
|
.get_by_id(event.channel_id)
|
|
.await
|
|
.ok()
|
|
.flatten()
|
|
{
|
|
if let Some(server_id) = channel.server_id {
|
|
Self::sync_user(repositories, user_id, server_id).await;
|
|
Self::invalidate_tree(¬ify, server_id, Some(vec![user_id]));
|
|
}
|
|
}
|
|
}
|
|
},
|
|
);
|
|
|
|
let notify = event_bus.clone();
|
|
event_bus.on_async_with::<ChannelUserPermissionCreatedEvent, _>(
|
|
repositories.clone(),
|
|
move |repositories, event| {
|
|
let channel_id = event.permission.channel_id;
|
|
let user_id = event.permission.user_id;
|
|
let notify = notify.clone();
|
|
async move {
|
|
if let Some(channel) = repositories
|
|
.channel
|
|
.get_by_id(channel_id)
|
|
.await
|
|
.ok()
|
|
.flatten()
|
|
{
|
|
if let Some(server_id) = channel.server_id {
|
|
Self::sync_user(repositories, user_id, server_id).await;
|
|
Self::invalidate_tree(¬ify, server_id, Some(vec![user_id]));
|
|
}
|
|
}
|
|
}
|
|
},
|
|
);
|
|
|
|
let notify = event_bus.clone();
|
|
event_bus.on_async_with::<ChannelUserPermissionDeletedEvent, _>(
|
|
repositories,
|
|
move |repositories, event| {
|
|
let channel_id = event.permission.channel_id;
|
|
let user_id = event.permission.user_id;
|
|
let notify = notify.clone();
|
|
async move {
|
|
if let Some(channel) = repositories
|
|
.channel
|
|
.get_by_id(channel_id)
|
|
.await
|
|
.ok()
|
|
.flatten()
|
|
{
|
|
if let Some(server_id) = channel.server_id {
|
|
Self::sync_user(repositories, user_id, server_id).await;
|
|
Self::invalidate_tree(¬ify, server_id, Some(vec![user_id]));
|
|
}
|
|
}
|
|
}
|
|
},
|
|
);
|
|
}
|
|
|
|
// -------------------------------------------------------------------------
|
|
// Méthodes d'exécution Asynchrones
|
|
// -------------------------------------------------------------------------
|
|
|
|
/// Recalcule le cache pour un utilisateur sur un serveur donné.
|
|
async fn sync_user(repositories: Arc<Repositories>, user_id: Uuid, server_id: Uuid) {
|
|
if let Err(err) = repositories
|
|
.computed_permission
|
|
.full_sync_user(user_id, server_id)
|
|
.await
|
|
{
|
|
tracing::error!(
|
|
"Erreur lors de la synchronisation des permissions pour l'utilisateur {} sur le serveur {}: {:?}",
|
|
user_id,
|
|
server_id,
|
|
err
|
|
);
|
|
}
|
|
}
|
|
|
|
/// Recalcule le cache pour tous les membres d'un rôle.
|
|
async fn sync_role_members(repositories: Arc<Repositories>, role_id: Uuid, server_id: Uuid) {
|
|
if let Err(err) = repositories
|
|
.computed_permission
|
|
.sync_role_members(role_id, server_id)
|
|
.await
|
|
{
|
|
tracing::error!(
|
|
"Erreur lors de la synchronisation des membres du rôle {} sur le serveur {}: {:?}",
|
|
role_id,
|
|
server_id,
|
|
err
|
|
);
|
|
}
|
|
}
|
|
|
|
/// Recalcule le cache pour TOUS les utilisateurs d'un serveur.
|
|
async fn sync_server(repositories: Arc<Repositories>, server_id: Uuid) {
|
|
if let Err(err) = repositories
|
|
.computed_permission
|
|
.full_sync_server(server_id)
|
|
.await
|
|
{
|
|
tracing::error!(
|
|
"Erreur lors de la synchronisation complète du serveur {}: {:?}",
|
|
server_id,
|
|
err
|
|
);
|
|
}
|
|
}
|
|
}
|