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:
dahoud
2026-01-10 10:39:58 +00:00
parent fd67140961
commit 093d04c224
60 changed files with 14652 additions and 220 deletions

View File

@@ -834,5 +834,39 @@ public class EventsResource {
return Response.ok("L'événement a été réouvert avec succès.").build();
}
/**
* Endpoint pour récupérer les événements de l'utilisateur et de ses amis.
*
* @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
*/
@GET
@Path("/friends/{userId}")
@Operation(
summary = "Récupérer les événements des amis",
description = "Retourne les événements créés par l'utilisateur et ses amis (relations d'amitié acceptées)")
public Response getEventsByFriends(
@PathParam("userId") UUID userId,
@QueryParam("page") @DefaultValue("0") int page,
@QueryParam("size") @DefaultValue("20") int size) {
LOG.info("[LOG] Récupération des événements des amis pour l'utilisateur ID : " + userId);
try {
List<Events> events = eventService.getEventsByFriends(userId, page, size);
List<EventCreateResponseDTO> responseDTOs = events.stream()
.map(EventCreateResponseDTO::new)
.collect(Collectors.toList());
return Response.ok(responseDTOs).build();
} catch (Exception e) {
LOG.error("[ERROR] Erreur lors de la récupération des événements des amis : " + e.getMessage(), e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity("{\"message\": \"Erreur lors de la récupération des événements des amis.\"}")
.build();
}
}
}

View File

@@ -486,4 +486,53 @@ public class FriendshipResource {
.build();
}
}
/**
* Récupérer les suggestions d'amis pour un utilisateur.
*
* @param userId ID de l'utilisateur.
* @param limit Nombre maximum de suggestions (optionnel, par défaut 10).
* @return Liste des suggestions d'amis.
*/
@GET
@Path("/suggestions/{userId}")
@Operation(
summary = "Récupérer les suggestions d'amis",
description = "Retourne une liste d'utilisateurs suggérés comme amis potentiels basée sur les amis en commun")
@APIResponses({
@APIResponse(
responseCode = "200",
description = "Suggestions d'amis récupérées",
content =
@Content(
mediaType = MediaType.APPLICATION_JSON,
schema = @Schema(implementation = com.lions.dev.dto.response.users.FriendSuggestionResponseDTO.class))),
@APIResponse(responseCode = "404", description = "Utilisateur non trouvé"),
@APIResponse(
responseCode = "500",
description = "Erreur lors de la récupération des suggestions d'amis")
})
public Response getFriendSuggestions(
@PathParam("userId") UUID userId,
@QueryParam("limit") @DefaultValue("10") int limit) {
logger.info("[LOG] Récupération des suggestions d'amis pour l'utilisateur : " + userId);
try {
List<com.lions.dev.dto.response.users.FriendSuggestionResponseDTO> suggestions =
friendshipService.getFriendSuggestions(userId, limit);
logger.info("[LOG] " + suggestions.size() + " suggestions d'amis récupérées avec succès.");
return Response.ok(suggestions).build();
} catch (UserNotFoundException e) {
logger.error("[ERROR] Utilisateur non trouvé : " + e.getMessage());
return Response.status(Response.Status.NOT_FOUND)
.entity("{\"message\": \"Utilisateur non trouvé.\"}")
.build();
} catch (Exception e) {
logger.error(
"[ERROR] Erreur lors de la récupération des suggestions d'amis : " + e.getMessage(), e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity("{\"message\": \"Erreur lors de la récupération des suggestions d'amis.\"}")
.build();
}
}
}

View File

@@ -0,0 +1,333 @@
package com.lions.dev.resource;
import com.lions.dev.dto.request.chat.SendMessageRequestDTO;
import com.lions.dev.dto.response.chat.ConversationResponseDTO;
import com.lions.dev.dto.response.chat.MessageResponseDTO;
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.repository.UsersRepository;
import com.lions.dev.service.MessageService;
import jakarta.inject.Inject;
import jakarta.ws.rs.*;
import jakarta.ws.rs.core.MediaType;
import jakarta.ws.rs.core.Response;
import org.eclipse.microprofile.openapi.annotations.Operation;
import org.eclipse.microprofile.openapi.annotations.tags.Tag;
import org.jboss.logging.Logger;
import java.util.List;
import java.util.UUID;
import java.util.stream.Collectors;
/**
* Resource REST pour la gestion des messages et conversations.
*
* Cette classe expose les endpoints HTTP pour:
* - Envoyer des messages
* - Récupérer les conversations
* - Récupérer les messages d'une conversation
* - Marquer les messages comme lus
* - Supprimer des messages et conversations
*/
@Path("/messages")
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
@Tag(name = "Messages", description = "Gestion des messages et conversations")
public class MessageResource {
private static final Logger LOG = Logger.getLogger(MessageResource.class);
@Inject
MessageService messageService;
@Inject
UsersRepository usersRepository;
/**
* Envoie un nouveau message.
*
* @param request Le DTO contenant les informations du message
* @return Le message créé
*/
@POST
@Operation(summary = "Envoyer un message", description = "Envoie un nouveau message à un utilisateur")
public Response sendMessage(SendMessageRequestDTO request) {
LOG.info("[LOG] Réception d'une demande d'envoi de message");
try {
// Validation
if (!request.isValid()) {
return Response.status(Response.Status.BAD_REQUEST)
.entity("{\"message\": \"Données invalides\"}")
.build();
}
// Envoyer le message
Message message = messageService.sendMessage(
request.getSenderId(),
request.getRecipientId(),
request.getContent(),
request.getMessageType(),
request.getMediaUrl()
);
MessageResponseDTO response = new MessageResponseDTO(message);
return Response.status(Response.Status.CREATED).entity(response).build();
} catch (Exception e) {
LOG.error("[ERROR] Erreur lors de l'envoi du message : " + e.getMessage(), e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity("{\"message\": \"Erreur lors de l'envoi du message\"}")
.build();
}
}
/**
* Récupère toutes les conversations d'un utilisateur.
*
* @param userId L'ID de l'utilisateur
* @return Liste des conversations
*/
@GET
@Path("/conversations/{userId}")
@Operation(summary = "Récupérer les conversations", description = "Récupère toutes les conversations d'un utilisateur")
public Response getUserConversations(@PathParam("userId") UUID userId) {
LOG.info("[LOG] Récupération des conversations pour l'utilisateur ID : " + userId);
try {
Users user = usersRepository.findById(userId);
if (user == null) {
return Response.status(Response.Status.NOT_FOUND)
.entity("{\"message\": \"Utilisateur non trouvé\"}")
.build();
}
List<Conversation> conversations = messageService.getUserConversations(userId);
List<ConversationResponseDTO> response = conversations.stream()
.map(conv -> new ConversationResponseDTO(conv, user))
.collect(Collectors.toList());
return Response.ok(response).build();
} catch (Exception e) {
LOG.error("[ERROR] Erreur lors de la récupération des conversations : " + e.getMessage(), e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity("{\"message\": \"Erreur lors de la récupération des conversations\"}")
.build();
}
}
/**
* Récupère les messages d'une conversation.
*
* @param conversationId L'ID de la conversation
* @param page Le numéro de la page (défaut: 0)
* @param size La taille de la page (défaut: 50)
* @return Liste des messages
*/
@GET
@Path("/conversation/{conversationId}")
@Operation(summary = "Récupérer les messages", description = "Récupère les messages d'une conversation avec pagination")
public Response getConversationMessages(
@PathParam("conversationId") UUID conversationId,
@QueryParam("page") @DefaultValue("0") int page,
@QueryParam("size") @DefaultValue("50") int size) {
LOG.info("[LOG] Récupération des messages pour la conversation ID : " + conversationId);
try {
List<Message> messages = messageService.getConversationMessages(conversationId, page, size);
List<MessageResponseDTO> response = messages.stream()
.map(MessageResponseDTO::new)
.collect(Collectors.toList());
return Response.ok(response).build();
} catch (Exception e) {
LOG.error("[ERROR] Erreur lors de la récupération des messages : " + e.getMessage(), e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity("{\"message\": \"Erreur lors de la récupération des messages\"}")
.build();
}
}
/**
* 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
*/
@GET
@Path("/conversation/between/{user1Id}/{user2Id}")
@Operation(summary = "Récupérer une conversation", description = "Récupère la conversation entre deux utilisateurs")
public Response getConversationBetweenUsers(
@PathParam("user1Id") UUID user1Id,
@PathParam("user2Id") UUID user2Id) {
LOG.info("[LOG] Recherche de conversation entre " + user1Id + " et " + user2Id);
try {
Users user1 = usersRepository.findById(user1Id);
if (user1 == null) {
return Response.status(Response.Status.NOT_FOUND)
.entity("{\"message\": \"Utilisateur non trouvé\"}")
.build();
}
Conversation conversation = messageService.getConversationBetweenUsers(user1Id, user2Id);
if (conversation == null) {
return Response.status(Response.Status.NOT_FOUND)
.entity("{\"message\": \"Conversation non trouvée\"}")
.build();
}
ConversationResponseDTO response = new ConversationResponseDTO(conversation, user1);
return Response.ok(response).build();
} catch (Exception e) {
LOG.error("[ERROR] Erreur lors de la récupération de la conversation : " + e.getMessage(), e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity("{\"message\": \"Erreur lors de la récupération de la conversation\"}")
.build();
}
}
/**
* Marque un message comme lu.
*
* @param messageId L'ID du message
* @return Le message mis à jour
*/
@PUT
@Path("/{messageId}/read")
@Operation(summary = "Marquer comme lu", description = "Marque un message comme lu")
public Response markMessageAsRead(@PathParam("messageId") UUID messageId) {
LOG.info("[LOG] Marquage du message comme lu : " + messageId);
try {
Message message = messageService.markMessageAsRead(messageId);
MessageResponseDTO response = new MessageResponseDTO(message);
return Response.ok(response).build();
} catch (Exception e) {
LOG.error("[ERROR] Erreur lors du marquage du message : " + e.getMessage(), e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity("{\"message\": \"Erreur lors du marquage du message\"}")
.build();
}
}
/**
* Marque tous les messages d'une conversation comme lus.
*
* @param conversationId L'ID de la conversation
* @param userId L'ID de l'utilisateur
* @return Le nombre de messages marqués comme lus
*/
@PUT
@Path("/conversation/{conversationId}/read/{userId}")
@Operation(summary = "Marquer tout comme lu", description = "Marque tous les messages d'une conversation comme lus")
public Response markAllMessagesAsRead(
@PathParam("conversationId") UUID conversationId,
@PathParam("userId") UUID userId) {
LOG.info("[LOG] Marquage de tous les messages comme lus pour la conversation " + conversationId);
try {
int count = messageService.markAllMessagesAsRead(conversationId, userId);
return Response.ok("{\"messagesMarkedAsRead\": " + count + "}").build();
} catch (Exception e) {
LOG.error("[ERROR] Erreur lors du marquage des messages : " + e.getMessage(), e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity("{\"message\": \"Erreur lors du marquage des messages\"}")
.build();
}
}
/**
* Récupère le nombre total de messages non lus pour un utilisateur.
*
* @param userId L'ID de l'utilisateur
* @return Le nombre de messages non lus
*/
@GET
@Path("/unread/count/{userId}")
@Operation(summary = "Compter les non lus", description = "Compte le nombre total de messages non lus")
public Response getTotalUnreadCount(@PathParam("userId") UUID userId) {
LOG.info("[LOG] Récupération du nombre de messages non lus pour l'utilisateur " + userId);
try {
long count = messageService.getTotalUnreadCount(userId);
return Response.ok("{\"unreadCount\": " + count + "}").build();
} catch (Exception e) {
LOG.error("[ERROR] Erreur lors du comptage des messages non lus : " + e.getMessage(), e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity("{\"message\": \"Erreur lors du comptage\"}")
.build();
}
}
/**
* Supprime un message.
*
* @param messageId L'ID du message
* @return Confirmation de suppression
*/
@DELETE
@Path("/{messageId}")
@Operation(summary = "Supprimer un message", description = "Supprime un message")
public Response deleteMessage(@PathParam("messageId") UUID messageId) {
LOG.info("[LOG] Suppression du message ID : " + messageId);
try {
boolean deleted = messageService.deleteMessage(messageId);
if (deleted) {
return Response.ok("{\"message\": \"Message supprimé avec succès\"}").build();
} else {
return Response.status(Response.Status.NOT_FOUND)
.entity("{\"message\": \"Message non trouvé\"}")
.build();
}
} catch (Exception e) {
LOG.error("[ERROR] Erreur lors de la suppression du message : " + e.getMessage(), e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity("{\"message\": \"Erreur lors de la suppression\"}")
.build();
}
}
/**
* Supprime une conversation.
*
* @param conversationId L'ID de la conversation
* @return Confirmation de suppression
*/
@DELETE
@Path("/conversation/{conversationId}")
@Operation(summary = "Supprimer une conversation", description = "Supprime une conversation et tous ses messages")
public Response deleteConversation(@PathParam("conversationId") UUID conversationId) {
LOG.info("[LOG] Suppression de la conversation ID : " + conversationId);
try {
boolean deleted = messageService.deleteConversation(conversationId);
if (deleted) {
return Response.ok("{\"message\": \"Conversation supprimée avec succès\"}").build();
} else {
return Response.status(Response.Status.NOT_FOUND)
.entity("{\"message\": \"Conversation non trouvée\"}")
.build();
}
} catch (Exception e) {
LOG.error("[ERROR] Erreur lors de la suppression de la conversation : " + e.getMessage(), e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity("{\"message\": \"Erreur lors de la suppression\"}")
.build();
}
}
}

View File

@@ -0,0 +1,247 @@
package com.lions.dev.resource;
import com.lions.dev.dto.response.notifications.NotificationResponseDTO;
import com.lions.dev.entity.notification.Notification;
import com.lions.dev.service.NotificationService;
import jakarta.inject.Inject;
import jakarta.transaction.Transactional;
import jakarta.ws.rs.*;
import jakarta.ws.rs.core.MediaType;
import jakarta.ws.rs.core.Response;
import java.util.List;
import java.util.UUID;
import java.util.stream.Collectors;
import org.eclipse.microprofile.openapi.annotations.Operation;
import org.eclipse.microprofile.openapi.annotations.tags.Tag;
import org.jboss.logging.Logger;
/**
* Ressource REST pour la gestion des notifications dans le système AfterWork.
*
* Cette classe expose des endpoints pour créer, récupérer, mettre à jour
* et supprimer des notifications.
*
* Tous les logs nécessaires pour la traçabilité sont intégrés.
*/
@Path("/notifications")
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
@Tag(name = "Notifications", description = "Opérations liées à la gestion des notifications")
public class NotificationResource {
@Inject
NotificationService notificationService;
private static final Logger LOG = Logger.getLogger(NotificationResource.class);
/**
* Récupère toutes les notifications d'un utilisateur.
*
* @param userId L'ID de l'utilisateur
* @return Liste des notifications de l'utilisateur
*/
@GET
@Path("/user/{userId}")
@Operation(
summary = "Récupérer les notifications d'un utilisateur",
description = "Retourne la liste de toutes les notifications d'un utilisateur, triées par date de création décroissante")
public Response getNotificationsByUserId(@PathParam("userId") UUID userId) {
LOG.info("[LOG] Récupération des notifications pour l'utilisateur ID : " + userId);
try {
List<Notification> notifications = notificationService.getNotificationsByUserId(userId);
List<NotificationResponseDTO> responseDTOs = notifications.stream()
.map(NotificationResponseDTO::new)
.collect(Collectors.toList());
LOG.info("[LOG] " + responseDTOs.size() + " notification(s) récupérée(s) pour l'utilisateur ID : " + userId);
return Response.ok(responseDTOs).build();
} catch (Exception e) {
LOG.error("[ERROR] Erreur lors de la récupération des notifications : " + e.getMessage(), e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity("{\"message\": \"Erreur lors de la récupération des notifications.\"}")
.build();
}
}
/**
* 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
*/
@GET
@Path("/user/{userId}/paginated")
@Operation(
summary = "Récupérer les notifications d'un utilisateur avec pagination",
description = "Retourne une liste paginée des notifications d'un utilisateur")
public Response getNotificationsByUserIdWithPagination(
@PathParam("userId") UUID userId,
@QueryParam("page") @DefaultValue("0") int page,
@QueryParam("size") @DefaultValue("20") int size) {
LOG.info("[LOG] Récupération paginée des notifications pour l'utilisateur ID : " + userId);
try {
List<Notification> notifications = notificationService.getNotificationsByUserIdWithPagination(userId, page, size);
List<NotificationResponseDTO> responseDTOs = notifications.stream()
.map(NotificationResponseDTO::new)
.collect(Collectors.toList());
return Response.ok(responseDTOs).build();
} catch (Exception e) {
LOG.error("[ERROR] Erreur lors de la récupération paginée des notifications : " + e.getMessage(), e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity("{\"message\": \"Erreur lors de la récupération des notifications.\"}")
.build();
}
}
/**
* Marque une notification comme lue.
*
* @param notificationId L'ID de la notification
* @return La notification mise à jour
*/
@PUT
@Path("/{id}/read")
@Transactional
@Operation(
summary = "Marquer une notification comme lue",
description = "Marque une notification spécifique comme lue")
public Response markAsRead(@PathParam("id") UUID notificationId) {
LOG.info("[LOG] Marquage de la notification ID : " + notificationId + " comme lue");
try {
Notification notification = notificationService.markAsRead(notificationId);
NotificationResponseDTO responseDTO = new NotificationResponseDTO(notification);
return Response.ok(responseDTO).build();
} catch (IllegalArgumentException e) {
LOG.warn("[WARN] Notification non trouvée : " + e.getMessage());
return Response.status(Response.Status.NOT_FOUND)
.entity("{\"message\": \"Notification non trouvée.\"}")
.build();
} catch (Exception e) {
LOG.error("[ERROR] Erreur lors du marquage de la notification : " + e.getMessage(), e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity("{\"message\": \"Erreur lors du marquage de la notification.\"}")
.build();
}
}
/**
* Marque toutes les notifications d'un utilisateur comme lues.
*
* @param userId L'ID de l'utilisateur
* @return Nombre de notifications mises à jour
*/
@PUT
@Path("/user/{userId}/mark-all-read")
@Transactional
@Operation(
summary = "Marquer toutes les notifications comme lues",
description = "Marque toutes les notifications d'un utilisateur comme lues")
public Response markAllAsRead(@PathParam("userId") UUID userId) {
LOG.info("[LOG] Marquage de toutes les notifications comme lues pour l'utilisateur ID : " + userId);
try {
int updated = notificationService.markAllAsRead(userId);
return Response.ok("{\"message\": \"" + updated + " notification(s) marquée(s) comme lue(s).\"}").build();
} catch (Exception e) {
LOG.error("[ERROR] Erreur lors du marquage de toutes les notifications : " + e.getMessage(), e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity("{\"message\": \"Erreur lors du marquage des notifications.\"}")
.build();
}
}
/**
* Supprime une notification.
*
* @param notificationId L'ID de la notification
* @return Réponse de confirmation
*/
@DELETE
@Path("/{id}")
@Transactional
@Operation(
summary = "Supprimer une notification",
description = "Supprime une notification spécifique")
public Response deleteNotification(@PathParam("id") UUID notificationId) {
LOG.info("[LOG] Suppression de la notification ID : " + notificationId);
try {
boolean deleted = notificationService.deleteNotification(notificationId);
if (deleted) {
return Response.noContent().build();
} else {
return Response.status(Response.Status.NOT_FOUND)
.entity("{\"message\": \"Notification non trouvée.\"}")
.build();
}
} catch (Exception e) {
LOG.error("[ERROR] Erreur lors de la suppression de la notification : " + e.getMessage(), e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity("{\"message\": \"Erreur lors de la suppression de la notification.\"}")
.build();
}
}
/**
* Récupère une notification par son ID.
*
* @param notificationId L'ID de la notification
* @return La notification trouvée
*/
@GET
@Path("/{id}")
@Operation(
summary = "Récupérer une notification par ID",
description = "Retourne les détails d'une notification spécifique")
public Response getNotificationById(@PathParam("id") UUID notificationId) {
LOG.info("[LOG] Récupération de la notification ID : " + notificationId);
try {
Notification notification = notificationService.getNotificationById(notificationId);
NotificationResponseDTO responseDTO = new NotificationResponseDTO(notification);
return Response.ok(responseDTO).build();
} catch (IllegalArgumentException e) {
LOG.warn("[WARN] Notification non trouvée : " + e.getMessage());
return Response.status(Response.Status.NOT_FOUND)
.entity("{\"message\": \"Notification non trouvée.\"}")
.build();
} catch (Exception e) {
LOG.error("[ERROR] Erreur lors de la récupération de la notification : " + e.getMessage(), e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity("{\"message\": \"Erreur lors de la récupération de la notification.\"}")
.build();
}
}
/**
* Compte le nombre de notifications non lues d'un utilisateur.
*
* @param userId L'ID de l'utilisateur
* @return Le nombre de notifications non lues
*/
@GET
@Path("/user/{userId}/unread-count")
@Operation(
summary = "Compter les notifications non lues",
description = "Retourne le nombre de notifications non lues d'un utilisateur")
public Response getUnreadCount(@PathParam("userId") UUID userId) {
LOG.info("[LOG] Comptage des notifications non lues pour l'utilisateur ID : " + userId);
try {
long count = notificationService.countUnreadNotifications(userId);
return Response.ok("{\"count\": " + count + "}").build();
} catch (Exception e) {
LOG.error("[ERROR] Erreur lors du comptage des notifications : " + e.getMessage(), e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity("{\"message\": \"Erreur lors du comptage des notifications.\"}")
.build();
}
}
}

View File

@@ -0,0 +1,394 @@
package com.lions.dev.resource;
import com.lions.dev.dto.request.social.SocialPostCreateRequestDTO;
import com.lions.dev.dto.response.social.SocialPostResponseDTO;
import com.lions.dev.entity.social.SocialPost;
import com.lions.dev.service.SocialPostService;
import jakarta.inject.Inject;
import jakarta.transaction.Transactional;
import jakarta.validation.Valid;
import jakarta.ws.rs.*;
import jakarta.ws.rs.core.MediaType;
import jakarta.ws.rs.core.Response;
import java.util.List;
import java.util.UUID;
import java.util.stream.Collectors;
import org.eclipse.microprofile.openapi.annotations.Operation;
import org.eclipse.microprofile.openapi.annotations.tags.Tag;
import org.jboss.logging.Logger;
/**
* Ressource REST pour la gestion des posts sociaux dans le système AfterWork.
*
* Cette classe expose des endpoints pour créer, récupérer, mettre à jour,
* supprimer et rechercher des posts sociaux.
*
* Tous les logs nécessaires pour la traçabilité sont intégrés.
*/
@Path("/posts")
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
@Tag(name = "Social Posts", description = "Opérations liées à la gestion des posts sociaux")
public class SocialPostResource {
@Inject
SocialPostService socialPostService;
private static final Logger LOG = Logger.getLogger(SocialPostResource.class);
/**
* 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
*/
@GET
@Operation(
summary = "Récupérer tous les posts",
description = "Retourne une liste paginée de tous les posts sociaux, triés par date de création décroissante")
public Response getAllPosts(
@QueryParam("page") @DefaultValue("0") int page,
@QueryParam("size") @DefaultValue("20") int size) {
LOG.info("[LOG] Récupération de tous les posts (page: " + page + ", size: " + size + ")");
try {
List<SocialPost> posts = socialPostService.getAllPosts(page, size);
List<SocialPostResponseDTO> responseDTOs = posts.stream()
.map(SocialPostResponseDTO::new)
.collect(Collectors.toList());
return Response.ok(responseDTOs).build();
} catch (Exception e) {
LOG.error("[ERROR] Erreur lors de la récupération des posts : " + e.getMessage(), e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity("{\"message\": \"Erreur lors de la récupération des posts.\"}")
.build();
}
}
/**
* Récupère un post par son ID.
*
* @param postId L'ID du post
* @return Le post trouvé
*/
@GET
@Path("/{id}")
@Operation(
summary = "Récupérer un post par ID",
description = "Retourne les détails d'un post social spécifique")
public Response getPostById(@PathParam("id") UUID postId) {
LOG.info("[LOG] Récupération du post ID : " + postId);
try {
SocialPost post = socialPostService.getPostById(postId);
SocialPostResponseDTO responseDTO = new SocialPostResponseDTO(post);
return Response.ok(responseDTO).build();
} catch (IllegalArgumentException e) {
LOG.warn("[WARN] Post non trouvé : " + e.getMessage());
return Response.status(Response.Status.NOT_FOUND)
.entity("{\"message\": \"Post non trouvé.\"}")
.build();
} catch (Exception e) {
LOG.error("[ERROR] Erreur lors de la récupération du post : " + e.getMessage(), e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity("{\"message\": \"Erreur lors de la récupération du post.\"}")
.build();
}
}
/**
* Crée un nouveau post social.
*
* @param requestDTO Le DTO contenant les informations du post à créer
* @return Le post créé
*/
@POST
@Transactional
@Operation(
summary = "Créer un nouveau post",
description = "Crée un nouveau post social et retourne ses détails")
public Response createPost(@Valid SocialPostCreateRequestDTO requestDTO) {
LOG.info("[LOG] Création d'un nouveau post par l'utilisateur ID : " + requestDTO.getUserId());
try {
SocialPost post = socialPostService.createPost(
requestDTO.getContent(),
requestDTO.getUserId(),
requestDTO.getImageUrl()
);
SocialPostResponseDTO responseDTO = new SocialPostResponseDTO(post);
return Response.status(Response.Status.CREATED).entity(responseDTO).build();
} catch (Exception e) {
LOG.error("[ERROR] Erreur lors de la création du post : " + e.getMessage(), e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity("{\"message\": \"Erreur lors de la création du post.\"}")
.build();
}
}
/**
* 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
*/
@PUT
@Path("/{id}")
@Transactional
@Operation(
summary = "Mettre à jour un post",
description = "Met à jour le contenu et/ou l'image d'un post existant")
public Response updatePost(
@PathParam("id") UUID postId,
@QueryParam("content") String content,
@QueryParam("imageUrl") String imageUrl) {
LOG.info("[LOG] Mise à jour du post ID : " + postId);
try {
SocialPost post = socialPostService.updatePost(postId, content, imageUrl);
SocialPostResponseDTO responseDTO = new SocialPostResponseDTO(post);
return Response.ok(responseDTO).build();
} catch (IllegalArgumentException e) {
LOG.warn("[WARN] Post non trouvé : " + e.getMessage());
return Response.status(Response.Status.NOT_FOUND)
.entity("{\"message\": \"Post non trouvé.\"}")
.build();
} catch (Exception e) {
LOG.error("[ERROR] Erreur lors de la mise à jour du post : " + e.getMessage(), e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity("{\"message\": \"Erreur lors de la mise à jour du post.\"}")
.build();
}
}
/**
* Supprime un post.
*
* @param postId L'ID du post
* @return Réponse de confirmation
*/
@DELETE
@Path("/{id}")
@Transactional
@Operation(
summary = "Supprimer un post",
description = "Supprime un post social spécifique")
public Response deletePost(@PathParam("id") UUID postId) {
LOG.info("[LOG] Suppression du post ID : " + postId);
try {
boolean deleted = socialPostService.deletePost(postId);
if (deleted) {
return Response.noContent().build();
} else {
return Response.status(Response.Status.NOT_FOUND)
.entity("{\"message\": \"Post non trouvé.\"}")
.build();
}
} catch (Exception e) {
LOG.error("[ERROR] Erreur lors de la suppression du post : " + e.getMessage(), e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity("{\"message\": \"Erreur lors de la suppression du post.\"}")
.build();
}
}
/**
* Recherche des posts par contenu.
*
* @param query Le terme de recherche
* @return Liste des posts correspondant à la recherche
*/
@GET
@Path("/search")
@Operation(
summary = "Rechercher des posts",
description = "Recherche des posts sociaux par contenu textuel")
public Response searchPosts(@QueryParam("q") String query) {
LOG.info("[LOG] Recherche de posts avec la requête : " + query);
if (query == null || query.trim().isEmpty()) {
return Response.status(Response.Status.BAD_REQUEST)
.entity("{\"message\": \"Le paramètre de recherche 'q' est requis.\"}")
.build();
}
try {
List<SocialPost> posts = socialPostService.searchPosts(query);
List<SocialPostResponseDTO> responseDTOs = posts.stream()
.map(SocialPostResponseDTO::new)
.collect(Collectors.toList());
return Response.ok(responseDTOs).build();
} catch (Exception e) {
LOG.error("[ERROR] Erreur lors de la recherche de posts : " + e.getMessage(), e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity("{\"message\": \"Erreur lors de la recherche de posts.\"}")
.build();
}
}
/**
* Like un post.
*
* @param postId L'ID du post
* @return Le post mis à jour
*/
@POST
@Path("/{id}/like")
@Transactional
@Operation(
summary = "Liker un post",
description = "Incrémente le compteur de likes d'un post")
public Response likePost(@PathParam("id") UUID postId) {
LOG.info("[LOG] Like du post ID : " + postId);
try {
SocialPost post = socialPostService.likePost(postId);
SocialPostResponseDTO responseDTO = new SocialPostResponseDTO(post);
return Response.ok(responseDTO).build();
} catch (IllegalArgumentException e) {
LOG.warn("[WARN] Post non trouvé : " + e.getMessage());
return Response.status(Response.Status.NOT_FOUND)
.entity("{\"message\": \"Post non trouvé.\"}")
.build();
} catch (Exception e) {
LOG.error("[ERROR] Erreur lors du like du post : " + e.getMessage(), e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity("{\"message\": \"Erreur lors du like du post.\"}")
.build();
}
}
/**
* Ajoute un commentaire à un post.
*
* @param postId L'ID du post
* @return Le post mis à jour
*/
@POST
@Path("/{id}/comment")
@Transactional
@Operation(
summary = "Commenter un post",
description = "Incrémente le compteur de commentaires d'un post")
public Response addComment(@PathParam("id") UUID postId) {
LOG.info("[LOG] Ajout de commentaire au post ID : " + postId);
try {
SocialPost post = socialPostService.addComment(postId);
SocialPostResponseDTO responseDTO = new SocialPostResponseDTO(post);
return Response.ok(responseDTO).build();
} catch (IllegalArgumentException e) {
LOG.warn("[WARN] Post non trouvé : " + e.getMessage());
return Response.status(Response.Status.NOT_FOUND)
.entity("{\"message\": \"Post non trouvé.\"}")
.build();
} catch (Exception e) {
LOG.error("[ERROR] Erreur lors de l'ajout du commentaire : " + e.getMessage(), e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity("{\"message\": \"Erreur lors de l'ajout du commentaire.\"}")
.build();
}
}
/**
* Partage un post.
*
* @param postId L'ID du post
* @return Le post mis à jour
*/
@POST
@Path("/{id}/share")
@Transactional
@Operation(
summary = "Partager un post",
description = "Incrémente le compteur de partages d'un post")
public Response sharePost(@PathParam("id") UUID postId) {
LOG.info("[LOG] Partage du post ID : " + postId);
try {
SocialPost post = socialPostService.sharePost(postId);
SocialPostResponseDTO responseDTO = new SocialPostResponseDTO(post);
return Response.ok(responseDTO).build();
} catch (IllegalArgumentException e) {
LOG.warn("[WARN] Post non trouvé : " + e.getMessage());
return Response.status(Response.Status.NOT_FOUND)
.entity("{\"message\": \"Post non trouvé.\"}")
.build();
} catch (Exception e) {
LOG.error("[ERROR] Erreur lors du partage du post : " + e.getMessage(), e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity("{\"message\": \"Erreur lors du partage du post.\"}")
.build();
}
}
/**
* Récupère tous les posts d'un utilisateur.
*
* @param userId L'ID de l'utilisateur
* @return Liste des posts de l'utilisateur
*/
@GET
@Path("/user/{userId}")
@Operation(
summary = "Récupérer les posts d'un utilisateur",
description = "Retourne tous les posts créés par un utilisateur spécifique")
public Response getPostsByUserId(@PathParam("userId") UUID userId) {
LOG.info("[LOG] Récupération des posts pour l'utilisateur ID : " + userId);
try {
List<SocialPost> posts = socialPostService.getPostsByUserId(userId);
List<SocialPostResponseDTO> responseDTOs = posts.stream()
.map(SocialPostResponseDTO::new)
.collect(Collectors.toList());
return Response.ok(responseDTOs).build();
} catch (Exception e) {
LOG.error("[ERROR] Erreur lors de la récupération des posts : " + e.getMessage(), e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity("{\"message\": \"Erreur lors de la récupération des posts.\"}")
.build();
}
}
/**
* Récupère les posts de l'utilisateur et de ses amis.
*
* @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
*/
@GET
@Path("/friends/{userId}")
@Operation(
summary = "Récupérer les posts des amis",
description = "Retourne les posts de l'utilisateur et de ses amis (relations d'amitié acceptées)")
public Response getPostsByFriends(
@PathParam("userId") UUID userId,
@QueryParam("page") @DefaultValue("0") int page,
@QueryParam("size") @DefaultValue("20") int size) {
LOG.info("[LOG] Récupération des posts des amis pour l'utilisateur ID : " + userId);
try {
List<SocialPost> posts = socialPostService.getPostsByFriends(userId, page, size);
List<SocialPostResponseDTO> responseDTOs = posts.stream()
.map(SocialPostResponseDTO::new)
.collect(Collectors.toList());
return Response.ok(responseDTOs).build();
} catch (Exception e) {
LOG.error("[ERROR] Erreur lors de la récupération des posts des amis : " + e.getMessage(), e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity("{\"message\": \"Erreur lors de la récupération des posts des amis.\"}")
.build();
}
}
}

View File

@@ -0,0 +1,263 @@
package com.lions.dev.resource;
import com.lions.dev.dto.request.story.StoryCreateRequestDTO;
import com.lions.dev.dto.response.story.StoryResponseDTO;
import com.lions.dev.entity.story.Story;
import com.lions.dev.service.StoryService;
import jakarta.inject.Inject;
import jakarta.transaction.Transactional;
import jakarta.validation.Valid;
import jakarta.ws.rs.*;
import jakarta.ws.rs.core.MediaType;
import jakarta.ws.rs.core.Response;
import java.util.List;
import java.util.UUID;
import java.util.stream.Collectors;
import org.eclipse.microprofile.openapi.annotations.Operation;
import org.eclipse.microprofile.openapi.annotations.tags.Tag;
import org.jboss.logging.Logger;
/**
* Ressource REST pour la gestion des stories dans le système AfterWork.
*
* Cette classe expose des endpoints pour créer, récupérer, supprimer
* et marquer les stories comme vues.
*
* Tous les logs nécessaires pour la traçabilité sont intégrés.
*/
@Path("/stories")
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
@Tag(name = "Stories", description = "Opérations liées à la gestion des stories")
public class StoryResource {
@Inject
StoryService storyService;
private static final Logger LOG = Logger.getLogger(StoryResource.class);
/**
* Récupère toutes les stories actives (non expirées).
*
* @param viewerId ID de l'utilisateur actuel (optionnel) pour marquer les stories vues
* @return Liste des stories actives
*/
@GET
@Operation(
summary = "Récupérer toutes les stories actives",
description = "Retourne une liste de toutes les stories actives (non expirées), triées par date de création décroissante")
public Response getAllActiveStories(@QueryParam("viewerId") UUID viewerId) {
LOG.info("[LOG] Récupération de toutes les stories actives");
try {
List<Story> stories = storyService.getAllActiveStories();
List<StoryResponseDTO> responseDTOs = stories.stream()
.map(story -> viewerId != null ? new StoryResponseDTO(story, viewerId) : new StoryResponseDTO(story))
.collect(Collectors.toList());
return Response.ok(responseDTOs).build();
} catch (Exception e) {
LOG.error("[ERROR] Erreur lors de la récupération des stories : " + e.getMessage(), e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity("{\"message\": \"Erreur lors de la récupération des stories.\"}")
.build();
}
}
/**
* Récupère une story par son ID.
*
* @param storyId L'ID de la story
* @param viewerId ID de l'utilisateur actuel (optionnel)
* @return La story trouvée
*/
@GET
@Path("/{id}")
@Operation(
summary = "Récupérer une story par ID",
description = "Retourne les détails d'une story spécifique")
public Response getStoryById(@PathParam("id") UUID storyId, @QueryParam("viewerId") UUID viewerId) {
LOG.info("[LOG] Récupération de la story ID : " + storyId);
try {
Story story = storyService.getStoryById(storyId);
StoryResponseDTO responseDTO = viewerId != null
? new StoryResponseDTO(story, viewerId)
: new StoryResponseDTO(story);
return Response.ok(responseDTO).build();
} catch (IllegalArgumentException e) {
LOG.warn("[WARN] Story non trouvée : " + e.getMessage());
return Response.status(Response.Status.NOT_FOUND)
.entity("{\"message\": \"Story non trouvée.\"}")
.build();
} catch (Exception e) {
LOG.error("[ERROR] Erreur lors de la récupération de la story : " + e.getMessage(), e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity("{\"message\": \"Erreur lors de la récupération de la story.\"}")
.build();
}
}
/**
* Récupère toutes les stories actives d'un utilisateur.
*
* @param userId L'ID de l'utilisateur
* @param viewerId ID de l'utilisateur actuel (optionnel)
* @return Liste des stories actives de l'utilisateur
*/
@GET
@Path("/user/{userId}")
@Operation(
summary = "Récupérer les stories d'un utilisateur",
description = "Retourne toutes les stories actives d'un utilisateur spécifique")
public Response getStoriesByUserId(@PathParam("userId") UUID userId, @QueryParam("viewerId") UUID viewerId) {
LOG.info("[LOG] Récupération des stories pour l'utilisateur ID : " + userId);
try {
List<Story> stories = storyService.getActiveStoriesByUserId(userId);
List<StoryResponseDTO> responseDTOs = stories.stream()
.map(story -> viewerId != null ? new StoryResponseDTO(story, viewerId) : new StoryResponseDTO(story))
.collect(Collectors.toList());
return Response.ok(responseDTOs).build();
} catch (Exception e) {
LOG.error("[ERROR] Erreur lors de la récupération des stories : " + e.getMessage(), e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity("{\"message\": \"Erreur lors de la récupération des stories.\"}")
.build();
}
}
/**
* Crée une nouvelle story.
*
* @param requestDTO Le DTO contenant les informations de la story à créer
* @return La story créée
*/
@POST
@Transactional
@Operation(
summary = "Créer une nouvelle story",
description = "Crée une nouvelle story et retourne ses détails")
public Response createStory(@Valid StoryCreateRequestDTO requestDTO) {
LOG.info("[LOG] Création d'une nouvelle story par l'utilisateur ID : " + requestDTO.getUserId());
try {
Story story = storyService.createStory(
requestDTO.getUserId(),
requestDTO.getMediaType(),
requestDTO.getMediaUrl(),
requestDTO.getThumbnailUrl(),
requestDTO.getDurationSeconds()
);
StoryResponseDTO responseDTO = new StoryResponseDTO(story);
return Response.status(Response.Status.CREATED).entity(responseDTO).build();
} catch (Exception e) {
LOG.error("[ERROR] Erreur lors de la création de la story : " + e.getMessage(), e);
return Response.status(Response.Status.BAD_REQUEST)
.entity("{\"message\": \"" + e.getMessage() + "\"}")
.build();
}
}
/**
* 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
*/
@POST
@Path("/{id}/view")
@Transactional
@Operation(
summary = "Marquer une story comme vue",
description = "Marque une story comme vue par un utilisateur et incrémente le compteur de vues")
public Response markStoryAsViewed(@PathParam("id") UUID storyId, @QueryParam("userId") UUID viewerId) {
LOG.info("[LOG] Marquage de la story ID : " + storyId + " comme vue par l'utilisateur ID : " + viewerId);
if (viewerId == null) {
return Response.status(Response.Status.BAD_REQUEST)
.entity("{\"message\": \"L'ID de l'utilisateur est obligatoire.\"}")
.build();
}
try {
Story story = storyService.markStoryAsViewed(storyId, viewerId);
StoryResponseDTO responseDTO = new StoryResponseDTO(story, viewerId);
return Response.ok(responseDTO).build();
} catch (IllegalArgumentException e) {
LOG.warn("[WARN] Story non trouvée : " + e.getMessage());
return Response.status(Response.Status.NOT_FOUND)
.entity("{\"message\": \"Story non trouvée.\"}")
.build();
} catch (Exception e) {
LOG.error("[ERROR] Erreur lors du marquage de la story : " + e.getMessage(), e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity("{\"message\": \"Erreur lors du marquage de la story.\"}")
.build();
}
}
/**
* Supprime une story.
*
* @param storyId L'ID de la story
* @return Confirmation de suppression
*/
@DELETE
@Path("/{id}")
@Transactional
@Operation(
summary = "Supprimer une story",
description = "Supprime définitivement une story")
public Response deleteStory(@PathParam("id") UUID storyId) {
LOG.info("[LOG] Suppression de la story ID : " + storyId);
try {
boolean deleted = storyService.deleteStory(storyId);
if (deleted) {
return Response.ok("{\"message\": \"Story supprimée avec succès.\"}").build();
} else {
return Response.status(Response.Status.NOT_FOUND)
.entity("{\"message\": \"Story non trouvée.\"}")
.build();
}
} catch (Exception e) {
LOG.error("[ERROR] Erreur lors de la suppression de la story : " + e.getMessage(), e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity("{\"message\": \"Erreur lors de la suppression de la story.\"}")
.build();
}
}
/**
* Récupère les stories les plus vues.
*
* @param limit Le nombre maximum de stories à retourner
* @param viewerId ID de l'utilisateur actuel (optionnel)
* @return Liste des stories les plus vues
*/
@GET
@Path("/popular")
@Operation(
summary = "Récupérer les stories les plus vues",
description = "Retourne les stories les plus populaires basées sur le nombre de vues")
public Response getMostViewedStories(@QueryParam("limit") @DefaultValue("10") int limit, @QueryParam("viewerId") UUID viewerId) {
LOG.info("[LOG] Récupération des " + limit + " stories les plus vues");
try {
List<Story> stories = storyService.getMostViewedStories(limit);
List<StoryResponseDTO> responseDTOs = stories.stream()
.map(story -> viewerId != null ? new StoryResponseDTO(story, viewerId) : new StoryResponseDTO(story))
.collect(Collectors.toList());
return Response.ok(responseDTOs).build();
} catch (Exception e) {
LOG.error("[ERROR] Erreur lors de la récupération des stories populaires : " + e.getMessage(), e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity("{\"message\": \"Erreur lors de la récupération des stories.\"}")
.build();
}
}
}

View File

@@ -6,6 +6,7 @@ import com.lions.dev.dto.response.users.UserAuthenticateResponseDTO;
import com.lions.dev.dto.response.users.UserCreateResponseDTO;
import com.lions.dev.dto.response.users.UserDeleteResponseDto;
import com.lions.dev.entity.users.Users;
import com.lions.dev.exception.UserNotFoundException;
import com.lions.dev.service.UsersService;
import jakarta.inject.Inject;
import jakarta.transaction.Transactional;
@@ -225,4 +226,43 @@ public class UsersResource {
}
}
/**
* Endpoint pour rechercher un utilisateur par email.
*
* @param email L'email de l'utilisateur à rechercher.
* @return Une réponse HTTP contenant les informations de l'utilisateur.
*/
@GET
@Path("/search")
@Operation(
summary = "Rechercher un utilisateur par email",
description = "Retourne les détails de l'utilisateur correspondant à l'email fourni")
public Response searchUserByEmail(@QueryParam("email") String email) {
if (email == null || email.isBlank()) {
LOG.warn("Tentative de recherche avec un email vide ou null");
return Response.status(Response.Status.BAD_REQUEST)
.entity("{\"message\": \"L'email est requis pour la recherche.\"}")
.build();
}
LOG.info("Recherche de l'utilisateur avec l'email : " + email);
try {
Users user = userService.getUserByEmail(email);
UserCreateResponseDTO responseDTO = new UserCreateResponseDTO(user);
LOG.info("Utilisateur trouvé : " + user.getEmail());
return Response.ok(responseDTO).build();
} catch (UserNotFoundException e) {
LOG.warn("Utilisateur non trouvé avec l'email : " + email);
return Response.status(Response.Status.NOT_FOUND)
.entity("{\"message\": \"Utilisateur non trouvé avec cet email.\"}")
.build();
} catch (Exception e) {
LOG.error("[ERROR] Erreur lors de la recherche de l'utilisateur : " + e.getMessage(), e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity("{\"message\": \"Erreur lors de la recherche de l'utilisateur.\"}")
.build();
}
}
}