feat: Extension des événements avec 10 nouveaux champs - Ajout de maxParticipants, tags, organizer, participationFee - Ajout de privacyRules, transportInfo, accommodationInfo - Ajout de accessibilityInfo, parkingInfo, securityProtocol - Mise à jour des DTOs et services - Vérification des permissions pour le CRUD (créateur uniquement) - Ajout de creatorId dans EventCreateResponseDTO

This commit is contained in:
dahoud
2026-01-13 20:45:18 +00:00
parent 56d0aad6a6
commit 0443bd251f
5 changed files with 282 additions and 34 deletions

View File

@@ -66,11 +66,25 @@ public class EventsResource {
@Operation(summary = "Créer un nouvel événement", description = "Crée un nouvel événement et retourne ses détails")
public Response createEvent(EventCreateRequestDTO eventCreateRequestDTO) {
LOG.info("[LOG] Tentative de création d'un nouvel événement : " + eventCreateRequestDTO.getTitle());
// Valider que creatorId est fourni
if (eventCreateRequestDTO.getCreatorId() == null) {
LOG.error("[ERROR] creatorId est obligatoire pour créer un événement");
return Response.status(Response.Status.BAD_REQUEST)
.entity("L'identifiant du créateur (creatorId) est obligatoire")
.build();
}
// Récupérer le créateur par son ID
Users creator = usersRepository.findById(eventCreateRequestDTO.getCreatorId());
if (creator == null) {
LOG.error("[ERROR] Créateur non trouvé avec l'ID : " + eventCreateRequestDTO.getCreatorId());
return Response.status(Response.Status.BAD_REQUEST).entity("Créateur non trouvé").build();
return Response.status(Response.Status.BAD_REQUEST)
.entity("Créateur non trouvé avec l'ID fourni")
.build();
}
// Créer l'événement
Events event = eventService.createEvent(eventCreateRequestDTO, creator);
LOG.info("[LOG] Événement créé avec succès : " + event.getTitle());
EventCreateResponseDTO responseDTO = new EventCreateResponseDTO(event);
@@ -100,10 +114,16 @@ public class EventsResource {
@Path("/{id}")
@Transactional
@Operation(summary = "Supprimer un événement", description = "Supprime un événement de la base de données")
public Response deleteEvent(@PathParam("id") UUID id) {
LOG.info("Tentative de suppression de l'événement avec l'ID : " + id);
public Response deleteEvent(@PathParam("id") UUID id, @QueryParam("userId") UUID userId) {
LOG.info("Tentative de suppression de l'événement avec l'ID : " + id + " par l'utilisateur : " + userId);
if (userId == null) {
LOG.error("[ERROR] userId est obligatoire pour supprimer un événement");
return Response.status(Response.Status.BAD_REQUEST).entity("L'identifiant de l'utilisateur (userId) est obligatoire").build();
}
try {
boolean deleted = eventService.deleteEvent(id);
boolean deleted = eventService.deleteEvent(id, userId);
if (deleted) {
LOG.info("Événement supprimé avec succès.");
return Response.noContent().build();
@@ -114,6 +134,9 @@ public class EventsResource {
} catch (EventNotFoundException e) {
LOG.error("[ERROR] Échec de la suppression : " + e.getMessage());
return Response.status(Response.Status.NOT_FOUND).entity("Événement non trouvé.").build();
} catch (SecurityException e) {
LOG.error("[ERROR] Permissions insuffisantes : " + e.getMessage());
return Response.status(Response.Status.FORBIDDEN).entity(e.getMessage()).build();
}
}
@@ -166,13 +189,26 @@ public class EventsResource {
@Path("/{id}")
@Transactional
@Operation(summary = "Mettre à jour un événement", description = "Modifie un événement existant")
public Response updateEvent(@PathParam("id") UUID id, EventUpdateRequestDTO eventUpdateRequestDTO) {
LOG.info("[LOG] Tentative de mise à jour de l'événement avec l'ID : " + id);
public Response updateEvent(@PathParam("id") UUID id, @QueryParam("userId") UUID userId, EventUpdateRequestDTO eventUpdateRequestDTO) {
LOG.info("[LOG] Tentative de mise à jour de l'événement avec l'ID : " + id + " par l'utilisateur : " + userId);
if (userId == null) {
LOG.error("[ERROR] userId est obligatoire pour mettre à jour un événement");
return Response.status(Response.Status.BAD_REQUEST).entity("L'identifiant de l'utilisateur (userId) est obligatoire").build();
}
Events event = eventsRepository.findById(id);
if (event == null) {
LOG.warn("[LOG] Événement non trouvé avec l'ID : " + id);
return Response.status(Response.Status.NOT_FOUND).entity("Événement non trouvé.").build();
}
// Vérifier que l'utilisateur est le créateur
if (!eventService.canModifyEvent(event, userId)) {
LOG.error("[ERROR] L'utilisateur " + userId + " n'a pas les permissions pour modifier l'événement " + id);
return Response.status(Response.Status.FORBIDDEN).entity("Vous n'avez pas les permissions pour modifier cet événement").build();
}
// Mise à jour des attributs de l'événement
event.setTitle(eventUpdateRequestDTO.getTitle());
event.setStartDate(eventUpdateRequestDTO.getStartDate());
@@ -206,18 +242,20 @@ public class EventsResource {
try {
List<FriendshipReadFriendDetailsResponseDTO> friends = friendshipService.listFriends(userId, 0, Integer.MAX_VALUE);
Set<UUID> friendIds = friends.stream().map(FriendshipReadFriendDetailsResponseDTO::getFriendId).collect(Collectors.toSet());
//friendIds = friendIds.stream().distinct().collect(Collectors.toSet());
LOG.info("[LOG] IDs d'amis + utilisateur (taille attendue: " + friendIds.size() + ") : " + friendIds);
if (friendIds.isEmpty()) {
LOG.warn("[LOG] Aucun ami trouvé.");
return Response.status(Response.Status.NOT_FOUND).entity("Aucun ami trouvé.").build();
}
// IMPORTANT: Ajouter l'ID de l'utilisateur lui-même pour inclure ses propres événements
friendIds.add(userId);
LOG.info("[LOG] IDs d'amis + utilisateur (taille: " + friendIds.size() + ") : " + friendIds);
// Rechercher les événements créés par l'utilisateur et ses amis
List<Events> events = eventsRepository.find("creator.id IN ?1", friendIds).list();
LOG.info("[LOG] Nombre d'événements récupérés dans la requête : " + events.size());
if (events.isEmpty()) {
return Response.status(Response.Status.NOT_FOUND).entity("Aucun événement trouvé.").build();
}
List<EventReadManyByIdResponseDTO> responseDTOs = events.stream().map(EventReadManyByIdResponseDTO::new).toList();
// Retourner une liste vide si aucun événement trouvé (pas d'erreur 404)
List<EventReadManyByIdResponseDTO> responseDTOs = events.stream()
.map(EventReadManyByIdResponseDTO::new)
.toList();
return Response.ok(responseDTOs).build();
} catch (Exception e) {
LOG.error("[ERROR] Erreur de récupération des événements : ", e);
@@ -366,13 +404,26 @@ public class EventsResource {
@Operation(
summary = "Mettre à jour le statut d'un événement",
description = "Modifie le statut d'un événement (ouvert, fermé, annulé, etc.)")
public Response updateEventStatus(@PathParam("id") UUID id, @QueryParam("status") String status) {
LOG.info("[LOG] Mise à jour du statut de l'événement avec l'ID : " + id);
public Response updateEventStatus(@PathParam("id") UUID id, @QueryParam("status") String status, @QueryParam("userId") UUID userId) {
LOG.info("[LOG] Mise à jour du statut de l'événement avec l'ID : " + id + " par l'utilisateur : " + userId);
if (userId == null) {
LOG.error("[ERROR] userId est obligatoire pour mettre à jour le statut d'un événement");
return Response.status(Response.Status.BAD_REQUEST).entity("L'identifiant de l'utilisateur (userId) est obligatoire").build();
}
Events event = eventsRepository.findById(id);
if (event == null) {
LOG.warn("[LOG] Événement non trouvé avec l'ID : " + id);
return Response.status(Response.Status.NOT_FOUND).entity("Événement non trouvé.").build();
}
// Vérifier que l'utilisateur est le créateur
if (!eventService.canModifyEvent(event, userId)) {
LOG.error("[ERROR] L'utilisateur " + userId + " n'a pas les permissions pour modifier le statut de l'événement " + id);
return Response.status(Response.Status.FORBIDDEN).entity("Vous n'avez pas les permissions pour modifier cet événement").build();
}
event.setStatus(status);
eventsRepository.persist(event);
LOG.info("[LOG] Statut de l'événement mis à jour avec succès : " + status);
@@ -423,8 +474,13 @@ public class EventsResource {
*/
@PUT
@Path("/{id}/image")
public Response updateEventImage(@PathParam("id") UUID id, String imageFilePath) {
LOG.info("[LOG] Tentative de mise à jour de l'image pour l'événement avec l'ID : " + id);
public Response updateEventImage(@PathParam("id") UUID id, @QueryParam("userId") UUID userId, String imageFilePath) {
LOG.info("[LOG] Tentative de mise à jour de l'image pour l'événement avec l'ID : " + id + " par l'utilisateur : " + userId);
if (userId == null) {
LOG.error("[ERROR] userId est obligatoire pour mettre à jour l'image d'un événement");
return Response.status(Response.Status.BAD_REQUEST).entity("L'identifiant de l'utilisateur (userId) est obligatoire").build();
}
try {
if (imageFilePath == null || imageFilePath.isEmpty()) {
@@ -444,9 +500,15 @@ public class EventsResource {
return Response.status(Response.Status.NOT_FOUND).entity("Événement non trouvé.").build();
}
// Vérifier que l'utilisateur est le créateur
if (!eventService.canModifyEvent(event, userId)) {
LOG.error("[ERROR] L'utilisateur " + userId + " n'a pas les permissions pour modifier l'image de l'événement " + id);
return Response.status(Response.Status.FORBIDDEN).entity("Vous n'avez pas les permissions pour modifier cet événement").build();
}
String imageUrl = file.getAbsolutePath();
event.setImageUrl(imageUrl);
eventService.updateEvent(event);
eventService.updateEvent(event, userId);
LOG.info("[LOG] Image de l'événement mise à jour avec succès pour : " + event.getTitle());
return Response.ok("Image de l'événement mise à jour avec succès.").build();
@@ -461,8 +523,13 @@ public class EventsResource {
@Path("/{id}/partial-update")
@Transactional
@Operation(summary = "Mettre à jour partiellement un événement", description = "Mise à jour partielle des informations d'un événement")
public Response partialUpdateEvent(@PathParam("id") UUID id, Map<String, Object> updates) {
LOG.info("[LOG] Tentative de mise à jour partielle de l'événement avec l'ID : " + id);
public Response partialUpdateEvent(@PathParam("id") UUID id, @QueryParam("userId") UUID userId, Map<String, Object> updates) {
LOG.info("[LOG] Tentative de mise à jour partielle de l'événement avec l'ID : " + id + " par l'utilisateur : " + userId);
if (userId == null) {
LOG.error("[ERROR] userId est obligatoire pour mettre à jour un événement");
return Response.status(Response.Status.BAD_REQUEST).entity("L'identifiant de l'utilisateur (userId) est obligatoire").build();
}
Events event = eventsRepository.findById(id);
if (event == null) {
@@ -470,9 +537,39 @@ public class EventsResource {
return Response.status(Response.Status.NOT_FOUND).entity("Événement non trouvé.").build();
}
// Vérifier que l'utilisateur est le créateur
if (!eventService.canModifyEvent(event, userId)) {
LOG.error("[ERROR] L'utilisateur " + userId + " n'a pas les permissions pour modifier l'événement " + id);
return Response.status(Response.Status.FORBIDDEN).entity("Vous n'avez pas les permissions pour modifier cet événement").build();
}
// Mise à jour des champs dynamiquement
updates.forEach((field, value) -> {
// Mise à jour des champs dynamiquement, à adapter selon la structure de l'événement
// Exemple d'utilisation de réflexion si applicable
switch (field) {
case "title":
event.setTitle(value != null ? value.toString() : null);
break;
case "description":
event.setDescription(value != null ? value.toString() : null);
break;
case "location":
event.setLocation(value != null ? value.toString() : null);
break;
case "category":
event.setCategory(value != null ? value.toString() : null);
break;
case "link":
event.setLink(value != null ? value.toString() : null);
break;
case "imageUrl":
event.setImageUrl(value != null ? value.toString() : null);
break;
case "status":
event.setStatus(value != null ? value.toString() : null);
break;
default:
LOG.warn("[LOG] Champ inconnu ignoré lors de la mise à jour partielle : " + field);
}
});
eventsRepository.persist(event);
@@ -519,8 +616,13 @@ public class EventsResource {
@Path("/{id}/cancel")
@Transactional
@Operation(summary = "Annuler un événement", description = "Annule un événement sans le supprimer.")
public Response cancelEvent(@PathParam("id") UUID id) {
LOG.info("[LOG] Annulation de l'événement avec l'ID : " + id);
public Response cancelEvent(@PathParam("id") UUID id, @QueryParam("userId") UUID userId) {
LOG.info("[LOG] Annulation de l'événement avec l'ID : " + id + " par l'utilisateur : " + userId);
if (userId == null) {
LOG.error("[ERROR] userId est obligatoire pour annuler un événement");
return Response.status(Response.Status.BAD_REQUEST).entity("L'identifiant de l'utilisateur (userId) est obligatoire").build();
}
Events event = eventsRepository.findById(id);
if (event == null) {
@@ -528,6 +630,12 @@ public class EventsResource {
return Response.status(Response.Status.NOT_FOUND).entity("Événement non trouvé.").build();
}
// Vérifier que l'utilisateur est le créateur
if (!eventService.canModifyEvent(event, userId)) {
LOG.error("[ERROR] L'utilisateur " + userId + " n'a pas les permissions pour annuler l'événement " + id);
return Response.status(Response.Status.FORBIDDEN).entity("Vous n'avez pas les permissions pour annuler cet événement").build();
}
event.setStatus("Annulé");
eventsRepository.persist(event);
LOG.info("[LOG] Événement annulé avec succès : " + event.getTitle());
@@ -716,6 +824,50 @@ public class EventsResource {
return Response.ok(responseDTOs).build();
}
@POST
@Path("/{id}/comments")
@Transactional
@Operation(summary = "Ajouter un commentaire à un événement", description = "Crée un nouveau commentaire pour un événement.")
public Response addComment(
@PathParam("id") UUID eventId,
@QueryParam("userId") UUID userId,
Map<String, String> requestBody) {
LOG.info("[LOG] Ajout d'un commentaire à l'événement ID : " + eventId + " par l'utilisateur ID : " + userId);
Events event = eventsRepository.findById(eventId);
if (event == null) {
LOG.warn("[LOG] Événement non trouvé avec l'ID : " + eventId);
return Response.status(Response.Status.NOT_FOUND).entity("Événement non trouvé.").build();
}
Users user = usersRepository.findById(userId);
if (user == null) {
LOG.warn("[LOG] Utilisateur non trouvé avec l'ID : " + userId);
return Response.status(Response.Status.NOT_FOUND).entity("Utilisateur non trouvé.").build();
}
String text = requestBody.get("text");
if (text == null || text.trim().isEmpty()) {
LOG.warn("[LOG] Le texte du commentaire est vide");
return Response.status(Response.Status.BAD_REQUEST).entity("Le texte du commentaire est requis.").build();
}
try {
Comment comment = new Comment(user, event, text);
// Le commentaire sera automatiquement ajouté à la liste des commentaires de l'événement via la relation JPA
eventsRepository.persist(event);
LOG.info("[LOG] Commentaire ajouté avec succès à l'événement : " + event.getTitle());
CommentResponseDTO responseDTO = new CommentResponseDTO(comment);
return Response.status(Response.Status.CREATED).entity(responseDTO).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("Erreur lors de l'ajout du commentaire.").build();
}
}
@GET
@Path("/recommendations/{userId}")
@Operation(summary = "Recommander des événements basés sur les intérêts", description = "Retourne une liste d'événements recommandés pour un utilisateur.")