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.).
12 KiB
Documentation : Édition et Suppression de Messages
Date de création : 2025-12-05
Version : 1.0.0
Statut : ✅ Implémenté
Vue d'ensemble
Ce document décrit l'implémentation complète de l'édition et de la suppression (soft delete) de messages dans le serveur de chat Veza. Ces fonctionnalités sont essentielles pour un système de chat moderne et respectent les meilleures pratiques de sécurité, permissions et cohérence temps réel.
Table des matières
- Architecture
- Événements WebSocket
- Permissions
- Base de données
- Services
- Exemples d'utilisation
- Conséquences UX
- Impact sur la recherche et pagination
Architecture
Composants principaux
-
Migration SQL (
migrations/005_message_edit_delete.sql)- Ajoute
deleted_atpour la traçabilité - Index pour les requêtes de nettoyage
- Ajoute
-
PermissionService (
src/security/permission.rs)can_edit_message(): Vérifie les permissions d'éditioncan_delete_message(): Vérifie les permissions de suppression
-
MessageEditService (
src/services/message_edit_service.rs)edit_message(): Édite un message avec validationdelete_message(): Supprime un message (soft delete)
-
MessageRepository (
src/repository/message_repository.rs)update(): Met à jour le contenu d'un messagedelete(): Marque un message comme suppriméget_by_id_including_deleted(): Récupère même les messages supprimés
-
WebSocket Handlers (
src/websocket/handler.rs)- Gère les événements
EditMessageetDeleteMessage - Broadcast les événements
MessageEditedetMessageDeleted
- Gère les événements
Événements WebSocket
Inbound Events (Client → Serveur)
EditMessage
Édite un message existant.
{
"type": "EditMessage",
"message_id": "550e8400-e29b-41d4-a716-446655440000",
"conversation_id": "660e8400-e29b-41d4-a716-446655440000",
"new_content": "Nouveau contenu du message"
}
Règles de validation :
new_contentdoit être différent du contenu précédentnew_contentne peut pas être vide (après trim)new_contentne peut pas dépasser 4000 caractères- Le message ne doit pas être supprimé
- L'utilisateur doit avoir les permissions d'édition
DeleteMessage
Supprime un message (soft delete).
{
"type": "DeleteMessage",
"message_id": "550e8400-e29b-41d4-a716-446655440000",
"conversation_id": "660e8400-e29b-41d4-a716-446655440000"
}
Règles de validation :
- L'utilisateur doit avoir les permissions de suppression
- L'opération est idempotente (supprimer un message déjà supprimé retourne OK)
Outbound Events (Serveur → Client)
MessageEdited
Notifie tous les clients d'une conversation qu'un message a été édité.
{
"type": "MessageEdited",
"message_id": "550e8400-e29b-41d4-a716-446655440000",
"conversation_id": "660e8400-e29b-41d4-a716-446655440000",
"editor_id": "770e8400-e29b-41d4-a716-446655440000",
"edited_at": "2025-12-05T10:30:00Z",
"new_content": "Nouveau contenu du message"
}
MessageDeleted
Notifie tous les clients d'une conversation qu'un message a été supprimé.
{
"type": "MessageDeleted",
"message_id": "550e8400-e29b-41d4-a716-446655440000",
"conversation_id": "660e8400-e29b-41d4-a716-446655440000",
"deleter_id": "770e8400-e29b-41d4-a716-446655440000",
"deleted_at": "2025-12-05T10:30:00Z"
}
Permissions
Règles d'édition
Un utilisateur peut éditer un message si :
- Il est l'auteur du message : L'auteur peut toujours éditer son propre message
- Il est admin/modérateur de la conversation : Les admins et modérateurs peuvent éditer n'importe quel message dans leur conversation
- Le message n'est pas supprimé : Un message supprimé ne peut jamais être édité
Règles de suppression
Un utilisateur peut supprimer un message si :
- Il est l'auteur du message : L'auteur peut toujours supprimer son propre message
- Il est admin/modérateur de la conversation : Les admins et modérateurs peuvent supprimer n'importe quel message dans leur conversation
Limitations de temps
Actuellement, il n'y a pas de limitation de temps pour l'édition ou la suppression. Un message peut être édité ou supprimé à tout moment tant que les permissions sont respectées.
Note : Pour une implémentation future, on pourrait ajouter :
- Fenêtre d'édition limitée (ex: 15 minutes après l'envoi)
- Fenêtre de suppression limitée (ex: 5 minutes après l'envoi)
Base de données
Schéma
La table messages contient les colonnes suivantes pour l'édition et la suppression :
CREATE TABLE messages (
id UUID PRIMARY KEY,
conversation_id UUID NOT NULL,
sender_id UUID NOT NULL,
content TEXT NOT NULL,
-- ... autres colonnes ...
is_edited BOOLEAN NOT NULL DEFAULT FALSE,
is_deleted BOOLEAN NOT NULL DEFAULT FALSE,
edited_at TIMESTAMPTZ,
deleted_at TIMESTAMPTZ,
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
Migration
La migration 005_message_edit_delete.sql ajoute :
deleted_at: Timestamp de suppression (pour la traçabilité)- Index sur
deleted_atpour les requêtes de nettoyage - Index sur
edited_atpour les requêtes de recherche
Soft Delete
Les messages ne sont jamais supprimés physiquement de la base de données. Au lieu de cela :
is_deletedest mis àtruedeleted_atest mis àNOW()- Le contenu reste dans la base de données (pour audit futur)
Note : Pour une implémentation future, on pourrait :
- Créer une table
message_archivepour stocker les messages supprimés - Vider le contenu du message après suppression (mettre
contentàNULLou"")
Services
MessageEditService
Service centralisé pour l'édition et la suppression de messages.
edit_message(user_id, message_id, new_content) -> Result<Message>
Édite un message avec validation complète.
Validation :
- Contenu non vide (après trim)
- Longueur maximale (4000 caractères)
- Contenu différent de l'original
- Message non supprimé
- Permissions d'édition
Mise à jour DB :
content= nouveau contenuis_edited=trueedited_at=NOW()updated_at=NOW()
delete_message(user_id, message_id) -> Result<Message>
Supprime un message (soft delete).
Validation :
- Permissions de suppression
Mise à jour DB :
is_deleted=truedeleted_at=NOW()updated_at=NOW()
Idempotence : Si le message est déjà supprimé, retourne le message tel quel sans erreur.
Exemples d'utilisation
Édition d'un message
Client :
{
"type": "EditMessage",
"message_id": "550e8400-e29b-41d4-a716-446655440000",
"conversation_id": "660e8400-e29b-41d4-a716-446655440000",
"new_content": "Correction : Nouveau contenu"
}
Réponse (confirmation) :
{
"type": "ActionConfirmed",
"action": "message_edited",
"success": true
}
Broadcast (tous les clients de la conversation) :
{
"type": "MessageEdited",
"message_id": "550e8400-e29b-41d4-a716-446655440000",
"conversation_id": "660e8400-e29b-41d4-a716-446655440000",
"editor_id": "770e8400-e29b-41d4-a716-446655440000",
"edited_at": "2025-12-05T10:30:00Z",
"new_content": "Correction : Nouveau contenu"
}
Suppression d'un message
Client :
{
"type": "DeleteMessage",
"message_id": "550e8400-e29b-41d4-a716-446655440000",
"conversation_id": "660e8400-e29b-41d4-a716-446655440000"
}
Réponse (confirmation) :
{
"type": "ActionConfirmed",
"action": "message_deleted",
"success": true
}
Broadcast (tous les clients de la conversation) :
{
"type": "MessageDeleted",
"message_id": "550e8400-e29b-41d4-a716-446655440000",
"conversation_id": "660e8400-e29b-41d4-a716-446655440000",
"deleter_id": "770e8400-e29b-41d4-a716-446655440000",
"deleted_at": "2025-12-05T10:30:00Z"
}
Gestion des erreurs
Permission refusée :
{
"type": "Error",
"message": "Permissions insuffisantes pour edit_message dans la conversation 660e8400-e29b-41d4-a716-446655440000"
}
Message introuvable :
{
"type": "Error",
"message": "Message 550e8400-e29b-41d4-a716-446655440000 introuvable"
}
Message supprimé (tentative d'édition) :
{
"type": "Error",
"message": "Un message supprimé ne peut pas être édité"
}
Conséquences UX
Affichage des messages édités
Lorsqu'un message est édité, l'interface utilisateur doit :
- Afficher le nouveau contenu : Remplacer l'ancien contenu par le nouveau
- Indicateur visuel : Afficher un indicateur "Édité" (ex: "✏️ Édité")
- Timestamp d'édition : Optionnellement afficher
edited_atau survol - Historique : Pour une implémentation future, on pourrait afficher l'historique des éditions
Exemple d'affichage :
[Utilisateur] Message original ✏️ Édité
Affichage des messages supprimés
Lorsqu'un message est supprimé, l'interface utilisateur doit :
- Placeholder : Afficher un placeholder comme "Message supprimé" ou "Ce message a été supprimé"
- Style visuel : Utiliser un style atténué (gris, italique)
- Informations limitées : Ne pas afficher le contenu original
- Timestamp : Optionnellement afficher
deleted_at
Exemple d'affichage :
[Utilisateur] Ce message a été supprimé
Cohérence multi-device
Les événements WebSocket garantissent que :
- Tous les clients connectés à la conversation reçoivent les mises à jour en temps réel
- Les modifications sont synchronisées instantanément
- Pas besoin de rafraîchir la page
Impact sur la recherche et pagination
Recherche
Les messages supprimés sont exclus des résultats de recherche par défaut.
Requête SQL :
SELECT * FROM messages
WHERE conversation_id = $1
AND is_deleted = false
AND content ILIKE $2
ORDER BY created_at DESC;
Note : Pour une implémentation future, on pourrait :
- Permettre aux admins de rechercher dans les messages supprimés
- Créer une vue
messages_activequi exclut automatiquement les messages supprimés
Pagination
Les messages supprimés sont exclus de la pagination par défaut.
Requête SQL :
SELECT * FROM messages
WHERE conversation_id = $1
AND is_deleted = false
ORDER BY created_at DESC
LIMIT $2 OFFSET $3;
Placeholder dans la liste : Si un message est supprimé pendant qu'un utilisateur consulte l'historique, il peut être remplacé par un placeholder dans la liste.
Impact sur les métriques
- Les messages supprimés ne sont pas comptés dans les statistiques de messages
- Les messages édités sont comptés comme des messages normaux (pas de double comptage)
Tests
Les tests sont disponibles dans tests/chat_edit_delete.rs :
- ✅ Édition par l'auteur
- ✅ Édition interdite pour un non-auteur
- ✅ Édition interdite pour un message supprimé
- ✅ Édition avec contenu identique interdite
- ✅ Édition avec contenu vide interdite
- ✅ Suppression par l'auteur
- ✅ Suppression par un admin
- ✅ Suppression interdite pour un non-auteur
- ✅ Suppression idempotente
- ✅ Validation de la longueur maximale
Note : Les tests nécessitent une base de données de test et sont marqués avec #[ignore].
Améliorations futures
- Limitation de temps : Fenêtre d'édition/suppression limitée
- Historique d'édition : Stocker l'historique des modifications
- Archive de messages : Table séparée pour les messages supprimés
- Raison de suppression : Champ optionnel pour la raison de suppression (modération)
- Recherche dans les supprimés : Permettre aux admins de rechercher dans les messages supprimés
- Notifications : Notifier l'auteur lorsqu'un admin supprime son message
Références
- Migration :
migrations/005_message_edit_delete.sql - Service :
src/services/message_edit_service.rs - Permissions :
src/security/permission.rs - Repository :
src/repository/message_repository.rs - WebSocket :
src/websocket/handler.rs - Tests :
tests/chat_edit_delete.rs