2025-12-03 19:33:26 +00:00
|
|
|
//! Handler WebSocket pour le chat server
|
|
|
|
|
//!
|
|
|
|
|
//! Ce module fournit un handler WebSocket utilisant Axum pour gérer
|
|
|
|
|
//! les connexions, déconnexions et le routage des messages de chat.
|
|
|
|
|
|
|
|
|
|
use axum::extract::ws::{Message, WebSocket};
|
|
|
|
|
use axum::extract::{Query, State, WebSocketUpgrade};
|
2026-02-18 11:42:48 +00:00
|
|
|
use axum::http::HeaderMap;
|
2025-12-03 19:33:26 +00:00
|
|
|
use axum::http::StatusCode;
|
|
|
|
|
use axum::response::{IntoResponse, Response};
|
P0: stabilisation backend/chat/stream + nouvelle base migrations v1
Backend Go:
- Remplacement complet des anciennes migrations par la base V1 alignée sur ORIGIN.
- Durcissement global du parsing JSON (BindAndValidateJSON + RespondWithAppError).
- Sécurisation de config.go, CORS, statuts de santé et monitoring.
- Implémentation des transactions P0 (RBAC, duplication de playlists, social toggles).
- Ajout d’un job worker structuré (emails, analytics, thumbnails) + tests associés.
- Nouvelle doc backend : AUDIT_CONFIG, BACKEND_CONFIG, AUTH_PASSWORD_RESET, JOB_WORKER_*.
Chat server (Rust):
- Refonte du pipeline JWT + sécurité, audit et rate limiting avancé.
- Implémentation complète du cycle de message (read receipts, delivered, edit/delete, typing).
- Nettoyage des panics, gestion d’erreurs robuste, logs structurés.
- Migrations chat alignées sur le schéma UUID et nouvelles features.
Stream server (Rust):
- Refonte du moteur de streaming (encoding pipeline + HLS) et des modules core.
- Transactions P0 pour les jobs et segments, garanties d’atomicité.
- Documentation détaillée de la pipeline (AUDIT_STREAM_*, DESIGN_STREAM_PIPELINE, TRANSACTIONS_P0_IMPLEMENTATION).
Documentation & audits:
- TRIAGE.md et AUDIT_STABILITY.md à jour avec l’état réel des 3 services.
- Cartographie complète des migrations et des transactions (DB_MIGRATIONS_*, DB_TRANSACTION_PLAN, AUDIT_DB_TRANSACTIONS, TRANSACTION_TESTS_PHASE3).
- Scripts de reset et de cleanup pour la lab DB et la V1.
Ce commit fige l’ensemble du travail de stabilisation P0 (UUID, backend, chat et stream) avant les phases suivantes (Coherence Guardian, WS hardening, etc.).
2025-12-06 10:14:38 +00:00
|
|
|
use futures_util::StreamExt;
|
2025-12-03 19:33:26 +00:00
|
|
|
use serde_json;
|
|
|
|
|
use std::collections::HashMap;
|
|
|
|
|
use std::sync::Arc;
|
2025-12-27 00:52:22 +00:00
|
|
|
use tracing::{debug, error, info, info_span, warn, Instrument};
|
2025-12-03 19:33:26 +00:00
|
|
|
use uuid::Uuid;
|
|
|
|
|
|
2026-02-11 21:04:11 +00:00
|
|
|
use crate::delivered_status::DeliveredStatusManager;
|
|
|
|
|
use crate::error::ChatError;
|
|
|
|
|
use crate::jwt_manager::{AccessTokenClaims, JwtManager};
|
|
|
|
|
use crate::monitoring::ChatMetrics;
|
2026-01-04 00:41:51 +00:00
|
|
|
use crate::reactions::ReactionsManager;
|
2026-02-11 21:04:11 +00:00
|
|
|
use crate::read_receipts::ReadReceiptManager;
|
|
|
|
|
use crate::repository::MessageRepository;
|
|
|
|
|
use crate::security::permission::PermissionService;
|
|
|
|
|
use crate::services::MessageEditService;
|
|
|
|
|
use crate::typing_indicator::TypingIndicatorManager;
|
P0: stabilisation backend/chat/stream + nouvelle base migrations v1
Backend Go:
- Remplacement complet des anciennes migrations par la base V1 alignée sur ORIGIN.
- Durcissement global du parsing JSON (BindAndValidateJSON + RespondWithAppError).
- Sécurisation de config.go, CORS, statuts de santé et monitoring.
- Implémentation des transactions P0 (RBAC, duplication de playlists, social toggles).
- Ajout d’un job worker structuré (emails, analytics, thumbnails) + tests associés.
- Nouvelle doc backend : AUDIT_CONFIG, BACKEND_CONFIG, AUTH_PASSWORD_RESET, JOB_WORKER_*.
Chat server (Rust):
- Refonte du pipeline JWT + sécurité, audit et rate limiting avancé.
- Implémentation complète du cycle de message (read receipts, delivered, edit/delete, typing).
- Nettoyage des panics, gestion d’erreurs robuste, logs structurés.
- Migrations chat alignées sur le schéma UUID et nouvelles features.
Stream server (Rust):
- Refonte du moteur de streaming (encoding pipeline + HLS) et des modules core.
- Transactions P0 pour les jobs et segments, garanties d’atomicité.
- Documentation détaillée de la pipeline (AUDIT_STREAM_*, DESIGN_STREAM_PIPELINE, TRANSACTIONS_P0_IMPLEMENTATION).
Documentation & audits:
- TRIAGE.md et AUDIT_STABILITY.md à jour avec l’état réel des 3 services.
- Cartographie complète des migrations et des transactions (DB_MIGRATIONS_*, DB_TRANSACTION_PLAN, AUDIT_DB_TRANSACTIONS, TRANSACTION_TESTS_PHASE3).
- Scripts de reset et de cleanup pour la lab DB et la V1.
Ce commit fige l’ensemble du travail de stabilisation P0 (UUID, backend, chat et stream) avant les phases suivantes (Coherence Guardian, WS hardening, etc.).
2025-12-06 10:14:38 +00:00
|
|
|
use crate::websocket::{IncomingMessage, OutgoingMessage, WebSocketClient, WebSocketManager};
|
2025-12-03 19:33:26 +00:00
|
|
|
|
|
|
|
|
/// État partagé pour le handler WebSocket
|
|
|
|
|
#[derive(Clone)]
|
|
|
|
|
pub struct WebSocketState {
|
2026-02-14 17:26:02 +00:00
|
|
|
/// Timeout d'inactivité (heartbeat) en secondes, configurable via CHAT_KEEPALIVE_TIMEOUT_SECS
|
|
|
|
|
pub keepalive_timeout_secs: u64,
|
2025-12-03 19:33:26 +00:00
|
|
|
// pub store: Arc<SimpleMessageStore>, // Remove SimpleMessageStore
|
|
|
|
|
pub message_repo: Arc<MessageRepository>, // Add MessageRepository
|
P0: stabilisation backend/chat/stream + nouvelle base migrations v1
Backend Go:
- Remplacement complet des anciennes migrations par la base V1 alignée sur ORIGIN.
- Durcissement global du parsing JSON (BindAndValidateJSON + RespondWithAppError).
- Sécurisation de config.go, CORS, statuts de santé et monitoring.
- Implémentation des transactions P0 (RBAC, duplication de playlists, social toggles).
- Ajout d’un job worker structuré (emails, analytics, thumbnails) + tests associés.
- Nouvelle doc backend : AUDIT_CONFIG, BACKEND_CONFIG, AUTH_PASSWORD_RESET, JOB_WORKER_*.
Chat server (Rust):
- Refonte du pipeline JWT + sécurité, audit et rate limiting avancé.
- Implémentation complète du cycle de message (read receipts, delivered, edit/delete, typing).
- Nettoyage des panics, gestion d’erreurs robuste, logs structurés.
- Migrations chat alignées sur le schéma UUID et nouvelles features.
Stream server (Rust):
- Refonte du moteur de streaming (encoding pipeline + HLS) et des modules core.
- Transactions P0 pour les jobs et segments, garanties d’atomicité.
- Documentation détaillée de la pipeline (AUDIT_STREAM_*, DESIGN_STREAM_PIPELINE, TRANSACTIONS_P0_IMPLEMENTATION).
Documentation & audits:
- TRIAGE.md et AUDIT_STABILITY.md à jour avec l’état réel des 3 services.
- Cartographie complète des migrations et des transactions (DB_MIGRATIONS_*, DB_TRANSACTION_PLAN, AUDIT_DB_TRANSACTIONS, TRANSACTION_TESTS_PHASE3).
- Scripts de reset et de cleanup pour la lab DB et la V1.
Ce commit fige l’ensemble du travail de stabilisation P0 (UUID, backend, chat et stream) avant les phases suivantes (Coherence Guardian, WS hardening, etc.).
2025-12-06 10:14:38 +00:00
|
|
|
pub read_receipt_manager: Arc<ReadReceiptManager>, // Add ReadReceiptManager
|
|
|
|
|
pub delivered_status_manager: Arc<DeliveredStatusManager>, // Add DeliveredStatusManager
|
|
|
|
|
pub typing_indicator_manager: Arc<TypingIndicatorManager>, // Add TypingIndicatorManager
|
|
|
|
|
pub message_edit_service: Arc<MessageEditService>, // Add MessageEditService
|
2026-01-04 00:41:51 +00:00
|
|
|
pub reactions_manager: Arc<ReactionsManager>, // Add ReactionsManager
|
2025-12-03 19:33:26 +00:00
|
|
|
pub ws_manager: Arc<WebSocketManager>,
|
|
|
|
|
pub jwt_manager: Arc<JwtManager>,
|
P0: stabilisation backend/chat/stream + nouvelle base migrations v1
Backend Go:
- Remplacement complet des anciennes migrations par la base V1 alignée sur ORIGIN.
- Durcissement global du parsing JSON (BindAndValidateJSON + RespondWithAppError).
- Sécurisation de config.go, CORS, statuts de santé et monitoring.
- Implémentation des transactions P0 (RBAC, duplication de playlists, social toggles).
- Ajout d’un job worker structuré (emails, analytics, thumbnails) + tests associés.
- Nouvelle doc backend : AUDIT_CONFIG, BACKEND_CONFIG, AUTH_PASSWORD_RESET, JOB_WORKER_*.
Chat server (Rust):
- Refonte du pipeline JWT + sécurité, audit et rate limiting avancé.
- Implémentation complète du cycle de message (read receipts, delivered, edit/delete, typing).
- Nettoyage des panics, gestion d’erreurs robuste, logs structurés.
- Migrations chat alignées sur le schéma UUID et nouvelles features.
Stream server (Rust):
- Refonte du moteur de streaming (encoding pipeline + HLS) et des modules core.
- Transactions P0 pour les jobs et segments, garanties d’atomicité.
- Documentation détaillée de la pipeline (AUDIT_STREAM_*, DESIGN_STREAM_PIPELINE, TRANSACTIONS_P0_IMPLEMENTATION).
Documentation & audits:
- TRIAGE.md et AUDIT_STABILITY.md à jour avec l’état réel des 3 services.
- Cartographie complète des migrations et des transactions (DB_MIGRATIONS_*, DB_TRANSACTION_PLAN, AUDIT_DB_TRANSACTIONS, TRANSACTION_TESTS_PHASE3).
- Scripts de reset et de cleanup pour la lab DB et la V1.
Ce commit fige l’ensemble du travail de stabilisation P0 (UUID, backend, chat et stream) avant les phases suivantes (Coherence Guardian, WS hardening, etc.).
2025-12-06 10:14:38 +00:00
|
|
|
pub permission_service: Arc<PermissionService>, // Add PermissionService
|
2025-12-06 13:45:07 +00:00
|
|
|
pub metrics: Arc<ChatMetrics>,
|
2026-02-11 21:45:39 +00:00
|
|
|
pub rate_limiter: Arc<crate::security::RateLimiter>,
|
2025-12-03 19:33:26 +00:00
|
|
|
}
|
|
|
|
|
|
2026-02-18 11:42:48 +00:00
|
|
|
/// Extract access token from query param (?token=) or Cookie header (access_token)
|
|
|
|
|
fn extract_token(params: &HashMap<String, String>, headers: &HeaderMap) -> Option<String> {
|
|
|
|
|
if let Some(t) = params.get("token") {
|
|
|
|
|
return Some(t.clone());
|
|
|
|
|
}
|
|
|
|
|
if let Some(cookie_header) = headers.get(axum::http::header::COOKIE) {
|
|
|
|
|
if let Ok(cookie_str) = cookie_header.to_str() {
|
|
|
|
|
for part in cookie_str.split(';') {
|
|
|
|
|
let part = part.trim();
|
|
|
|
|
if part.starts_with("access_token=") {
|
|
|
|
|
let value = part.trim_start_matches("access_token=").trim();
|
|
|
|
|
if !value.is_empty() {
|
|
|
|
|
return Some(value.to_string());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
None
|
|
|
|
|
}
|
|
|
|
|
|
2025-12-03 19:33:26 +00:00
|
|
|
/// Handler principal pour les connexions WebSocket
|
|
|
|
|
///
|
|
|
|
|
/// Cette fonction gère la mise à niveau de la connexion HTTP vers WebSocket
|
|
|
|
|
/// et délègue la gestion de la connexion à `handle_socket`.
|
2025-12-27 00:52:22 +00:00
|
|
|
/// FIX #13: Extrait le request_id depuis les extensions Axum (ajouté par le middleware)
|
2025-12-03 19:33:26 +00:00
|
|
|
pub async fn websocket_handler(
|
|
|
|
|
ws: WebSocketUpgrade,
|
|
|
|
|
Query(params): Query<HashMap<String, String>>,
|
2026-02-18 11:42:48 +00:00
|
|
|
headers: HeaderMap,
|
2025-12-03 19:33:26 +00:00
|
|
|
State(state): State<WebSocketState>,
|
2025-12-27 00:52:22 +00:00
|
|
|
request_id: Option<axum::extract::Extension<Uuid>>,
|
2025-12-03 19:33:26 +00:00
|
|
|
) -> Response {
|
2025-12-27 00:52:22 +00:00
|
|
|
// FIX #13: Extraire le request_id pour la corrélation
|
|
|
|
|
let request_id = request_id.map(|ext| *ext).unwrap_or_else(Uuid::new_v4);
|
|
|
|
|
|
|
|
|
|
// Créer un span avec le request_id pour la corrélation
|
|
|
|
|
let span = info_span!(
|
|
|
|
|
"websocket_upgrade",
|
|
|
|
|
request_id = %request_id,
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
async move {
|
|
|
|
|
info!(request_id = %request_id, "🔌 Nouvelle connexion WebSocket demandée");
|
|
|
|
|
|
2026-02-18 11:42:48 +00:00
|
|
|
let token = match extract_token(¶ms, &headers) {
|
2025-12-27 00:52:22 +00:00
|
|
|
Some(t) => t,
|
|
|
|
|
None => {
|
2026-02-18 11:42:48 +00:00
|
|
|
error!(request_id = %request_id, "❌ Token manquant (query ?token= ou cookie access_token)");
|
2025-12-27 00:52:22 +00:00
|
|
|
return (StatusCode::UNAUTHORIZED, "Missing token").into_response();
|
|
|
|
|
}
|
|
|
|
|
};
|
2025-12-03 19:33:26 +00:00
|
|
|
|
2026-02-18 11:42:48 +00:00
|
|
|
match state.jwt_manager.validate_access_token(&token).await {
|
2025-12-27 00:52:22 +00:00
|
|
|
Ok(claims) => {
|
|
|
|
|
info!(
|
|
|
|
|
request_id = %request_id,
|
|
|
|
|
username = %claims.username,
|
|
|
|
|
user_id = %claims.user_id,
|
|
|
|
|
"✅ Connexion autorisée"
|
|
|
|
|
);
|
|
|
|
|
// FIX #13: Passer le request_id au handler de socket
|
|
|
|
|
ws.on_upgrade(move |socket| handle_socket(socket, state, claims, request_id))
|
|
|
|
|
}
|
|
|
|
|
Err(e) => {
|
|
|
|
|
error!(request_id = %request_id, error = %e, "❌ Token invalide");
|
|
|
|
|
(StatusCode::UNAUTHORIZED, "Invalid token").into_response()
|
|
|
|
|
}
|
2025-12-03 19:33:26 +00:00
|
|
|
}
|
|
|
|
|
}
|
2025-12-27 00:52:22 +00:00
|
|
|
.instrument(span)
|
|
|
|
|
.await
|
2025-12-03 19:33:26 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Gère une connexion WebSocket individuelle
|
2025-12-06 16:21:59 +00:00
|
|
|
///
|
P0: stabilisation backend/chat/stream + nouvelle base migrations v1
Backend Go:
- Remplacement complet des anciennes migrations par la base V1 alignée sur ORIGIN.
- Durcissement global du parsing JSON (BindAndValidateJSON + RespondWithAppError).
- Sécurisation de config.go, CORS, statuts de santé et monitoring.
- Implémentation des transactions P0 (RBAC, duplication de playlists, social toggles).
- Ajout d’un job worker structuré (emails, analytics, thumbnails) + tests associés.
- Nouvelle doc backend : AUDIT_CONFIG, BACKEND_CONFIG, AUTH_PASSWORD_RESET, JOB_WORKER_*.
Chat server (Rust):
- Refonte du pipeline JWT + sécurité, audit et rate limiting avancé.
- Implémentation complète du cycle de message (read receipts, delivered, edit/delete, typing).
- Nettoyage des panics, gestion d’erreurs robuste, logs structurés.
- Migrations chat alignées sur le schéma UUID et nouvelles features.
Stream server (Rust):
- Refonte du moteur de streaming (encoding pipeline + HLS) et des modules core.
- Transactions P0 pour les jobs et segments, garanties d’atomicité.
- Documentation détaillée de la pipeline (AUDIT_STREAM_*, DESIGN_STREAM_PIPELINE, TRANSACTIONS_P0_IMPLEMENTATION).
Documentation & audits:
- TRIAGE.md et AUDIT_STABILITY.md à jour avec l’état réel des 3 services.
- Cartographie complète des migrations et des transactions (DB_MIGRATIONS_*, DB_TRANSACTION_PLAN, AUDIT_DB_TRANSACTIONS, TRANSACTION_TESTS_PHASE3).
- Scripts de reset et de cleanup pour la lab DB et la V1.
Ce commit fige l’ensemble du travail de stabilisation P0 (UUID, backend, chat et stream) avant les phases suivantes (Coherence Guardian, WS hardening, etc.).
2025-12-06 10:14:38 +00:00
|
|
|
/// Note: Toutes les erreurs sont gérées explicitement pour éviter les panics.
|
|
|
|
|
/// Tokio capture automatiquement les panics dans les handlers, mais nous
|
|
|
|
|
/// nous assurons que toutes les erreurs sont gérées explicitement avec `?` ou `match`.
|
2025-12-27 00:52:22 +00:00
|
|
|
/// FIX #13: Accepte le request_id pour la corrélation
|
|
|
|
|
async fn handle_socket(
|
|
|
|
|
socket: WebSocket,
|
|
|
|
|
state: WebSocketState,
|
|
|
|
|
claims: AccessTokenClaims,
|
|
|
|
|
request_id: Uuid,
|
|
|
|
|
) {
|
|
|
|
|
// FIX #13: Créer un span avec le request_id pour toute la durée de la connexion WebSocket
|
|
|
|
|
let span = info_span!(
|
|
|
|
|
"websocket_connection",
|
|
|
|
|
request_id = %request_id,
|
|
|
|
|
user_id = %claims.user_id,
|
|
|
|
|
username = %claims.username,
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
async move {
|
2025-12-03 19:33:26 +00:00
|
|
|
let (sender, mut receiver) = socket.split();
|
|
|
|
|
|
|
|
|
|
// ID du client (généré localement pour cette connexion)
|
|
|
|
|
let client_id = Uuid::new_v4();
|
|
|
|
|
// MIGRATION UUID: user_id est déjà String (UUID)
|
|
|
|
|
let client = Arc::new(WebSocketClient::new(
|
|
|
|
|
client_id,
|
|
|
|
|
claims.user_id.clone(),
|
|
|
|
|
sender,
|
|
|
|
|
));
|
|
|
|
|
|
|
|
|
|
state.ws_manager.add_client(client.clone()).await;
|
|
|
|
|
|
|
|
|
|
info!(
|
2025-12-27 00:52:22 +00:00
|
|
|
request_id = %request_id,
|
|
|
|
|
client_id = %client_id,
|
|
|
|
|
username = %claims.username,
|
|
|
|
|
"✅ Connexion WebSocket établie"
|
2025-12-03 19:33:26 +00:00
|
|
|
);
|
|
|
|
|
|
2025-12-06 13:45:07 +00:00
|
|
|
// Metrics: connection
|
2025-12-06 16:21:59 +00:00
|
|
|
state
|
|
|
|
|
.metrics
|
|
|
|
|
.websocket_connected(claims.user_id.clone())
|
|
|
|
|
.await;
|
2025-12-06 13:45:07 +00:00
|
|
|
|
2025-12-03 19:33:26 +00:00
|
|
|
// Envoyer un message de bienvenue
|
|
|
|
|
let welcome_msg = OutgoingMessage::ActionConfirmed {
|
|
|
|
|
action: "connected".to_string(),
|
|
|
|
|
success: true,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
if client.send_message(welcome_msg).await.is_err() {
|
|
|
|
|
error!("❌ Impossible d'envoyer le message de bienvenue");
|
|
|
|
|
state.ws_manager.remove_client(client_id).await;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2026-02-14 17:26:02 +00:00
|
|
|
let keepalive_timeout = std::time::Duration::from_secs(state.keepalive_timeout_secs);
|
2025-12-06 11:00:20 +00:00
|
|
|
|
|
|
|
|
// Boucle principale de gestion des messages avec timeout
|
|
|
|
|
loop {
|
|
|
|
|
match tokio::time::timeout(keepalive_timeout, receiver.next()).await {
|
|
|
|
|
Ok(Some(msg)) => {
|
|
|
|
|
match msg {
|
|
|
|
|
Ok(Message::Text(text)) => {
|
|
|
|
|
debug!("📨 Message WebSocket reçu: {}", text);
|
|
|
|
|
|
2025-12-06 16:21:59 +00:00
|
|
|
match handle_incoming_message(&text, &state, client.clone(), &claims).await
|
|
|
|
|
{
|
2025-12-06 11:00:20 +00:00
|
|
|
Ok(should_continue) => {
|
|
|
|
|
if !should_continue {
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
Err(e) => {
|
|
|
|
|
error!("❌ Erreur lors du traitement du message: {}", e);
|
|
|
|
|
|
|
|
|
|
// Envoyer un message d'erreur au client
|
|
|
|
|
let error_msg = OutgoingMessage::Error {
|
|
|
|
|
message: format!("Erreur: {}", e),
|
|
|
|
|
};
|
|
|
|
|
if client.send_message(error_msg).await.is_err() {
|
|
|
|
|
error!("❌ Impossible d'envoyer le message d'erreur au client");
|
|
|
|
|
break; // Fermer la connexion si on ne peut même pas envoyer d'erreur
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
Ok(Message::Close(_)) => {
|
|
|
|
|
info!("👋 Connexion WebSocket fermée par le client");
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
Ok(Message::Ping(_)) => {
|
|
|
|
|
debug!("🏓 Ping WebSocket reçu");
|
|
|
|
|
if client.send_message(OutgoingMessage::Pong).await.is_err() {
|
|
|
|
|
error!("❌ Erreur lors de l'envoi du Pong");
|
2025-12-03 19:33:26 +00:00
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
2025-12-06 11:00:20 +00:00
|
|
|
Ok(Message::Pong(_)) => {
|
|
|
|
|
debug!("🏓 Pong WebSocket reçu");
|
|
|
|
|
}
|
|
|
|
|
Ok(_) => {
|
|
|
|
|
debug!("⚠️ Type de message WebSocket non géré");
|
|
|
|
|
}
|
2025-12-03 19:33:26 +00:00
|
|
|
Err(e) => {
|
2025-12-06 11:00:20 +00:00
|
|
|
error!("❌ Erreur WebSocket: {}", e);
|
|
|
|
|
break;
|
2025-12-03 19:33:26 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2025-12-06 11:00:20 +00:00
|
|
|
Ok(None) => {
|
|
|
|
|
// Fin du stream
|
2025-12-03 19:33:26 +00:00
|
|
|
break;
|
|
|
|
|
}
|
2025-12-06 11:00:20 +00:00
|
|
|
Err(_) => {
|
2025-12-06 16:21:59 +00:00
|
|
|
info!(
|
|
|
|
|
"💤 Timeout inactivité ({}s) pour client {}, fermeture",
|
|
|
|
|
keepalive_timeout.as_secs(),
|
|
|
|
|
client_id
|
|
|
|
|
);
|
2025-12-03 19:33:26 +00:00
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
info!(
|
2025-12-27 00:52:22 +00:00
|
|
|
request_id = %request_id,
|
|
|
|
|
client_id = %client_id,
|
|
|
|
|
username = %claims.username,
|
|
|
|
|
"🔌 Connexion WebSocket terminée"
|
2025-12-03 19:33:26 +00:00
|
|
|
);
|
|
|
|
|
state.ws_manager.remove_client(client_id).await;
|
2025-12-06 16:21:59 +00:00
|
|
|
|
2025-12-06 13:45:07 +00:00
|
|
|
// Metrics: disconnection
|
|
|
|
|
state.metrics.websocket_disconnected(claims.user_id).await;
|
2025-12-27 00:52:22 +00:00
|
|
|
}
|
|
|
|
|
.instrument(span)
|
|
|
|
|
.await;
|
2025-12-03 19:33:26 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Traite un message entrant et route selon le type
|
|
|
|
|
///
|
|
|
|
|
/// Retourne `Ok(true)` si la connexion doit continuer, `Ok(false)` pour fermer
|
|
|
|
|
async fn handle_incoming_message(
|
|
|
|
|
text: &str,
|
|
|
|
|
state: &WebSocketState,
|
|
|
|
|
client: Arc<WebSocketClient>,
|
|
|
|
|
claims: &AccessTokenClaims,
|
|
|
|
|
) -> Result<bool, ChatError> {
|
|
|
|
|
// Parser le message JSON
|
|
|
|
|
let incoming: IncomingMessage = serde_json::from_str(text)
|
|
|
|
|
.map_err(|e| ChatError::serialization_error("IncomingMessage", text, e))?;
|
|
|
|
|
|
2026-02-11 21:45:39 +00:00
|
|
|
// Determine the rate limit action category for this message
|
|
|
|
|
let rate_action = match &incoming {
|
|
|
|
|
IncomingMessage::SendMessage { .. } => Some(crate::security::RateLimitAction::SendMessage),
|
|
|
|
|
IncomingMessage::AddReaction { .. } | IncomingMessage::RemoveReaction { .. } => {
|
|
|
|
|
Some(crate::security::RateLimitAction::AddReaction)
|
|
|
|
|
}
|
|
|
|
|
IncomingMessage::EditMessage { .. } => Some(crate::security::RateLimitAction::EditMessage),
|
|
|
|
|
IncomingMessage::DeleteMessage { .. } => {
|
|
|
|
|
Some(crate::security::RateLimitAction::DeleteMessage)
|
|
|
|
|
}
|
|
|
|
|
IncomingMessage::Typing { .. } => Some(crate::security::RateLimitAction::Typing),
|
|
|
|
|
IncomingMessage::JoinConversation { .. } => {
|
|
|
|
|
Some(crate::security::RateLimitAction::JoinConversation)
|
|
|
|
|
}
|
|
|
|
|
IncomingMessage::SearchMessages { .. } => {
|
|
|
|
|
Some(crate::security::RateLimitAction::SearchMessages)
|
|
|
|
|
}
|
2026-02-22 02:42:47 +00:00
|
|
|
IncomingMessage::CallOffer { .. }
|
|
|
|
|
| IncomingMessage::CallAnswer { .. }
|
|
|
|
|
| IncomingMessage::ICECandidate { .. }
|
|
|
|
|
| IncomingMessage::CallHangup { .. }
|
|
|
|
|
| IncomingMessage::CallReject { .. } => {
|
|
|
|
|
Some(crate::security::RateLimitAction::CallSignaling)
|
|
|
|
|
}
|
2026-02-11 21:45:39 +00:00
|
|
|
// Ping, MarkAsRead, Delivered, LeaveConversation, FetchHistory, SyncMessages
|
|
|
|
|
// are not rate-limited
|
|
|
|
|
_ => None,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// Check rate limit if applicable
|
|
|
|
|
if let Some(action) = rate_action {
|
|
|
|
|
match state.rate_limiter.check_rate_limit(&claims.user_id, action).await {
|
|
|
|
|
Ok(false) => {
|
|
|
|
|
tracing::warn!(
|
|
|
|
|
user_id = %claims.user_id,
|
|
|
|
|
action = ?action,
|
|
|
|
|
"Rate limit exceeded for WebSocket action"
|
|
|
|
|
);
|
|
|
|
|
// Send error to client via WebSocket and continue connection
|
|
|
|
|
let _ = client
|
|
|
|
|
.send_message(crate::websocket::OutgoingMessage::Error {
|
|
|
|
|
message: "Too many requests. Please slow down.".to_string(),
|
|
|
|
|
})
|
|
|
|
|
.await;
|
|
|
|
|
return Ok(true); // Continue connection, just skip this message
|
|
|
|
|
}
|
|
|
|
|
Ok(true) => { /* Allowed, proceed */ }
|
|
|
|
|
Err(e) => {
|
|
|
|
|
tracing::error!("Rate limiter error: {}", e);
|
|
|
|
|
// Fail open — don't block on rate limiter errors
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2025-12-03 19:33:26 +00:00
|
|
|
match incoming {
|
|
|
|
|
IncomingMessage::SendMessage {
|
|
|
|
|
conversation_id,
|
|
|
|
|
content,
|
2026-02-12 22:33:02 +00:00
|
|
|
parent_message_id: _,
|
2026-01-04 00:41:51 +00:00
|
|
|
attachments,
|
2025-12-03 19:33:26 +00:00
|
|
|
} => {
|
|
|
|
|
info!(
|
|
|
|
|
"💬 Envoi de message via WebSocket par {} (conversation: {})",
|
|
|
|
|
claims.username, conversation_id
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
// MIGRATION UUID: user_id est déjà String (UUID), on le parse directement
|
|
|
|
|
let sender_uuid = Uuid::parse_str(&claims.user_id)
|
|
|
|
|
.map_err(|e| ChatError::validation_error(&format!("Invalid user UUID: {}", e)))?;
|
|
|
|
|
|
P0: stabilisation backend/chat/stream + nouvelle base migrations v1
Backend Go:
- Remplacement complet des anciennes migrations par la base V1 alignée sur ORIGIN.
- Durcissement global du parsing JSON (BindAndValidateJSON + RespondWithAppError).
- Sécurisation de config.go, CORS, statuts de santé et monitoring.
- Implémentation des transactions P0 (RBAC, duplication de playlists, social toggles).
- Ajout d’un job worker structuré (emails, analytics, thumbnails) + tests associés.
- Nouvelle doc backend : AUDIT_CONFIG, BACKEND_CONFIG, AUTH_PASSWORD_RESET, JOB_WORKER_*.
Chat server (Rust):
- Refonte du pipeline JWT + sécurité, audit et rate limiting avancé.
- Implémentation complète du cycle de message (read receipts, delivered, edit/delete, typing).
- Nettoyage des panics, gestion d’erreurs robuste, logs structurés.
- Migrations chat alignées sur le schéma UUID et nouvelles features.
Stream server (Rust):
- Refonte du moteur de streaming (encoding pipeline + HLS) et des modules core.
- Transactions P0 pour les jobs et segments, garanties d’atomicité.
- Documentation détaillée de la pipeline (AUDIT_STREAM_*, DESIGN_STREAM_PIPELINE, TRANSACTIONS_P0_IMPLEMENTATION).
Documentation & audits:
- TRIAGE.md et AUDIT_STABILITY.md à jour avec l’état réel des 3 services.
- Cartographie complète des migrations et des transactions (DB_MIGRATIONS_*, DB_TRANSACTION_PLAN, AUDIT_DB_TRANSACTIONS, TRANSACTION_TESTS_PHASE3).
- Scripts de reset et de cleanup pour la lab DB et la V1.
Ce commit fige l’ensemble du travail de stabilisation P0 (UUID, backend, chat et stream) avant les phases suivantes (Coherence Guardian, WS hardening, etc.).
2025-12-06 10:14:38 +00:00
|
|
|
// Vérifier les permissions avant d'envoyer le message
|
|
|
|
|
state
|
|
|
|
|
.permission_service
|
|
|
|
|
.can_send_message(sender_uuid, conversation_id)
|
|
|
|
|
.await
|
|
|
|
|
.map_err(|e| {
|
|
|
|
|
warn!(
|
|
|
|
|
user_id = %sender_uuid,
|
|
|
|
|
conversation_id = %conversation_id,
|
|
|
|
|
error = %e,
|
|
|
|
|
"Permission refusée pour l'envoi de message"
|
|
|
|
|
);
|
|
|
|
|
e
|
|
|
|
|
})?;
|
|
|
|
|
|
2026-01-04 00:41:51 +00:00
|
|
|
// Préparer les métadonnées pour les pièces jointes
|
2026-02-12 22:33:02 +00:00
|
|
|
let _metadata = attachments.as_ref().map(|a| serde_json::to_value(a).unwrap_or(serde_json::Value::Null));
|
2026-01-04 00:41:51 +00:00
|
|
|
|
2025-12-03 19:33:26 +00:00
|
|
|
// Enregistrer le message dans le store
|
2026-01-04 00:41:51 +00:00
|
|
|
// Note: On pourrait étendre MessageRepository::create pour accepter metadata et parent_message_id
|
2025-12-03 19:33:26 +00:00
|
|
|
let message = state
|
|
|
|
|
.message_repo
|
|
|
|
|
.create(conversation_id, sender_uuid, &content)
|
|
|
|
|
.await
|
|
|
|
|
.map_err(|e| {
|
|
|
|
|
ChatError::internal_error(format!(
|
|
|
|
|
"Erreur lors de l'enregistrement du message: {}",
|
|
|
|
|
e
|
|
|
|
|
))
|
|
|
|
|
})?;
|
|
|
|
|
|
|
|
|
|
// Diffuser le message à tous les clients de la conversation
|
|
|
|
|
let outgoing_message = OutgoingMessage::NewMessage {
|
|
|
|
|
conversation_id,
|
|
|
|
|
message_id: message.id,
|
|
|
|
|
sender_id: message.sender_id,
|
|
|
|
|
content: message.content.clone(),
|
|
|
|
|
created_at: message.created_at,
|
2026-01-04 00:41:51 +00:00
|
|
|
attachments,
|
2025-12-03 19:33:26 +00:00
|
|
|
};
|
|
|
|
|
state
|
|
|
|
|
.ws_manager
|
|
|
|
|
.broadcast_to_conversation(conversation_id, outgoing_message)
|
|
|
|
|
.await?;
|
|
|
|
|
|
|
|
|
|
// Envoyer confirmation au sender
|
|
|
|
|
let confirmation = OutgoingMessage::ActionConfirmed {
|
|
|
|
|
action: "message_sent".to_string(),
|
|
|
|
|
success: true,
|
|
|
|
|
};
|
|
|
|
|
client.send_message(confirmation).await?;
|
|
|
|
|
|
|
|
|
|
info!(
|
|
|
|
|
"✅ Message WebSocket envoyé et diffusé - ID: {}",
|
|
|
|
|
message.id
|
|
|
|
|
);
|
|
|
|
|
}
|
2026-01-04 00:41:51 +00:00
|
|
|
IncomingMessage::AddReaction {
|
|
|
|
|
message_id,
|
|
|
|
|
conversation_id,
|
|
|
|
|
emoji,
|
|
|
|
|
} => {
|
|
|
|
|
info!(
|
|
|
|
|
"❤️ Ajout de réaction {} au message {} par {}",
|
|
|
|
|
emoji, message_id, claims.username
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
let user_uuid = Uuid::parse_str(&claims.user_id)
|
|
|
|
|
.map_err(|e| ChatError::validation_error(&format!("Invalid user UUID: {}", e)))?;
|
|
|
|
|
|
|
|
|
|
// Vérifier les permissions
|
|
|
|
|
state
|
|
|
|
|
.permission_service
|
|
|
|
|
.can_read_conversation(user_uuid, conversation_id)
|
|
|
|
|
.await
|
|
|
|
|
.map_err(|e| {
|
|
|
|
|
warn!(
|
|
|
|
|
user_id = %user_uuid,
|
|
|
|
|
conversation_id = %conversation_id,
|
|
|
|
|
error = %e,
|
|
|
|
|
"Permission refusée pour ajouter une réaction"
|
|
|
|
|
);
|
|
|
|
|
e
|
|
|
|
|
})?;
|
|
|
|
|
|
|
|
|
|
// Convertir l'emoji string en enum (optionnel, on peut aussi stocker le string directement)
|
|
|
|
|
if let Some(reaction_emoji) = crate::reactions::ReactionEmoji::from_str(&emoji) {
|
|
|
|
|
state
|
|
|
|
|
.reactions_manager
|
|
|
|
|
.add_reaction(message_id, user_uuid, reaction_emoji)
|
|
|
|
|
.await
|
|
|
|
|
.map_err(|e| ChatError::internal_error(format!("Erreur DB réaction: {}", e)))?;
|
|
|
|
|
|
|
|
|
|
// Diffuser la réaction
|
|
|
|
|
let reaction_msg = OutgoingMessage::ReactionAdded {
|
|
|
|
|
message_id,
|
|
|
|
|
conversation_id,
|
|
|
|
|
user_id: user_uuid,
|
|
|
|
|
emoji,
|
|
|
|
|
};
|
|
|
|
|
state
|
|
|
|
|
.ws_manager
|
|
|
|
|
.broadcast_to_conversation(conversation_id, reaction_msg)
|
|
|
|
|
.await?;
|
|
|
|
|
|
|
|
|
|
client.send_message(OutgoingMessage::ActionConfirmed {
|
|
|
|
|
action: "reaction_added".to_string(),
|
|
|
|
|
success: true,
|
|
|
|
|
}).await?;
|
|
|
|
|
} else {
|
|
|
|
|
return Err(ChatError::validation_error("Emoji non supporté"));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
IncomingMessage::RemoveReaction {
|
|
|
|
|
message_id,
|
|
|
|
|
conversation_id,
|
|
|
|
|
} => {
|
|
|
|
|
info!(
|
|
|
|
|
"💔 Retrait de réaction du message {} par {}",
|
|
|
|
|
message_id, claims.username
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
let user_uuid = Uuid::parse_str(&claims.user_id)
|
|
|
|
|
.map_err(|e| ChatError::validation_error(&format!("Invalid user UUID: {}", e)))?;
|
|
|
|
|
|
|
|
|
|
state
|
|
|
|
|
.reactions_manager
|
|
|
|
|
.remove_reaction(message_id, user_uuid)
|
|
|
|
|
.await
|
|
|
|
|
.map_err(|e| ChatError::internal_error(format!("Erreur DB réaction: {}", e)))?;
|
|
|
|
|
|
|
|
|
|
// Diffuser le retrait
|
|
|
|
|
let reaction_msg = OutgoingMessage::ReactionRemoved {
|
|
|
|
|
message_id,
|
|
|
|
|
conversation_id,
|
|
|
|
|
user_id: user_uuid,
|
|
|
|
|
};
|
|
|
|
|
state
|
|
|
|
|
.ws_manager
|
|
|
|
|
.broadcast_to_conversation(conversation_id, reaction_msg)
|
|
|
|
|
.await?;
|
|
|
|
|
|
|
|
|
|
client.send_message(OutgoingMessage::ActionConfirmed {
|
|
|
|
|
action: "reaction_removed".to_string(),
|
|
|
|
|
success: true,
|
|
|
|
|
}).await?;
|
|
|
|
|
}
|
2025-12-03 19:33:26 +00:00
|
|
|
IncomingMessage::JoinConversation { conversation_id } => {
|
|
|
|
|
info!(
|
|
|
|
|
"🔗 Client {} ({}) rejoint la conversation {}",
|
|
|
|
|
client.id, claims.username, conversation_id
|
|
|
|
|
);
|
|
|
|
|
|
P0: stabilisation backend/chat/stream + nouvelle base migrations v1
Backend Go:
- Remplacement complet des anciennes migrations par la base V1 alignée sur ORIGIN.
- Durcissement global du parsing JSON (BindAndValidateJSON + RespondWithAppError).
- Sécurisation de config.go, CORS, statuts de santé et monitoring.
- Implémentation des transactions P0 (RBAC, duplication de playlists, social toggles).
- Ajout d’un job worker structuré (emails, analytics, thumbnails) + tests associés.
- Nouvelle doc backend : AUDIT_CONFIG, BACKEND_CONFIG, AUTH_PASSWORD_RESET, JOB_WORKER_*.
Chat server (Rust):
- Refonte du pipeline JWT + sécurité, audit et rate limiting avancé.
- Implémentation complète du cycle de message (read receipts, delivered, edit/delete, typing).
- Nettoyage des panics, gestion d’erreurs robuste, logs structurés.
- Migrations chat alignées sur le schéma UUID et nouvelles features.
Stream server (Rust):
- Refonte du moteur de streaming (encoding pipeline + HLS) et des modules core.
- Transactions P0 pour les jobs et segments, garanties d’atomicité.
- Documentation détaillée de la pipeline (AUDIT_STREAM_*, DESIGN_STREAM_PIPELINE, TRANSACTIONS_P0_IMPLEMENTATION).
Documentation & audits:
- TRIAGE.md et AUDIT_STABILITY.md à jour avec l’état réel des 3 services.
- Cartographie complète des migrations et des transactions (DB_MIGRATIONS_*, DB_TRANSACTION_PLAN, AUDIT_DB_TRANSACTIONS, TRANSACTION_TESTS_PHASE3).
- Scripts de reset et de cleanup pour la lab DB et la V1.
Ce commit fige l’ensemble du travail de stabilisation P0 (UUID, backend, chat et stream) avant les phases suivantes (Coherence Guardian, WS hardening, etc.).
2025-12-06 10:14:38 +00:00
|
|
|
// MIGRATION UUID: user_id est déjà String (UUID), on le parse directement
|
|
|
|
|
let user_uuid = Uuid::parse_str(&claims.user_id)
|
|
|
|
|
.map_err(|e| ChatError::validation_error(&format!("Invalid user UUID: {}", e)))?;
|
|
|
|
|
|
|
|
|
|
// Vérifier les permissions avant de rejoindre
|
|
|
|
|
state
|
|
|
|
|
.permission_service
|
|
|
|
|
.can_join_conversation(user_uuid, conversation_id)
|
|
|
|
|
.await
|
|
|
|
|
.map_err(|e| {
|
|
|
|
|
warn!(
|
|
|
|
|
user_id = %user_uuid,
|
|
|
|
|
conversation_id = %conversation_id,
|
|
|
|
|
error = %e,
|
|
|
|
|
"Permission refusée pour rejoindre la conversation"
|
|
|
|
|
);
|
|
|
|
|
e
|
|
|
|
|
})?;
|
|
|
|
|
|
2025-12-03 19:33:26 +00:00
|
|
|
client.add_conversation(conversation_id).await;
|
|
|
|
|
|
|
|
|
|
let outgoing = OutgoingMessage::ActionConfirmed {
|
|
|
|
|
action: "joined_conversation".to_string(),
|
|
|
|
|
success: true,
|
|
|
|
|
};
|
|
|
|
|
client.send_message(outgoing).await?;
|
|
|
|
|
}
|
|
|
|
|
IncomingMessage::LeaveConversation { conversation_id } => {
|
|
|
|
|
info!(
|
|
|
|
|
"🔚 Client {} ({}) quitte la conversation {}",
|
|
|
|
|
client.id, claims.username, conversation_id
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
client.remove_conversation(conversation_id).await;
|
|
|
|
|
|
|
|
|
|
let outgoing = OutgoingMessage::ActionConfirmed {
|
|
|
|
|
action: "left_conversation".to_string(),
|
|
|
|
|
success: true,
|
|
|
|
|
};
|
|
|
|
|
client.send_message(outgoing).await?;
|
|
|
|
|
}
|
|
|
|
|
IncomingMessage::MarkAsRead {
|
|
|
|
|
conversation_id,
|
|
|
|
|
message_id,
|
|
|
|
|
} => {
|
P0: stabilisation backend/chat/stream + nouvelle base migrations v1
Backend Go:
- Remplacement complet des anciennes migrations par la base V1 alignée sur ORIGIN.
- Durcissement global du parsing JSON (BindAndValidateJSON + RespondWithAppError).
- Sécurisation de config.go, CORS, statuts de santé et monitoring.
- Implémentation des transactions P0 (RBAC, duplication de playlists, social toggles).
- Ajout d’un job worker structuré (emails, analytics, thumbnails) + tests associés.
- Nouvelle doc backend : AUDIT_CONFIG, BACKEND_CONFIG, AUTH_PASSWORD_RESET, JOB_WORKER_*.
Chat server (Rust):
- Refonte du pipeline JWT + sécurité, audit et rate limiting avancé.
- Implémentation complète du cycle de message (read receipts, delivered, edit/delete, typing).
- Nettoyage des panics, gestion d’erreurs robuste, logs structurés.
- Migrations chat alignées sur le schéma UUID et nouvelles features.
Stream server (Rust):
- Refonte du moteur de streaming (encoding pipeline + HLS) et des modules core.
- Transactions P0 pour les jobs et segments, garanties d’atomicité.
- Documentation détaillée de la pipeline (AUDIT_STREAM_*, DESIGN_STREAM_PIPELINE, TRANSACTIONS_P0_IMPLEMENTATION).
Documentation & audits:
- TRIAGE.md et AUDIT_STABILITY.md à jour avec l’état réel des 3 services.
- Cartographie complète des migrations et des transactions (DB_MIGRATIONS_*, DB_TRANSACTION_PLAN, AUDIT_DB_TRANSACTIONS, TRANSACTION_TESTS_PHASE3).
- Scripts de reset et de cleanup pour la lab DB et la V1.
Ce commit fige l’ensemble du travail de stabilisation P0 (UUID, backend, chat et stream) avant les phases suivantes (Coherence Guardian, WS hardening, etc.).
2025-12-06 10:14:38 +00:00
|
|
|
info!(
|
2025-12-03 19:33:26 +00:00
|
|
|
"👁️ Client {} marque le message {} comme lu dans {}",
|
|
|
|
|
client.id, message_id, conversation_id
|
|
|
|
|
);
|
|
|
|
|
|
P0: stabilisation backend/chat/stream + nouvelle base migrations v1
Backend Go:
- Remplacement complet des anciennes migrations par la base V1 alignée sur ORIGIN.
- Durcissement global du parsing JSON (BindAndValidateJSON + RespondWithAppError).
- Sécurisation de config.go, CORS, statuts de santé et monitoring.
- Implémentation des transactions P0 (RBAC, duplication de playlists, social toggles).
- Ajout d’un job worker structuré (emails, analytics, thumbnails) + tests associés.
- Nouvelle doc backend : AUDIT_CONFIG, BACKEND_CONFIG, AUTH_PASSWORD_RESET, JOB_WORKER_*.
Chat server (Rust):
- Refonte du pipeline JWT + sécurité, audit et rate limiting avancé.
- Implémentation complète du cycle de message (read receipts, delivered, edit/delete, typing).
- Nettoyage des panics, gestion d’erreurs robuste, logs structurés.
- Migrations chat alignées sur le schéma UUID et nouvelles features.
Stream server (Rust):
- Refonte du moteur de streaming (encoding pipeline + HLS) et des modules core.
- Transactions P0 pour les jobs et segments, garanties d’atomicité.
- Documentation détaillée de la pipeline (AUDIT_STREAM_*, DESIGN_STREAM_PIPELINE, TRANSACTIONS_P0_IMPLEMENTATION).
Documentation & audits:
- TRIAGE.md et AUDIT_STABILITY.md à jour avec l’état réel des 3 services.
- Cartographie complète des migrations et des transactions (DB_MIGRATIONS_*, DB_TRANSACTION_PLAN, AUDIT_DB_TRANSACTIONS, TRANSACTION_TESTS_PHASE3).
- Scripts de reset et de cleanup pour la lab DB et la V1.
Ce commit fige l’ensemble du travail de stabilisation P0 (UUID, backend, chat et stream) avant les phases suivantes (Coherence Guardian, WS hardening, etc.).
2025-12-06 10:14:38 +00:00
|
|
|
// Parser l'user_id depuis les claims JWT
|
|
|
|
|
let user_uuid = Uuid::parse_str(&claims.user_id)
|
|
|
|
|
.map_err(|e| ChatError::validation_error(&format!("Invalid user UUID: {}", e)))?;
|
2025-12-03 19:33:26 +00:00
|
|
|
|
P0: stabilisation backend/chat/stream + nouvelle base migrations v1
Backend Go:
- Remplacement complet des anciennes migrations par la base V1 alignée sur ORIGIN.
- Durcissement global du parsing JSON (BindAndValidateJSON + RespondWithAppError).
- Sécurisation de config.go, CORS, statuts de santé et monitoring.
- Implémentation des transactions P0 (RBAC, duplication de playlists, social toggles).
- Ajout d’un job worker structuré (emails, analytics, thumbnails) + tests associés.
- Nouvelle doc backend : AUDIT_CONFIG, BACKEND_CONFIG, AUTH_PASSWORD_RESET, JOB_WORKER_*.
Chat server (Rust):
- Refonte du pipeline JWT + sécurité, audit et rate limiting avancé.
- Implémentation complète du cycle de message (read receipts, delivered, edit/delete, typing).
- Nettoyage des panics, gestion d’erreurs robuste, logs structurés.
- Migrations chat alignées sur le schéma UUID et nouvelles features.
Stream server (Rust):
- Refonte du moteur de streaming (encoding pipeline + HLS) et des modules core.
- Transactions P0 pour les jobs et segments, garanties d’atomicité.
- Documentation détaillée de la pipeline (AUDIT_STREAM_*, DESIGN_STREAM_PIPELINE, TRANSACTIONS_P0_IMPLEMENTATION).
Documentation & audits:
- TRIAGE.md et AUDIT_STABILITY.md à jour avec l’état réel des 3 services.
- Cartographie complète des migrations et des transactions (DB_MIGRATIONS_*, DB_TRANSACTION_PLAN, AUDIT_DB_TRANSACTIONS, TRANSACTION_TESTS_PHASE3).
- Scripts de reset et de cleanup pour la lab DB et la V1.
Ce commit fige l’ensemble du travail de stabilisation P0 (UUID, backend, chat et stream) avant les phases suivantes (Coherence Guardian, WS hardening, etc.).
2025-12-06 10:14:38 +00:00
|
|
|
// Vérifier que le message existe
|
|
|
|
|
let message = state
|
|
|
|
|
.message_repo
|
|
|
|
|
.get_by_id(message_id)
|
|
|
|
|
.await
|
|
|
|
|
.map_err(|e| {
|
|
|
|
|
ChatError::internal_error(format!(
|
|
|
|
|
"Erreur lors de la récupération du message: {}",
|
|
|
|
|
e
|
|
|
|
|
))
|
|
|
|
|
})?;
|
|
|
|
|
|
2025-12-06 16:21:59 +00:00
|
|
|
let message =
|
|
|
|
|
message.ok_or_else(|| ChatError::not_found("Message", &message_id.to_string()))?;
|
P0: stabilisation backend/chat/stream + nouvelle base migrations v1
Backend Go:
- Remplacement complet des anciennes migrations par la base V1 alignée sur ORIGIN.
- Durcissement global du parsing JSON (BindAndValidateJSON + RespondWithAppError).
- Sécurisation de config.go, CORS, statuts de santé et monitoring.
- Implémentation des transactions P0 (RBAC, duplication de playlists, social toggles).
- Ajout d’un job worker structuré (emails, analytics, thumbnails) + tests associés.
- Nouvelle doc backend : AUDIT_CONFIG, BACKEND_CONFIG, AUTH_PASSWORD_RESET, JOB_WORKER_*.
Chat server (Rust):
- Refonte du pipeline JWT + sécurité, audit et rate limiting avancé.
- Implémentation complète du cycle de message (read receipts, delivered, edit/delete, typing).
- Nettoyage des panics, gestion d’erreurs robuste, logs structurés.
- Migrations chat alignées sur le schéma UUID et nouvelles features.
Stream server (Rust):
- Refonte du moteur de streaming (encoding pipeline + HLS) et des modules core.
- Transactions P0 pour les jobs et segments, garanties d’atomicité.
- Documentation détaillée de la pipeline (AUDIT_STREAM_*, DESIGN_STREAM_PIPELINE, TRANSACTIONS_P0_IMPLEMENTATION).
Documentation & audits:
- TRIAGE.md et AUDIT_STABILITY.md à jour avec l’état réel des 3 services.
- Cartographie complète des migrations et des transactions (DB_MIGRATIONS_*, DB_TRANSACTION_PLAN, AUDIT_DB_TRANSACTIONS, TRANSACTION_TESTS_PHASE3).
- Scripts de reset et de cleanup pour la lab DB et la V1.
Ce commit fige l’ensemble du travail de stabilisation P0 (UUID, backend, chat et stream) avant les phases suivantes (Coherence Guardian, WS hardening, etc.).
2025-12-06 10:14:38 +00:00
|
|
|
|
|
|
|
|
// Vérifier que le message appartient à la conversation indiquée
|
|
|
|
|
if message.conversation_id != conversation_id {
|
|
|
|
|
return Err(ChatError::validation_error(
|
|
|
|
|
"Le message n'appartient pas à la conversation indiquée",
|
|
|
|
|
));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Vérifier les permissions pour marquer comme lu
|
|
|
|
|
state
|
|
|
|
|
.permission_service
|
|
|
|
|
.can_mark_read(user_uuid, conversation_id)
|
|
|
|
|
.await
|
|
|
|
|
.map_err(|e| {
|
|
|
|
|
warn!(
|
|
|
|
|
user_id = %user_uuid,
|
|
|
|
|
conversation_id = %conversation_id,
|
|
|
|
|
error = %e,
|
|
|
|
|
"Permission refusée pour marquer comme lu"
|
|
|
|
|
);
|
|
|
|
|
e
|
|
|
|
|
})?;
|
|
|
|
|
|
|
|
|
|
// Marquer le message comme lu
|
|
|
|
|
let receipt = state
|
|
|
|
|
.read_receipt_manager
|
|
|
|
|
.mark_as_read(user_uuid, message_id, conversation_id)
|
|
|
|
|
.await
|
|
|
|
|
.map_err(|e| {
|
2025-12-06 16:21:59 +00:00
|
|
|
ChatError::internal_error(format!("Erreur lors du marquage comme lu: {}", e))
|
P0: stabilisation backend/chat/stream + nouvelle base migrations v1
Backend Go:
- Remplacement complet des anciennes migrations par la base V1 alignée sur ORIGIN.
- Durcissement global du parsing JSON (BindAndValidateJSON + RespondWithAppError).
- Sécurisation de config.go, CORS, statuts de santé et monitoring.
- Implémentation des transactions P0 (RBAC, duplication de playlists, social toggles).
- Ajout d’un job worker structuré (emails, analytics, thumbnails) + tests associés.
- Nouvelle doc backend : AUDIT_CONFIG, BACKEND_CONFIG, AUTH_PASSWORD_RESET, JOB_WORKER_*.
Chat server (Rust):
- Refonte du pipeline JWT + sécurité, audit et rate limiting avancé.
- Implémentation complète du cycle de message (read receipts, delivered, edit/delete, typing).
- Nettoyage des panics, gestion d’erreurs robuste, logs structurés.
- Migrations chat alignées sur le schéma UUID et nouvelles features.
Stream server (Rust):
- Refonte du moteur de streaming (encoding pipeline + HLS) et des modules core.
- Transactions P0 pour les jobs et segments, garanties d’atomicité.
- Documentation détaillée de la pipeline (AUDIT_STREAM_*, DESIGN_STREAM_PIPELINE, TRANSACTIONS_P0_IMPLEMENTATION).
Documentation & audits:
- TRIAGE.md et AUDIT_STABILITY.md à jour avec l’état réel des 3 services.
- Cartographie complète des migrations et des transactions (DB_MIGRATIONS_*, DB_TRANSACTION_PLAN, AUDIT_DB_TRANSACTIONS, TRANSACTION_TESTS_PHASE3).
- Scripts de reset et de cleanup pour la lab DB et la V1.
Ce commit fige l’ensemble du travail de stabilisation P0 (UUID, backend, chat et stream) avant les phases suivantes (Coherence Guardian, WS hardening, etc.).
2025-12-06 10:14:38 +00:00
|
|
|
})?;
|
|
|
|
|
|
|
|
|
|
// Créer le message outbound pour notifier les autres participants
|
|
|
|
|
let message_read = OutgoingMessage::MessageRead {
|
|
|
|
|
message_id,
|
|
|
|
|
user_id: user_uuid,
|
|
|
|
|
conversation_id,
|
|
|
|
|
read_at: receipt.read_at,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// Broadcast aux autres participants de la conversation
|
|
|
|
|
state
|
|
|
|
|
.ws_manager
|
|
|
|
|
.broadcast_to_conversation(conversation_id, message_read.clone())
|
|
|
|
|
.await?;
|
|
|
|
|
|
|
|
|
|
// Envoyer confirmation au client qui a initié l'action
|
|
|
|
|
let confirmation = OutgoingMessage::ActionConfirmed {
|
2025-12-03 19:33:26 +00:00
|
|
|
action: "marked_as_read".to_string(),
|
|
|
|
|
success: true,
|
|
|
|
|
};
|
P0: stabilisation backend/chat/stream + nouvelle base migrations v1
Backend Go:
- Remplacement complet des anciennes migrations par la base V1 alignée sur ORIGIN.
- Durcissement global du parsing JSON (BindAndValidateJSON + RespondWithAppError).
- Sécurisation de config.go, CORS, statuts de santé et monitoring.
- Implémentation des transactions P0 (RBAC, duplication de playlists, social toggles).
- Ajout d’un job worker structuré (emails, analytics, thumbnails) + tests associés.
- Nouvelle doc backend : AUDIT_CONFIG, BACKEND_CONFIG, AUTH_PASSWORD_RESET, JOB_WORKER_*.
Chat server (Rust):
- Refonte du pipeline JWT + sécurité, audit et rate limiting avancé.
- Implémentation complète du cycle de message (read receipts, delivered, edit/delete, typing).
- Nettoyage des panics, gestion d’erreurs robuste, logs structurés.
- Migrations chat alignées sur le schéma UUID et nouvelles features.
Stream server (Rust):
- Refonte du moteur de streaming (encoding pipeline + HLS) et des modules core.
- Transactions P0 pour les jobs et segments, garanties d’atomicité.
- Documentation détaillée de la pipeline (AUDIT_STREAM_*, DESIGN_STREAM_PIPELINE, TRANSACTIONS_P0_IMPLEMENTATION).
Documentation & audits:
- TRIAGE.md et AUDIT_STABILITY.md à jour avec l’état réel des 3 services.
- Cartographie complète des migrations et des transactions (DB_MIGRATIONS_*, DB_TRANSACTION_PLAN, AUDIT_DB_TRANSACTIONS, TRANSACTION_TESTS_PHASE3).
- Scripts de reset et de cleanup pour la lab DB et la V1.
Ce commit fige l’ensemble du travail de stabilisation P0 (UUID, backend, chat et stream) avant les phases suivantes (Coherence Guardian, WS hardening, etc.).
2025-12-06 10:14:38 +00:00
|
|
|
client.send_message(confirmation).await?;
|
|
|
|
|
|
|
|
|
|
info!(
|
|
|
|
|
"✅ Message {} marqué comme lu par {} dans la conversation {}",
|
|
|
|
|
message_id, user_uuid, conversation_id
|
|
|
|
|
);
|
|
|
|
|
}
|
2025-12-06 16:21:59 +00:00
|
|
|
IncomingMessage::Typing {
|
|
|
|
|
conversation_id,
|
|
|
|
|
is_typing,
|
|
|
|
|
} => {
|
P0: stabilisation backend/chat/stream + nouvelle base migrations v1
Backend Go:
- Remplacement complet des anciennes migrations par la base V1 alignée sur ORIGIN.
- Durcissement global du parsing JSON (BindAndValidateJSON + RespondWithAppError).
- Sécurisation de config.go, CORS, statuts de santé et monitoring.
- Implémentation des transactions P0 (RBAC, duplication de playlists, social toggles).
- Ajout d’un job worker structuré (emails, analytics, thumbnails) + tests associés.
- Nouvelle doc backend : AUDIT_CONFIG, BACKEND_CONFIG, AUTH_PASSWORD_RESET, JOB_WORKER_*.
Chat server (Rust):
- Refonte du pipeline JWT + sécurité, audit et rate limiting avancé.
- Implémentation complète du cycle de message (read receipts, delivered, edit/delete, typing).
- Nettoyage des panics, gestion d’erreurs robuste, logs structurés.
- Migrations chat alignées sur le schéma UUID et nouvelles features.
Stream server (Rust):
- Refonte du moteur de streaming (encoding pipeline + HLS) et des modules core.
- Transactions P0 pour les jobs et segments, garanties d’atomicité.
- Documentation détaillée de la pipeline (AUDIT_STREAM_*, DESIGN_STREAM_PIPELINE, TRANSACTIONS_P0_IMPLEMENTATION).
Documentation & audits:
- TRIAGE.md et AUDIT_STABILITY.md à jour avec l’état réel des 3 services.
- Cartographie complète des migrations et des transactions (DB_MIGRATIONS_*, DB_TRANSACTION_PLAN, AUDIT_DB_TRANSACTIONS, TRANSACTION_TESTS_PHASE3).
- Scripts de reset et de cleanup pour la lab DB et la V1.
Ce commit fige l’ensemble du travail de stabilisation P0 (UUID, backend, chat et stream) avant les phases suivantes (Coherence Guardian, WS hardening, etc.).
2025-12-06 10:14:38 +00:00
|
|
|
info!(
|
|
|
|
|
"⌨️ Client {} ({}) typing indicator: {} dans conversation {}",
|
|
|
|
|
client.id, claims.username, is_typing, conversation_id
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
// Parser l'user_id depuis les claims JWT
|
|
|
|
|
let user_uuid = Uuid::parse_str(&claims.user_id)
|
|
|
|
|
.map_err(|e| ChatError::validation_error(&format!("Invalid user UUID: {}", e)))?;
|
|
|
|
|
|
|
|
|
|
// Vérifier les permissions avant d'envoyer le signal typing
|
|
|
|
|
state
|
|
|
|
|
.permission_service
|
|
|
|
|
.can_send_message(user_uuid, conversation_id)
|
|
|
|
|
.await
|
|
|
|
|
.map_err(|e| {
|
|
|
|
|
warn!(
|
|
|
|
|
user_id = %user_uuid,
|
|
|
|
|
conversation_id = %conversation_id,
|
|
|
|
|
error = %e,
|
|
|
|
|
"Permission refusée pour typing indicator"
|
|
|
|
|
);
|
|
|
|
|
e
|
|
|
|
|
})?;
|
|
|
|
|
|
|
|
|
|
if is_typing {
|
|
|
|
|
// User a commencé à taper
|
|
|
|
|
state
|
|
|
|
|
.typing_indicator_manager
|
|
|
|
|
.user_started_typing(user_uuid, conversation_id)
|
|
|
|
|
.await;
|
|
|
|
|
} else {
|
|
|
|
|
// User a arrêté de taper
|
|
|
|
|
state
|
|
|
|
|
.typing_indicator_manager
|
|
|
|
|
.user_stopped_typing(user_uuid, conversation_id)
|
|
|
|
|
.await;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Broadcast aux autres participants de la conversation
|
|
|
|
|
let typing_message = OutgoingMessage::UserTyping {
|
|
|
|
|
conversation_id,
|
|
|
|
|
user_id: user_uuid,
|
|
|
|
|
is_typing,
|
|
|
|
|
};
|
|
|
|
|
state
|
|
|
|
|
.ws_manager
|
|
|
|
|
.broadcast_to_conversation(conversation_id, typing_message.clone())
|
|
|
|
|
.await?;
|
|
|
|
|
|
|
|
|
|
// Envoyer confirmation au client qui a initié l'action
|
|
|
|
|
let confirmation = OutgoingMessage::ActionConfirmed {
|
|
|
|
|
action: "typing_indicator".to_string(),
|
|
|
|
|
success: true,
|
|
|
|
|
};
|
|
|
|
|
client.send_message(confirmation).await?;
|
|
|
|
|
|
|
|
|
|
info!(
|
|
|
|
|
"✅ Typing indicator {} diffusé pour {} dans la conversation {}",
|
|
|
|
|
if is_typing { "activé" } else { "désactivé" },
|
|
|
|
|
user_uuid,
|
|
|
|
|
conversation_id
|
|
|
|
|
);
|
|
|
|
|
}
|
2025-12-06 16:21:59 +00:00
|
|
|
IncomingMessage::Delivered {
|
|
|
|
|
conversation_id,
|
|
|
|
|
message_id,
|
|
|
|
|
} => {
|
P0: stabilisation backend/chat/stream + nouvelle base migrations v1
Backend Go:
- Remplacement complet des anciennes migrations par la base V1 alignée sur ORIGIN.
- Durcissement global du parsing JSON (BindAndValidateJSON + RespondWithAppError).
- Sécurisation de config.go, CORS, statuts de santé et monitoring.
- Implémentation des transactions P0 (RBAC, duplication de playlists, social toggles).
- Ajout d’un job worker structuré (emails, analytics, thumbnails) + tests associés.
- Nouvelle doc backend : AUDIT_CONFIG, BACKEND_CONFIG, AUTH_PASSWORD_RESET, JOB_WORKER_*.
Chat server (Rust):
- Refonte du pipeline JWT + sécurité, audit et rate limiting avancé.
- Implémentation complète du cycle de message (read receipts, delivered, edit/delete, typing).
- Nettoyage des panics, gestion d’erreurs robuste, logs structurés.
- Migrations chat alignées sur le schéma UUID et nouvelles features.
Stream server (Rust):
- Refonte du moteur de streaming (encoding pipeline + HLS) et des modules core.
- Transactions P0 pour les jobs et segments, garanties d’atomicité.
- Documentation détaillée de la pipeline (AUDIT_STREAM_*, DESIGN_STREAM_PIPELINE, TRANSACTIONS_P0_IMPLEMENTATION).
Documentation & audits:
- TRIAGE.md et AUDIT_STABILITY.md à jour avec l’état réel des 3 services.
- Cartographie complète des migrations et des transactions (DB_MIGRATIONS_*, DB_TRANSACTION_PLAN, AUDIT_DB_TRANSACTIONS, TRANSACTION_TESTS_PHASE3).
- Scripts de reset et de cleanup pour la lab DB et la V1.
Ce commit fige l’ensemble du travail de stabilisation P0 (UUID, backend, chat et stream) avant les phases suivantes (Coherence Guardian, WS hardening, etc.).
2025-12-06 10:14:38 +00:00
|
|
|
info!(
|
|
|
|
|
"📬 Client {} ({}) marque le message {} comme délivré dans {}",
|
|
|
|
|
client.id, message_id, conversation_id, claims.username
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
// Parser l'user_id depuis les claims JWT
|
|
|
|
|
let user_uuid = Uuid::parse_str(&claims.user_id)
|
|
|
|
|
.map_err(|e| ChatError::validation_error(&format!("Invalid user UUID: {}", e)))?;
|
|
|
|
|
|
|
|
|
|
// Vérifier les permissions pour marquer comme délivré
|
|
|
|
|
state
|
|
|
|
|
.permission_service
|
|
|
|
|
.can_read_conversation(user_uuid, conversation_id)
|
|
|
|
|
.await
|
|
|
|
|
.map_err(|e| {
|
|
|
|
|
warn!(
|
|
|
|
|
user_id = %user_uuid,
|
|
|
|
|
conversation_id = %conversation_id,
|
|
|
|
|
error = %e,
|
|
|
|
|
"Permission refusée pour marquer comme délivré"
|
|
|
|
|
);
|
|
|
|
|
e
|
|
|
|
|
})?;
|
|
|
|
|
|
|
|
|
|
// Vérifier que le message existe et appartient à la conversation
|
|
|
|
|
let message = state
|
|
|
|
|
.message_repo
|
|
|
|
|
.get_by_id(message_id)
|
|
|
|
|
.await
|
|
|
|
|
.map_err(|e| {
|
|
|
|
|
ChatError::internal_error(format!(
|
|
|
|
|
"Erreur lors de la récupération du message: {}",
|
|
|
|
|
e
|
|
|
|
|
))
|
|
|
|
|
})?;
|
|
|
|
|
|
2025-12-06 16:21:59 +00:00
|
|
|
let message =
|
|
|
|
|
message.ok_or_else(|| ChatError::not_found("Message", &message_id.to_string()))?;
|
P0: stabilisation backend/chat/stream + nouvelle base migrations v1
Backend Go:
- Remplacement complet des anciennes migrations par la base V1 alignée sur ORIGIN.
- Durcissement global du parsing JSON (BindAndValidateJSON + RespondWithAppError).
- Sécurisation de config.go, CORS, statuts de santé et monitoring.
- Implémentation des transactions P0 (RBAC, duplication de playlists, social toggles).
- Ajout d’un job worker structuré (emails, analytics, thumbnails) + tests associés.
- Nouvelle doc backend : AUDIT_CONFIG, BACKEND_CONFIG, AUTH_PASSWORD_RESET, JOB_WORKER_*.
Chat server (Rust):
- Refonte du pipeline JWT + sécurité, audit et rate limiting avancé.
- Implémentation complète du cycle de message (read receipts, delivered, edit/delete, typing).
- Nettoyage des panics, gestion d’erreurs robuste, logs structurés.
- Migrations chat alignées sur le schéma UUID et nouvelles features.
Stream server (Rust):
- Refonte du moteur de streaming (encoding pipeline + HLS) et des modules core.
- Transactions P0 pour les jobs et segments, garanties d’atomicité.
- Documentation détaillée de la pipeline (AUDIT_STREAM_*, DESIGN_STREAM_PIPELINE, TRANSACTIONS_P0_IMPLEMENTATION).
Documentation & audits:
- TRIAGE.md et AUDIT_STABILITY.md à jour avec l’état réel des 3 services.
- Cartographie complète des migrations et des transactions (DB_MIGRATIONS_*, DB_TRANSACTION_PLAN, AUDIT_DB_TRANSACTIONS, TRANSACTION_TESTS_PHASE3).
- Scripts de reset et de cleanup pour la lab DB et la V1.
Ce commit fige l’ensemble du travail de stabilisation P0 (UUID, backend, chat et stream) avant les phases suivantes (Coherence Guardian, WS hardening, etc.).
2025-12-06 10:14:38 +00:00
|
|
|
|
|
|
|
|
// Vérifier que le message appartient à la conversation indiquée
|
|
|
|
|
if message.conversation_id != conversation_id {
|
|
|
|
|
return Err(ChatError::validation_error(
|
|
|
|
|
"Le message n'appartient pas à la conversation indiquée",
|
|
|
|
|
));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Vérifier que le message appartient bien à la conversation (double vérification)
|
|
|
|
|
let belongs = state
|
|
|
|
|
.delivered_status_manager
|
|
|
|
|
.verify_message_belongs_to_conversation(message_id, conversation_id)
|
|
|
|
|
.await
|
|
|
|
|
.map_err(|e| {
|
|
|
|
|
ChatError::internal_error(format!(
|
|
|
|
|
"Erreur lors de la vérification du message: {}",
|
|
|
|
|
e
|
|
|
|
|
))
|
|
|
|
|
})?;
|
|
|
|
|
|
|
|
|
|
if !belongs {
|
|
|
|
|
return Err(ChatError::validation_error(
|
|
|
|
|
"Le message n'appartient pas à la conversation indiquée",
|
|
|
|
|
));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Marquer le message comme délivré
|
|
|
|
|
let status = state
|
|
|
|
|
.delivered_status_manager
|
|
|
|
|
.mark_delivered(user_uuid, message_id, conversation_id)
|
|
|
|
|
.await
|
|
|
|
|
.map_err(|e| {
|
|
|
|
|
ChatError::internal_error(format!(
|
|
|
|
|
"Erreur lors du marquage comme délivré: {}",
|
|
|
|
|
e
|
|
|
|
|
))
|
|
|
|
|
})?;
|
|
|
|
|
|
|
|
|
|
// Créer le message outbound pour notifier les autres participants
|
|
|
|
|
let message_delivered = OutgoingMessage::MessageDelivered {
|
|
|
|
|
message_id,
|
|
|
|
|
user_id: user_uuid,
|
|
|
|
|
conversation_id,
|
|
|
|
|
delivered_at: status.delivered_at,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// Broadcast aux autres participants de la conversation
|
|
|
|
|
state
|
|
|
|
|
.ws_manager
|
|
|
|
|
.broadcast_to_conversation(conversation_id, message_delivered.clone())
|
|
|
|
|
.await?;
|
|
|
|
|
|
|
|
|
|
// Envoyer confirmation au client qui a initié l'action
|
|
|
|
|
let confirmation = OutgoingMessage::ActionConfirmed {
|
|
|
|
|
action: "marked_as_delivered".to_string(),
|
|
|
|
|
success: true,
|
|
|
|
|
};
|
|
|
|
|
client.send_message(confirmation).await?;
|
|
|
|
|
|
|
|
|
|
info!(
|
|
|
|
|
"✅ Message {} marqué comme délivré par {} dans la conversation {}",
|
|
|
|
|
message_id, user_uuid, conversation_id
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
IncomingMessage::EditMessage {
|
|
|
|
|
message_id,
|
|
|
|
|
conversation_id,
|
|
|
|
|
new_content,
|
|
|
|
|
} => {
|
|
|
|
|
info!(
|
|
|
|
|
"✏️ Client {} ({}) édite le message {} dans {}",
|
|
|
|
|
client.id, claims.username, message_id, conversation_id
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
// Parser l'user_id depuis les claims JWT
|
|
|
|
|
let user_uuid = Uuid::parse_str(&claims.user_id)
|
|
|
|
|
.map_err(|e| ChatError::validation_error(&format!("Invalid user UUID: {}", e)))?;
|
|
|
|
|
|
|
|
|
|
// Éditer le message via le service
|
|
|
|
|
let updated_message = state
|
|
|
|
|
.message_edit_service
|
|
|
|
|
.edit_message(user_uuid, message_id, &new_content)
|
|
|
|
|
.await
|
|
|
|
|
.map_err(|e| {
|
|
|
|
|
warn!(
|
|
|
|
|
user_id = %user_uuid,
|
|
|
|
|
message_id = %message_id,
|
|
|
|
|
error = %e,
|
|
|
|
|
"Erreur lors de l'édition du message"
|
|
|
|
|
);
|
|
|
|
|
e
|
|
|
|
|
})?;
|
|
|
|
|
|
|
|
|
|
// Vérifier que le message appartient à la conversation indiquée
|
|
|
|
|
if updated_message.conversation_id != conversation_id {
|
|
|
|
|
return Err(ChatError::validation_error(
|
|
|
|
|
"Le message n'appartient pas à la conversation indiquée",
|
|
|
|
|
));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Créer le message outbound pour notifier les autres participants
|
|
|
|
|
let message_edited = OutgoingMessage::MessageEdited {
|
|
|
|
|
message_id,
|
|
|
|
|
conversation_id,
|
|
|
|
|
editor_id: user_uuid,
|
2025-12-06 16:21:59 +00:00
|
|
|
edited_at: updated_message
|
|
|
|
|
.edited_at
|
|
|
|
|
.unwrap_or(updated_message.updated_at),
|
P0: stabilisation backend/chat/stream + nouvelle base migrations v1
Backend Go:
- Remplacement complet des anciennes migrations par la base V1 alignée sur ORIGIN.
- Durcissement global du parsing JSON (BindAndValidateJSON + RespondWithAppError).
- Sécurisation de config.go, CORS, statuts de santé et monitoring.
- Implémentation des transactions P0 (RBAC, duplication de playlists, social toggles).
- Ajout d’un job worker structuré (emails, analytics, thumbnails) + tests associés.
- Nouvelle doc backend : AUDIT_CONFIG, BACKEND_CONFIG, AUTH_PASSWORD_RESET, JOB_WORKER_*.
Chat server (Rust):
- Refonte du pipeline JWT + sécurité, audit et rate limiting avancé.
- Implémentation complète du cycle de message (read receipts, delivered, edit/delete, typing).
- Nettoyage des panics, gestion d’erreurs robuste, logs structurés.
- Migrations chat alignées sur le schéma UUID et nouvelles features.
Stream server (Rust):
- Refonte du moteur de streaming (encoding pipeline + HLS) et des modules core.
- Transactions P0 pour les jobs et segments, garanties d’atomicité.
- Documentation détaillée de la pipeline (AUDIT_STREAM_*, DESIGN_STREAM_PIPELINE, TRANSACTIONS_P0_IMPLEMENTATION).
Documentation & audits:
- TRIAGE.md et AUDIT_STABILITY.md à jour avec l’état réel des 3 services.
- Cartographie complète des migrations et des transactions (DB_MIGRATIONS_*, DB_TRANSACTION_PLAN, AUDIT_DB_TRANSACTIONS, TRANSACTION_TESTS_PHASE3).
- Scripts de reset et de cleanup pour la lab DB et la V1.
Ce commit fige l’ensemble du travail de stabilisation P0 (UUID, backend, chat et stream) avant les phases suivantes (Coherence Guardian, WS hardening, etc.).
2025-12-06 10:14:38 +00:00
|
|
|
new_content: updated_message.content.clone(),
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// Broadcast aux autres participants de la conversation
|
|
|
|
|
state
|
|
|
|
|
.ws_manager
|
|
|
|
|
.broadcast_to_conversation(conversation_id, message_edited.clone())
|
|
|
|
|
.await?;
|
|
|
|
|
|
|
|
|
|
// Envoyer confirmation au client qui a initié l'action
|
|
|
|
|
let confirmation = OutgoingMessage::ActionConfirmed {
|
|
|
|
|
action: "message_edited".to_string(),
|
|
|
|
|
success: true,
|
|
|
|
|
};
|
|
|
|
|
client.send_message(confirmation).await?;
|
|
|
|
|
|
|
|
|
|
info!(
|
|
|
|
|
"✅ Message {} édité par {} dans la conversation {}",
|
|
|
|
|
message_id, user_uuid, conversation_id
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
IncomingMessage::DeleteMessage {
|
|
|
|
|
message_id,
|
|
|
|
|
conversation_id,
|
|
|
|
|
} => {
|
|
|
|
|
info!(
|
|
|
|
|
"🗑️ Client {} ({}) supprime le message {} dans {}",
|
|
|
|
|
client.id, claims.username, message_id, conversation_id
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
// Parser l'user_id depuis les claims JWT
|
|
|
|
|
let user_uuid = Uuid::parse_str(&claims.user_id)
|
|
|
|
|
.map_err(|e| ChatError::validation_error(&format!("Invalid user UUID: {}", e)))?;
|
|
|
|
|
|
|
|
|
|
// Supprimer le message via le service
|
|
|
|
|
let deleted_message = state
|
|
|
|
|
.message_edit_service
|
|
|
|
|
.delete_message(user_uuid, message_id)
|
|
|
|
|
.await
|
|
|
|
|
.map_err(|e| {
|
|
|
|
|
warn!(
|
|
|
|
|
user_id = %user_uuid,
|
|
|
|
|
message_id = %message_id,
|
|
|
|
|
error = %e,
|
|
|
|
|
"Erreur lors de la suppression du message"
|
|
|
|
|
);
|
|
|
|
|
e
|
|
|
|
|
})?;
|
|
|
|
|
|
|
|
|
|
// Vérifier que le message appartient à la conversation indiquée
|
|
|
|
|
if deleted_message.conversation_id != conversation_id {
|
|
|
|
|
return Err(ChatError::validation_error(
|
|
|
|
|
"Le message n'appartient pas à la conversation indiquée",
|
|
|
|
|
));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Créer le message outbound pour notifier les autres participants
|
|
|
|
|
let message_deleted = OutgoingMessage::MessageDeleted {
|
|
|
|
|
message_id,
|
|
|
|
|
conversation_id,
|
|
|
|
|
deleter_id: user_uuid,
|
2025-12-06 16:21:59 +00:00
|
|
|
deleted_at: deleted_message
|
|
|
|
|
.deleted_at
|
|
|
|
|
.unwrap_or(deleted_message.updated_at),
|
P0: stabilisation backend/chat/stream + nouvelle base migrations v1
Backend Go:
- Remplacement complet des anciennes migrations par la base V1 alignée sur ORIGIN.
- Durcissement global du parsing JSON (BindAndValidateJSON + RespondWithAppError).
- Sécurisation de config.go, CORS, statuts de santé et monitoring.
- Implémentation des transactions P0 (RBAC, duplication de playlists, social toggles).
- Ajout d’un job worker structuré (emails, analytics, thumbnails) + tests associés.
- Nouvelle doc backend : AUDIT_CONFIG, BACKEND_CONFIG, AUTH_PASSWORD_RESET, JOB_WORKER_*.
Chat server (Rust):
- Refonte du pipeline JWT + sécurité, audit et rate limiting avancé.
- Implémentation complète du cycle de message (read receipts, delivered, edit/delete, typing).
- Nettoyage des panics, gestion d’erreurs robuste, logs structurés.
- Migrations chat alignées sur le schéma UUID et nouvelles features.
Stream server (Rust):
- Refonte du moteur de streaming (encoding pipeline + HLS) et des modules core.
- Transactions P0 pour les jobs et segments, garanties d’atomicité.
- Documentation détaillée de la pipeline (AUDIT_STREAM_*, DESIGN_STREAM_PIPELINE, TRANSACTIONS_P0_IMPLEMENTATION).
Documentation & audits:
- TRIAGE.md et AUDIT_STABILITY.md à jour avec l’état réel des 3 services.
- Cartographie complète des migrations et des transactions (DB_MIGRATIONS_*, DB_TRANSACTION_PLAN, AUDIT_DB_TRANSACTIONS, TRANSACTION_TESTS_PHASE3).
- Scripts de reset et de cleanup pour la lab DB et la V1.
Ce commit fige l’ensemble du travail de stabilisation P0 (UUID, backend, chat et stream) avant les phases suivantes (Coherence Guardian, WS hardening, etc.).
2025-12-06 10:14:38 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// Broadcast aux autres participants de la conversation
|
|
|
|
|
state
|
|
|
|
|
.ws_manager
|
|
|
|
|
.broadcast_to_conversation(conversation_id, message_deleted.clone())
|
|
|
|
|
.await?;
|
|
|
|
|
|
|
|
|
|
// Envoyer confirmation au client qui a initié l'action
|
|
|
|
|
let confirmation = OutgoingMessage::ActionConfirmed {
|
|
|
|
|
action: "message_deleted".to_string(),
|
|
|
|
|
success: true,
|
|
|
|
|
};
|
|
|
|
|
client.send_message(confirmation).await?;
|
|
|
|
|
|
|
|
|
|
info!(
|
|
|
|
|
"✅ Message {} supprimé par {} dans la conversation {}",
|
|
|
|
|
message_id, user_uuid, conversation_id
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
IncomingMessage::FetchHistory {
|
|
|
|
|
conversation_id,
|
|
|
|
|
before,
|
|
|
|
|
after,
|
|
|
|
|
limit,
|
|
|
|
|
} => {
|
|
|
|
|
info!(
|
|
|
|
|
"📜 Client {} ({}) demande l'historique de la conversation {}",
|
|
|
|
|
client.id, claims.username, conversation_id
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
// Parser l'user_id depuis les claims JWT
|
|
|
|
|
let user_uuid = Uuid::parse_str(&claims.user_id)
|
|
|
|
|
.map_err(|e| ChatError::validation_error(&format!("Invalid user UUID: {}", e)))?;
|
|
|
|
|
|
|
|
|
|
// Vérifier les permissions pour lire l'historique
|
|
|
|
|
state
|
|
|
|
|
.permission_service
|
|
|
|
|
.can_read_conversation(user_uuid, conversation_id)
|
|
|
|
|
.await
|
|
|
|
|
.map_err(|e| {
|
|
|
|
|
warn!(
|
|
|
|
|
user_id = %user_uuid,
|
|
|
|
|
conversation_id = %conversation_id,
|
|
|
|
|
error = %e,
|
|
|
|
|
"Permission refusée pour lire l'historique"
|
|
|
|
|
);
|
|
|
|
|
e
|
|
|
|
|
})?;
|
|
|
|
|
|
|
|
|
|
// Récupérer l'historique
|
|
|
|
|
let limit = limit.unwrap_or(50).min(100);
|
2026-02-11 21:04:11 +00:00
|
|
|
let (messages, has_more_before, has_more_after): (
|
|
|
|
|
Vec<crate::models::message::Message>,
|
|
|
|
|
bool,
|
|
|
|
|
bool,
|
|
|
|
|
) = state
|
P0: stabilisation backend/chat/stream + nouvelle base migrations v1
Backend Go:
- Remplacement complet des anciennes migrations par la base V1 alignée sur ORIGIN.
- Durcissement global du parsing JSON (BindAndValidateJSON + RespondWithAppError).
- Sécurisation de config.go, CORS, statuts de santé et monitoring.
- Implémentation des transactions P0 (RBAC, duplication de playlists, social toggles).
- Ajout d’un job worker structuré (emails, analytics, thumbnails) + tests associés.
- Nouvelle doc backend : AUDIT_CONFIG, BACKEND_CONFIG, AUTH_PASSWORD_RESET, JOB_WORKER_*.
Chat server (Rust):
- Refonte du pipeline JWT + sécurité, audit et rate limiting avancé.
- Implémentation complète du cycle de message (read receipts, delivered, edit/delete, typing).
- Nettoyage des panics, gestion d’erreurs robuste, logs structurés.
- Migrations chat alignées sur le schéma UUID et nouvelles features.
Stream server (Rust):
- Refonte du moteur de streaming (encoding pipeline + HLS) et des modules core.
- Transactions P0 pour les jobs et segments, garanties d’atomicité.
- Documentation détaillée de la pipeline (AUDIT_STREAM_*, DESIGN_STREAM_PIPELINE, TRANSACTIONS_P0_IMPLEMENTATION).
Documentation & audits:
- TRIAGE.md et AUDIT_STABILITY.md à jour avec l’état réel des 3 services.
- Cartographie complète des migrations et des transactions (DB_MIGRATIONS_*, DB_TRANSACTION_PLAN, AUDIT_DB_TRANSACTIONS, TRANSACTION_TESTS_PHASE3).
- Scripts de reset et de cleanup pour la lab DB et la V1.
Ce commit fige l’ensemble du travail de stabilisation P0 (UUID, backend, chat et stream) avant les phases suivantes (Coherence Guardian, WS hardening, etc.).
2025-12-06 10:14:38 +00:00
|
|
|
.message_repo
|
|
|
|
|
.fetch_history(conversation_id, before, after, limit, false)
|
|
|
|
|
.await
|
|
|
|
|
.map_err(|e| {
|
|
|
|
|
ChatError::internal_error(format!(
|
|
|
|
|
"Erreur lors de la récupération de l'historique: {}",
|
|
|
|
|
e
|
|
|
|
|
))
|
|
|
|
|
})?;
|
|
|
|
|
|
|
|
|
|
// Envoyer le chunk d'historique
|
|
|
|
|
let message_count = messages.len();
|
|
|
|
|
let history_chunk = OutgoingMessage::HistoryChunk {
|
|
|
|
|
conversation_id,
|
|
|
|
|
messages,
|
|
|
|
|
has_more_before,
|
|
|
|
|
has_more_after,
|
|
|
|
|
};
|
|
|
|
|
client.send_message(history_chunk).await?;
|
|
|
|
|
|
|
|
|
|
info!(
|
|
|
|
|
"✅ Historique envoyé pour la conversation {} ({} messages)",
|
|
|
|
|
conversation_id, message_count
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
IncomingMessage::SearchMessages {
|
|
|
|
|
conversation_id,
|
|
|
|
|
query,
|
|
|
|
|
limit,
|
|
|
|
|
offset,
|
|
|
|
|
} => {
|
|
|
|
|
info!(
|
|
|
|
|
"🔍 Client {} ({}) recherche dans la conversation {}: '{}'",
|
|
|
|
|
client.id, claims.username, conversation_id, query
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
// Parser l'user_id depuis les claims JWT
|
|
|
|
|
let user_uuid = Uuid::parse_str(&claims.user_id)
|
|
|
|
|
.map_err(|e| ChatError::validation_error(&format!("Invalid user UUID: {}", e)))?;
|
|
|
|
|
|
|
|
|
|
// Vérifier les permissions pour rechercher
|
|
|
|
|
state
|
|
|
|
|
.permission_service
|
|
|
|
|
.can_read_conversation(user_uuid, conversation_id)
|
|
|
|
|
.await
|
|
|
|
|
.map_err(|e| {
|
|
|
|
|
warn!(
|
|
|
|
|
user_id = %user_uuid,
|
|
|
|
|
conversation_id = %conversation_id,
|
|
|
|
|
error = %e,
|
|
|
|
|
"Permission refusée pour rechercher"
|
|
|
|
|
);
|
|
|
|
|
e
|
|
|
|
|
})?;
|
|
|
|
|
|
|
|
|
|
// Valider la query (ne pas être vide)
|
|
|
|
|
if query.trim().is_empty() {
|
2025-12-06 16:21:59 +00:00
|
|
|
return Err(ChatError::validation_error(
|
|
|
|
|
"La requête de recherche ne peut pas être vide",
|
|
|
|
|
));
|
P0: stabilisation backend/chat/stream + nouvelle base migrations v1
Backend Go:
- Remplacement complet des anciennes migrations par la base V1 alignée sur ORIGIN.
- Durcissement global du parsing JSON (BindAndValidateJSON + RespondWithAppError).
- Sécurisation de config.go, CORS, statuts de santé et monitoring.
- Implémentation des transactions P0 (RBAC, duplication de playlists, social toggles).
- Ajout d’un job worker structuré (emails, analytics, thumbnails) + tests associés.
- Nouvelle doc backend : AUDIT_CONFIG, BACKEND_CONFIG, AUTH_PASSWORD_RESET, JOB_WORKER_*.
Chat server (Rust):
- Refonte du pipeline JWT + sécurité, audit et rate limiting avancé.
- Implémentation complète du cycle de message (read receipts, delivered, edit/delete, typing).
- Nettoyage des panics, gestion d’erreurs robuste, logs structurés.
- Migrations chat alignées sur le schéma UUID et nouvelles features.
Stream server (Rust):
- Refonte du moteur de streaming (encoding pipeline + HLS) et des modules core.
- Transactions P0 pour les jobs et segments, garanties d’atomicité.
- Documentation détaillée de la pipeline (AUDIT_STREAM_*, DESIGN_STREAM_PIPELINE, TRANSACTIONS_P0_IMPLEMENTATION).
Documentation & audits:
- TRIAGE.md et AUDIT_STABILITY.md à jour avec l’état réel des 3 services.
- Cartographie complète des migrations et des transactions (DB_MIGRATIONS_*, DB_TRANSACTION_PLAN, AUDIT_DB_TRANSACTIONS, TRANSACTION_TESTS_PHASE3).
- Scripts de reset et de cleanup pour la lab DB et la V1.
Ce commit fige l’ensemble du travail de stabilisation P0 (UUID, backend, chat et stream) avant les phases suivantes (Coherence Guardian, WS hardening, etc.).
2025-12-06 10:14:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Rechercher les messages
|
|
|
|
|
let limit = limit.unwrap_or(50).min(100);
|
|
|
|
|
let offset = offset.unwrap_or(0);
|
|
|
|
|
let (messages, total) = state
|
|
|
|
|
.message_repo
|
|
|
|
|
.search_messages(conversation_id, &query, limit, offset, false)
|
|
|
|
|
.await
|
|
|
|
|
.map_err(|e| {
|
2025-12-06 16:21:59 +00:00
|
|
|
ChatError::internal_error(format!("Erreur lors de la recherche: {}", e))
|
P0: stabilisation backend/chat/stream + nouvelle base migrations v1
Backend Go:
- Remplacement complet des anciennes migrations par la base V1 alignée sur ORIGIN.
- Durcissement global du parsing JSON (BindAndValidateJSON + RespondWithAppError).
- Sécurisation de config.go, CORS, statuts de santé et monitoring.
- Implémentation des transactions P0 (RBAC, duplication de playlists, social toggles).
- Ajout d’un job worker structuré (emails, analytics, thumbnails) + tests associés.
- Nouvelle doc backend : AUDIT_CONFIG, BACKEND_CONFIG, AUTH_PASSWORD_RESET, JOB_WORKER_*.
Chat server (Rust):
- Refonte du pipeline JWT + sécurité, audit et rate limiting avancé.
- Implémentation complète du cycle de message (read receipts, delivered, edit/delete, typing).
- Nettoyage des panics, gestion d’erreurs robuste, logs structurés.
- Migrations chat alignées sur le schéma UUID et nouvelles features.
Stream server (Rust):
- Refonte du moteur de streaming (encoding pipeline + HLS) et des modules core.
- Transactions P0 pour les jobs et segments, garanties d’atomicité.
- Documentation détaillée de la pipeline (AUDIT_STREAM_*, DESIGN_STREAM_PIPELINE, TRANSACTIONS_P0_IMPLEMENTATION).
Documentation & audits:
- TRIAGE.md et AUDIT_STABILITY.md à jour avec l’état réel des 3 services.
- Cartographie complète des migrations et des transactions (DB_MIGRATIONS_*, DB_TRANSACTION_PLAN, AUDIT_DB_TRANSACTIONS, TRANSACTION_TESTS_PHASE3).
- Scripts de reset et de cleanup pour la lab DB et la V1.
Ce commit fige l’ensemble du travail de stabilisation P0 (UUID, backend, chat et stream) avant les phases suivantes (Coherence Guardian, WS hardening, etc.).
2025-12-06 10:14:38 +00:00
|
|
|
})?;
|
|
|
|
|
|
|
|
|
|
// Envoyer les résultats
|
|
|
|
|
let search_results = OutgoingMessage::SearchResults {
|
|
|
|
|
conversation_id,
|
|
|
|
|
messages,
|
|
|
|
|
query: query.clone(),
|
|
|
|
|
total,
|
|
|
|
|
};
|
|
|
|
|
client.send_message(search_results).await?;
|
|
|
|
|
|
|
|
|
|
info!(
|
|
|
|
|
"✅ Recherche terminée pour '{}' dans {} ({} résultats)",
|
|
|
|
|
query, conversation_id, total
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
IncomingMessage::SyncMessages {
|
|
|
|
|
conversation_id,
|
|
|
|
|
since,
|
|
|
|
|
} => {
|
|
|
|
|
info!(
|
|
|
|
|
"🔄 Client {} ({}) synchronise la conversation {} depuis {}",
|
|
|
|
|
client.id, claims.username, conversation_id, since
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
// Parser l'user_id depuis les claims JWT
|
|
|
|
|
let user_uuid = Uuid::parse_str(&claims.user_id)
|
|
|
|
|
.map_err(|e| ChatError::validation_error(&format!("Invalid user UUID: {}", e)))?;
|
|
|
|
|
|
|
|
|
|
// Vérifier les permissions pour synchroniser
|
|
|
|
|
state
|
|
|
|
|
.permission_service
|
|
|
|
|
.can_read_conversation(user_uuid, conversation_id)
|
|
|
|
|
.await
|
|
|
|
|
.map_err(|e| {
|
|
|
|
|
warn!(
|
|
|
|
|
user_id = %user_uuid,
|
|
|
|
|
conversation_id = %conversation_id,
|
|
|
|
|
error = %e,
|
|
|
|
|
"Permission refusée pour synchroniser"
|
|
|
|
|
);
|
|
|
|
|
e
|
|
|
|
|
})?;
|
|
|
|
|
|
|
|
|
|
// Récupérer les messages depuis since
|
|
|
|
|
let messages = state
|
|
|
|
|
.message_repo
|
|
|
|
|
.fetch_since(conversation_id, since)
|
|
|
|
|
.await
|
|
|
|
|
.map_err(|e| {
|
2025-12-06 16:21:59 +00:00
|
|
|
ChatError::internal_error(format!("Erreur lors de la synchronisation: {}", e))
|
P0: stabilisation backend/chat/stream + nouvelle base migrations v1
Backend Go:
- Remplacement complet des anciennes migrations par la base V1 alignée sur ORIGIN.
- Durcissement global du parsing JSON (BindAndValidateJSON + RespondWithAppError).
- Sécurisation de config.go, CORS, statuts de santé et monitoring.
- Implémentation des transactions P0 (RBAC, duplication de playlists, social toggles).
- Ajout d’un job worker structuré (emails, analytics, thumbnails) + tests associés.
- Nouvelle doc backend : AUDIT_CONFIG, BACKEND_CONFIG, AUTH_PASSWORD_RESET, JOB_WORKER_*.
Chat server (Rust):
- Refonte du pipeline JWT + sécurité, audit et rate limiting avancé.
- Implémentation complète du cycle de message (read receipts, delivered, edit/delete, typing).
- Nettoyage des panics, gestion d’erreurs robuste, logs structurés.
- Migrations chat alignées sur le schéma UUID et nouvelles features.
Stream server (Rust):
- Refonte du moteur de streaming (encoding pipeline + HLS) et des modules core.
- Transactions P0 pour les jobs et segments, garanties d’atomicité.
- Documentation détaillée de la pipeline (AUDIT_STREAM_*, DESIGN_STREAM_PIPELINE, TRANSACTIONS_P0_IMPLEMENTATION).
Documentation & audits:
- TRIAGE.md et AUDIT_STABILITY.md à jour avec l’état réel des 3 services.
- Cartographie complète des migrations et des transactions (DB_MIGRATIONS_*, DB_TRANSACTION_PLAN, AUDIT_DB_TRANSACTIONS, TRANSACTION_TESTS_PHASE3).
- Scripts de reset et de cleanup pour la lab DB et la V1.
Ce commit fige l’ensemble du travail de stabilisation P0 (UUID, backend, chat et stream) avant les phases suivantes (Coherence Guardian, WS hardening, etc.).
2025-12-06 10:14:38 +00:00
|
|
|
})?;
|
|
|
|
|
|
|
|
|
|
// Calculer le dernier timestamp de sync (maintenant)
|
|
|
|
|
let last_sync = chrono::Utc::now();
|
|
|
|
|
|
|
|
|
|
// Envoyer le chunk de synchronisation
|
|
|
|
|
let message_count = messages.len();
|
|
|
|
|
let sync_chunk = OutgoingMessage::SyncChunk {
|
|
|
|
|
conversation_id,
|
|
|
|
|
messages,
|
|
|
|
|
last_sync,
|
|
|
|
|
};
|
|
|
|
|
client.send_message(sync_chunk).await?;
|
|
|
|
|
|
|
|
|
|
info!(
|
|
|
|
|
"✅ Synchronisation terminée pour {} ({} messages)",
|
|
|
|
|
conversation_id, message_count
|
|
|
|
|
);
|
2025-12-03 19:33:26 +00:00
|
|
|
}
|
2026-02-22 02:42:47 +00:00
|
|
|
IncomingMessage::CallOffer {
|
|
|
|
|
conversation_id,
|
|
|
|
|
target_user_id,
|
|
|
|
|
sdp,
|
|
|
|
|
call_type,
|
|
|
|
|
} => {
|
|
|
|
|
let sender_uuid = Uuid::parse_str(&claims.user_id)
|
|
|
|
|
.map_err(|e| ChatError::validation_error(&format!("Invalid user UUID: {}", e)))?;
|
|
|
|
|
state
|
|
|
|
|
.permission_service
|
|
|
|
|
.can_send_message(sender_uuid, conversation_id)
|
|
|
|
|
.await
|
|
|
|
|
.map_err(|e| {
|
|
|
|
|
warn!(
|
|
|
|
|
user_id = %sender_uuid,
|
|
|
|
|
conversation_id = %conversation_id,
|
|
|
|
|
error = %e,
|
|
|
|
|
"Permission refusée pour CallOffer"
|
|
|
|
|
);
|
|
|
|
|
e
|
|
|
|
|
})?;
|
|
|
|
|
let msg = OutgoingMessage::CallOffer {
|
|
|
|
|
conversation_id,
|
|
|
|
|
caller_user_id: sender_uuid,
|
|
|
|
|
sdp: sdp.clone(),
|
|
|
|
|
call_type: call_type.clone(),
|
|
|
|
|
};
|
|
|
|
|
state
|
|
|
|
|
.ws_manager
|
|
|
|
|
.send_to_user(&target_user_id.to_string(), msg, Some(client.id))
|
|
|
|
|
.await?;
|
|
|
|
|
info!(
|
|
|
|
|
"📞 CallOffer relayé de {} vers {} (conversation: {})",
|
|
|
|
|
claims.username, target_user_id, conversation_id
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
IncomingMessage::CallAnswer {
|
|
|
|
|
conversation_id,
|
|
|
|
|
caller_user_id,
|
|
|
|
|
sdp,
|
|
|
|
|
} => {
|
2026-02-22 02:46:10 +00:00
|
|
|
let callee_uuid = Uuid::parse_str(&claims.user_id)
|
|
|
|
|
.map_err(|e| ChatError::validation_error(&format!("Invalid user UUID: {}", e)))?;
|
2026-02-22 02:42:47 +00:00
|
|
|
let msg = OutgoingMessage::CallAnswer {
|
|
|
|
|
conversation_id,
|
|
|
|
|
target_user_id: caller_user_id,
|
2026-02-22 02:46:10 +00:00
|
|
|
from_user_id: callee_uuid,
|
2026-02-22 02:42:47 +00:00
|
|
|
sdp: sdp.clone(),
|
|
|
|
|
};
|
|
|
|
|
state
|
|
|
|
|
.ws_manager
|
|
|
|
|
.send_to_user(&caller_user_id.to_string(), msg, Some(client.id))
|
|
|
|
|
.await?;
|
|
|
|
|
info!(
|
|
|
|
|
"📞 CallAnswer relayé vers {} (conversation: {})",
|
|
|
|
|
caller_user_id, conversation_id
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
IncomingMessage::ICECandidate {
|
|
|
|
|
conversation_id,
|
|
|
|
|
target_user_id,
|
|
|
|
|
candidate,
|
|
|
|
|
} => {
|
|
|
|
|
let sender_uuid = Uuid::parse_str(&claims.user_id)
|
|
|
|
|
.map_err(|e| ChatError::validation_error(&format!("Invalid user UUID: {}", e)))?;
|
|
|
|
|
let msg = OutgoingMessage::ICECandidate {
|
|
|
|
|
conversation_id,
|
|
|
|
|
from_user_id: sender_uuid,
|
|
|
|
|
candidate: candidate.clone(),
|
|
|
|
|
};
|
|
|
|
|
state
|
|
|
|
|
.ws_manager
|
|
|
|
|
.send_to_user(&target_user_id.to_string(), msg, Some(client.id))
|
|
|
|
|
.await?;
|
|
|
|
|
debug!(
|
|
|
|
|
"📞 ICECandidate relayé de {} vers {} (conversation: {})",
|
|
|
|
|
claims.username, target_user_id, conversation_id
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
IncomingMessage::CallHangup {
|
|
|
|
|
conversation_id,
|
|
|
|
|
target_user_id,
|
|
|
|
|
} => {
|
|
|
|
|
let sender_uuid = Uuid::parse_str(&claims.user_id)
|
|
|
|
|
.map_err(|e| ChatError::validation_error(&format!("Invalid user UUID: {}", e)))?;
|
|
|
|
|
let msg = OutgoingMessage::CallHangup {
|
|
|
|
|
conversation_id,
|
|
|
|
|
user_id: sender_uuid,
|
|
|
|
|
};
|
|
|
|
|
state
|
|
|
|
|
.ws_manager
|
|
|
|
|
.send_to_user(&target_user_id.to_string(), msg, Some(client.id))
|
|
|
|
|
.await?;
|
|
|
|
|
info!(
|
|
|
|
|
"📞 CallHangup relayé de {} vers {} (conversation: {})",
|
|
|
|
|
claims.username, target_user_id, conversation_id
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
IncomingMessage::CallReject {
|
|
|
|
|
conversation_id,
|
|
|
|
|
caller_user_id,
|
|
|
|
|
} => {
|
|
|
|
|
let sender_uuid = Uuid::parse_str(&claims.user_id)
|
|
|
|
|
.map_err(|e| ChatError::validation_error(&format!("Invalid user UUID: {}", e)))?;
|
|
|
|
|
let msg = OutgoingMessage::CallRejected {
|
|
|
|
|
conversation_id,
|
|
|
|
|
user_id: sender_uuid,
|
|
|
|
|
};
|
|
|
|
|
state
|
|
|
|
|
.ws_manager
|
|
|
|
|
.send_to_user(&caller_user_id.to_string(), msg, Some(client.id))
|
|
|
|
|
.await?;
|
|
|
|
|
info!(
|
|
|
|
|
"📞 CallReject relayé vers {} (conversation: {})",
|
|
|
|
|
caller_user_id, conversation_id
|
|
|
|
|
);
|
|
|
|
|
}
|
2025-12-03 19:33:26 +00:00
|
|
|
IncomingMessage::Ping => {
|
|
|
|
|
debug!("🏓 Ping WebSocket reçu");
|
|
|
|
|
client.send_message(OutgoingMessage::Pong).await?;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Ok(true) // Continuer la connexion
|
|
|
|
|
}
|