Files
geo/api/docs/CHAT_MODULE.md
Pierre 3443277d4a feat: Release version 3.1.4 - Mode terrain et génération PDF
 Nouvelles fonctionnalités:
- Ajout du mode terrain pour utilisation mobile hors connexion
- Génération automatique de reçus PDF avec template personnalisé
- Révision complète du système de cartes avec amélioration des performances

🔧 Améliorations techniques:
- Refactoring du module chat avec architecture simplifiée
- Optimisation du système de sécurité NIST SP 800-63B
- Amélioration de la gestion des secteurs géographiques
- Support UTF-8 étendu pour les noms d'utilisateurs

📱 Application mobile:
- Nouveau mode terrain dans user_field_mode_page
- Interface utilisateur adaptative pour conditions difficiles
- Synchronisation offline améliorée

🗺️ Cartographie:
- Optimisation des performances MapBox
- Meilleure gestion des tuiles hors ligne
- Amélioration de l'affichage des secteurs

📄 Documentation:
- Ajout guide Android (ANDROID-GUIDE.md)
- Documentation sécurité API (API-SECURITY.md)
- Guide module chat (CHAT_MODULE.md)

🐛 Corrections:
- Résolution des erreurs 400 lors de la création d'utilisateurs
- Correction de la validation des noms d'utilisateurs
- Fix des problèmes de synchronisation chat

🤖 Generated with Claude Code (https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-08-19 19:38:03 +02:00

10 KiB

Module Chat - Documentation API

Vue d'ensemble

Le module Chat permet aux utilisateurs de l'application GeoSector de communiquer entre eux via une messagerie intégrée. Il supporte les conversations privées, de groupe et les diffusions (broadcast).

Architecture

Tables de base de données

  • chat_rooms : Salles de conversation
  • chat_messages : Messages échangés
  • chat_participants : Participants aux conversations
  • chat_read_receipts : Accusés de lecture

Permissions par rôle

Rôle Permissions
1 - Utilisateur Conversations privées et groupes avec membres de son entité
2 - Admin entité Toutes conversations de son entité + création de diffusions
> 2 - Super admin Accès total à toutes les conversations

Flux d'utilisation du module Chat

📱 Vue d'ensemble du flux

Le module Chat fonctionne en mode chargement dynamique : les données sont récupérées à la demande, pas toutes en une fois au login.

1. Au login (/api/login)

La réponse du login contient un objet chat avec les informations de base :

{
  "status": "success",
  "user": {...},
  "amicale": {...},
  "chat": {
    "total_rooms": 5,           // Nombre total de conversations
    "unread_messages": 12,       // Total messages non lus
    "chat_enabled": true,        // Module activé pour cet utilisateur
    "last_active_room": {        // Dernière conversation active
      "id": "uuid-room-123",
      "title": "Discussion équipe",
      "type": "group",
      "last_message": "À demain !",
      "last_message_at": "2025-01-17 18:30:00"
    }
  }
}

→ Permet d'afficher un badge de notification et de savoir si le chat est disponible

2. Ouverture de la page Chat

Étape 1 : Chargement initial

GET /api/chat/rooms

→ Récupère la liste des conversations avec aperçu du dernier message

Étape 2 : Sélection d'une conversation

GET /api/chat/rooms/{room_id}/messages?limit=50

→ Charge les 50 derniers messages (pagination disponible)

Étape 3 : Marquage comme lu

POST /api/chat/rooms/{room_id}/read

→ Met à jour les compteurs de messages non lus

3. Actions utilisateur

Action Endpoint Description
Envoyer un message POST /api/chat/rooms/{id}/messages Envoie et retourne le message créé
Créer une conversation POST /api/chat/rooms Crée une nouvelle room
Obtenir les destinataires GET /api/chat/recipients Liste des contacts disponibles
Charger plus de messages GET /api/chat/rooms/{id}/messages?before={msg_id} Pagination

4. Stratégies de rafraîchissement

Polling (recommandé pour débuter)

  • Rafraîchir /api/chat/rooms toutes les 30 secondes
  • Rafraîchir les messages de la conversation active toutes les 10 secondes

Pull to refresh

  • Permettre à l'utilisateur de rafraîchir manuellement

Lifecycle events

  • Recharger quand l'app revient au premier plan
  • Rafraîchir après envoi d'un message

5. Exemple d'implémentation Flutter

class ChatService {
  Timer? _roomsTimer;
  Timer? _messagesTimer;
  
  // 1. Au login, stocker les infos de base
  void initFromLogin(Map<String, dynamic> chatData) {
    _unreadCount = chatData['unread_messages'];
    _chatEnabled = chatData['chat_enabled'];
    notifyListeners();
  }
  
  // 2. À l'ouverture du chat
  Future<void> openChatPage() async {
    // Charger les conversations
    final rooms = await api.get('/api/chat/rooms');
    _rooms = rooms['rooms'];
    
    // Démarrer le polling
    _startPolling();
  }
  
  // 3. Sélection d'une conversation
  Future<void> selectRoom(String roomId) async {
    // Charger les messages
    final response = await api.get('/api/chat/rooms/$roomId/messages');
    _currentMessages = response['messages'];
    
    // Marquer comme lu
    await api.post('/api/chat/rooms/$roomId/read');
    
    // Rafraîchir plus fréquemment cette conversation
    _startMessagePolling(roomId);
  }
  
  // 4. Polling automatique
  void _startPolling() {
    _roomsTimer = Timer.periodic(Duration(seconds: 30), (_) {
      _refreshRooms();
    });
  }
  
  // 5. Nettoyage
  void dispose() {
    _roomsTimer?.cancel();
    _messagesTimer?.cancel();
  }
}

Endpoints API

1. GET /api/chat/rooms

Description : Récupère la liste des conversations de l'utilisateur

Réponse :

{
  "status": "success",
  "rooms": [
    {
      "id": "uuid-room-1",
      "title": "Discussion équipe",
      "type": "group",
      "created_at": "2025-01-17 10:00:00",
      "created_by": 123,
      "updated_at": "2025-01-17 14:30:00",
      "last_message": "Bonjour tout le monde",
      "last_message_at": "2025-01-17 14:30:00",
      "unread_count": 3,
      "participant_count": 5,
      "participants": [
        {
          "user_id": 123,
          "name": "Jean Dupont",
          "first_name": "Jean",
          "is_admin": true
        }
      ]
    }
  ]
}

2. POST /api/chat/rooms

Description : Crée une nouvelle conversation

Body :

{
  "type": "private|group|broadcast",
  "title": "Titre optionnel (requis pour group/broadcast)",
  "participants": [456, 789],  // IDs des participants
  "initial_message": "Message initial optionnel"
}

Règles :

  • private : Maximum 2 participants (incluant le créateur)
  • group : Plusieurs participants possibles
  • broadcast : Réservé aux admins (rôle >= 2)

Réponse :

{
  "status": "success",
  "room": {
    "id": "uuid-new-room",
    "title": "Nouvelle conversation",
    "type": "group",
    "created_at": "2025-01-17 15:00:00",
    "participants": [...]
  },
  "existing": false  // true si conversation privée existante trouvée
}

3. GET /api/chat/rooms/{id}/messages

Description : Récupère les messages d'une conversation

Paramètres :

  • limit : Nombre de messages (défaut: 50, max: 100)
  • before : ID du message pour pagination

Réponse :

{
  "status": "success",
  "messages": [
    {
      "id": "uuid-message-1",
      "content": "Bonjour !",
      "sender_id": 123,
      "sender_name": "Jean Dupont",
      "sender_first_name": "Jean",
      "sent_at": "2025-01-17 14:00:00",
      "edited_at": null,
      "is_deleted": false,
      "is_read": true,
      "is_mine": false,
      "read_count": 3
    }
  ],
  "has_more": true
}

4. POST /api/chat/rooms/{id}/messages

Description : Envoie un message dans une conversation

Body :

{
  "content": "Contenu du message (max 5000 caractères)"
}

Réponse :

{
  "status": "success",
  "message": {
    "id": "uuid-new-message",
    "content": "Message envoyé",
    "sender_id": 123,
    "sender_name": "Jean Dupont",
    "sent_at": "2025-01-17 15:30:00",
    "is_mine": true,
    "is_read": false,
    "read_count": 0
  }
}

5. POST /api/chat/rooms/{id}/read

Description : Marque les messages comme lus

Body (optionnel) :

{
  "message_ids": ["uuid-1", "uuid-2"]  // Si omis, marque tous les messages
}

Réponse :

{
  "status": "success",
  "unread_count": 0  // Nombre de messages non lus restants
}

6. GET /api/chat/recipients

Description : Liste des destinataires possibles pour créer une conversation

Réponse :

{
  "status": "success",
  "recipients": [
    {
      "id": 456,
      "name": "Marie Martin",
      "first_name": "Marie",
      "role": 1,
      "entite_id": 5
    }
  ],
  "recipients_by_entity": {
    "Amicale de Grenoble": [
      {...}
    ],
    "Amicale de Lyon": [
      {...}
    ]
  }
}

Fonctionnalités clés

1. Types de conversations

Private (Conversation privée)

  • Entre 2 utilisateurs uniquement
  • Détection automatique de conversation existante
  • Pas de titre requis

Group (Groupe)

  • Plusieurs participants
  • Titre optionnel mais recommandé
  • Admin de groupe (créateur)

Broadcast (Diffusion)

  • Réservé aux admins (rôle >= 2)
  • Communication unidirectionnelle possible
  • Pour annonces importantes

2. Gestion des permissions

Le système vérifie automatiquement :

  • L'appartenance à une conversation avant lecture/écriture
  • Les droits de création selon le type de conversation
  • La visibilité des destinataires selon le rôle

3. Statuts de lecture

  • Accusés de lecture individuels : Chaque message peut être marqué comme lu
  • Compteur de non-lus : Par conversation et global
  • Last read : Timestamp de dernière lecture par participant

4. Optimisations

  • Pagination : Chargement progressif des messages
  • Index optimisés : Pour les requêtes fréquentes
  • Vue SQL : Pour récupération rapide du dernier message

Sécurité

Chiffrement

  • Les noms d'utilisateurs sont stockés chiffrés (AES-256)
  • Déchiffrement à la volée lors de la lecture

Validation

  • Longueur maximale des messages : 5000 caractères
  • Trim automatique du contenu
  • Vérification des permissions à chaque action

Isolation

  • Les utilisateurs ne voient que leurs conversations autorisées
  • Filtrage par entité selon le rôle
  • Soft delete pour conservation de l'historique

Migration

Exécuter le script SQL :

mysql -u root -p geo_app < scripts/sql/create_chat_tables.sql

Évolutions futures possibles

  1. Notifications push : Intégration avec Firebase/WebSocket
  2. Fichiers joints : Support d'images et documents
  3. Réactions : Emojis sur les messages
  4. Mentions : @username pour notifier
  5. Recherche : Dans l'historique des messages
  6. Chiffrement E2E : Pour conversations sensibles
  7. Statuts de présence : En ligne/Hors ligne
  8. Indicateur de frappe : "X est en train d'écrire..."

Tests

Cas de test recommandés

  1. Création de conversation privée

    • Vérifier la détection de conversation existante
    • Tester avec utilisateurs de différentes entités
  2. Envoi de messages

    • Messages avec caractères UTF-8 (émojis, accents)
    • Messages très longs (limite 5000)
    • Messages vides (doivent être rejetés)
  3. Marquage comme lu

    • Marquer messages spécifiques
    • Marquer tous les messages d'une room
    • Vérifier les compteurs
  4. Permissions

    • Utilisateur simple ne peut pas créer de broadcast
    • Accès refusé aux conversations non autorisées
    • Filtrage correct des destinataires

Support

Pour toute question ou problème :

  • Vérifier les logs dans /logs/
  • Consulter les tables chat_* en base de données
  • Tester avec les scripts de test fournis