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:
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
333
src/main/java/com/lions/dev/resource/MessageResource.java
Normal file
333
src/main/java/com/lions/dev/resource/MessageResource.java
Normal 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();
|
||||
}
|
||||
}
|
||||
}
|
||||
247
src/main/java/com/lions/dev/resource/NotificationResource.java
Normal file
247
src/main/java/com/lions/dev/resource/NotificationResource.java
Normal 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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
394
src/main/java/com/lions/dev/resource/SocialPostResource.java
Normal file
394
src/main/java/com/lions/dev/resource/SocialPostResource.java
Normal 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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
263
src/main/java/com/lions/dev/resource/StoryResource.java
Normal file
263
src/main/java/com/lions/dev/resource/StoryResource.java
Normal 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();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user