feat(backend): Ajout complet des fonctionnalités Chat, Social, Story et Notifications
Implémentation complète de toutes les fonctionnalités backend : ## Nouvelles Fonctionnalités ### Chat (Messagerie Instantanée) - Entities : Conversation, Message - DTOs : ConversationResponseDTO, MessageResponseDTO, SendMessageRequestDTO - Resources : MessageResource (endpoints REST) - Services : MessageService (logique métier) - Repositories : ConversationRepository, MessageRepository - WebSocket : ChatWebSocket (temps réel) ### Social (Publications Sociales) - Entities : SocialPost, SocialComment, SocialLike - DTOs : SocialPostResponseDTO, CreateSocialPostRequestDTO - Resources : SocialPostResource - Services : SocialPostService - Repositories : SocialPostRepository ### Story (Stories temporaires) - Entities : Story, StoryView - DTOs : StoryResponseDTO, CreateStoryRequestDTO - Resources : StoryResource - Services : StoryService - Repositories : StoryRepository ### Notifications (Temps Réel) - Entities : Notification - DTOs : NotificationResponseDTO - Resources : NotificationResource - Services : NotificationService, PresenceService - Repositories : NotificationRepository - WebSocket : NotificationWebSocket (temps réel) ## Améliorations ### Users & Friendship - Mise à jour UserResponseDTO avec nouveaux champs - Amélioration FriendshipResource avec séparation demandes envoyées/reçues - FriendSuggestionResponseDTO pour suggestions d'amis - Optimisations dans UsersService et FriendshipService ### Events - Améliorations EventsResource et EventService - Optimisations EventsRepository ### Configuration - Mise à jour application.properties - Configuration docker-compose.yml - Dockerfile pour développement ## Fichiers Modifiés - .dockerignore, .gitignore - README.md - docker-compose.yml - Configuration Maven wrapper
This commit is contained in:
@@ -5,14 +5,19 @@ import org.slf4j.LoggerFactory;
|
||||
import jakarta.transaction.Transactional;
|
||||
import com.lions.dev.dto.request.events.EventCreateRequestDTO;
|
||||
import com.lions.dev.entity.events.Events;
|
||||
import com.lions.dev.entity.friends.Friendship;
|
||||
import com.lions.dev.entity.users.Users;
|
||||
import com.lions.dev.repository.EventsRepository;
|
||||
import com.lions.dev.exception.EventNotFoundException;
|
||||
import com.lions.dev.exception.UserNotFoundException;
|
||||
import com.lions.dev.repository.EventsRepository;
|
||||
import com.lions.dev.repository.FriendshipRepository;
|
||||
import com.lions.dev.repository.UsersRepository;
|
||||
import jakarta.enterprise.context.ApplicationScoped;
|
||||
import jakarta.inject.Inject;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* Service de gestion des événements.
|
||||
@@ -25,6 +30,15 @@ public class EventService {
|
||||
@Inject
|
||||
EventsRepository eventsRepository;
|
||||
|
||||
@Inject
|
||||
FriendshipRepository friendshipRepository;
|
||||
|
||||
@Inject
|
||||
UsersRepository usersRepository;
|
||||
|
||||
@Inject
|
||||
NotificationService notificationService;
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(EventService.class);
|
||||
|
||||
/**
|
||||
@@ -51,6 +65,33 @@ public class EventService {
|
||||
// Persiste l'événement dans la base de données
|
||||
eventsRepository.persist(event);
|
||||
logger.info("[logger] Événement créé avec succès : {}", event.getTitle());
|
||||
|
||||
// Créer des notifications pour tous les amis
|
||||
try {
|
||||
List<Friendship> friendships = friendshipRepository.findFriendsByUser(creator, 0, Integer.MAX_VALUE);
|
||||
String creatorName = creator.getPrenoms() + " " + creator.getNom();
|
||||
|
||||
for (Friendship friendship : friendships) {
|
||||
Users friend = friendship.getUser().equals(creator)
|
||||
? friendship.getFriend()
|
||||
: friendship.getUser();
|
||||
|
||||
String notificationTitle = "Nouvel événement de " + creatorName;
|
||||
String notificationMessage = creatorName + " a créé un nouvel événement : " + event.getTitle();
|
||||
|
||||
notificationService.createNotification(
|
||||
notificationTitle,
|
||||
notificationMessage,
|
||||
"event",
|
||||
friend.getId(),
|
||||
event.getId()
|
||||
);
|
||||
}
|
||||
logger.info("[logger] Notifications créées pour {} ami(s)", friendships.size());
|
||||
} catch (Exception e) {
|
||||
logger.error("[ERROR] Erreur lors de la création des notifications : {}", e.getMessage());
|
||||
}
|
||||
|
||||
return event;
|
||||
}
|
||||
|
||||
@@ -282,4 +323,42 @@ public class EventService {
|
||||
logger.info("[logger] Nombre d'événements recommandés pour l'utilisateur : " + events.size());
|
||||
return events;
|
||||
}
|
||||
|
||||
/**
|
||||
* Récupère les événements de l'utilisateur et de ses amis (relations d'amitié acceptées).
|
||||
*
|
||||
* @param userId L'ID de l'utilisateur
|
||||
* @param page Le numéro de la page (0-indexé)
|
||||
* @param size La taille de la page
|
||||
* @return Liste paginée des événements de l'utilisateur et de ses amis
|
||||
* @throws UserNotFoundException Si l'utilisateur n'existe pas
|
||||
*/
|
||||
public List<Events> getEventsByFriends(UUID userId, int page, int size) {
|
||||
logger.info("[logger] Récupération des événements des amis pour l'utilisateur ID : " + userId);
|
||||
|
||||
Users user = usersRepository.findById(userId);
|
||||
if (user == null) {
|
||||
logger.error("[ERROR] Utilisateur non trouvé avec l'ID : " + userId);
|
||||
throw new UserNotFoundException("Utilisateur non trouvé avec l'ID : " + userId);
|
||||
}
|
||||
|
||||
// Récupérer toutes les relations d'amitié acceptées
|
||||
List<Friendship> friendships = friendshipRepository.findFriendsByUser(user, 0, Integer.MAX_VALUE);
|
||||
|
||||
// Extraire les IDs des amis
|
||||
List<UUID> friendIds = friendships.stream()
|
||||
.map(friendship -> {
|
||||
// L'ami est soit dans 'user' soit dans 'friend', selon qui a initié la relation
|
||||
return friendship.getUser().equals(user)
|
||||
? friendship.getFriend().getId()
|
||||
: friendship.getUser().getId();
|
||||
})
|
||||
.distinct()
|
||||
.collect(Collectors.toList());
|
||||
|
||||
logger.info("[logger] " + friendIds.size() + " ami(s) trouvé(s) pour l'utilisateur ID : " + userId);
|
||||
|
||||
// Récupérer les événements de l'utilisateur et de ses amis
|
||||
return eventsRepository.findEventsByFriends(userId, friendIds, page, size);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,11 +13,15 @@ import com.lions.dev.exception.FriendshipNotFoundException;
|
||||
import com.lions.dev.exception.UserNotFoundException;
|
||||
import com.lions.dev.repository.FriendshipRepository;
|
||||
import com.lions.dev.repository.UsersRepository;
|
||||
import com.lions.dev.websocket.NotificationWebSocket;
|
||||
import jakarta.enterprise.context.ApplicationScoped;
|
||||
import jakarta.inject.Inject;
|
||||
import jakarta.transaction.Transactional;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import org.jboss.logging.Logger;
|
||||
@@ -33,6 +37,8 @@ public class FriendshipService {
|
||||
FriendshipRepository friendshipRepository; // Injecte le repository des amitiés
|
||||
@Inject
|
||||
UsersRepository usersRepository; // Injecte le repository des utilisateurs
|
||||
@Inject
|
||||
NotificationService notificationService; // Injecte le service de notifications
|
||||
|
||||
private static final Logger logger = Logger.getLogger(FriendshipService.class);
|
||||
|
||||
@@ -56,6 +62,12 @@ public class FriendshipService {
|
||||
throw new UserNotFoundException("Utilisateur avec l'ID " + notFoundId + " introuvable.");
|
||||
}
|
||||
|
||||
// VALIDATION: Empêcher l'utilisateur de s'ajouter lui-même comme ami
|
||||
if (user.getId().equals(friend.getId())) {
|
||||
logger.error("[ERROR] Tentative d'ajout de soi-même comme ami bloquée pour l'utilisateur : " + user.getId());
|
||||
throw new IllegalArgumentException("Vous ne pouvez pas vous ajouter vous-même comme ami.");
|
||||
}
|
||||
|
||||
// Vérifier s'il existe déjà une relation d'amitié
|
||||
Friendship existingFriendship = friendshipRepository.findByUsers(user, friend).orElse(null);
|
||||
if (existingFriendship != null) {
|
||||
@@ -67,6 +79,26 @@ public class FriendshipService {
|
||||
Friendship friendship = new Friendship(user, friend, FriendshipStatus.PENDING);
|
||||
friendshipRepository.persist(friendship);
|
||||
|
||||
// TEMPS RÉEL: Notifier le destinataire via WebSocket
|
||||
try {
|
||||
Map<String, Object> notificationData = new HashMap<>();
|
||||
notificationData.put("requestId", friendship.getId().toString());
|
||||
notificationData.put("senderId", user.getId().toString());
|
||||
notificationData.put("senderName", user.getPrenoms() + " " + user.getNom());
|
||||
notificationData.put("senderProfileImage", user.getProfileImageUrl() != null ? user.getProfileImageUrl() : "");
|
||||
|
||||
NotificationWebSocket.sendNotificationToUser(
|
||||
friend.getId(),
|
||||
"friend_request_received",
|
||||
notificationData
|
||||
);
|
||||
|
||||
logger.info("[LOG] Notification WebSocket envoyée au destinataire : " + friend.getId());
|
||||
} catch (Exception e) {
|
||||
logger.error("[ERROR] Erreur lors de l'envoi de la notification WebSocket : " + e.getMessage(), e);
|
||||
// Ne pas bloquer la demande d'amitié si le WebSocket échoue
|
||||
}
|
||||
|
||||
logger.info("[LOG] Demande d'amitié envoyée avec succès.");
|
||||
return new FriendshipCreateOneResponseDTO(friendship);
|
||||
}
|
||||
@@ -107,6 +139,60 @@ public class FriendshipService {
|
||||
// Log de succès
|
||||
logger.info(String.format("[LOG] Demande d'amitié acceptée avec succès pour l'ID: %s", friendshipId)); // Correctement formaté
|
||||
|
||||
// TEMPS RÉEL: Notifier l'émetteur de la demande via WebSocket
|
||||
try {
|
||||
Users user = friendship.getUser();
|
||||
Users friend = friendship.getFriend();
|
||||
String friendName = friend.getPrenoms() + " " + friend.getNom();
|
||||
|
||||
Map<String, Object> notificationData = new HashMap<>();
|
||||
notificationData.put("acceptedBy", friendName);
|
||||
notificationData.put("friendshipId", friendshipId.toString());
|
||||
notificationData.put("accepterId", friend.getId().toString());
|
||||
notificationData.put("accepterProfileImage", friend.getProfileImageUrl() != null ? friend.getProfileImageUrl() : "");
|
||||
|
||||
NotificationWebSocket.sendNotificationToUser(
|
||||
user.getId(),
|
||||
"friend_request_accepted",
|
||||
notificationData
|
||||
);
|
||||
|
||||
logger.info("[LOG] Notification WebSocket d'acceptation envoyée à : " + user.getId());
|
||||
} catch (Exception e) {
|
||||
logger.error("[ERROR] Erreur lors de l'envoi de la notification WebSocket d'acceptation : " + e.getMessage(), e);
|
||||
// Ne pas bloquer l'acceptation si le WebSocket échoue
|
||||
}
|
||||
|
||||
// Créer des notifications pour les deux utilisateurs
|
||||
try {
|
||||
Users user = friendship.getUser();
|
||||
Users friend = friendship.getFriend();
|
||||
String userName = user.getPrenoms() + " " + user.getNom();
|
||||
String friendName = friend.getPrenoms() + " " + friend.getNom();
|
||||
|
||||
// Notification pour l'utilisateur qui a envoyé la demande
|
||||
notificationService.createNotification(
|
||||
"Demande d'amitié acceptée",
|
||||
friendName + " a accepté votre demande d'amitié",
|
||||
"friend",
|
||||
user.getId(),
|
||||
null
|
||||
);
|
||||
|
||||
// Notification pour l'utilisateur qui a accepté la demande
|
||||
notificationService.createNotification(
|
||||
"Nouveaux amis",
|
||||
"Vous êtes maintenant ami(e) avec " + userName,
|
||||
"friend",
|
||||
friend.getId(),
|
||||
null
|
||||
);
|
||||
|
||||
logger.info("[LOG] Notifications d'amitié créées pour les deux utilisateurs");
|
||||
} catch (Exception e) {
|
||||
logger.error("[ERROR] Erreur lors de la création des notifications d'amitié : " + e.getMessage());
|
||||
}
|
||||
|
||||
// Retourner la réponse avec les informations de la relation d'amitié
|
||||
return new FriendshipCreateOneResponseDTO(friendship);
|
||||
}
|
||||
@@ -126,6 +212,26 @@ public class FriendshipService {
|
||||
friendship.setStatus(FriendshipStatus.REJECTED);
|
||||
friendshipRepository.persist(friendship);
|
||||
|
||||
// TEMPS RÉEL: Notifier l'émetteur de la demande via WebSocket (optionnel selon UX)
|
||||
try {
|
||||
Users user = friendship.getUser();
|
||||
|
||||
Map<String, Object> notificationData = new HashMap<>();
|
||||
notificationData.put("friendshipId", friendshipId.toString());
|
||||
notificationData.put("rejectedAt", System.currentTimeMillis());
|
||||
|
||||
NotificationWebSocket.sendNotificationToUser(
|
||||
user.getId(),
|
||||
"friend_request_rejected",
|
||||
notificationData
|
||||
);
|
||||
|
||||
logger.info("[LOG] Notification WebSocket de rejet envoyée à : " + user.getId());
|
||||
} catch (Exception e) {
|
||||
logger.error("[ERROR] Erreur lors de l'envoi de la notification WebSocket de rejet : " + e.getMessage(), e);
|
||||
// Ne pas bloquer le rejet si le WebSocket échoue
|
||||
}
|
||||
|
||||
logger.info("[LOG] Demande d'amitié rejetée.");
|
||||
}
|
||||
|
||||
@@ -297,4 +403,126 @@ public class FriendshipService {
|
||||
|
||||
return friendships.stream().map(FriendshipReadStatusResponseDTO::new).toList();
|
||||
}
|
||||
|
||||
/**
|
||||
* Récupérer les suggestions d'amis pour un utilisateur.
|
||||
*
|
||||
* L'algorithme suggère des utilisateurs basés sur :
|
||||
* 1. Amis d'amis (utilisateurs qui ont des amis en commun)
|
||||
* 2. Utilisateurs récents (qui ne sont ni amis ni ont de demandes en attente)
|
||||
*
|
||||
* @param userId ID de l'utilisateur.
|
||||
* @param limit Nombre maximum de suggestions à retourner.
|
||||
* @return Liste des suggestions d'amis.
|
||||
*/
|
||||
public List<com.lions.dev.dto.response.users.FriendSuggestionResponseDTO> getFriendSuggestions(UUID userId, int limit) {
|
||||
logger.info("[LOG] Récupération des suggestions d'amis pour l'utilisateur : " + userId);
|
||||
|
||||
Users user = usersRepository.findById(userId);
|
||||
if (user == null) {
|
||||
logger.error("[ERROR] Utilisateur non trouvé.");
|
||||
throw new UserNotFoundException("Utilisateur introuvable.");
|
||||
}
|
||||
|
||||
// Récupérer tous les amis actuels de l'utilisateur (ACCEPTED)
|
||||
// Utiliser une taille de page élevée pour récupérer tous les résultats
|
||||
List<Friendship> currentFriendships = friendshipRepository.findByUserAndStatus(user, FriendshipStatus.ACCEPTED, 0, 10000);
|
||||
Set<UUID> currentFriendIds = new HashSet<>();
|
||||
for (Friendship friendship : currentFriendships) {
|
||||
// Ajouter les IDs des amis (que l'utilisateur ait envoyé ou reçu la demande)
|
||||
if (friendship.getUser().getId().equals(userId)) {
|
||||
currentFriendIds.add(friendship.getFriend().getId());
|
||||
} else {
|
||||
currentFriendIds.add(friendship.getUser().getId());
|
||||
}
|
||||
}
|
||||
|
||||
// Récupérer toutes les demandes en attente pour exclure ces utilisateurs
|
||||
List<Friendship> pendingFriendships = friendshipRepository.findByUserAndStatus(user, FriendshipStatus.PENDING, 0, 10000);
|
||||
Set<UUID> pendingUserIds = new HashSet<>();
|
||||
for (Friendship friendship : pendingFriendships) {
|
||||
if (friendship.getUser().getId().equals(userId)) {
|
||||
pendingUserIds.add(friendship.getFriend().getId());
|
||||
} else {
|
||||
pendingUserIds.add(friendship.getUser().getId());
|
||||
}
|
||||
}
|
||||
|
||||
// Map pour compter les amis en commun
|
||||
Map<UUID, Integer> mutualFriendsCount = new HashMap<>();
|
||||
|
||||
// Pour chaque ami, trouver ses amis (amis d'amis)
|
||||
for (UUID friendId : currentFriendIds) {
|
||||
Users friend = usersRepository.findById(friendId);
|
||||
if (friend == null) continue;
|
||||
|
||||
List<Friendship> friendsOfFriend = friendshipRepository.findByUserAndStatus(friend, FriendshipStatus.ACCEPTED, 0, 10000);
|
||||
|
||||
for (Friendship fof : friendsOfFriend) {
|
||||
UUID potentialFriendId;
|
||||
if (fof.getUser().getId().equals(friendId)) {
|
||||
potentialFriendId = fof.getFriend().getId();
|
||||
} else {
|
||||
potentialFriendId = fof.getUser().getId();
|
||||
}
|
||||
|
||||
// Exclure l'utilisateur lui-même, ses amis actuels et les demandes en attente
|
||||
if (!potentialFriendId.equals(userId) &&
|
||||
!currentFriendIds.contains(potentialFriendId) &&
|
||||
!pendingUserIds.contains(potentialFriendId)) {
|
||||
mutualFriendsCount.put(potentialFriendId, mutualFriendsCount.getOrDefault(potentialFriendId, 0) + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Trier par nombre d'amis en commun (décroissant)
|
||||
List<Map.Entry<UUID, Integer>> sortedSuggestions = mutualFriendsCount.entrySet()
|
||||
.stream()
|
||||
.sorted(Map.Entry.<UUID, Integer>comparingByValue().reversed())
|
||||
.limit(limit)
|
||||
.toList();
|
||||
|
||||
// Créer les DTOs
|
||||
List<com.lions.dev.dto.response.users.FriendSuggestionResponseDTO> suggestions = new ArrayList<>();
|
||||
for (Map.Entry<UUID, Integer> entry : sortedSuggestions) {
|
||||
Users suggestedUser = usersRepository.findById(entry.getKey());
|
||||
if (suggestedUser != null) {
|
||||
String reason = entry.getValue() > 1
|
||||
? entry.getValue() + " amis en commun"
|
||||
: "1 ami en commun";
|
||||
suggestions.add(new com.lions.dev.dto.response.users.FriendSuggestionResponseDTO(
|
||||
suggestedUser,
|
||||
entry.getValue(),
|
||||
reason
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
// Si pas assez de suggestions, ajouter des utilisateurs récents
|
||||
if (suggestions.size() < limit) {
|
||||
int remaining = limit - suggestions.size();
|
||||
Set<UUID> excludedIds = new HashSet<>(currentFriendIds);
|
||||
excludedIds.addAll(pendingUserIds);
|
||||
excludedIds.add(userId);
|
||||
excludedIds.addAll(mutualFriendsCount.keySet());
|
||||
|
||||
// Récupérer des utilisateurs récents qui ne sont pas dans les exclusions
|
||||
List<Users> recentUsers = usersRepository.findAll()
|
||||
.stream()
|
||||
.filter(u -> !excludedIds.contains(u.getId()))
|
||||
.limit(remaining)
|
||||
.toList();
|
||||
|
||||
for (Users recentUser : recentUsers) {
|
||||
suggestions.add(new com.lions.dev.dto.response.users.FriendSuggestionResponseDTO(
|
||||
recentUser,
|
||||
0,
|
||||
"Nouvel utilisateur"
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
logger.info("[LOG] " + suggestions.size() + " suggestions d'amis générées.");
|
||||
return suggestions;
|
||||
}
|
||||
}
|
||||
|
||||
339
src/main/java/com/lions/dev/service/MessageService.java
Normal file
339
src/main/java/com/lions/dev/service/MessageService.java
Normal file
@@ -0,0 +1,339 @@
|
||||
package com.lions.dev.service;
|
||||
|
||||
import com.lions.dev.entity.chat.Conversation;
|
||||
import com.lions.dev.entity.chat.Message;
|
||||
import com.lions.dev.entity.users.Users;
|
||||
import com.lions.dev.exception.UserNotFoundException;
|
||||
import com.lions.dev.repository.ConversationRepository;
|
||||
import com.lions.dev.repository.MessageRepository;
|
||||
import com.lions.dev.repository.UsersRepository;
|
||||
import com.lions.dev.websocket.ChatWebSocket;
|
||||
import jakarta.enterprise.context.ApplicationScoped;
|
||||
import jakarta.inject.Inject;
|
||||
import jakarta.transaction.Transactional;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* Service de gestion des messages et conversations.
|
||||
*
|
||||
* Ce service contient la logique métier pour l'envoi de messages,
|
||||
* la récupération de conversations, et la gestion des messages non lus.
|
||||
*
|
||||
* Tous les logs nécessaires pour la traçabilité sont intégrés.
|
||||
*/
|
||||
@ApplicationScoped
|
||||
public class MessageService {
|
||||
|
||||
@Inject
|
||||
MessageRepository messageRepository;
|
||||
|
||||
@Inject
|
||||
ConversationRepository conversationRepository;
|
||||
|
||||
@Inject
|
||||
UsersRepository usersRepository;
|
||||
|
||||
@Inject
|
||||
NotificationService notificationService;
|
||||
|
||||
/**
|
||||
* Envoie un message d'un utilisateur à un autre.
|
||||
*
|
||||
* @param senderId L'ID de l'expéditeur
|
||||
* @param recipientId L'ID du destinataire
|
||||
* @param content Le contenu du message
|
||||
* @param messageType Le type de message (text, image, etc.)
|
||||
* @param mediaUrl L'URL du média (optionnel)
|
||||
* @return Le message créé
|
||||
* @throws UserNotFoundException Si l'un des utilisateurs n'existe pas
|
||||
*/
|
||||
@Transactional
|
||||
public Message sendMessage(
|
||||
UUID senderId,
|
||||
UUID recipientId,
|
||||
String content,
|
||||
String messageType,
|
||||
String mediaUrl) {
|
||||
System.out.println("[LOG] Envoi de message de " + senderId + " à " + recipientId);
|
||||
|
||||
// Récupérer les utilisateurs
|
||||
Users sender = usersRepository.findById(senderId);
|
||||
Users recipient = usersRepository.findById(recipientId);
|
||||
|
||||
if (sender == null) {
|
||||
throw new UserNotFoundException("Expéditeur non trouvé avec l'ID : " + senderId);
|
||||
}
|
||||
if (recipient == null) {
|
||||
throw new UserNotFoundException("Destinataire non trouvé avec l'ID : " + recipientId);
|
||||
}
|
||||
|
||||
// Trouver ou créer la conversation
|
||||
Conversation conversation = conversationRepository.findOrCreate(sender, recipient);
|
||||
|
||||
// Créer le message
|
||||
Message message = new Message(conversation, sender, content);
|
||||
message.setMessageType(messageType != null ? messageType : "text");
|
||||
if (mediaUrl != null && !mediaUrl.isEmpty()) {
|
||||
message.setMediaUrl(mediaUrl);
|
||||
}
|
||||
message.markAsDelivered();
|
||||
|
||||
// Persister le message
|
||||
messageRepository.persist(message);
|
||||
System.out.println("[LOG] Message créé avec l'ID : " + message.getId());
|
||||
|
||||
// Mettre à jour la conversation
|
||||
conversation.updateLastMessage(message);
|
||||
conversationRepository.persist(conversation);
|
||||
|
||||
// Créer une notification pour le destinataire
|
||||
try {
|
||||
String senderName = sender.getPrenoms() + " " + sender.getNom();
|
||||
String notificationMessage = content.length() > 50
|
||||
? content.substring(0, 50) + "..."
|
||||
: content;
|
||||
|
||||
notificationService.createNotification(
|
||||
"Nouveau message de " + senderName,
|
||||
notificationMessage,
|
||||
"message",
|
||||
recipientId,
|
||||
null
|
||||
);
|
||||
System.out.println("[LOG] Notification créée pour le destinataire");
|
||||
} catch (Exception e) {
|
||||
System.out.println("[ERROR] Erreur lors de la création de la notification : " + e.getMessage());
|
||||
}
|
||||
|
||||
// TEMPS RÉEL : Envoyer le message via WebSocket au destinataire
|
||||
try {
|
||||
Map<String, Object> messageData = new HashMap<>();
|
||||
messageData.put("id", message.getId().toString());
|
||||
messageData.put("conversationId", conversation.getId().toString());
|
||||
messageData.put("senderId", senderId.toString());
|
||||
messageData.put("senderFirstName", sender.getPrenoms());
|
||||
messageData.put("senderLastName", sender.getNom());
|
||||
messageData.put("senderProfileImageUrl", sender.getProfileImageUrl() != null ? sender.getProfileImageUrl() : "");
|
||||
messageData.put("content", content);
|
||||
messageData.put("timestamp", message.getCreatedAt().toString());
|
||||
messageData.put("isRead", message.isRead());
|
||||
messageData.put("attachmentUrl", mediaUrl != null ? mediaUrl : "");
|
||||
messageData.put("attachmentType", messageType != null ? messageType : "text");
|
||||
|
||||
// Envoyer au destinataire via ChatWebSocket
|
||||
ChatWebSocket.sendMessageToUser(recipientId, messageData);
|
||||
|
||||
System.out.println("[LOG] Message envoyé via WebSocket au destinataire : " + recipientId);
|
||||
|
||||
// Envoyer confirmation de délivrance à l'expéditeur
|
||||
try {
|
||||
Map<String, Object> deliveryConfirmation = new HashMap<>();
|
||||
deliveryConfirmation.put("messageId", message.getId().toString());
|
||||
deliveryConfirmation.put("isDelivered", true);
|
||||
deliveryConfirmation.put("timestamp", System.currentTimeMillis());
|
||||
|
||||
ChatWebSocket.sendDeliveryConfirmation(senderId, deliveryConfirmation);
|
||||
|
||||
System.out.println("[LOG] Confirmation de délivrance envoyée à l'expéditeur : " + senderId);
|
||||
} catch (Exception deliveryEx) {
|
||||
System.out.println("[ERROR] Erreur envoi confirmation délivrance : " + deliveryEx.getMessage());
|
||||
// Ne pas bloquer si la confirmation échoue
|
||||
}
|
||||
} catch (Exception e) {
|
||||
System.out.println("[ERROR] Erreur lors de l'envoi du message via WebSocket : " + e.getMessage());
|
||||
// Ne pas bloquer l'envoi du message si WebSocket échoue
|
||||
}
|
||||
|
||||
return message;
|
||||
}
|
||||
|
||||
/**
|
||||
* Récupère toutes les conversations d'un utilisateur.
|
||||
*
|
||||
* @param userId L'ID de l'utilisateur
|
||||
* @return Liste des conversations
|
||||
* @throws UserNotFoundException Si l'utilisateur n'existe pas
|
||||
*/
|
||||
public List<Conversation> getUserConversations(UUID userId) {
|
||||
System.out.println("[LOG] Récupération des conversations pour l'utilisateur ID : " + userId);
|
||||
|
||||
Users user = usersRepository.findById(userId);
|
||||
if (user == null) {
|
||||
throw new UserNotFoundException("Utilisateur non trouvé avec l'ID : " + userId);
|
||||
}
|
||||
|
||||
return conversationRepository.findByUser(user);
|
||||
}
|
||||
|
||||
/**
|
||||
* Récupère tous les messages d'une conversation avec pagination.
|
||||
*
|
||||
* @param conversationId L'ID de la conversation
|
||||
* @param page Le numéro de la page
|
||||
* @param size La taille de la page
|
||||
* @return Liste paginée des messages
|
||||
*/
|
||||
public List<Message> getConversationMessages(UUID conversationId, int page, int size) {
|
||||
System.out.println("[LOG] Récupération des messages pour la conversation ID : " + conversationId);
|
||||
return messageRepository.findByConversationId(conversationId, page, size);
|
||||
}
|
||||
|
||||
/**
|
||||
* Récupère une conversation spécifique.
|
||||
*
|
||||
* @param conversationId L'ID de la conversation
|
||||
* @return La conversation
|
||||
*/
|
||||
public Conversation getConversation(UUID conversationId) {
|
||||
System.out.println("[LOG] Récupération de la conversation ID : " + conversationId);
|
||||
return conversationRepository.findById(conversationId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Récupère une conversation entre deux utilisateurs.
|
||||
*
|
||||
* @param user1Id L'ID du premier utilisateur
|
||||
* @param user2Id L'ID du deuxième utilisateur
|
||||
* @return La conversation ou null si elle n'existe pas
|
||||
* @throws UserNotFoundException Si l'un des utilisateurs n'existe pas
|
||||
*/
|
||||
public Conversation getConversationBetweenUsers(UUID user1Id, UUID user2Id) {
|
||||
System.out.println("[LOG] Recherche de conversation entre " + user1Id + " et " + user2Id);
|
||||
|
||||
Users user1 = usersRepository.findById(user1Id);
|
||||
Users user2 = usersRepository.findById(user2Id);
|
||||
|
||||
if (user1 == null || user2 == null) {
|
||||
throw new UserNotFoundException("Un ou plusieurs utilisateurs non trouvés");
|
||||
}
|
||||
|
||||
return conversationRepository.findBetweenUsers(user1, user2);
|
||||
}
|
||||
|
||||
/**
|
||||
* Marque un message comme lu.
|
||||
*
|
||||
* @param messageId L'ID du message
|
||||
* @return Le message mis à jour
|
||||
*/
|
||||
@Transactional
|
||||
public Message markMessageAsRead(UUID messageId) {
|
||||
System.out.println("[LOG] Marquage du message comme lu : " + messageId);
|
||||
|
||||
Message message = messageRepository.findById(messageId);
|
||||
if (message == null) {
|
||||
throw new IllegalArgumentException("Message non trouvé avec l'ID : " + messageId);
|
||||
}
|
||||
|
||||
message.markAsRead();
|
||||
messageRepository.persist(message);
|
||||
|
||||
// Envoyer confirmation de lecture à l'expéditeur via WebSocket
|
||||
try {
|
||||
// Récupérer le destinataire (l'autre utilisateur de la conversation)
|
||||
Conversation conversation = message.getConversation();
|
||||
UUID recipientId = conversation.getUser1().getId().equals(message.getSender().getId())
|
||||
? conversation.getUser2().getId()
|
||||
: conversation.getUser1().getId();
|
||||
|
||||
Map<String, Object> readConfirmation = new HashMap<>();
|
||||
readConfirmation.put("messageId", message.getId().toString());
|
||||
readConfirmation.put("userId", recipientId.toString());
|
||||
readConfirmation.put("timestamp", java.time.LocalDateTime.now().toString());
|
||||
|
||||
// Envoyer via ChatWebSocket avec type "read"
|
||||
com.lions.dev.websocket.ChatWebSocket.sendReadConfirmation(
|
||||
message.getSender().getId(),
|
||||
readConfirmation
|
||||
);
|
||||
|
||||
System.out.println("[LOG] Confirmation de lecture envoyée à l'expéditeur : " + message.getSender().getId());
|
||||
} catch (Exception e) {
|
||||
System.out.println("[ERROR] Erreur envoi confirmation lecture : " + e.getMessage());
|
||||
}
|
||||
|
||||
return message;
|
||||
}
|
||||
|
||||
/**
|
||||
* Marque tous les messages d'une conversation comme lus pour un utilisateur.
|
||||
*
|
||||
* @param conversationId L'ID de la conversation
|
||||
* @param userId L'ID de l'utilisateur
|
||||
* @return Le nombre de messages marqués comme lus
|
||||
*/
|
||||
@Transactional
|
||||
public int markAllMessagesAsRead(UUID conversationId, UUID userId) {
|
||||
System.out.println("[LOG] Marquage de tous les messages comme lus pour la conversation " + conversationId);
|
||||
|
||||
Conversation conversation = conversationRepository.findById(conversationId);
|
||||
if (conversation == null) {
|
||||
throw new IllegalArgumentException("Conversation non trouvée");
|
||||
}
|
||||
|
||||
Users user = usersRepository.findById(userId);
|
||||
if (user == null) {
|
||||
throw new UserNotFoundException("Utilisateur non trouvé");
|
||||
}
|
||||
|
||||
// Marquer les messages comme lus
|
||||
int count = messageRepository.markAllAsRead(conversationId, userId);
|
||||
|
||||
// Mettre à jour le compteur de la conversation
|
||||
conversation.markAllAsReadForUser(user);
|
||||
conversationRepository.persist(conversation);
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compte le nombre total de messages non lus pour un utilisateur.
|
||||
*
|
||||
* @param userId L'ID de l'utilisateur
|
||||
* @return Le nombre de messages non lus
|
||||
*/
|
||||
public long getTotalUnreadCount(UUID userId) {
|
||||
System.out.println("[LOG] Récupération du nombre total de messages non lus pour l'utilisateur " + userId);
|
||||
return conversationRepository.countTotalUnreadMessages(userId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Supprime un message.
|
||||
*
|
||||
* @param messageId L'ID du message
|
||||
* @return true si le message a été supprimé
|
||||
*/
|
||||
@Transactional
|
||||
public boolean deleteMessage(UUID messageId) {
|
||||
System.out.println("[LOG] Suppression du message ID : " + messageId);
|
||||
|
||||
Message message = messageRepository.findById(messageId);
|
||||
if (message == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
messageRepository.delete(message);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Supprime une conversation et tous ses messages.
|
||||
*
|
||||
* @param conversationId L'ID de la conversation
|
||||
* @return true si la conversation a été supprimée
|
||||
*/
|
||||
@Transactional
|
||||
public boolean deleteConversation(UUID conversationId) {
|
||||
System.out.println("[LOG] Suppression de la conversation ID : " + conversationId);
|
||||
|
||||
// Supprimer d'abord tous les messages
|
||||
messageRepository.deleteByConversationId(conversationId);
|
||||
|
||||
// Puis supprimer la conversation
|
||||
return conversationRepository.deleteConversation(conversationId);
|
||||
}
|
||||
}
|
||||
218
src/main/java/com/lions/dev/service/NotificationService.java
Normal file
218
src/main/java/com/lions/dev/service/NotificationService.java
Normal file
@@ -0,0 +1,218 @@
|
||||
package com.lions.dev.service;
|
||||
|
||||
import com.lions.dev.entity.events.Events;
|
||||
import com.lions.dev.entity.notification.Notification;
|
||||
import com.lions.dev.entity.users.Users;
|
||||
import com.lions.dev.exception.UserNotFoundException;
|
||||
import com.lions.dev.repository.EventsRepository;
|
||||
import com.lions.dev.repository.NotificationRepository;
|
||||
import com.lions.dev.repository.UsersRepository;
|
||||
import jakarta.enterprise.context.ApplicationScoped;
|
||||
import jakarta.inject.Inject;
|
||||
import jakarta.transaction.Transactional;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* Service de gestion des notifications.
|
||||
*
|
||||
* Ce service contient la logique métier pour la création, récupération,
|
||||
* mise à jour et suppression des notifications.
|
||||
*
|
||||
* Tous les logs nécessaires pour la traçabilité sont intégrés.
|
||||
*/
|
||||
@ApplicationScoped
|
||||
public class NotificationService {
|
||||
|
||||
@Inject
|
||||
NotificationRepository notificationRepository;
|
||||
|
||||
@Inject
|
||||
UsersRepository usersRepository;
|
||||
|
||||
@Inject
|
||||
EventsRepository eventsRepository;
|
||||
|
||||
/**
|
||||
* Récupère toutes les notifications d'un utilisateur.
|
||||
*
|
||||
* @param userId L'ID de l'utilisateur
|
||||
* @return Liste des notifications de l'utilisateur
|
||||
* @throws UserNotFoundException Si l'utilisateur n'existe pas
|
||||
*/
|
||||
public List<Notification> getNotificationsByUserId(UUID userId) {
|
||||
System.out.println("[LOG] Récupération des notifications pour l'utilisateur ID : " + userId);
|
||||
|
||||
Users user = usersRepository.findById(userId);
|
||||
if (user == null) {
|
||||
System.out.println("[ERROR] Utilisateur non trouvé avec l'ID : " + userId);
|
||||
throw new UserNotFoundException("Utilisateur non trouvé avec l'ID : " + userId);
|
||||
}
|
||||
|
||||
List<Notification> notifications = notificationRepository.findByUserId(userId);
|
||||
System.out.println("[LOG] " + notifications.size() + " notification(s) récupérée(s) pour l'utilisateur ID : " + userId);
|
||||
return notifications;
|
||||
}
|
||||
|
||||
/**
|
||||
* Récupère les notifications d'un utilisateur avec pagination.
|
||||
*
|
||||
* @param userId L'ID de l'utilisateur
|
||||
* @param page Le numéro de la page (0-indexé)
|
||||
* @param size La taille de la page
|
||||
* @return Liste paginée des notifications
|
||||
* @throws UserNotFoundException Si l'utilisateur n'existe pas
|
||||
*/
|
||||
public List<Notification> getNotificationsByUserIdWithPagination(UUID userId, int page, int size) {
|
||||
System.out.println("[LOG] Récupération paginée des notifications pour l'utilisateur ID : " + userId);
|
||||
|
||||
Users user = usersRepository.findById(userId);
|
||||
if (user == null) {
|
||||
System.out.println("[ERROR] Utilisateur non trouvé avec l'ID : " + userId);
|
||||
throw new UserNotFoundException("Utilisateur non trouvé avec l'ID : " + userId);
|
||||
}
|
||||
|
||||
return notificationRepository.findByUserIdWithPagination(userId, page, size);
|
||||
}
|
||||
|
||||
/**
|
||||
* Crée une nouvelle notification.
|
||||
*
|
||||
* @param title Le titre de la notification
|
||||
* @param message Le message de la notification
|
||||
* @param type Le type de notification (event, friend, reminder, other)
|
||||
* @param userId L'ID de l'utilisateur destinataire
|
||||
* @param eventId L'ID de l'événement associé (optionnel)
|
||||
* @return La notification créée
|
||||
* @throws UserNotFoundException Si l'utilisateur n'existe pas
|
||||
*/
|
||||
@Transactional
|
||||
public Notification createNotification(
|
||||
String title,
|
||||
String message,
|
||||
String type,
|
||||
UUID userId,
|
||||
UUID eventId) {
|
||||
System.out.println("[LOG] Création d'une notification : " + title + " pour l'utilisateur ID : " + userId);
|
||||
|
||||
Users user = usersRepository.findById(userId);
|
||||
if (user == null) {
|
||||
System.out.println("[ERROR] Utilisateur non trouvé avec l'ID : " + userId);
|
||||
throw new UserNotFoundException("Utilisateur non trouvé avec l'ID : " + userId);
|
||||
}
|
||||
|
||||
Notification notification = new Notification(title, message, type, user);
|
||||
|
||||
if (eventId != null) {
|
||||
Events event = eventsRepository.findById(eventId);
|
||||
if (event != null) {
|
||||
notification.setEvent(event);
|
||||
System.out.println("[LOG] Notification associée à l'événement ID : " + eventId);
|
||||
}
|
||||
}
|
||||
|
||||
notificationRepository.persist(notification);
|
||||
System.out.println("[LOG] Notification créée avec succès : " + notification.getId());
|
||||
return notification;
|
||||
}
|
||||
|
||||
/**
|
||||
* Marque une notification comme lue.
|
||||
*
|
||||
* @param notificationId L'ID de la notification
|
||||
* @return La notification mise à jour
|
||||
*/
|
||||
@Transactional
|
||||
public Notification markAsRead(UUID notificationId) {
|
||||
System.out.println("[LOG] Marquage de la notification ID : " + notificationId + " comme lue");
|
||||
|
||||
Notification notification = notificationRepository.findById(notificationId);
|
||||
if (notification == null) {
|
||||
System.out.println("[ERROR] Notification non trouvée avec l'ID : " + notificationId);
|
||||
throw new IllegalArgumentException("Notification non trouvée avec l'ID : " + notificationId);
|
||||
}
|
||||
|
||||
notification.markAsRead();
|
||||
notificationRepository.persist(notification);
|
||||
System.out.println("[LOG] Notification marquée comme lue avec succès");
|
||||
return notification;
|
||||
}
|
||||
|
||||
/**
|
||||
* Marque toutes les notifications d'un utilisateur comme lues.
|
||||
*
|
||||
* @param userId L'ID de l'utilisateur
|
||||
* @return Le nombre de notifications mises à jour
|
||||
* @throws UserNotFoundException Si l'utilisateur n'existe pas
|
||||
*/
|
||||
@Transactional
|
||||
public int markAllAsRead(UUID userId) {
|
||||
System.out.println("[LOG] Marquage de toutes les notifications comme lues pour l'utilisateur ID : " + userId);
|
||||
|
||||
Users user = usersRepository.findById(userId);
|
||||
if (user == null) {
|
||||
System.out.println("[ERROR] Utilisateur non trouvé avec l'ID : " + userId);
|
||||
throw new UserNotFoundException("Utilisateur non trouvé avec l'ID : " + userId);
|
||||
}
|
||||
|
||||
int updated = notificationRepository.markAllAsReadByUserId(userId);
|
||||
System.out.println("[LOG] " + updated + " notification(s) marquée(s) comme lue(s)");
|
||||
return updated;
|
||||
}
|
||||
|
||||
/**
|
||||
* Supprime une notification.
|
||||
*
|
||||
* @param notificationId L'ID de la notification
|
||||
* @return true si la notification a été supprimée, false sinon
|
||||
*/
|
||||
@Transactional
|
||||
public boolean deleteNotification(UUID notificationId) {
|
||||
System.out.println("[LOG] Suppression de la notification ID : " + notificationId);
|
||||
|
||||
Notification notification = notificationRepository.findById(notificationId);
|
||||
if (notification == null) {
|
||||
System.out.println("[ERROR] Notification non trouvée avec l'ID : " + notificationId);
|
||||
return false;
|
||||
}
|
||||
|
||||
notificationRepository.delete(notification);
|
||||
System.out.println("[LOG] Notification supprimée avec succès");
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Récupère une notification par son ID.
|
||||
*
|
||||
* @param notificationId L'ID de la notification
|
||||
* @return La notification trouvée
|
||||
*/
|
||||
public Notification getNotificationById(UUID notificationId) {
|
||||
System.out.println("[LOG] Récupération de la notification ID : " + notificationId);
|
||||
|
||||
Notification notification = notificationRepository.findById(notificationId);
|
||||
if (notification == null) {
|
||||
System.out.println("[ERROR] Notification non trouvée avec l'ID : " + notificationId);
|
||||
throw new IllegalArgumentException("Notification non trouvée avec l'ID : " + notificationId);
|
||||
}
|
||||
|
||||
return notification;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compte le nombre de notifications non lues d'un utilisateur.
|
||||
*
|
||||
* @param userId L'ID de l'utilisateur
|
||||
* @return Le nombre de notifications non lues
|
||||
* @throws UserNotFoundException Si l'utilisateur n'existe pas
|
||||
*/
|
||||
public long countUnreadNotifications(UUID userId) {
|
||||
Users user = usersRepository.findById(userId);
|
||||
if (user == null) {
|
||||
throw new UserNotFoundException("Utilisateur non trouvé avec l'ID : " + userId);
|
||||
}
|
||||
|
||||
return notificationRepository.countUnreadByUserId(userId);
|
||||
}
|
||||
}
|
||||
|
||||
122
src/main/java/com/lions/dev/service/PresenceService.java
Normal file
122
src/main/java/com/lions/dev/service/PresenceService.java
Normal file
@@ -0,0 +1,122 @@
|
||||
package com.lions.dev.service;
|
||||
|
||||
import com.lions.dev.entity.users.Users;
|
||||
import com.lions.dev.repository.UsersRepository;
|
||||
import com.lions.dev.websocket.NotificationWebSocket;
|
||||
import jakarta.enterprise.context.ApplicationScoped;
|
||||
import jakarta.inject.Inject;
|
||||
import jakarta.transaction.Transactional;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* Service pour gérer la présence des utilisateurs (online/offline).
|
||||
*
|
||||
* Ce service gère:
|
||||
* - Le marquage des utilisateurs comme en ligne/hors ligne
|
||||
* - Le heartbeat pour maintenir le statut online
|
||||
* - La diffusion de la présence aux amis via WebSocket
|
||||
*/
|
||||
@ApplicationScoped
|
||||
public class PresenceService {
|
||||
|
||||
@Inject
|
||||
UsersRepository usersRepository;
|
||||
|
||||
/**
|
||||
* Marque un utilisateur comme en ligne et broadcast sa présence.
|
||||
*
|
||||
* @param userId L'ID de l'utilisateur
|
||||
*/
|
||||
@Transactional
|
||||
public void setUserOnline(UUID userId) {
|
||||
Users user = usersRepository.findById(userId);
|
||||
if (user != null) {
|
||||
user.updatePresence();
|
||||
usersRepository.persist(user);
|
||||
|
||||
// Broadcast présence aux autres utilisateurs
|
||||
broadcastPresenceToAll(userId, true, user.getLastSeen());
|
||||
|
||||
System.out.println("[PRESENCE] Utilisateur " + userId + " marqué online");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Marque un utilisateur comme hors ligne.
|
||||
*
|
||||
* @param userId L'ID de l'utilisateur
|
||||
*/
|
||||
@Transactional
|
||||
public void setUserOffline(UUID userId) {
|
||||
Users user = usersRepository.findById(userId);
|
||||
if (user != null) {
|
||||
user.setOffline();
|
||||
usersRepository.persist(user);
|
||||
|
||||
// Broadcast présence aux autres utilisateurs
|
||||
broadcastPresenceToAll(userId, false, user.getLastSeen());
|
||||
|
||||
System.out.println("[PRESENCE] Utilisateur " + userId + " marqué offline");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Met à jour le heartbeat d'un utilisateur (keep-alive).
|
||||
*
|
||||
* @param userId L'ID de l'utilisateur
|
||||
*/
|
||||
@Transactional
|
||||
public void heartbeat(UUID userId) {
|
||||
Users user = usersRepository.findById(userId);
|
||||
if (user != null) {
|
||||
user.updatePresence();
|
||||
usersRepository.persist(user);
|
||||
System.out.println("[PRESENCE] Heartbeat reçu pour utilisateur " + userId);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Broadcast la présence d'un utilisateur à tous les utilisateurs connectés via WebSocket.
|
||||
*
|
||||
* @param userId L'ID de l'utilisateur
|
||||
* @param isOnline Le statut online
|
||||
* @param lastSeen La dernière fois que l'utilisateur était en ligne
|
||||
*/
|
||||
private void broadcastPresenceToAll(UUID userId, boolean isOnline, LocalDateTime lastSeen) {
|
||||
try {
|
||||
Map<String, Object> presenceData = new HashMap<>();
|
||||
presenceData.put("userId", userId.toString());
|
||||
presenceData.put("isOnline", isOnline);
|
||||
presenceData.put("lastSeen", lastSeen != null ? lastSeen.toString() : null);
|
||||
presenceData.put("timestamp", System.currentTimeMillis());
|
||||
|
||||
// Envoyer via NotificationWebSocket
|
||||
NotificationWebSocket.broadcastPresenceUpdate(presenceData);
|
||||
|
||||
System.out.println("[PRESENCE] Broadcast de la présence de " + userId + " : " + isOnline);
|
||||
} catch (Exception e) {
|
||||
System.out.println("[ERROR] Erreur lors du broadcast de présence : " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Récupère le statut de présence d'un utilisateur.
|
||||
*
|
||||
* @param userId L'ID de l'utilisateur
|
||||
* @return Map contenant isOnline et lastSeen
|
||||
*/
|
||||
public Map<String, Object> getUserPresence(UUID userId) {
|
||||
Users user = usersRepository.findById(userId);
|
||||
Map<String, Object> presence = new HashMap<>();
|
||||
|
||||
if (user != null) {
|
||||
presence.put("userId", userId.toString());
|
||||
presence.put("isOnline", user.isOnline());
|
||||
presence.put("lastSeen", user.getLastSeen() != null ? user.getLastSeen().toString() : null);
|
||||
}
|
||||
|
||||
return presence;
|
||||
}
|
||||
}
|
||||
308
src/main/java/com/lions/dev/service/SocialPostService.java
Normal file
308
src/main/java/com/lions/dev/service/SocialPostService.java
Normal file
@@ -0,0 +1,308 @@
|
||||
package com.lions.dev.service;
|
||||
|
||||
import com.lions.dev.entity.friends.Friendship;
|
||||
import com.lions.dev.entity.friends.FriendshipStatus;
|
||||
import com.lions.dev.entity.social.SocialPost;
|
||||
import com.lions.dev.entity.users.Users;
|
||||
import com.lions.dev.exception.UserNotFoundException;
|
||||
import com.lions.dev.repository.FriendshipRepository;
|
||||
import com.lions.dev.repository.SocialPostRepository;
|
||||
import com.lions.dev.repository.UsersRepository;
|
||||
import jakarta.enterprise.context.ApplicationScoped;
|
||||
import jakarta.inject.Inject;
|
||||
import jakarta.transaction.Transactional;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* Service de gestion des posts sociaux.
|
||||
*
|
||||
* Ce service contient la logique métier pour la création, récupération,
|
||||
* mise à jour et suppression des posts sociaux.
|
||||
*
|
||||
* Tous les logs nécessaires pour la traçabilité sont intégrés.
|
||||
*/
|
||||
@ApplicationScoped
|
||||
public class SocialPostService {
|
||||
|
||||
@Inject
|
||||
SocialPostRepository socialPostRepository;
|
||||
|
||||
@Inject
|
||||
UsersRepository usersRepository;
|
||||
|
||||
@Inject
|
||||
FriendshipRepository friendshipRepository;
|
||||
|
||||
@Inject
|
||||
NotificationService notificationService;
|
||||
|
||||
/**
|
||||
* Récupère tous les posts avec pagination.
|
||||
*
|
||||
* @param page Le numéro de la page (0-indexé)
|
||||
* @param size La taille de la page
|
||||
* @return Liste paginée des posts
|
||||
*/
|
||||
public List<SocialPost> getAllPosts(int page, int size) {
|
||||
System.out.println("[LOG] Récupération de tous les posts (page: " + page + ", size: " + size + ")");
|
||||
return socialPostRepository.findAllWithPagination(page, size);
|
||||
}
|
||||
|
||||
/**
|
||||
* Récupère tous les posts d'un utilisateur.
|
||||
*
|
||||
* @param userId L'ID de l'utilisateur
|
||||
* @return Liste des posts de l'utilisateur
|
||||
* @throws UserNotFoundException Si l'utilisateur n'existe pas
|
||||
*/
|
||||
public List<SocialPost> getPostsByUserId(UUID userId) {
|
||||
System.out.println("[LOG] Récupération des posts pour l'utilisateur ID : " + userId);
|
||||
|
||||
Users user = usersRepository.findById(userId);
|
||||
if (user == null) {
|
||||
System.out.println("[ERROR] Utilisateur non trouvé avec l'ID : " + userId);
|
||||
throw new UserNotFoundException("Utilisateur non trouvé avec l'ID : " + userId);
|
||||
}
|
||||
|
||||
return socialPostRepository.findByUserId(userId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Crée un nouveau post social.
|
||||
*
|
||||
* @param content Le contenu du post
|
||||
* @param userId L'ID de l'utilisateur créateur
|
||||
* @param imageUrl L'URL de l'image (optionnel)
|
||||
* @return Le post créé
|
||||
* @throws UserNotFoundException Si l'utilisateur n'existe pas
|
||||
*/
|
||||
@Transactional
|
||||
public SocialPost createPost(String content, UUID userId, String imageUrl) {
|
||||
System.out.println("[LOG] Création d'un post par l'utilisateur ID : " + userId);
|
||||
|
||||
Users user = usersRepository.findById(userId);
|
||||
if (user == null) {
|
||||
System.out.println("[ERROR] Utilisateur non trouvé avec l'ID : " + userId);
|
||||
throw new UserNotFoundException("Utilisateur non trouvé avec l'ID : " + userId);
|
||||
}
|
||||
|
||||
SocialPost post = new SocialPost(content, user);
|
||||
if (imageUrl != null && !imageUrl.isEmpty()) {
|
||||
post.setImageUrl(imageUrl);
|
||||
}
|
||||
|
||||
socialPostRepository.persist(post);
|
||||
System.out.println("[LOG] Post créé avec succès : " + post.getId());
|
||||
|
||||
// Créer des notifications pour tous les amis
|
||||
try {
|
||||
List<Friendship> friendships = friendshipRepository.findFriendsByUser(user, 0, Integer.MAX_VALUE);
|
||||
String userName = user.getPrenoms() + " " + user.getNom();
|
||||
|
||||
for (Friendship friendship : friendships) {
|
||||
Users friend = friendship.getUser().equals(user)
|
||||
? friendship.getFriend()
|
||||
: friendship.getUser();
|
||||
|
||||
String notificationTitle = "Nouveau post de " + userName;
|
||||
String notificationMessage = userName + " a publié un nouveau post : " +
|
||||
(content.length() > 50 ? content.substring(0, 50) + "..." : content);
|
||||
|
||||
notificationService.createNotification(
|
||||
notificationTitle,
|
||||
notificationMessage,
|
||||
"post",
|
||||
friend.getId(),
|
||||
null
|
||||
);
|
||||
}
|
||||
System.out.println("[LOG] Notifications créées pour " + friendships.size() + " ami(s)");
|
||||
} catch (Exception e) {
|
||||
System.out.println("[ERROR] Erreur lors de la création des notifications : " + e.getMessage());
|
||||
}
|
||||
|
||||
return post;
|
||||
}
|
||||
|
||||
/**
|
||||
* Récupère un post par son ID.
|
||||
*
|
||||
* @param postId L'ID du post
|
||||
* @return Le post trouvé
|
||||
*/
|
||||
public SocialPost getPostById(UUID postId) {
|
||||
System.out.println("[LOG] Récupération du post ID : " + postId);
|
||||
|
||||
SocialPost post = socialPostRepository.findById(postId);
|
||||
if (post == null) {
|
||||
System.out.println("[ERROR] Post non trouvé avec l'ID : " + postId);
|
||||
throw new IllegalArgumentException("Post non trouvé avec l'ID : " + postId);
|
||||
}
|
||||
|
||||
return post;
|
||||
}
|
||||
|
||||
/**
|
||||
* Met à jour un post.
|
||||
*
|
||||
* @param postId L'ID du post
|
||||
* @param content Le nouveau contenu
|
||||
* @param imageUrl La nouvelle URL d'image (optionnel)
|
||||
* @return Le post mis à jour
|
||||
*/
|
||||
@Transactional
|
||||
public SocialPost updatePost(UUID postId, String content, String imageUrl) {
|
||||
System.out.println("[LOG] Mise à jour du post ID : " + postId);
|
||||
|
||||
SocialPost post = socialPostRepository.findById(postId);
|
||||
if (post == null) {
|
||||
System.out.println("[ERROR] Post non trouvé avec l'ID : " + postId);
|
||||
throw new IllegalArgumentException("Post non trouvé avec l'ID : " + postId);
|
||||
}
|
||||
|
||||
post.setContent(content);
|
||||
if (imageUrl != null) {
|
||||
post.setImageUrl(imageUrl);
|
||||
}
|
||||
|
||||
socialPostRepository.persist(post);
|
||||
System.out.println("[LOG] Post mis à jour avec succès");
|
||||
return post;
|
||||
}
|
||||
|
||||
/**
|
||||
* Supprime un post.
|
||||
*
|
||||
* @param postId L'ID du post
|
||||
* @return true si le post a été supprimé, false sinon
|
||||
*/
|
||||
@Transactional
|
||||
public boolean deletePost(UUID postId) {
|
||||
System.out.println("[LOG] Suppression du post ID : " + postId);
|
||||
|
||||
SocialPost post = socialPostRepository.findById(postId);
|
||||
if (post == null) {
|
||||
System.out.println("[ERROR] Post non trouvé avec l'ID : " + postId);
|
||||
return false;
|
||||
}
|
||||
|
||||
socialPostRepository.delete(post);
|
||||
System.out.println("[LOG] Post supprimé avec succès");
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Recherche des posts par contenu.
|
||||
*
|
||||
* @param query Le terme de recherche
|
||||
* @return Liste des posts correspondant à la recherche
|
||||
*/
|
||||
public List<SocialPost> searchPosts(String query) {
|
||||
System.out.println("[LOG] Recherche de posts avec la requête : " + query);
|
||||
return socialPostRepository.searchByContent(query);
|
||||
}
|
||||
|
||||
/**
|
||||
* Like un post (incrémente le compteur de likes).
|
||||
*
|
||||
* @param postId L'ID du post
|
||||
* @return Le post mis à jour
|
||||
*/
|
||||
@Transactional
|
||||
public SocialPost likePost(UUID postId) {
|
||||
System.out.println("[LOG] Like du post ID : " + postId);
|
||||
|
||||
SocialPost post = socialPostRepository.findById(postId);
|
||||
if (post == null) {
|
||||
System.out.println("[ERROR] Post non trouvé avec l'ID : " + postId);
|
||||
throw new IllegalArgumentException("Post non trouvé avec l'ID : " + postId);
|
||||
}
|
||||
|
||||
post.incrementLikes();
|
||||
socialPostRepository.persist(post);
|
||||
return post;
|
||||
}
|
||||
|
||||
/**
|
||||
* Ajoute un commentaire à un post (incrémente le compteur de commentaires).
|
||||
*
|
||||
* @param postId L'ID du post
|
||||
* @return Le post mis à jour
|
||||
*/
|
||||
@Transactional
|
||||
public SocialPost addComment(UUID postId) {
|
||||
System.out.println("[LOG] Ajout de commentaire au post ID : " + postId);
|
||||
|
||||
SocialPost post = socialPostRepository.findById(postId);
|
||||
if (post == null) {
|
||||
System.out.println("[ERROR] Post non trouvé avec l'ID : " + postId);
|
||||
throw new IllegalArgumentException("Post non trouvé avec l'ID : " + postId);
|
||||
}
|
||||
|
||||
post.incrementComments();
|
||||
socialPostRepository.persist(post);
|
||||
return post;
|
||||
}
|
||||
|
||||
/**
|
||||
* Partage un post (incrémente le compteur de partages).
|
||||
*
|
||||
* @param postId L'ID du post
|
||||
* @return Le post mis à jour
|
||||
*/
|
||||
@Transactional
|
||||
public SocialPost sharePost(UUID postId) {
|
||||
System.out.println("[LOG] Partage du post ID : " + postId);
|
||||
|
||||
SocialPost post = socialPostRepository.findById(postId);
|
||||
if (post == null) {
|
||||
System.out.println("[ERROR] Post non trouvé avec l'ID : " + postId);
|
||||
throw new IllegalArgumentException("Post non trouvé avec l'ID : " + postId);
|
||||
}
|
||||
|
||||
post.incrementShares();
|
||||
socialPostRepository.persist(post);
|
||||
return post;
|
||||
}
|
||||
|
||||
/**
|
||||
* Récupère les posts de l'utilisateur et de ses amis (relations d'amitié acceptées).
|
||||
*
|
||||
* @param userId L'ID de l'utilisateur
|
||||
* @param page Le numéro de la page (0-indexé)
|
||||
* @param size La taille de la page
|
||||
* @return Liste paginée des posts de l'utilisateur et de ses amis
|
||||
* @throws UserNotFoundException Si l'utilisateur n'existe pas
|
||||
*/
|
||||
public List<SocialPost> getPostsByFriends(UUID userId, int page, int size) {
|
||||
System.out.println("[LOG] Récupération des posts des amis pour l'utilisateur ID : " + userId);
|
||||
|
||||
Users user = usersRepository.findById(userId);
|
||||
if (user == null) {
|
||||
System.out.println("[ERROR] Utilisateur non trouvé avec l'ID : " + userId);
|
||||
throw new UserNotFoundException("Utilisateur non trouvé avec l'ID : " + userId);
|
||||
}
|
||||
|
||||
// Récupérer toutes les relations d'amitié acceptées
|
||||
List<Friendship> friendships = friendshipRepository.findFriendsByUser(user, 0, Integer.MAX_VALUE);
|
||||
|
||||
// Extraire les IDs des amis
|
||||
List<UUID> friendIds = friendships.stream()
|
||||
.map(friendship -> {
|
||||
// L'ami est soit dans 'user' soit dans 'friend', selon qui a initié la relation
|
||||
return friendship.getUser().equals(user)
|
||||
? friendship.getFriend().getId()
|
||||
: friendship.getUser().getId();
|
||||
})
|
||||
.distinct()
|
||||
.collect(Collectors.toList());
|
||||
|
||||
System.out.println("[LOG] " + friendIds.size() + " ami(s) trouvé(s) pour l'utilisateur ID : " + userId);
|
||||
|
||||
// Récupérer les posts de l'utilisateur et de ses amis
|
||||
return socialPostRepository.findPostsByFriends(userId, friendIds, page, size);
|
||||
}
|
||||
}
|
||||
|
||||
212
src/main/java/com/lions/dev/service/StoryService.java
Normal file
212
src/main/java/com/lions/dev/service/StoryService.java
Normal file
@@ -0,0 +1,212 @@
|
||||
package com.lions.dev.service;
|
||||
|
||||
import com.lions.dev.entity.story.MediaType;
|
||||
import com.lions.dev.entity.story.Story;
|
||||
import com.lions.dev.entity.users.Users;
|
||||
import com.lions.dev.exception.UserNotFoundException;
|
||||
import com.lions.dev.repository.StoryRepository;
|
||||
import com.lions.dev.repository.UsersRepository;
|
||||
import jakarta.enterprise.context.ApplicationScoped;
|
||||
import jakarta.inject.Inject;
|
||||
import jakarta.transaction.Transactional;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* Service de gestion des stories.
|
||||
*
|
||||
* Ce service contient la logique métier pour la création, récupération,
|
||||
* mise à jour et suppression des stories.
|
||||
*
|
||||
* Tous les logs nécessaires pour la traçabilité sont intégrés.
|
||||
*/
|
||||
@ApplicationScoped
|
||||
public class StoryService {
|
||||
|
||||
@Inject
|
||||
StoryRepository storyRepository;
|
||||
|
||||
@Inject
|
||||
UsersRepository usersRepository;
|
||||
|
||||
/**
|
||||
* Récupère toutes les stories actives (non expirées).
|
||||
*
|
||||
* @return Liste des stories actives
|
||||
*/
|
||||
public List<Story> getAllActiveStories() {
|
||||
System.out.println("[LOG] Récupération de toutes les stories actives");
|
||||
return storyRepository.findAllActive();
|
||||
}
|
||||
|
||||
/**
|
||||
* Récupère toutes les stories actives d'un utilisateur.
|
||||
*
|
||||
* @param userId L'ID de l'utilisateur
|
||||
* @return Liste des stories actives de l'utilisateur
|
||||
* @throws UserNotFoundException Si l'utilisateur n'existe pas
|
||||
*/
|
||||
public List<Story> getActiveStoriesByUserId(UUID userId) {
|
||||
System.out.println("[LOG] Récupération des stories actives pour l'utilisateur ID : " + userId);
|
||||
|
||||
Users user = usersRepository.findById(userId);
|
||||
if (user == null) {
|
||||
System.out.println("[ERROR] Utilisateur non trouvé avec l'ID : " + userId);
|
||||
throw new UserNotFoundException("Utilisateur non trouvé avec l'ID : " + userId);
|
||||
}
|
||||
|
||||
return storyRepository.findActiveByUserId(userId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Crée une nouvelle story.
|
||||
*
|
||||
* @param userId L'ID de l'utilisateur créateur
|
||||
* @param mediaType Le type de média (IMAGE ou VIDEO)
|
||||
* @param mediaUrl L'URL du média
|
||||
* @param thumbnailUrl L'URL du thumbnail (optionnel, pour les vidéos)
|
||||
* @param durationSeconds La durée en secondes (optionnel, pour les vidéos)
|
||||
* @return La story créée
|
||||
* @throws UserNotFoundException Si l'utilisateur n'existe pas
|
||||
* @throws IllegalArgumentException Si les paramètres sont invalides
|
||||
*/
|
||||
@Transactional
|
||||
public Story createStory(UUID userId, MediaType mediaType, String mediaUrl, String thumbnailUrl, Integer durationSeconds) {
|
||||
System.out.println("[LOG] Création d'une story par l'utilisateur ID : " + userId);
|
||||
|
||||
// Validation de l'utilisateur
|
||||
Users user = usersRepository.findById(userId);
|
||||
if (user == null) {
|
||||
System.out.println("[ERROR] Utilisateur non trouvé avec l'ID : " + userId);
|
||||
throw new UserNotFoundException("Utilisateur non trouvé avec l'ID : " + userId);
|
||||
}
|
||||
|
||||
// Validation des paramètres
|
||||
if (mediaUrl == null || mediaUrl.trim().isEmpty()) {
|
||||
System.out.println("[ERROR] L'URL du média est obligatoire");
|
||||
throw new IllegalArgumentException("L'URL du média est obligatoire");
|
||||
}
|
||||
|
||||
if (mediaType == null) {
|
||||
System.out.println("[ERROR] Le type de média est obligatoire");
|
||||
throw new IllegalArgumentException("Le type de média est obligatoire");
|
||||
}
|
||||
|
||||
// Création de la story
|
||||
Story story = new Story(user, mediaType, mediaUrl);
|
||||
|
||||
if (thumbnailUrl != null && !thumbnailUrl.trim().isEmpty()) {
|
||||
story.setThumbnailUrl(thumbnailUrl);
|
||||
}
|
||||
|
||||
if (durationSeconds != null && durationSeconds > 0) {
|
||||
story.setDurationSeconds(durationSeconds);
|
||||
}
|
||||
|
||||
storyRepository.persist(story);
|
||||
System.out.println("[LOG] Story créée avec succès : " + story.getId());
|
||||
return story;
|
||||
}
|
||||
|
||||
/**
|
||||
* Récupère une story par son ID.
|
||||
*
|
||||
* @param storyId L'ID de la story
|
||||
* @return La story trouvée
|
||||
* @throws IllegalArgumentException Si la story n'existe pas
|
||||
*/
|
||||
public Story getStoryById(UUID storyId) {
|
||||
System.out.println("[LOG] Récupération de la story ID : " + storyId);
|
||||
|
||||
Story story = storyRepository.findById(storyId);
|
||||
if (story == null) {
|
||||
System.out.println("[ERROR] Story non trouvée avec l'ID : " + storyId);
|
||||
throw new IllegalArgumentException("Story non trouvée avec l'ID : " + storyId);
|
||||
}
|
||||
|
||||
return story;
|
||||
}
|
||||
|
||||
/**
|
||||
* Marque une story comme vue par un utilisateur.
|
||||
*
|
||||
* @param storyId L'ID de la story
|
||||
* @param viewerId L'ID de l'utilisateur qui voit la story
|
||||
* @return La story mise à jour
|
||||
* @throws UserNotFoundException Si l'utilisateur n'existe pas
|
||||
* @throws IllegalArgumentException Si la story n'existe pas
|
||||
*/
|
||||
@Transactional
|
||||
public Story markStoryAsViewed(UUID storyId, UUID viewerId) {
|
||||
System.out.println("[LOG] Marquage de la story ID : " + storyId + " comme vue par l'utilisateur ID : " + viewerId);
|
||||
|
||||
// Validation de l'utilisateur
|
||||
Users viewer = usersRepository.findById(viewerId);
|
||||
if (viewer == null) {
|
||||
System.out.println("[ERROR] Utilisateur non trouvé avec l'ID : " + viewerId);
|
||||
throw new UserNotFoundException("Utilisateur non trouvé avec l'ID : " + viewerId);
|
||||
}
|
||||
|
||||
// Validation de la story
|
||||
Story story = storyRepository.findById(storyId);
|
||||
if (story == null) {
|
||||
System.out.println("[ERROR] Story non trouvée avec l'ID : " + storyId);
|
||||
throw new IllegalArgumentException("Story non trouvée avec l'ID : " + storyId);
|
||||
}
|
||||
|
||||
// Marquer comme vue
|
||||
boolean isNewView = story.markAsViewed(viewerId);
|
||||
if (isNewView) {
|
||||
storyRepository.persist(story);
|
||||
System.out.println("[LOG] Story marquée comme vue (nouvelle vue)");
|
||||
} else {
|
||||
System.out.println("[LOG] Story déjà vue par cet utilisateur");
|
||||
}
|
||||
|
||||
return story;
|
||||
}
|
||||
|
||||
/**
|
||||
* Supprime une story.
|
||||
*
|
||||
* @param storyId L'ID de la story
|
||||
* @return true si la story a été supprimée, false sinon
|
||||
*/
|
||||
@Transactional
|
||||
public boolean deleteStory(UUID storyId) {
|
||||
System.out.println("[LOG] Suppression de la story ID : " + storyId);
|
||||
|
||||
Story story = storyRepository.findById(storyId);
|
||||
if (story == null) {
|
||||
System.out.println("[ERROR] Story non trouvée avec l'ID : " + storyId);
|
||||
return false;
|
||||
}
|
||||
|
||||
storyRepository.delete(story);
|
||||
System.out.println("[LOG] Story supprimée avec succès");
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Désactive toutes les stories expirées.
|
||||
* Cette méthode doit être appelée périodiquement par un job schedulé.
|
||||
*
|
||||
* @return Le nombre de stories désactivées
|
||||
*/
|
||||
@Transactional
|
||||
public int deactivateExpiredStories() {
|
||||
System.out.println("[LOG] Désactivation des stories expirées");
|
||||
return storyRepository.deactivateExpiredStories();
|
||||
}
|
||||
|
||||
/**
|
||||
* Récupère les stories les plus vues.
|
||||
*
|
||||
* @param limit Le nombre maximum de stories à retourner
|
||||
* @return Liste des stories les plus vues
|
||||
*/
|
||||
public List<Story> getMostViewedStories(int limit) {
|
||||
System.out.println("[LOG] Récupération des " + limit + " stories les plus vues");
|
||||
return storyRepository.findMostViewedStories(limit);
|
||||
}
|
||||
}
|
||||
@@ -191,4 +191,21 @@ public class UsersService {
|
||||
}
|
||||
return deleted;
|
||||
}
|
||||
|
||||
/**
|
||||
* Recherche un utilisateur par son email.
|
||||
*
|
||||
* @param email L'email de l'utilisateur à rechercher.
|
||||
* @return L'utilisateur trouvé.
|
||||
* @throws UserNotFoundException Si l'utilisateur n'est pas trouvé.
|
||||
*/
|
||||
public Users getUserByEmail(String email) {
|
||||
Optional<Users> userOptional = usersRepository.findByEmail(email);
|
||||
if (userOptional.isEmpty()) {
|
||||
System.out.println("[ERROR] Utilisateur non trouvé avec l'email : " + email);
|
||||
throw new UserNotFoundException("Utilisateur non trouvé avec l'email : " + email);
|
||||
}
|
||||
System.out.println("[LOG] Utilisateur trouvé avec l'email : " + email);
|
||||
return userOptional.get();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user