diff --git a/pom.xml b/pom.xml index c2dedb7..cde4864 100644 --- a/pom.xml +++ b/pom.xml @@ -1,173 +1,185 @@ - - 4.0.0 - com.lions.dev - mic-after-work-server - 1.0.0-SNAPSHOT + + 4.0.0 + com.lions.dev + mic-after-work-server + 1.0.0-SNAPSHOT - - 3.13.0 - 17 - UTF-8 - UTF-8 - quarkus-bom - io.quarkus.platform - 3.13.0 - true - 3.2.5 - - - - - - ${quarkus.platform.group-id} - ${quarkus.platform.artifact-id} - ${quarkus.platform.version} - pom - import - - - + + 3.13.0 + 17 + UTF-8 + UTF-8 + quarkus-bom + io.quarkus.platform + 3.13.0 + true + 3.2.5 + + - - io.quarkus - quarkus-smallrye-jwt - - - - org.springframework.security - spring-security-core - 6.3.3 - - - - com.fasterxml.jackson.datatype - jackson-datatype-jsr310 - - - io.quarkiverse.groovy - quarkus-groovy-junit5 - 3.12.1 - - - io.quarkus - quarkus-smallrye-openapi - - - io.quarkus - quarkus-resteasy-reactive-jackson - - - io.quarkus - quarkus-hibernate-orm-panache - - - io.quarkus - quarkus-jdbc-oracle - - - io.quarkus - quarkus-arc - - - io.quarkus - quarkus-hibernate-orm - - - io.quarkus - quarkus-junit5 - test - - - io.rest-assured - rest-assured - test - - - - org.hibernate.validator - hibernate-validator - - org.projectlombok - lombok - 1.18.30 - provided + ${quarkus.platform.group-id} + ${quarkus.platform.artifact-id} + ${quarkus.platform.version} + pom + import + - - - - ${quarkus.platform.group-id} - quarkus-maven-plugin - ${quarkus.platform.version} - true - - - - build - generate-code - generate-code-tests - native-image-agent - - - - - - maven-compiler-plugin - ${compiler-plugin.version} - - - -parameters - - - - - maven-surefire-plugin - ${surefire-plugin.version} - - - org.jboss.logmanager.LogManager - ${maven.home} - - - - - maven-failsafe-plugin - ${surefire-plugin.version} - - - - integration-test - verify - - - - - - ${project.build.directory}/${project.build.finalName}-runner - org.jboss.logmanager.LogManager - ${maven.home} - - - - - + + + + org.hibernate.validator + hibernate-validator + + + jakarta.el + jakarta.el-api + 5.0.0 + + + io.quarkus + quarkus-jdbc-postgresql + 3.13.0 + + + io.quarkus + quarkus-smallrye-jwt + + + org.springframework.security + spring-security-core + 6.3.4 + + + com.fasterxml.jackson.datatype + jackson-datatype-jsr310 + + + io.quarkiverse.groovy + quarkus-groovy-junit5 + 3.16.1 + + + io.quarkus + quarkus-smallrye-openapi + + + io.quarkus + quarkus-rest-jackson + + + io.quarkus + quarkus-hibernate-orm-panache + + + io.quarkus + quarkus-jdbc-oracle + + + io.quarkus + quarkus-arc + + + io.quarkus + quarkus-hibernate-orm + + + io.quarkus + quarkus-junit5 + test + + + io.rest-assured + rest-assured + test + - - - native - - - native - - - - false - true - - - + + org.projectlombok + lombok + 1.18.34 + provided + + + + + + + ${quarkus.platform.group-id} + quarkus-maven-plugin + ${quarkus.platform.version} + true + + + + build + generate-code + generate-code-tests + native-image-agent + + + + + + maven-compiler-plugin + ${compiler-plugin.version} + + + -parameters + + + + + maven-surefire-plugin + ${surefire-plugin.version} + + + org.jboss.logmanager.LogManager + ${maven.home} + + + + + maven-failsafe-plugin + ${surefire-plugin.version} + + + + integration-test + verify + + + + + + ${project.build.directory}/${project.build.finalName}-runner + + org.jboss.logmanager.LogManager + ${maven.home} + + + + + + + + + native + + + native + + + + false + true + + + diff --git a/src/main/docker/docker-compose.yml b/src/main/docker/docker-compose.yml new file mode 100644 index 0000000..200b4ae --- /dev/null +++ b/src/main/docker/docker-compose.yml @@ -0,0 +1,58 @@ +version: '3.8' + +services: + # Service pour la base de données PostgreSQL + db: + image: postgres:13 + container_name: afterwork_db + environment: + POSTGRES_USER: ${DB_USERNAME} + POSTGRES_PASSWORD: ${DB_PASSWORD} + POSTGRES_DB: ${DB_NAME} + ports: + - "5432:5432" + networks: + - afterwork-network + volumes: + - db_data:/var/lib/postgresql/data + + # Service pour l'application Quarkus + app: + build: + context: . + dockerfile: src/main/docker/Dockerfile.jvm + container_name: afterwork-quarkus + environment: + DB_USERNAME: ${DB_USERNAME} + DB_PASSWORD: ${DB_PASSWORD} + DB_HOST: db + DB_PORT: 5432 + DB_NAME: ${DB_NAME} + JAVA_OPTS_APPEND: "-Dquarkus.http.host=0.0.0.0" + ports: + - "8080:8080" + depends_on: + - db + networks: + - afterwork-network + + # Service pour Swagger UI + swagger-ui: + image: swaggerapi/swagger-ui + container_name: afterwork-swagger-ui + environment: + SWAGGER_JSON: http://app:8080/openapi + ports: + - "8081:8080" + depends_on: + - app + networks: + - afterwork-network + +networks: + afterwork-network: + driver: bridge + +volumes: + db_data: + driver: local diff --git a/src/main/java/com/lions/dev/core/errors/GlobalExceptionHandler.java b/src/main/java/com/lions/dev/core/errors/GlobalExceptionHandler.java new file mode 100644 index 0000000..e0ccaa1 --- /dev/null +++ b/src/main/java/com/lions/dev/core/errors/GlobalExceptionHandler.java @@ -0,0 +1,63 @@ +package com.lions.dev.core.errors; + +import com.lions.dev.core.errors.exceptions.BadRequestException; +import com.lions.dev.core.errors.exceptions.EventNotFoundException; +import com.lions.dev.core.errors.exceptions.NotFoundException; +import com.lions.dev.core.errors.exceptions.ServerException; +import com.lions.dev.core.errors.exceptions.UnauthorizedException; +import jakarta.ws.rs.core.Response; +import jakarta.ws.rs.ext.ExceptionMapper; +import jakarta.ws.rs.ext.Provider; +import org.jboss.logging.Logger; + +/** + * Gestionnaire global des exceptions pour l'API. + * Ce gestionnaire intercepte les exceptions spécifiques et renvoie des réponses appropriées. + */ +@Provider +public class GlobalExceptionHandler implements ExceptionMapper { + + private static final Logger logger = Logger.getLogger(GlobalExceptionHandler.class); + + /** + * Gère les exceptions non traitées et retourne une réponse appropriée. + * + * @param exception L'exception interceptée. + * @return Une réponse HTTP avec un message d'erreur et le code de statut approprié. + */ + @Override + public Response toResponse(Throwable exception) { + if (exception instanceof BadRequestException) { + logger.warn("BadRequestException intercepted: " + exception.getMessage()); + return buildResponse(Response.Status.BAD_REQUEST, exception.getMessage()); + } else if (exception instanceof EventNotFoundException || exception instanceof NotFoundException) { + logger.warn("NotFoundException intercepted: " + exception.getMessage()); + return buildResponse(Response.Status.NOT_FOUND, exception.getMessage()); + } else if (exception instanceof UnauthorizedException) { + logger.warn("UnauthorizedException intercepted: " + exception.getMessage()); + return buildResponse(Response.Status.UNAUTHORIZED, exception.getMessage()); + } else if (exception instanceof ServerException) { + logger.error("ServerException intercepted: " + exception.getMessage()); + return buildResponse(Response.Status.INTERNAL_SERVER_ERROR, "Erreur interne du serveur."); + } else if (exception instanceof RuntimeException) { + logger.error("RuntimeException intercepted: " + exception.getMessage()); + return buildResponse(Response.Status.INTERNAL_SERVER_ERROR, "Erreur inattendue."); + } else { + logger.error("Unexpected error: " + exception.getMessage(), exception); + return buildResponse(Response.Status.INTERNAL_SERVER_ERROR, "Erreur inattendue : " + exception.getMessage()); + } + } + + /** + * Crée une réponse HTTP avec un code de statut et un message d'erreur. + * + * @param status Le code de statut HTTP. + * @param message Le message d'erreur. + * @return La réponse HTTP formée. + */ + private Response buildResponse(Response.Status status, String message) { + return Response.status(status) + .entity("{\"error\":\"" + message + "\"}") + .build(); + } +} diff --git a/src/main/java/com/lions/dev/core/errors/exceptions/BadRequestException.java b/src/main/java/com/lions/dev/core/errors/exceptions/BadRequestException.java index 14ddcb2..cf57486 100644 --- a/src/main/java/com/lions/dev/core/errors/exceptions/BadRequestException.java +++ b/src/main/java/com/lions/dev/core/errors/exceptions/BadRequestException.java @@ -18,4 +18,5 @@ public class BadRequestException extends WebApplicationException { super(message, Response.Status.BAD_REQUEST); System.out.println("[ERROR] Requête invalide : " + message); } + } diff --git a/src/main/java/com/lions/dev/core/errors/exceptions/EventNotFoundException.java b/src/main/java/com/lions/dev/core/errors/exceptions/EventNotFoundException.java new file mode 100644 index 0000000..4fb83a5 --- /dev/null +++ b/src/main/java/com/lions/dev/core/errors/exceptions/EventNotFoundException.java @@ -0,0 +1,15 @@ +package com.lions.dev.core.errors.exceptions; + +/** + * Exception lancée lorsque l'événement n'est pas trouvé. + */ +public class EventNotFoundException extends RuntimeException { + + public EventNotFoundException(String message) { + super(message); + } + + public EventNotFoundException(java.util.UUID eventId) { + super("L'événement avec l'ID " + eventId + " n'a pas été trouvé."); + } +} diff --git a/src/main/java/com/lions/dev/dto/request/events/EventCreateRequestDTO.java b/src/main/java/com/lions/dev/dto/request/events/EventCreateRequestDTO.java new file mode 100644 index 0000000..422e445 --- /dev/null +++ b/src/main/java/com/lions/dev/dto/request/events/EventCreateRequestDTO.java @@ -0,0 +1,42 @@ +package com.lions.dev.dto.request.events; + +import java.util.UUID; +import lombok.Getter; +import lombok.Setter; +import jakarta.validation.constraints.NotNull; +import jakarta.validation.constraints.Size; +import java.time.LocalDateTime; + +/** + * DTO pour la création d'un événement. + * Ce DTO est utilisé dans les requêtes de création d'événements, envoyant les informations + * nécessaires comme le titre, les dates, la description, le créateur, et d'autres attributs. + */ +@Getter +@Setter +public class EventCreateRequestDTO { + + @NotNull(message = "Le titre de l'événement est obligatoire.") + @Size(min = 3, max = 100, message = "Le titre doit comporter entre 3 et 100 caractères.") + private String title; // Titre de l'événement + + private String description; // Description de l'événement + + @NotNull(message = "La date de début est obligatoire.") + private LocalDateTime startDate; // Date de début de l'événement + + @NotNull(message = "La date de fin est obligatoire.") + private LocalDateTime endDate; // Date de fin de l'événement + + private String location; // Lieu de l'événement + private String category; // Catégorie de l'événement + private String link; // Lien d'information supplémentaire + private String imageUrl; // URL de l'image associée à l'événement + + @NotNull(message = "L'identifiant du créateur est obligatoire.") + private UUID creatorId; // Identifiant du créateur de l'événement + + public EventCreateRequestDTO() { + System.out.println("[LOG] DTO de requête de création d'événement initialisé."); + } +} diff --git a/src/main/java/com/lions/dev/dto/request/events/EventDeleteRequestDTO.java b/src/main/java/com/lions/dev/dto/request/events/EventDeleteRequestDTO.java new file mode 100644 index 0000000..57c59c7 --- /dev/null +++ b/src/main/java/com/lions/dev/dto/request/events/EventDeleteRequestDTO.java @@ -0,0 +1,20 @@ +package com.lions.dev.dto.request.events; + +import jakarta.validation.constraints.NotNull; +import java.util.UUID; + +/** + * DTO pour la suppression d'un événement. + * Ce DTO est utilisé pour capturer l'ID d'un événement à supprimer. + */ +@lombok.Getter +@lombok.Setter +public class EventDeleteRequestDTO { + + @NotNull(message = "L'ID de l'événement est obligatoire.") + private UUID eventId; // ID de l'événement à supprimer + + public EventDeleteRequestDTO() { + System.out.println("[LOG] DTO de requête de suppression d'événement initialisé."); + } +} diff --git a/src/main/java/com/lions/dev/dto/request/events/EventReadManyByIdRequestDTO.java b/src/main/java/com/lions/dev/dto/request/events/EventReadManyByIdRequestDTO.java new file mode 100644 index 0000000..a77220d --- /dev/null +++ b/src/main/java/com/lions/dev/dto/request/events/EventReadManyByIdRequestDTO.java @@ -0,0 +1,22 @@ +package com.lions.dev.dto.request.events; + +import java.util.UUID; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; + +/** + * DTO de requête pour obtenir les événements créés par un utilisateur spécifique. + * Permet l'ajout futur de critères de filtre si nécessaire. + */ +@Getter +@Setter +@NoArgsConstructor +@AllArgsConstructor +public class EventReadManyByIdRequestDTO { + + private UUID userId; // Identifiant de l'utilisateur pour lequel on souhaite obtenir les événements + + // Ajoutez ici d'autres critères de filtre si besoin, comme une plage de dates, un statut, etc. +} diff --git a/src/main/java/com/lions/dev/dto/request/events/EventReadOneByIdRequestDTO.java b/src/main/java/com/lions/dev/dto/request/events/EventReadOneByIdRequestDTO.java new file mode 100644 index 0000000..7765d9b --- /dev/null +++ b/src/main/java/com/lions/dev/dto/request/events/EventReadOneByIdRequestDTO.java @@ -0,0 +1,20 @@ +package com.lions.dev.dto.request.events; + +import jakarta.validation.constraints.NotNull; +import java.util.UUID; + +/** + * DTO pour lire un événement par son ID. + * Ce DTO est utilisé dans les requêtes pour récupérer les informations d'un événement spécifique. + */ +@lombok.Getter +@lombok.Setter +public class EventReadOneByIdRequestDTO { + + @NotNull(message = "L'ID de l'événement est obligatoire.") + private UUID eventId; // ID de l'événement à lire + + public EventReadOneByIdRequestDTO() { + System.out.println("[LOG] DTO de requête de lecture d'événement initialisé."); + } +} diff --git a/src/main/java/com/lions/dev/dto/request/events/EventRequestDTO.java b/src/main/java/com/lions/dev/dto/request/events/EventRequestDTO.java deleted file mode 100644 index fecb22a..0000000 --- a/src/main/java/com/lions/dev/dto/request/events/EventRequestDTO.java +++ /dev/null @@ -1,60 +0,0 @@ -package com.lions.dev.dto.request.events; - -import com.lions.dev.entity.users.Users; -import jakarta.validation.constraints.NotNull; -import jakarta.validation.constraints.Size; -import java.time.LocalDateTime; - -/** - * DTO pour la création d'un événement. - * Ce DTO est utilisé dans les requêtes de création d'événements, envoyant les informations - * nécessaires comme le titre, les dates et le créateur. - */ -public class EventRequestDTO { - - @NotNull(message = "Le titre de l'événement est obligatoire.") - @Size(min = 3, max = 100, message = "Le titre doit comporter entre 3 et 100 caractères.") - private String title; // Titre de l'événement - - @NotNull(message = "La date de début est obligatoire.") - private LocalDateTime startDate; // Date de début de l'événement - - @NotNull(message = "La date de fin est obligatoire.") - private LocalDateTime endDate; // Date de fin de l'événement - - @NotNull(message = "Le créateur de l'événement est obligatoire.") - private Users creator; // Utilisateur créateur de l'événement - - // Getters et setters - public String getTitle() { - return title; - } - - public void setTitle(String title) { - this.title = title; - } - - public LocalDateTime getStartDate() { - return startDate; - } - - public void setStartDate(LocalDateTime startDate) { - this.startDate = startDate; - } - - public LocalDateTime getEndDate() { - return endDate; - } - - public void setEndDate(LocalDateTime endDate) { - this.endDate = endDate; - } - - public Users getCreator() { - return creator; - } - - public void setCreator(Users creator) { - this.creator = creator; - } -} diff --git a/src/main/java/com/lions/dev/dto/request/events/EventUpdateRequestDTO.java b/src/main/java/com/lions/dev/dto/request/events/EventUpdateRequestDTO.java new file mode 100644 index 0000000..e0f1605 --- /dev/null +++ b/src/main/java/com/lions/dev/dto/request/events/EventUpdateRequestDTO.java @@ -0,0 +1,23 @@ +package com.lions.dev.dto.request.events; + +import java.time.LocalDateTime; +import lombok.Getter; +import lombok.Setter; + +/** + * DTO pour la mise à jour d'un événement. + * Ce DTO est utilisé dans les requêtes de mise à jour des événements. + */ +@Getter +@Setter +public class EventUpdateRequestDTO { + private String title; + private String description; + private LocalDateTime startDate; + private LocalDateTime endDate; + private String location; + private String category; + private String link; + private String imageUrl; + private String status; +} diff --git a/src/main/java/com/lions/dev/dto/request/friends/FriendshipCreateOneRequestDTO.java b/src/main/java/com/lions/dev/dto/request/friends/FriendshipCreateOneRequestDTO.java new file mode 100644 index 0000000..b439a6b --- /dev/null +++ b/src/main/java/com/lions/dev/dto/request/friends/FriendshipCreateOneRequestDTO.java @@ -0,0 +1,31 @@ +package com.lions.dev.dto.request.friends; + +import lombok.Getter; +import lombok.Setter; +import lombok.NoArgsConstructor; + +import java.util.UUID; + +/** + * DTO pour envoyer une demande d'amitié. + * Contient les informations nécessaires pour initier une demande d'amitié. + */ +@Getter +@Setter +@NoArgsConstructor +public class FriendshipCreateOneRequestDTO { + + private UUID userId; // ID de l'utilisateur qui envoie la demande + private UUID friendId; // ID de l'utilisateur qui reçoit la demande + + /** + * Constructeur avec paramètres pour initialiser les IDs. + * + * @param userId L'ID de l'utilisateur qui envoie la demande d'amitié. + * @param friendId L'ID de l'utilisateur qui reçoit la demande d'amitié. + */ + public FriendshipCreateOneRequestDTO(UUID userId, UUID friendId) { + this.userId = userId; + this.friendId = friendId; + } +} diff --git a/src/main/java/com/lions/dev/dto/request/friends/FriendshipReadFriendDetailsRequestDTO.java b/src/main/java/com/lions/dev/dto/request/friends/FriendshipReadFriendDetailsRequestDTO.java new file mode 100644 index 0000000..9b69a5b --- /dev/null +++ b/src/main/java/com/lions/dev/dto/request/friends/FriendshipReadFriendDetailsRequestDTO.java @@ -0,0 +1,31 @@ +package com.lions.dev.dto.request.friends; + +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; + +import java.util.UUID; + +/** + * DTO pour récupérer les détails d'un ami. + * Contient les informations nécessaires pour récupérer les détails d'un ami spécifique. + */ +@Getter +@Setter +@NoArgsConstructor +public class FriendshipReadFriendDetailsRequestDTO { + + private UUID userId; // ID de l'utilisateur demandant les détails + private UUID friendId; // ID de l'ami dont les détails sont requis + + /** + * Constructeur avec paramètres pour initialiser les IDs. + * + * @param userId L'ID de l'utilisateur demandant les détails de l'ami. + * @param friendId L'ID de l'ami dont les détails sont requis. + */ + public FriendshipReadFriendDetailsRequestDTO(UUID userId, UUID friendId) { + this.userId = userId; + this.friendId = friendId; + } +} diff --git a/src/main/java/com/lions/dev/dto/request/friends/FriendshipReadStatusRequestDTO.java b/src/main/java/com/lions/dev/dto/request/friends/FriendshipReadStatusRequestDTO.java new file mode 100644 index 0000000..8faf8d5 --- /dev/null +++ b/src/main/java/com/lions/dev/dto/request/friends/FriendshipReadStatusRequestDTO.java @@ -0,0 +1,38 @@ +package com.lions.dev.dto.request.friends; + +import com.lions.dev.entity.friends.FriendshipStatus; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; + +import java.util.UUID; + +/** + * DTO de requête pour récupérer les demandes d'amitié par statut. + * Contient les informations nécessaires pour filtrer les demandes d'amitié d'un utilisateur. + */ +@Getter +@Setter +@NoArgsConstructor +public class FriendshipReadStatusRequestDTO { + + private UUID userId; // ID de l'utilisateur + private FriendshipStatus status; // Statut des demandes (PENDING, ACCEPTED, REJECTED) + private int page = 1; // Numéro de la page pour la pagination + private int size = 10; // Taille de la page pour la pagination + + /** + * Constructeur avec paramètres pour initialiser les informations de la demande. + * + * @param userId ID de l'utilisateur + * @param status Statut des demandes à récupérer + * @param page Numéro de la page pour la pagination + * @param size Nombre d'éléments par page + */ + public FriendshipReadStatusRequestDTO(UUID userId, FriendshipStatus status, int page, int size) { + this.userId = userId; + this.status = status; + this.page = page; + this.size = size; + } +} diff --git a/src/main/java/com/lions/dev/dto/request/users/UserRequestDTO.java b/src/main/java/com/lions/dev/dto/request/users/UserCreateRequestDTO.java similarity index 94% rename from src/main/java/com/lions/dev/dto/request/users/UserRequestDTO.java rename to src/main/java/com/lions/dev/dto/request/users/UserCreateRequestDTO.java index 9fd32d2..4e47ec9 100644 --- a/src/main/java/com/lions/dev/dto/request/users/UserRequestDTO.java +++ b/src/main/java/com/lions/dev/dto/request/users/UserCreateRequestDTO.java @@ -13,7 +13,7 @@ import lombok.Setter; */ @Getter @Setter -public class UserRequestDTO { +public class UserCreateRequestDTO { @NotNull(message = "Le nom est obligatoire.") @Size(min = 1, max = 100, message = "Le nom doit comporter entre 1 et 100 caractères.") @@ -31,6 +31,8 @@ public class UserRequestDTO { @Size(min = 6, message = "Le mot de passe doit comporter au moins 6 caractères.") private String motDePasse; + private String profileImageUrl; + // Ajout du rôle avec validation @NotNull(message = "Le rôle est obligatoire.") private String role; // Rôle de l'utilisateur (par exemple : ADMIN, USER, etc.) diff --git a/src/main/java/com/lions/dev/dto/request/users/UserDeleteRequestDto.java b/src/main/java/com/lions/dev/dto/request/users/UserDeleteRequestDto.java new file mode 100644 index 0000000..5f4305b --- /dev/null +++ b/src/main/java/com/lions/dev/dto/request/users/UserDeleteRequestDto.java @@ -0,0 +1,32 @@ +package com.lions.dev.dto.request.users; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; +import java.util.UUID; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * DTO pour la requête de suppression d'un utilisateur. + * Utilisé pour encapsuler l'ID de l'utilisateur à supprimer. + */ +@Getter +@Setter +@AllArgsConstructor +@NoArgsConstructor +public class UserDeleteRequestDto { + + private static final Logger logger = LoggerFactory.getLogger(UserDeleteRequestDto.class); + + /** + * Identifiant unique de l'utilisateur à supprimer. + */ + private UUID userId; + + // Méthode pour loguer les détails de la requête de suppression + public void logRequestDetails() { + logger.info("Demande de suppression pour l'utilisateur avec l'ID : {}", userId); + } +} diff --git a/src/main/java/com/lions/dev/dto/response/comments/CommentResponseDTO.java b/src/main/java/com/lions/dev/dto/response/comments/CommentResponseDTO.java new file mode 100644 index 0000000..3ef04d5 --- /dev/null +++ b/src/main/java/com/lions/dev/dto/response/comments/CommentResponseDTO.java @@ -0,0 +1,71 @@ +package com.lions.dev.dto.response.comments; + +import com.lions.dev.entity.comment.Comment; // Import de l'entité Comment +import lombok.Getter; +import lombok.Setter; +import lombok.NoArgsConstructor; +import lombok.AllArgsConstructor; + +import java.util.UUID; + +/** + * DTO (Data Transfer Object) pour le commentaire. + *

+ * Cette classe est utilisée pour représenter un commentaire d'un événement dans les réponses de l'API. + * Elle permet de transférer les informations du commentaire sans exposer des données sensibles ou non nécessaires. + *

+ */ +@Getter +@Setter +@NoArgsConstructor +@AllArgsConstructor +public class CommentResponseDTO { + + /** + * Identifiant unique du commentaire. + * C'est un UUID généré de manière unique pour chaque commentaire. + */ + private UUID id; + + /** + * Texte du commentaire. + * Contient le contenu écrit par l'utilisateur pour un événement donné. + */ + private String texte; + + /** + * Identifiant de l'utilisateur qui a écrit le commentaire. + * Il permet d'identifier l'auteur du commentaire sans exposer d'autres informations sensibles. + */ + private UUID userId; + + /** + * Nom de l'utilisateur ayant écrit le commentaire. + * Le nom est inclus pour permettre une identification facile de l'auteur du commentaire. + */ + private String userNom; + + /** + * Prénom de l'utilisateur ayant écrit le commentaire. + * Prénom associé à l'auteur du commentaire. + */ + private String userPrenoms; + + /** + * Constructeur de DTO à partir d'une entité Comment. + *

+ * Ce constructeur permet de convertir l'entité {@link Comment} en un DTO simple qui peut être retourné dans les réponses API. + *

+ * + * @param comment L'entité {@link Comment} dont les informations sont extraites pour le DTO. + */ + public CommentResponseDTO(Comment comment) { + if (comment != null) { + this.id = comment.getId(); // Identifiant unique du commentaire + this.texte = comment.getText(); // Texte du commentaire + this.userId = comment.getUser().getId(); // Identifiant de l'utilisateur (auteur du commentaire) + this.userNom = comment.getUser().getNom(); // Nom de l'utilisateur + this.userPrenoms = comment.getUser().getPrenoms(); // Prénom de l'utilisateur + } + } +} diff --git a/src/main/java/com/lions/dev/dto/response/events/EventCreateResponseDTO.java b/src/main/java/com/lions/dev/dto/response/events/EventCreateResponseDTO.java new file mode 100644 index 0000000..2ade755 --- /dev/null +++ b/src/main/java/com/lions/dev/dto/response/events/EventCreateResponseDTO.java @@ -0,0 +1,48 @@ +package com.lions.dev.dto.response.events; + +import com.lions.dev.entity.events.Events; +import java.time.LocalDateTime; + +/** + * DTO pour renvoyer les informations d'un événement. + * Ce DTO est utilisé pour structurer les données retournées dans les réponses + * après les opérations sur les événements (création, récupération). + */ +@lombok.Getter +public class EventCreateResponseDTO { + + private String id; // Identifiant de l'événement + private String title; // Titre de l'événement + private String description; // Description de l'événement + private LocalDateTime startDate; // Date de début de l'événement + private LocalDateTime endDate; // Date de fin de l'événement + private String location; // Lieu de l'événement + private String category; // Catégorie de l'événement + private String link; // Lien vers plus d'informations + private String imageUrl; // URL d'une image pour l'événement + private String creatorEmail; // Email du créateur de l'événement + private String creatorFirstName; // Prénom du créateur de l'événement + private String creatorLastName; // Nom de famille du création de l'événement + private String status; // Statut de l'événement + + /** + * Constructeur qui transforme une entité Events en DTO. + * + * @param event L'événement à convertir en DTO. + */ + public EventCreateResponseDTO(Events event) { + this.id = event.getId().toString(); + this.title = event.getTitle(); + this.description = event.getDescription(); + this.startDate = event.getStartDate(); + this.endDate = event.getEndDate(); + this.location = event.getLocation(); + this.category = event.getCategory(); + this.link = event.getLink(); + this.imageUrl = event.getImageUrl(); + this.creatorEmail = event.getCreator().getEmail(); + this.creatorFirstName = event.getCreator().getPrenoms(); + this.creatorLastName = event.getCreator().getNom(); + this.status = event.getStatus(); + } +} diff --git a/src/main/java/com/lions/dev/dto/response/events/EventDeleteResponseDTO.java b/src/main/java/com/lions/dev/dto/response/events/EventDeleteResponseDTO.java new file mode 100644 index 0000000..4760f95 --- /dev/null +++ b/src/main/java/com/lions/dev/dto/response/events/EventDeleteResponseDTO.java @@ -0,0 +1,36 @@ +package com.lions.dev.dto.response.events; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * DTO pour la réponse après la tentative de suppression d'un événement. + * Indique si la suppression a réussi ou échoué. + */ +@Getter +@Setter +@AllArgsConstructor +@NoArgsConstructor +public class EventDeleteResponseDTO { + + private static final Logger logger = LoggerFactory.getLogger(EventDeleteResponseDTO.class); + + /** + * Statut indiquant si la suppression a réussi ou échoué. + */ + private boolean success; + + /** + * Message décrivant le résultat de l'opération. + */ + private String message; + + // Méthode pour loguer les détails de la réponse + public void logResponseDetails() { + logger.info("[LOG] Suppression d'événement - Succès : {}, Message : {}", success, message); + } +} diff --git a/src/main/java/com/lions/dev/dto/response/events/EventReadManyByIdResponseDTO.java b/src/main/java/com/lions/dev/dto/response/events/EventReadManyByIdResponseDTO.java new file mode 100644 index 0000000..1795430 --- /dev/null +++ b/src/main/java/com/lions/dev/dto/response/events/EventReadManyByIdResponseDTO.java @@ -0,0 +1,50 @@ +package com.lions.dev.dto.response.events; + +import com.lions.dev.entity.events.Events; +import java.time.LocalDateTime; +import lombok.Getter; + +/** + * DTO pour renvoyer les informations des événements créés par un utilisateur spécifique. + * Ce DTO est utilisé pour structurer les données retournées dans la réponse. + */ +@Getter +public class EventReadManyByIdResponseDTO { + + private String id; // Identifiant de l'événement + private String title; // Titre de l'événement + private String description; // Description de l'événement + private LocalDateTime startDate; // Date de début de l'événement + private LocalDateTime endDate; // Date de fin de l'événement + private String location; // Lieu de l'événement + private String category; // Catégorie de l'événement + private String link; // Lien vers plus d'informations + private String imageUrl; // URL de l'image de l'événement + private String status; // Statut de l'événement + private String creatorEmail; // Email de l'utilisateur qui a créé l'événement + private String creatorFirstName; // Prénom de l'utilisateur qui a criané l'événement + private String creatorLastName; // Nom de l'utilisateur qui a criané l'événement + private String profileImageUrl; // URL de l'image de profil de l'utilisateur qui a criané l'événement + + /** + * Constructeur qui transforme une entité Events en DTO de réponse. + * + * @param event L'événement à convertir en DTO. + */ + public EventReadManyByIdResponseDTO(Events event) { + this.id = event.getId().toString(); + this.title = event.getTitle(); + this.description = event.getDescription(); + this.startDate = event.getStartDate(); + this.endDate = event.getEndDate(); + this.location = event.getLocation(); + this.category = event.getCategory(); + this.link = event.getLink(); + this.imageUrl = event.getImageUrl(); + this.status = event.getStatus(); + this.creatorEmail = event.getCreator().getEmail(); + this.creatorFirstName = event.getCreator().getPrenoms(); + this.creatorLastName = event.getCreator().getNom(); + this.profileImageUrl = event.getCreator().getProfileImageUrl(); + } +} diff --git a/src/main/java/com/lions/dev/dto/response/events/EventResponseDTO.java b/src/main/java/com/lions/dev/dto/response/events/EventResponseDTO.java deleted file mode 100644 index c88338a..0000000 --- a/src/main/java/com/lions/dev/dto/response/events/EventResponseDTO.java +++ /dev/null @@ -1,46 +0,0 @@ -package com.lions.dev.dto.response.events; - -import com.lions.dev.entity.events.Events; -import java.time.LocalDateTime; - -/** - * DTO pour renvoyer les informations d'un événement. - * Ce DTO est utilisé pour structurer les données retournées dans les réponses - * après les opérations sur les événements (création, récupération). - */ -public class EventResponseDTO { - - private String title; // Titre de l'événement - private LocalDateTime startDate; // Date de début de l'événement - private LocalDateTime endDate; // Date de fin de l'événement - private String creatorEmail; // Email du créateur de l'événement - - /** - * Constructeur qui transforme une entité Events en DTO. - * - * @param event L'événement à convertir en DTO. - */ - public EventResponseDTO(Events event) { - this.title = event.getTitle(); - this.startDate = event.getStartDate(); - this.endDate = event.getEndDate(); - this.creatorEmail = event.getCreator().getEmail(); - } - - // Getters - public String getTitle() { - return title; - } - - public LocalDateTime getStartDate() { - return startDate; - } - - public LocalDateTime getEndDate() { - return endDate; - } - - public String getCreatorEmail() { - return creatorEmail; - } -} diff --git a/src/main/java/com/lions/dev/dto/response/events/EventUpdateResponseDTO.java b/src/main/java/com/lions/dev/dto/response/events/EventUpdateResponseDTO.java new file mode 100644 index 0000000..39bd55c --- /dev/null +++ b/src/main/java/com/lions/dev/dto/response/events/EventUpdateResponseDTO.java @@ -0,0 +1,33 @@ +package com.lions.dev.dto.response.events; + +import com.lions.dev.entity.events.Events; +import java.time.LocalDateTime; +import lombok.Getter; + +/** + * DTO pour renvoyer les informations après la mise à jour d'un événement. + */ +@Getter +public class EventUpdateResponseDTO { + private String title; + private String description; + private LocalDateTime startDate; + private LocalDateTime endDate; + private String location; + private String category; + private String link; + private String imageUrl; + private String creatorEmail; + + public EventUpdateResponseDTO(Events event) { + this.title = event.getTitle(); + this.description = event.getDescription(); + this.startDate = event.getStartDate(); + this.endDate = event.getEndDate(); + this.location = event.getLocation(); + this.category = event.getCategory(); + this.link = event.getLink(); + this.imageUrl = event.getImageUrl(); + this.creatorEmail = event.getCreator().getEmail(); + } +} diff --git a/src/main/java/com/lions/dev/dto/response/friends/FriendshipCreateOneResponseDTO.java b/src/main/java/com/lions/dev/dto/response/friends/FriendshipCreateOneResponseDTO.java new file mode 100644 index 0000000..368d5d0 --- /dev/null +++ b/src/main/java/com/lions/dev/dto/response/friends/FriendshipCreateOneResponseDTO.java @@ -0,0 +1,41 @@ +package com.lions.dev.dto.response.friends; + +import com.lions.dev.entity.friends.Friendship; +import com.lions.dev.entity.friends.FriendshipStatus; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; + +import java.time.LocalDateTime; +import java.util.UUID; + +/** + * DTO de réponse pour une relation d'amitié. + * Contient les informations sur une relation d'amitié existante. + */ +@Getter +@Setter +@NoArgsConstructor +public class FriendshipCreateOneResponseDTO { + + private UUID id; // ID de la relation d'amitié + private UUID userId; // ID de l'utilisateur qui a envoyé la demande + private UUID friendId; // ID de l'utilisateur qui a reçu la demande + private FriendshipStatus status; // Statut de la relation d'amitié (PENDING, ACCEPTED, REJECTED) + private LocalDateTime createdAt; // Date de création de la relation d'amitié + private LocalDateTime updatedAt; // Date de la dernière mise à jour + + /** + * Constructeur pour mapper l'entité `Friendship` à ce DTO. + * + * @param friendship L'entité `Friendship` à convertir en DTO. + */ + public FriendshipCreateOneResponseDTO(Friendship friendship) { + this.id = friendship.getId(); + this.userId = friendship.getUser().getId(); + this.friendId = friendship.getFriend().getId(); + this.status = friendship.getStatus(); + this.createdAt = friendship.getCreatedAt(); + this.updatedAt = friendship.getUpdatedAt(); + } +} diff --git a/src/main/java/com/lions/dev/dto/response/friends/FriendshipReadFriendDetailsResponseDTO.java b/src/main/java/com/lions/dev/dto/response/friends/FriendshipReadFriendDetailsResponseDTO.java new file mode 100644 index 0000000..792760e --- /dev/null +++ b/src/main/java/com/lions/dev/dto/response/friends/FriendshipReadFriendDetailsResponseDTO.java @@ -0,0 +1,57 @@ +package com.lions.dev.dto.response.friends; + +import com.lions.dev.entity.friends.FriendshipStatus; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; + +import java.time.LocalDateTime; +import java.util.UUID; + +/** + * DTO de réponse pour les détails d'un ami. + * Contient toutes les informations disponibles sur un ami spécifique. + */ +@Getter +@Setter +@NoArgsConstructor +public class FriendshipReadFriendDetailsResponseDTO { + + private UUID userId; // ID de l'utilisateur qui a initié la relation + private UUID friendId; // ID de l'ami + private String friendLastName; // Nom de l'ami + private String friendFirstName; // Prénom de l'ami + private String friendEmail; // Email de l'ami + private String friendProfileImageUrl; + private FriendshipStatus status; // Statut de la relation d'amitié + private LocalDateTime createdAt; // Date de création de la relation d'amitié + private LocalDateTime updatedAt; // Date de la dernière mise à jour de la relation + + /** + * Constructeur pour initialiser le DTO avec des informations sur l'ami. + * + * @param userId L'ID de l'utilisateur initiant la demande d'amitié. + * @param friendId L'ID de l'ami. + * @param friendLastName Le nom de l'ami. + * @param friendFirstName Le prénom de l'ami. + * @param friendEmail L'email de l'ami. + * @param friendProfileImageUrl L'URL de l'image de profil de l'ami. + * @param status Le statut de la relation d'amitié. + * @param createdAt La date de création de la relation. + * @param updatedAt La date de la dernière mise à jour de la relation. + */ + public FriendshipReadFriendDetailsResponseDTO(UUID userId, UUID friendId, String friendLastName, + String friendFirstName, + String friendEmail, String friendProfileImageUrl, FriendshipStatus status, + LocalDateTime createdAt, LocalDateTime updatedAt) { + this.userId = userId; + this.friendId = friendId; + this.friendLastName = friendLastName; + this.friendFirstName = friendFirstName; + this.friendEmail = friendEmail; + this.friendProfileImageUrl = friendProfileImageUrl; + this.status = status; + this.createdAt = createdAt; + this.updatedAt = updatedAt; + } +} diff --git a/src/main/java/com/lions/dev/dto/response/friends/FriendshipReadStatusResponseDTO.java b/src/main/java/com/lions/dev/dto/response/friends/FriendshipReadStatusResponseDTO.java new file mode 100644 index 0000000..5f9fb63 --- /dev/null +++ b/src/main/java/com/lions/dev/dto/response/friends/FriendshipReadStatusResponseDTO.java @@ -0,0 +1,47 @@ +package com.lions.dev.dto.response.friends; + +import com.lions.dev.entity.friends.Friendship; +import com.lions.dev.entity.friends.FriendshipStatus; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; + +import java.time.LocalDateTime; +import java.util.UUID; + +/** + * DTO de réponse pour les demandes d'amitié filtrées par statut. + * Contient les informations essentielles sans données sensibles. + */ +@Getter +@Setter +@NoArgsConstructor +public class FriendshipReadStatusResponseDTO { + + private UUID friendshipId; // ID de la relation d'amitié + private UUID userId; // ID de l'utilisateur ayant initié la demande + private String userNom; // Nom de l'utilisateur ayant initié la demande + private String userPrenoms; // Prénoms de l'utilisateur ayant initié la demande + private UUID friendId; // ID de l'utilisateur ayant reçu la demande + private String friendNom; // Nom de l'utilisateur ayant reçu la demande + private String friendPrenoms; // Prénoms de l'utilisateur ayant reçu la demande + private FriendshipStatus status; // Statut de la demande d'amitié + private LocalDateTime createdAt; // Date de création de la demande + + /** + * Constructeur qui mappe directement l'entité `Friendship` à ce DTO. + * + * @param friendship L'entité `Friendship` à convertir en DTO. + */ + public FriendshipReadStatusResponseDTO(Friendship friendship) { + this.friendshipId = friendship.getId(); + this.userId = friendship.getUser().getId(); + this.userNom = friendship.getUser().getNom(); + this.userPrenoms = friendship.getUser().getPrenoms(); + this.friendId = friendship.getFriend().getId(); + this.friendNom = friendship.getFriend().getNom(); + this.friendPrenoms = friendship.getFriend().getPrenoms(); + this.status = friendship.getStatus(); + this.createdAt = friendship.getCreatedAt(); + } +} diff --git a/src/main/java/com/lions/dev/dto/response/users/UserAuthenticateResponseDTO.java b/src/main/java/com/lions/dev/dto/response/users/UserAuthenticateResponseDTO.java index 71bb156..3443103 100644 --- a/src/main/java/com/lions/dev/dto/response/users/UserAuthenticateResponseDTO.java +++ b/src/main/java/com/lions/dev/dto/response/users/UserAuthenticateResponseDTO.java @@ -20,12 +20,6 @@ public class UserAuthenticateResponseDTO { private static final Logger logger = LoggerFactory.getLogger(UserAuthenticateResponseDTO.class); - /** - * Jeton JWT généré après une authentification réussie. - * Il doit être utilisé pour toutes les communications sécurisées avec l'API. - */ - // private String token; - /** * Identifiant unique de l'utilisateur authentifié. */ @@ -55,11 +49,13 @@ public class UserAuthenticateResponseDTO { * Log de création de l'objet DTO. */ static { - logger.info("UserAuthenticateResponseDTO - DTO pour la réponse d'authentification initialisé"); + logger.info("[LOG] UserAuthenticateResponseDTO - DTO pour la réponse d'authentification initialisé"); } - // Méthode personnalisée pour loguer les détails de la réponse + /** + * Méthode personnalisée pour loguer les détails de la réponse. + */ public void logResponseDetails() { - logger.info("Réponse d'authentification - Utilisateur: {}, {}, Email: {}, Rôle: {}, ID: {}, Token généré", prenoms, nom, email, role, userId); + logger.info("[LOG] Réponse d'authentification - Utilisateur: {}, {}, Email: {}, Rôle: {}, ID: {}", prenoms, nom, email, role, userId); } } diff --git a/src/main/java/com/lions/dev/dto/response/users/UserCreateResponseDTO.java b/src/main/java/com/lions/dev/dto/response/users/UserCreateResponseDTO.java new file mode 100644 index 0000000..7d3cf5f --- /dev/null +++ b/src/main/java/com/lions/dev/dto/response/users/UserCreateResponseDTO.java @@ -0,0 +1,35 @@ +package com.lions.dev.dto.response.users; + +import com.lions.dev.entity.users.Users; +import java.util.UUID; +import lombok.Getter; + +/** + * DTO pour renvoyer les informations d'un utilisateur. + * Ce DTO est utilisé pour structurer les données retournées dans les réponses + * après les opérations sur les utilisateurs (création, récupération). + */ +@Getter +public class UserCreateResponseDTO { + + private UUID uuid; // Identifiant unique de l'utilisateur + private String nom; // Nom de l'utilisateur + private String prenoms; // Prénoms de l'utilisateur + private String email; // Email de l'utilisateur + private String role; // Roğe de l'utilisateur + private String profileImageUrl; // Url de l'image de profil de l'utilisateur + /** + * Constructeur qui transforme une entité Users en DTO. + * + * @param user L'utilisateur à convertir en DTO. + */ + public UserCreateResponseDTO(Users user) { + this.uuid = user.getId(); + this.nom = user.getNom(); + this.prenoms = user.getPrenoms(); + this.email = user.getEmail(); + this.role = user.getRole(); + this.profileImageUrl = user.getProfileImageUrl(); + System.out.println("[LOG] DTO créé pour l'utilisateur : " + this.email); + } +} diff --git a/src/main/java/com/lions/dev/dto/response/users/UserDeleteResponseDto.java b/src/main/java/com/lions/dev/dto/response/users/UserDeleteResponseDto.java new file mode 100644 index 0000000..c7a360e --- /dev/null +++ b/src/main/java/com/lions/dev/dto/response/users/UserDeleteResponseDto.java @@ -0,0 +1,38 @@ +package com.lions.dev.dto.response.users; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * DTO pour la réponse après la tentative de suppression d'un utilisateur. + * Indique si la suppression a réussi ou échoué. + */ +@Getter +@Setter +@AllArgsConstructor +@NoArgsConstructor +public class UserDeleteResponseDto { + + private static final Logger logger = LoggerFactory.getLogger(UserDeleteResponseDto.class); + + /** + * Statut indiquant si la suppression a réussi ou échoué. + */ + private boolean success; + + /** + * Message décrivant le résultat de l'opération. + */ + private String message; + + /** + * Méthode pour loguer les détails de la réponse. + */ + public void logResponseDetails() { + logger.info("[LOG] Suppression d'utilisateur - Succès : {}, Message : {}", success, message); + } +} diff --git a/src/main/java/com/lions/dev/dto/response/users/UserResponseDTO.java b/src/main/java/com/lions/dev/dto/response/users/UserResponseDTO.java index 394b9b1..0921ca9 100644 --- a/src/main/java/com/lions/dev/dto/response/users/UserResponseDTO.java +++ b/src/main/java/com/lions/dev/dto/response/users/UserResponseDTO.java @@ -1,31 +1,69 @@ -package com.lions.dev.dto.response.users; +package com.lions.dev.dto; -import com.lions.dev.entity.users.Users; +import com.lions.dev.entity.users.Users; // Import de l'entité Users import java.util.UUID; +import lombok.AllArgsConstructor; import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; /** - * DTO pour renvoyer les informations d'un utilisateur. - * Ce DTO est utilisé pour structurer les données retournées dans les réponses - * après les opérations sur les utilisateurs (création, récupération). + * DTO (Data Transfer Object) pour l'utilisateur. + *

+ * Cette classe sert de représentation simplifiée d'un utilisateur, avec un ensemble d'informations nécessaires à + * la réponse de l'API. Elle est utilisée pour transférer des données entre le backend (serveur) et le frontend (client) + * tout en excluant les informations sensibles comme le mot de passe. + *

*/ @Getter +@Setter +@NoArgsConstructor +@AllArgsConstructor public class UserResponseDTO { - private UUID uuid; - private String nom; // Nom de l'utilisateur - private String prenoms; // Prénoms de l'utilisateur - private String email; // Email de l'utilisateur + /** + * Identifiant unique de l'utilisateur. Il s'agit d'un UUID généré de manière unique. + */ + private UUID id; /** - * Constructeur qui transforme une entité Users en DTO. + * Nom de famille de l'utilisateur. C'est une donnée importante pour l'affichage du profil. + */ + private String nom; + + /** + * Prénom(s) de l'utilisateur. Représente le ou les prénoms associés à l'utilisateur. + */ + private String prenoms; + + /** + * Adresse email de l'utilisateur. C'est une donnée souvent utilisée pour les communications. + */ + private String email; + + /** + * URL de l'image de profil de l'utilisateur. Si l'utilisateur a une image de profil, cette URL + * pointe vers l'emplacement de l'image. + */ + private String profileImageUrl; + + /** + * Constructeur de DTO à partir d'une entité Users. + *

+ * Ce constructeur prend une entité {@link Users} et extrait les données nécessaires pour + * peupler les champs du DTO. Cette transformation permet de transférer des données sans exposer + * des informations sensibles. + *

* - * @param user L'utilisateur à convertir en DTO. + * @param user L'entité {@link Users} dont les données sont extraites. */ public UserResponseDTO(Users user) { - this.uuid = user.getId(); - this.nom = user.getNom(); - this.prenoms = user.getPrenoms(); - this.email = user.getEmail(); + if (user != null) { + this.id = user.getId(); // Identifiant unique de l'utilisateur + this.nom = user.getNom(); // Nom de famille + this.prenoms = user.getPrenoms(); // Prénom(s) + this.email = user.getEmail(); // Email + this.profileImageUrl = user.getProfileImageUrl(); // URL de l'image de profil + } } } diff --git a/src/main/java/com/lions/dev/entity/comment/Comment.java b/src/main/java/com/lions/dev/entity/comment/Comment.java index 04259e7..397128a 100644 --- a/src/main/java/com/lions/dev/entity/comment/Comment.java +++ b/src/main/java/com/lions/dev/entity/comment/Comment.java @@ -1,22 +1,21 @@ package com.lions.dev.entity.comment; import com.lions.dev.entity.BaseEntity; -import com.lions.dev.entity.users.Users; import com.lions.dev.entity.events.Events; +import com.lions.dev.entity.users.Users; import jakarta.persistence.*; +import java.time.LocalDateTime; import lombok.Getter; import lombok.NoArgsConstructor; import lombok.Setter; import lombok.ToString; -import java.time.LocalDateTime; - /** * Entité représentant un commentaire d'un utilisateur sur un événement dans le système AfterWork. - * Chaque commentaire est lié à un utilisateur et à un événement, et contient le texte du commentaire - * ainsi que la date de création. + * Chaque commentaire est lié à un utilisateur et à un événement, et contient le texte du + * commentaire ainsi que la date de création. * - * Des logs et des commentaires sont inclus pour assurer une traçabilité claire. + *

L'entité gère la relation entre les commentaires, les utilisateurs et les événements. */ @Entity @Table(name = "comments") @@ -30,7 +29,7 @@ public class Comment extends BaseEntity { private String text; // Le texte du commentaire @Column(name = "comment_date", nullable = false) - private LocalDateTime commentDate; // La date à laquelle le commentaire a été publié + private LocalDateTime commentDate; // La date de création du commentaire @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "user_id", nullable = false) @@ -43,26 +42,45 @@ public class Comment extends BaseEntity { /** * Constructeur pour créer un nouveau commentaire. * - * @param user L'utilisateur qui commente. - * @param event L'événement commenté. + *

Le constructeur initialise un commentaire avec l'utilisateur, l'événement et le texte + * fournis. Il définit également la date de création du commentaire. + * + * @param user L'utilisateur qui fait le commentaire. + * @param event L'événement auquel ce commentaire est lié. * @param text Le texte du commentaire. */ public Comment(Users user, Events event, String text) { this.user = user; this.event = event; this.text = text; - this.commentDate = LocalDateTime.now(); // Définit automatiquement la date actuelle - System.out.println("[LOG] Nouveau commentaire ajouté par " + user.getEmail() + " sur l'événement : " + event.getTitle() + " - Texte : " + text); + this.commentDate = + LocalDateTime.now(); // La date est définie automatiquement lors de la création + System.out.println( + "[LOG] Nouveau commentaire ajouté par " + + user.getEmail() + + " sur l'événement : " + + event.getTitle() + + " - Texte : " + + text); } /** * Modifie le texte du commentaire. * + *

Cette méthode permet de mettre à jour le texte d'un commentaire existant et de mettre à jour + * la date du commentaire pour refléter le changement. + * * @param newText Le nouveau texte du commentaire. */ public void updateComment(String newText) { - System.out.println("[LOG] Modification du commentaire de " + user.getEmail() + " sur l'événement : " + event.getTitle() + " - Nouveau texte : " + newText); + System.out.println( + "[LOG] Modification du commentaire de " + + user.getEmail() + + " sur l'événement : " + + event.getTitle() + + " - Nouveau texte : " + + newText); this.text = newText; - this.commentDate = LocalDateTime.now(); // Met à jour la date de modification + this.commentDate = LocalDateTime.now(); // Mise à jour de la date de modification } } diff --git a/src/main/java/com/lions/dev/entity/events/Events.java b/src/main/java/com/lions/dev/entity/events/Events.java index 23276b4..d204562 100644 --- a/src/main/java/com/lions/dev/entity/events/Events.java +++ b/src/main/java/com/lions/dev/entity/events/Events.java @@ -1,8 +1,10 @@ package com.lions.dev.entity.events; import com.lions.dev.entity.BaseEntity; +import com.lions.dev.entity.comment.Comment; import com.lions.dev.entity.users.Users; import jakarta.persistence.*; +import java.util.List; import lombok.Getter; import lombok.NoArgsConstructor; import lombok.Setter; @@ -14,9 +16,8 @@ import java.util.Set; /** * Entité représentant un événement dans le système AfterWork. - * Chaque événement possède un titre, une date de début, une date de fin, un créateur, - * et des participants. - * + * Chaque événement possède un titre, une description, une date de début, une date de fin, + * un créateur, une catégorie, un lieu, une URL d'image, et des participants. * Tous les logs et commentaires nécessaires pour la traçabilité et la documentation sont inclus. */ @Entity @@ -27,17 +28,33 @@ import java.util.Set; @ToString public class Events extends BaseEntity { - // Attributs de l'entité événement - @Column(name = "title", nullable = false) private String title; // Le titre de l'événement + @Column(name = "description",length = 1000) + private String description; // La description de l'événement + @Column(name = "start_date", nullable = false) private LocalDateTime startDate; // La date de début de l'événement @Column(name = "end_date", nullable = false) private LocalDateTime endDate; // La date de fin de l'événement + @Column(name = "location") + private String location; // Le lieu de l'événement + + @Column(name = "category") + private String category; // La catégorie de l'événement + + @Column(name = "link") + private String link; // Un lien vers plus d'informations sur l'événement + + @Column(name = "image_url") + private String imageUrl; // URL d'une image associée à l'événement + + @Column(name = "status", nullable = false) + private String status = "ouvert"; // Le statut de l'événement (en cours, terminé, annulé, etc.) + @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "creator_id", nullable = false) private Users creator; // L'utilisateur créateur de l'événement @@ -50,6 +67,8 @@ public class Events extends BaseEntity { ) private Set participants = new HashSet<>(); // Les participants à l'événement + // Méthodes + /** * Ajoute un utilisateur en tant que participant à l'événement. * @@ -80,4 +99,26 @@ public class Events extends BaseEntity { System.out.println("[LOG] Nombre de participants à l'événement : " + this.title + " - " + count); return count; } + + /** + * Ferme l'événement en changeant son statut. + */ + public void setClosed(boolean closed) { + this.status = closed ? "fermé" : "ouvert"; + System.out.println("[LOG] Statut de l'événement mis à jour : " + this.title + " - " + this.status); + } + + @OneToMany(fetch = FetchType.LAZY, mappedBy = "event") + private List comments; // Liste des commentaires associés à l'événement + + /** + * Retourne la liste des commentaires associés à cet événement. + * + * @return Une liste de commentaires. + */ + public List getComments() { + System.out.println("[LOG] Récupération des commentaires pour l'événement : " + this.title); + return comments; + } + } diff --git a/src/main/java/com/lions/dev/entity/friends/Friendship.java b/src/main/java/com/lions/dev/entity/friends/Friendship.java new file mode 100644 index 0000000..475f4ae --- /dev/null +++ b/src/main/java/com/lions/dev/entity/friends/Friendship.java @@ -0,0 +1,49 @@ +package com.lions.dev.entity.friends; + +import com.lions.dev.entity.BaseEntity; +import com.lions.dev.entity.users.Users; +import jakarta.persistence.*; +import lombok.*; + +/** Représentation de l'entité Friendship qui gère les relations d'amitié entre utilisateurs. */ +@Entity +@Getter +@Setter +@NoArgsConstructor +@AllArgsConstructor +@Builder +@ToString +@Table(name = "friendships") +public class Friendship extends BaseEntity { + + // Utilisateur qui initie la demande + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "user_id", nullable = false) + private Users user; + + // L'ami avec qui la relation est établie + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "friend_id", nullable = false) + private Users friend; + + // Statut de la relation (en attente, acceptée, rejetée) + @Enumerated(EnumType.STRING) + @Column(nullable = false) + private FriendshipStatus status; + + /** + * Mise à jour du statut de la relation d'amitié avec log des changements. + * + * @param newStatus Nouveau statut de l'amitié + */ + public void setStatus(FriendshipStatus newStatus) { + this.status = newStatus; + System.out.println( + "[LOG] Statut changé pour l'amitié entre " + + this.user.getEmail() + + " et " + + this.friend.getEmail() + + " - Nouveau statut : " + + this.status); + } +} diff --git a/src/main/java/com/lions/dev/entity/friends/FriendshipStatus.java b/src/main/java/com/lions/dev/entity/friends/FriendshipStatus.java new file mode 100644 index 0000000..11c8316 --- /dev/null +++ b/src/main/java/com/lions/dev/entity/friends/FriendshipStatus.java @@ -0,0 +1,7 @@ +package com.lions.dev.entity.friends; + +public enum FriendshipStatus { + PENDING, // Demande envoyée, en attente d'acceptation + ACCEPTED, // Demande acceptée + REJECTED // Demande rejetée +} \ No newline at end of file diff --git a/src/main/java/com/lions/dev/entity/users/Users.java b/src/main/java/com/lions/dev/entity/users/Users.java index 465823a..5da1c15 100644 --- a/src/main/java/com/lions/dev/entity/users/Users.java +++ b/src/main/java/com/lions/dev/entity/users/Users.java @@ -1,7 +1,10 @@ package com.lions.dev.entity.users; import com.lions.dev.entity.BaseEntity; +import com.lions.dev.entity.events.Events; import jakarta.persistence.*; +import java.util.HashSet; +import java.util.Set; import lombok.Getter; import lombok.NoArgsConstructor; import lombok.Setter; @@ -23,8 +26,6 @@ import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; @ToString public class Users extends BaseEntity { - // Attributs de l'entité utilisateur - @Column(name = "nom", nullable = false, length = 100) private String nom; // Le nom de l'utilisateur @@ -40,6 +41,12 @@ public class Users extends BaseEntity { @Column(name = "role", nullable = false) private String role; // Le rôle de l'utilisateur (ADMIN, MODERATOR, USER, etc.) + @Column(name = "profile_image_url") + private String profileImageUrl; // L'URL de l'image de profil de l'utilisateur + + @Column(name = "preferred_category") + private String preferredCategory; // La catégorie préférée de l'utilisateur + // Utilisation de BCrypt pour hacher les mots de passe de manière sécurisée private static final BCryptPasswordEncoder encoder = new BCryptPasswordEncoder(); @@ -75,4 +82,49 @@ public class Users extends BaseEntity { System.out.println("[LOG] Vérification du rôle ADMIN pour l'utilisateur : " + this.email + " - Résultat : " + isAdmin); return isAdmin; } + + @OneToMany(fetch = FetchType.LAZY) + @JoinColumn(name = "favorite_events") + private Set favoriteEvents = new HashSet<>(); // Liste des événements favoris + + /** + * Ajoute un événement aux favoris de l'utilisateur. + * + * @param event L'événement à ajouter. + */ + public void addFavoriteEvent(Events event) { + favoriteEvents.add(event); + System.out.println("[LOG] Événement ajouté aux favoris pour l'utilisateur : " + this.email); + } + + /** + * Retourne la liste des événements favoris de l'utilisateur. + * + * @return Une liste d'événements favoris. + */ + public Set getFavoriteEvents() { + System.out.println("[LOG] Récupération des événements favoris pour l'utilisateur : " + this.email); + return favoriteEvents; + } + + /** + * Retourne la catégorie préférée de l'utilisateur. + * + * @return La catégorie préférée de l'utilisateur. + */ + public String getPreferredCategory() { + System.out.println("[LOG] Récupération de la catégorie préférée pour l'utilisateur : " + this.email); + return preferredCategory; + } + + /** + * Définit la catégorie préférée de l'utilisateur. + * + * @param category La catégorie à définir. + */ + public void setPreferredCategory(String category) { + this.preferredCategory = category; + System.out.println("[LOG] Catégorie préférée définie pour l'utilisateur : " + this.email + " - Catégorie : " + category); + } + } diff --git a/src/main/java/com/lions/dev/exception/EventNotFoundException.java b/src/main/java/com/lions/dev/exception/EventNotFoundException.java index cf0b026..e310b71 100644 --- a/src/main/java/com/lions/dev/exception/EventNotFoundException.java +++ b/src/main/java/com/lions/dev/exception/EventNotFoundException.java @@ -2,6 +2,7 @@ package com.lions.dev.exception; import jakarta.ws.rs.WebApplicationException; import jakarta.ws.rs.core.Response; +import java.util.UUID; /** * Exception levée lorsque l'événement demandé n'est pas trouvé dans la base de données. @@ -10,12 +11,12 @@ import jakarta.ws.rs.core.Response; public class EventNotFoundException extends WebApplicationException { /** - * Constructeur qui prend un message d'erreur à afficher lorsque l'exception est levée. + * Constructeur qui prend un UUID et convertit l'UUID en message détaillant l'erreur. * - * @param message Le message détaillant l'erreur. + * @param eventId L'UUID de l'événement qui n'a pas été trouvé. */ - public EventNotFoundException(String message) { - super(message, Response.Status.NOT_FOUND); - System.out.println("[ERROR] Événement non trouvé : " + message); + public EventNotFoundException(UUID eventId) { + super("Événement non trouvé avec l'ID : " + eventId.toString(), Response.Status.NOT_FOUND); + System.out.println("[ERROR] Événement non trouvé avec l'ID : " + eventId.toString()); } -} \ No newline at end of file +} diff --git a/src/main/java/com/lions/dev/exception/FriendshipNotFoundException.java b/src/main/java/com/lions/dev/exception/FriendshipNotFoundException.java new file mode 100644 index 0000000..b84d376 --- /dev/null +++ b/src/main/java/com/lions/dev/exception/FriendshipNotFoundException.java @@ -0,0 +1,11 @@ +package com.lions.dev.exception; + +/** + * Exception levée lorsque la relation d'amitié n'est pas trouvée. + */ +public class FriendshipNotFoundException extends RuntimeException { + + public FriendshipNotFoundException(String message) { + super(message); + } +} diff --git a/src/main/java/com/lions/dev/repository/EventsRepository.java b/src/main/java/com/lions/dev/repository/EventsRepository.java index 843d335..a9fce37 100644 --- a/src/main/java/com/lions/dev/repository/EventsRepository.java +++ b/src/main/java/com/lions/dev/repository/EventsRepository.java @@ -3,79 +3,50 @@ package com.lions.dev.repository; import com.lions.dev.entity.events.Events; import io.quarkus.hibernate.orm.panache.PanacheRepositoryBase; import jakarta.enterprise.context.ApplicationScoped; - import java.time.LocalDateTime; import java.util.List; -import java.util.Optional; import java.util.UUID; +import org.jboss.logging.Logger; /** * Repository pour l'entité Events. - * Ce repository gère les opérations de base (CRUD) sur les événements ainsi que des méthodes de filtrage personnalisées. - * - * Utilisation de Panache pour simplifier les opérations sur la base de données. + * Ce repository gère les opérations de base (CRUD) sur les événements et inclut + * des méthodes personnalisées comme la récupération des événements après une certaine date. */ @ApplicationScoped public class EventsRepository implements PanacheRepositoryBase { - /** - * Recherche un événement par son titre. - * - * @param title Le titre de l'événement à rechercher. - * @return Un Optional contenant l'événement s'il est trouvé, sinon un Optional vide. - */ - public Optional findByTitle(String title) { - System.out.println("[LOG] Recherche de l'événement avec le titre : " + title); - Events event = find("title", title).firstResult(); - if (event != null) { - System.out.println("[LOG] Événement trouvé : " + event.getTitle()); - } else { - System.out.println("[LOG] Aucun événement trouvé avec le titre : " + title); - } - return Optional.ofNullable(event); - } + private static final Logger LOG = Logger.getLogger(EventsRepository.class); /** - * Récupère tous les événements créés par un utilisateur spécifique. + * Récupère tous les événements après une date donnée. * - * @param userId L'ID de l'utilisateur créateur des événements. - * @return Une liste d'événements créés par l'utilisateur. + * @param startDate La date de début de filtre. + * @return Une liste d'événements après cette date. */ - public List findByCreator(UUID userId) { - System.out.println("[LOG] Récupération des événements créés par l'utilisateur avec l'ID : " + userId); - List events = list("creator.id", userId); - System.out.println("[LOG] Nombre d'événements trouvés pour l'utilisateur : " + events.size()); + public List findEventsAfterDate(LocalDateTime startDate) { + LOG.info("[LOG] Récupération des événements après la date : " + startDate); + List events = list("startDate > ?1", startDate); + LOG.info("[LOG] Nombre d'événements trouvés après la date " + startDate + " : " + events.size()); return events; } /** - * Supprime un événement par son identifiant UUID. + * Récupère tous les événements entre deux dates. * - * @param id L'UUID de l'événement à supprimer. - * @return true si l'événement a été supprimé, sinon false. + * @param startDate La date de début de filtre. + * @param endDate La date de fin de filtre. + * @return Une liste d'événements entre ces deux dates. */ - public boolean deleteById(UUID id) { - System.out.println("[LOG] Suppression de l'événement avec l'ID : " + id); - long deletedCount = delete("id", id); // Utiliser long pour récupérer le nombre d'enregistrements supprimés - boolean deleted = deletedCount > 0; // Convertir en boolean - if (deleted) { - System.out.println("[LOG] Événement avec l'ID " + id + " supprimé avec succès."); - } else { - System.out.println("[LOG] Aucune suppression, événement avec l'ID " + id + " introuvable."); + public List findEventsBetweenDates(LocalDateTime startDate, LocalDateTime endDate) { + if (endDate.isBefore(startDate)) { + LOG.warn("[LOG] La date de fin " + endDate + " est antérieure à la date de début " + startDate); + return List.of(); // Retourner une liste vide en cas de dates invalides } - return deleted; - } - /** - * Récupère une liste d'événements avec filtrage par date de début. - * - * @param startDate La date de début à partir de laquelle rechercher les événements. - * @return Une liste d'événements filtrés. - */ - public List findEventsAfterDate(LocalDateTime startDate) { - System.out.println("[LOG] Récupération des événements après la date : " + startDate); - List events = list("startDate >= ?1", startDate); - System.out.println("[LOG] Nombre d'événements trouvés après la date : " + startDate + " : " + events.size()); + LOG.info("[LOG] Récupération des événements entre les dates : " + startDate + " et " + endDate); + List events = list("startDate >= ?1 and endDate <= ?2", startDate, endDate); + LOG.info("[LOG] Nombre d'événements trouvés entre les dates " + startDate + " et " + endDate + " : " + events.size()); return events; } } diff --git a/src/main/java/com/lions/dev/repository/FriendshipRepository.java b/src/main/java/com/lions/dev/repository/FriendshipRepository.java new file mode 100644 index 0000000..7f24780 --- /dev/null +++ b/src/main/java/com/lions/dev/repository/FriendshipRepository.java @@ -0,0 +1,98 @@ +package com.lions.dev.repository; + +import com.lions.dev.entity.friends.Friendship; +import com.lions.dev.entity.friends.FriendshipStatus; +import com.lions.dev.entity.users.Users; +import io.quarkus.hibernate.orm.panache.PanacheRepositoryBase; +import jakarta.enterprise.context.ApplicationScoped; +import org.jboss.logging.Logger; + +import java.util.List; +import java.util.Optional; +import java.util.UUID; + +/** + * Repository pour gérer les relations d'amitié (Friendship) dans la base de données. + * Cette classe contient des méthodes pour récupérer, ajouter, et supprimer des relations d'amitié. + * Elle est utilisée pour interagir avec la table des relations d'amitié en base de données. + * + * Elle est annotée avec @ApplicationScoped pour être gérée par le conteneur CDI de Quarkus. + */ +@ApplicationScoped +public class FriendshipRepository implements PanacheRepositoryBase { + + // Logger pour les logs de la classe + private static final Logger logger = Logger.getLogger(FriendshipRepository.class); + + /** + * Trouver une relation d'amitié entre deux utilisateurs spécifiés. + * Cette méthode recherche une relation d'amitié entre deux utilisateurs donnés. + * Elle peut être utilisée pour vérifier si une demande d'amitié existe déjà. + * + * @param user L'utilisateur qui envoie la demande d'amitié. + * @param friend L'ami qui reçoit la demande. + * @return Une Optional contenant la relation d'amitié si elle existe. + */ + public Optional findByUsers(Users user, Users friend) { + logger.infof("Recherche de la relation d'amitié entre les utilisateurs : %s et %s", user.getId(), friend.getId()); + + // Requête qui cherche une relation d'amitié entre deux utilisateurs spécifiques + Optional friendship = find("user = ?1 and friend = ?2", user, friend).firstResultOptional(); + + if (friendship.isPresent()) { + logger.infof("Relation d'amitié trouvée entre %s et %s", user.getId(), friend.getId()); + } else { + logger.warnf("Aucune relation d'amitié trouvée entre %s et %s", user.getId(), friend.getId()); + } + + return friendship; + } + + /** + * Récupérer la liste des amis d'un utilisateur avec un statut d'amitié spécifique (ACCEPTED). + * Cette méthode récupère les relations d'amitié acceptées pour un utilisateur donné, + * avec la possibilité de paginer les résultats. + * + * @param user L'utilisateur dont on souhaite récupérer les amis. + * @param page Le numéro de la page à récupérer. + * @param size La taille de la page (nombre d'éléments). + * @return Une liste paginée de relations d'amitié acceptées. + */ + public List findFriendsByUser(Users user, int page, int size) { + logger.infof("Récupération des amis pour l'utilisateur %s, page %d, taille %d", user.getId(), page, size); + + // Utilisation d'une requête pour récupérer les relations d'amitié acceptées pour l'utilisateur spécifié + List friendships = find("(user.id = ?1 OR friend.id = ?1) AND status = ?2", user.getId(), FriendshipStatus.ACCEPTED) + .page(page, size) + .stream() + .filter(friendship -> !friendship.getUser().equals(friendship.getFriend())) // Exclure les relations où l'utilisateur est ami avec lui-même + .distinct() // Appliquer distinct pour éviter les doublons + .toList(); + + logger.infof("Nombre d'amis récupérés pour l'utilisateur %s : %d", user.getId(), friendships.size()); + return friendships; + } + + /** + * Récupérer toutes les relations d'amitié d'un utilisateur avec un statut spécifique. + * Cette méthode permet de filtrer les relations par statut (par exemple, ACCEPTED, PENDING). + * Elle est également paginée. + * + * @param user L'utilisateur dont on souhaite récupérer les relations d'amitié. + * @param status Le statut des relations d'amitié à filtrer (ACCEPTED, PENDING, etc.). + * @param page Le numéro de la page à récupérer. + * @param size La taille de la page (nombre d'éléments). + * @return Une liste paginée de relations d'amitié avec le statut spécifié. + */ + public List findByUserAndStatus(Users user, FriendshipStatus status, int page, int size) { + logger.infof("Récupération des relations d'amitié pour l'utilisateur %s avec le statut %s, page %d, taille %d", user.getId(), status, page, size); + + // Requête pour récupérer les relations avec un statut spécifique + List friendships = find("(user = ?1 OR friend = ?1) AND status = ?2", user, status) + .page(page, size) + .list(); + + logger.infof("Nombre de relations récupérées pour l'utilisateur %s avec le statut %s : %d", user.getId(), status, friendships.size()); + return friendships; + } +} diff --git a/src/main/java/com/lions/dev/repository/UsersRepository.java b/src/main/java/com/lions/dev/repository/UsersRepository.java index 63046e1..17a143d 100644 --- a/src/main/java/com/lions/dev/repository/UsersRepository.java +++ b/src/main/java/com/lions/dev/repository/UsersRepository.java @@ -63,5 +63,4 @@ public class UsersRepository implements PanacheRepositoryBase { } return deleted; } - } diff --git a/src/main/java/com/lions/dev/resource/EventsResource.java b/src/main/java/com/lions/dev/resource/EventsResource.java index 0890d05..3603bc8 100644 --- a/src/main/java/com/lions/dev/resource/EventsResource.java +++ b/src/main/java/com/lions/dev/resource/EventsResource.java @@ -1,24 +1,41 @@ package com.lions.dev.resource; +import com.lions.dev.core.errors.exceptions.EventNotFoundException; +import com.lions.dev.dto.UserResponseDTO; +import com.lions.dev.dto.request.events.EventCreateRequestDTO; +import com.lions.dev.dto.request.events.EventReadManyByIdRequestDTO; +import com.lions.dev.dto.request.events.EventUpdateRequestDTO; +import com.lions.dev.dto.response.comments.CommentResponseDTO; +import com.lions.dev.dto.response.events.EventCreateResponseDTO; +import com.lions.dev.dto.response.events.EventReadManyByIdResponseDTO; +import com.lions.dev.dto.response.events.EventUpdateResponseDTO; +import com.lions.dev.dto.response.friends.FriendshipReadFriendDetailsResponseDTO; +import com.lions.dev.entity.comment.Comment; import com.lions.dev.entity.events.Events; +import com.lions.dev.entity.users.Users; import com.lions.dev.repository.EventsRepository; -import com.lions.dev.dto.request.events.EventRequestDTO; -import com.lions.dev.dto.response.events.EventResponseDTO; -import com.lions.dev.exception.EventNotFoundException; +import com.lions.dev.repository.UsersRepository; +import com.lions.dev.service.EventService; +import com.lions.dev.service.FriendshipService; import jakarta.inject.Inject; import jakarta.transaction.Transactional; import jakarta.ws.rs.*; import jakarta.ws.rs.core.Response; +import java.io.File; import java.time.LocalDateTime; +import java.util.ArrayList; import java.util.List; +import java.util.Map; +import java.util.Set; 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 événements dans le système AfterWork. - * Cette classe expose des endpoints pour créer, récupérer, et supprimer des événements. + * Cette classe expose des endpoints pour créer, récupérer, mettre à jour et supprimer des événements. * * Tous les logs nécessaires pour la traçabilité sont intégrés. */ @@ -31,102 +48,791 @@ public class EventsResource { @Inject EventsRepository eventsRepository; + @Inject + UsersRepository usersRepository; + + @Inject + EventService eventService; + + @Inject + FriendshipService friendshipService; + private static final Logger LOG = Logger.getLogger(EventsResource.class); - /** - * Endpoint pour créer un nouvel événement. - * - * @param eventRequestDTO Le DTO contenant les informations de l'événement à créer. - * @return Une réponse HTTP contenant l'événement créé ou un message d'erreur. - */ + // *********** Création d'un événement *********** + @POST @Transactional @Operation(summary = "Créer un nouvel événement", description = "Crée un nouvel événement et retourne ses détails") - public Response createEvent(EventRequestDTO eventRequestDTO) { - LOG.info("Tentative de création d'un nouvel événement : " + eventRequestDTO.getTitle()); - - Events event = new Events(); - event.setTitle(eventRequestDTO.getTitle()); - event.setStartDate(eventRequestDTO.getStartDate()); - event.setEndDate(eventRequestDTO.getEndDate()); - event.setCreator(eventRequestDTO.getCreator()); // Créateur de l'événement - - eventsRepository.persist(event); - LOG.info("Événement créé avec succès : " + event.getTitle()); - - EventResponseDTO responseDTO = new EventResponseDTO(event); + public Response createEvent(EventCreateRequestDTO eventCreateRequestDTO) { + LOG.info("[LOG] Tentative de création d'un nouvel événement : " + eventCreateRequestDTO.getTitle()); + 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(); + } + Events event = eventService.createEvent(eventCreateRequestDTO, creator); + LOG.info("[LOG] Événement créé avec succès : " + event.getTitle()); + EventCreateResponseDTO responseDTO = new EventCreateResponseDTO(event); return Response.status(Response.Status.CREATED).entity(responseDTO).build(); } - /** - * Endpoint pour récupérer les détails d'un événement par ID. - * - * @param id L'ID de l'événement. - * @return Une réponse HTTP contenant les informations de l'événement. - */ + // *********** Récupération d'un événement par ID *********** + @GET @Path("/{id}") @Operation(summary = "Récupérer un événement par ID", description = "Retourne les détails de l'événement demandé") public Response getEventById(@PathParam("id") UUID id) { - LOG.info("Récupération de l'événement avec l'ID : " + id); - + LOG.info("[LOG] Récupération de l'événement avec l'ID : " + id); Events event = eventsRepository.findById(id); if (event == null) { - LOG.warn("Événement non trouvé avec l'ID : " + id); - return Response.status(Response.Status.NOT_FOUND) - .entity("Événement non trouvé.").build(); + LOG.warn("[LOG] Événement non trouvé avec l'ID : " + id); + return Response.status(Response.Status.NOT_FOUND).entity("Événement non trouvé.").build(); } - - EventResponseDTO responseDTO = new EventResponseDTO(event); - LOG.info("Événement trouvé : " + event.getTitle()); + EventCreateResponseDTO responseDTO = new EventCreateResponseDTO(event); + LOG.info("[LOG] Événement trouvé : " + event.getTitle()); return Response.ok(responseDTO).build(); } - /** - * Endpoint pour récupérer une liste de tous les événements après une date donnée. - * - * @param startDate La date de début à partir de laquelle filtrer les événements. - * @return Une réponse HTTP contenant la liste des événements après cette date. - */ - @GET - @Path("/after-date") - @Operation(summary = "Récupérer les événements après une date", description = "Retourne les événements après une date donnée") - public Response getEventsAfterDate(@QueryParam("startDate") LocalDateTime startDate) { - LOG.info("Récupération des événements après la date : " + startDate); + // *********** Suppression d'un événement *********** - List events = eventsRepository.findEventsAfterDate(startDate); - if (events.isEmpty()) { - LOG.warn("Aucun événement trouvé après la date : " + startDate); - return Response.status(Response.Status.NOT_FOUND) - .entity("Aucun événement trouvé après cette date.").build(); - } - - List responseDTOs = events.stream().map(EventResponseDTO::new).toList(); - LOG.info("Nombre d'événements trouvés après la date : " + events.size()); - return Response.ok(responseDTOs).build(); - } - - /** - * Endpoint pour supprimer un événement par ID. - * - * @param id L'ID de l'événement à supprimer. - * @return Une réponse HTTP indiquant le succès ou l'échec de la suppression. - */ @DELETE @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); - - boolean deleted = eventsRepository.deleteById(id); - if (deleted) { - LOG.info("Événement supprimé avec succès."); - return Response.noContent().build(); - } else { - LOG.warn("Échec de la suppression : événement introuvable avec l'ID : " + id); - return Response.status(Response.Status.NOT_FOUND) - .entity("Événement non trouvé.").build(); + try { + boolean deleted = eventService.deleteEvent(id); + if (deleted) { + LOG.info("Événement supprimé avec succès."); + return Response.noContent().build(); + } else { + LOG.warn("Échec de la suppression : événement introuvable avec l'ID : " + id); + return Response.status(Response.Status.NOT_FOUND).entity("Événement non trouvé.").build(); + } + } 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(); } } + + // *********** Ajouter un participant à un événement *********** + + @POST + @Path("/{id}/participants") + @Transactional + @Operation(summary = "Ajouter un participant à un événement", description = "Ajoute un utilisateur à un événement") + public Response addParticipant(@PathParam("id") UUID eventId, Users user) { + LOG.info("Ajout d'un participant à l'événement : " + eventId); + Events event = eventsRepository.findById(eventId); + if (event == null) { + LOG.warn("Événement non trouvé avec l'ID : " + eventId); + return Response.status(Response.Status.NOT_FOUND).entity("Événement non trouvé.").build(); + } + event.addParticipant(user); + eventsRepository.persist(event); + LOG.info("Participant ajouté avec succès à l'événement : " + event.getTitle()); + return Response.ok(new EventCreateResponseDTO(event)).build(); + } + + // *********** Retirer un participant d'un événement *********** + + @DELETE + @Path("/{id}/participants/{userId}") + @Transactional + @Operation(summary = "Retirer un participant d'un événement", description = "Supprime un utilisateur de la liste des participants d'un événement") + public Response removeParticipant(@PathParam("id") UUID eventId, @PathParam("userId") UUID userId) { + LOG.info("Retrait d'un participant de l'événement : " + eventId); + Events event = eventsRepository.findById(eventId); + if (event == null) { + LOG.warn("É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("Utilisateur non trouvé avec l'ID : " + userId); + return Response.status(Response.Status.NOT_FOUND).entity("Utilisateur non trouvé.").build(); + } + event.removeParticipant(user); + eventsRepository.persist(event); + LOG.info("Participant retiré avec succès de l'événement : " + event.getTitle()); + return Response.noContent().build(); + } + + // *********** Mettre à jour un événement *********** + + @PUT + @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); + 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(); + } + // Mise à jour des attributs de l'événement + event.setTitle(eventUpdateRequestDTO.getTitle()); + event.setStartDate(eventUpdateRequestDTO.getStartDate()); + event.setEndDate(eventUpdateRequestDTO.getEndDate()); + event.setDescription(eventUpdateRequestDTO.getDescription()); + event.setLocation(eventUpdateRequestDTO.getLocation()); + event.setCategory(eventUpdateRequestDTO.getCategory()); + event.setLink(eventUpdateRequestDTO.getLink()); + event.setImageUrl(eventUpdateRequestDTO.getImageUrl()); + eventsRepository.persist(event); + LOG.info("[LOG] Événement mis à jour avec succès : " + event.getTitle()); + EventUpdateResponseDTO responseDTO = new EventUpdateResponseDTO(event); + return Response.ok(responseDTO).build(); + } + + // *********** Récupérer les événements créés par un utilisateur spécifique et ses amis *********** + + @POST + @Path("/created-by-user-and-friends") + @Consumes("application/json") + @Produces("application/json") + @Operation(summary = "Récupérer les événements créés par un utilisateur et ses amis", description = "Retourne la liste des événements créés par un utilisateur spécifique et ses amis") + public Response getEventsCreatedByUserAndFriends(EventReadManyByIdRequestDTO requestDTO) { + UUID userId = requestDTO.getUserId(); + LOG.info("[LOG] Récupération des événements pour l'utilisateur avec l'ID : " + userId + " et ses amis"); + 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(); + } + try { + List friends = friendshipService.listFriends(userId, 0, Integer.MAX_VALUE); + Set 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(); + } + List 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 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); + return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity("{\"message\": \"Erreur.\"}").build(); + } + } + + // *********** Récupérer les événements par catégorie *********** + + /** + * Endpoint pour récupérer les événements par catégorie. + * + * @param category La catégorie d'événement à filtrer. + * @return Une réponse HTTP contenant la liste des événements dans cette catégorie. + */ + @GET + @Path("/category/{category}") + @Operation( + summary = "Récupérer les événements par catégorie", + description = "Retourne la liste des événements correspondant à une catégorie donnée") + public Response getEventsByCategory(@PathParam("category") String category) { + LOG.info("[LOG] Récupération des événements dans la catégorie : " + category); + List events = eventService.findEventsByCategory(category); + if (events.isEmpty()) { + LOG.warn("[LOG] Aucun événement trouvé pour la catégorie : " + category); + return Response.status(Response.Status.NOT_FOUND) + .entity("Aucun événement trouvé pour cette catégorie.") + .build(); + } + List responseDTOs = events.stream() + .map(EventCreateResponseDTO::new) + .toList(); + LOG.info("[LOG] Nombre d'événements trouvés dans la catégorie '" + category + "' : " + events.size()); + return Response.ok(responseDTOs).build(); + } + + // *********** Récupérer les événements entre deux dates *********** + + /** + * Endpoint pour récupérer les événements entre deux dates spécifiques. + * + * @param startDate La date de début pour filtrer les événements. + * @param endDate La date de fin pour filtrer les événements. + * @return Une réponse HTTP contenant la liste des événements entre les deux dates. + */ + @GET + @Path("/between-dates") + @Operation( + summary = "Récupérer les événements entre deux dates", + description = "Retourne la liste des événements qui se déroulent entre deux dates spécifiques") + public Response findEventsBetweenDates( + @QueryParam("startDate") LocalDateTime startDate, + @QueryParam("endDate") LocalDateTime endDate) { + + LOG.info("[LOG] Récupération des événements entre les dates : " + startDate + " et " + endDate); + if (startDate == null || endDate == null || endDate.isBefore(startDate)) { + LOG.error("[ERROR] Les dates fournies sont invalides."); + return Response.status(Response.Status.BAD_REQUEST) + .entity("Les dates sont invalides ou mal formatées.") + .build(); + } + List events = eventService.findEventsBetweenDates(startDate, endDate); + if (events.isEmpty()) { + LOG.warn("[LOG] Aucun événement trouvé entre les dates : " + startDate + " et " + endDate); + return Response.status(Response.Status.NOT_FOUND) + .entity("Aucun événement trouvé entre ces dates.") + .build(); + } + List responseDTOs = events.stream() + .map(EventCreateResponseDTO::new) + .toList(); + LOG.info("[LOG] Nombre d'événements trouvés entre les dates : " + events.size()); + return Response.ok(responseDTOs).build(); + } + + // *********** Récupérer les événements par statut *********** + + /** + * Endpoint pour récupérer les événements par statut. + * + * @param status Le statut des événements à filtrer (en cours, terminé, etc.). + * @return Une réponse HTTP contenant la liste des événements avec ce statut. + */ + @GET + @Path("/status/{status}") + @Operation( + summary = "Récupérer les événements par statut", + description = "Retourne la liste des événements correspondant à un statut spécifique") + public Response getEventsByStatus(@PathParam("status") String status) { + LOG.info("[LOG] Récupération des événements avec le statut : " + status); + List events = eventService.findEventsByStatus(status); + if (events.isEmpty()) { + LOG.warn("[LOG] Aucun événement trouvé avec le statut : " + status); + return Response.status(Response.Status.NOT_FOUND) + .entity("Aucun événement trouvé pour ce statut.") + .build(); + } + List responseDTOs = events.stream() + .map(EventCreateResponseDTO::new) + .toList(); + LOG.info("[LOG] Nombre d'événements trouvés avec le statut '" + status + "' : " + events.size()); + return Response.ok(responseDTOs).build(); + } + + // *********** Rechercher des événements par mots-clés *********** + + /** + * Endpoint pour rechercher des événements par mots-clés. + * + * @param keyword Le mot-clé à rechercher. + * @return Une réponse HTTP contenant la liste des événements correspondant au mot-clé. + */ + @GET + @Path("/search") + @Operation( + summary = "Rechercher des événements par mots-clés", + description = "Retourne la liste des événements dont le titre ou la description contient les mots-clés spécifiés") + public Response searchEvents(@QueryParam("keyword") String keyword) { + LOG.info("[LOG] Recherche d'événements avec le mot-clé : " + keyword); + List events = eventService.searchEvents(keyword); + if (events.isEmpty()) { + LOG.warn("[LOG] Aucun événement trouvé avec le mot-clé : " + keyword); + return Response.status(Response.Status.NOT_FOUND) + .entity("Aucun événement trouvé pour ce mot-clé.") + .build(); + } + List responseDTOs = events.stream() + .map(EventCreateResponseDTO::new) + .toList(); + LOG.info("[LOG] Nombre d'événements trouvés avec le mot-clé '" + keyword + "' : " + events.size()); + return Response.ok(responseDTOs).build(); + } + + // *********** Mettre à jour le statut d'un événement *********** + + /** + * Endpoint pour mettre à jour le statut d'un événement. + * + * @param id L'ID de l'événement. + * @param status Le nouveau statut de l'événement. + * @return Une réponse HTTP indiquant la mise à jour du statut. + */ + @PUT + @Path("/{id}/status") + @Transactional + @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); + 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(); + } + event.setStatus(status); + eventsRepository.persist(event); + LOG.info("[LOG] Statut de l'événement mis à jour avec succès : " + status); + EventUpdateResponseDTO responseDTO = new EventUpdateResponseDTO(event); + return Response.ok(responseDTO).build(); + } + + // *********** Récupérer les événements auxquels un utilisateur est inscrit *********** + + /** + * Endpoint pour récupérer les événements auxquels un utilisateur est inscrit. + * + * @param userId L'ID de l'utilisateur. + * @return Une réponse HTTP contenant la liste des événements. + */ + @GET + @Path("/user/{userId}") + @Operation( + summary = "Récupérer les événements auxquels un utilisateur est inscrit", + description = "Retourne la liste des événements auxquels un utilisateur spécifique est inscrit") + public Response getEventsByUser(@PathParam("userId") UUID userId) { + LOG.info("[LOG] Récupération des événements pour l'utilisateur avec l'ID : " + userId); + 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(); + } + List events = eventService.findEventsByUser(user); + if (events.isEmpty()) { + LOG.warn("[LOG] Aucun événement trouvé pour l'utilisateur avec l'ID : " + userId); + return Response.status(Response.Status.NOT_FOUND).entity("Aucun événement trouvé.").build(); + } + List responseDTOs = events.stream() + .map(EventCreateResponseDTO::new) + .toList(); + LOG.info("[LOG] Nombre d'événements trouvés pour l'utilisateur : " + events.size()); + return Response.ok(responseDTOs).build(); + } + + // *********** Mettre à jour l'image d'un événement *********** + + /** + * Endpoint pour mettre à jour l'image d'un événement. + * + * @param id L'identifiant de l'événement. + * @param imageFilePath Le chemin vers l'image de l'événement. + * @return Un message indiquant si la mise à jour a réussi ou non. + */ + @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); + + try { + if (imageFilePath == null || imageFilePath.isEmpty()) { + LOG.error("[ERROR] Le chemin de l'image est vide ou null."); + return Response.status(Response.Status.BAD_REQUEST).entity("Le chemin de l'image est vide ou null.").build(); + } + + File file = new File(imageFilePath); + if (!file.exists()) { + LOG.error("[ERROR] Le fichier spécifié n'existe pas : " + imageFilePath); + return Response.status(Response.Status.NOT_FOUND).entity("Le fichier spécifié n'existe pas.").build(); + } + + Events event = eventService.getEventById(id); + if (event == null) { + LOG.error("[ERROR] Événement non trouvé avec l'ID : " + id); + return Response.status(Response.Status.NOT_FOUND).entity("Événement non trouvé.").build(); + } + + String imageUrl = file.getAbsolutePath(); + event.setImageUrl(imageUrl); + eventService.updateEvent(event); + + 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(); + } catch (Exception e) { + LOG.error("[ERROR] Erreur lors de la mise à jour de l'image de l'événement : ", e); + return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity("Erreur lors de la mise à jour de l'image de l'événement.").build(); + } + } + + // *********** Mettre à jour partiellement un événement *********** + @PATCH + @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 updates) { + LOG.info("[LOG] Tentative de mise à jour partielle de l'événement avec l'ID : " + id); + + 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(); + } + + 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 + }); + + eventsRepository.persist(event); + LOG.info("[LOG] Événement mis à jour partiellement avec succès : " + event.getTitle()); + return Response.ok(new EventUpdateResponseDTO(event)).build(); + } + + // *********** Récupérer les événements à venir *********** + @GET + @Path("/upcoming") + @Operation(summary = "Récupérer les événements à venir", description = "Retourne les événements futurs.") + public Response getUpcomingEvents() { + LOG.info("[LOG] Récupération des événements à venir."); + + List events = eventService.findUpcomingEvents(); + if (events.isEmpty()) { + LOG.warn("[LOG] Aucun événement futur trouvé."); + return Response.status(Response.Status.NOT_FOUND).entity("Aucun événement futur trouvé.").build(); + } + + List responseDTOs = events.stream().map(EventCreateResponseDTO::new).toList(); + return Response.ok(responseDTOs).build(); + } + + // *********** Récupérer les événements passés *********** + @GET + @Path("/past") + @Operation(summary = "Récupérer les événements passés", description = "Retourne les événements déjà terminés.") + public Response getPastEvents() { + LOG.info("[LOG] Récupération des événements passés."); + + List events = eventService.findPastEvents(); + if (events.isEmpty()) { + LOG.warn("[LOG] Aucun événement passé trouvé."); + return Response.status(Response.Status.NOT_FOUND).entity("Aucun événement passé trouvé.").build(); + } + + List responseDTOs = events.stream().map(EventCreateResponseDTO::new).toList(); + return Response.ok(responseDTOs).build(); + } + + // *********** Annuler un événement *********** + @POST + @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); + + 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(); + } + + event.setStatus("Annulé"); + eventsRepository.persist(event); + LOG.info("[LOG] Événement annulé avec succès : " + event.getTitle()); + return Response.ok(new EventUpdateResponseDTO(event)).build(); + } + + // *********** Récupérer les événements par localisation *********** + @GET + @Path("/location/{location}") + @Operation(summary = "Récupérer les événements par localisation", description = "Retourne les événements situés à une localisation spécifique.") + public Response getEventsByLocation(@PathParam("location") String location) { + LOG.info("[LOG] Récupération des événements à la localisation : " + location); + + List events = eventService.findEventsByLocation(location); + if (events.isEmpty()) { + LOG.warn("[LOG] Aucun événement trouvé pour la localisation : " + location); + return Response.status(Response.Status.NOT_FOUND).entity("Aucun événement trouvé pour cette localisation.").build(); + } + + List responseDTOs = events.stream().map(EventCreateResponseDTO::new).toList(); + return Response.ok(responseDTOs).build(); + } + + // *********** Récupérer les événements populaires *********** + @GET + @Path("/popular") + @Operation(summary = "Récupérer les événements populaires", description = "Retourne les événements ayant le plus de participants.") + public Response getPopularEvents() { + LOG.info("[LOG] Récupération des événements populaires."); + + List events = eventService.findPopularEvents(); + if (events.isEmpty()) { + LOG.warn("[LOG] Aucun événement populaire trouvé."); + return Response.status(Response.Status.NOT_FOUND).entity("Aucun événement populaire trouvé.").build(); + } + + List responseDTOs = events.stream().map(EventCreateResponseDTO::new).toList(); + return Response.ok(responseDTOs).build(); + } + + // *********** Étendre la durée d'un événement *********** + @PATCH + @Path("/{id}/extend") + @Transactional + @Operation(summary = "Étendre la durée d'un événement", description = "Permet de modifier la date de fin d'un événement.") + public Response extendEventDuration(@PathParam("id") UUID id, LocalDateTime newEndDate) { + LOG.info("[LOG] Extension de la durée de l'événement avec l'ID : " + id); + + 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(); + } + + if (newEndDate.isBefore(event.getStartDate())) { + LOG.error("[ERROR] La nouvelle date de fin est antérieure à la date de début."); + return Response.status(Response.Status.BAD_REQUEST).entity("La nouvelle date de fin doit être postérieure à la date de début.").build(); + } + + event.setEndDate(newEndDate); + eventsRepository.persist(event); + LOG.info("[LOG] Durée de l'événement étendue avec succès : " + event.getTitle()); + return Response.ok(new EventUpdateResponseDTO(event)).build(); + } + + // *********** Inviter des utilisateurs à un événement *********** + @POST + @Path("/{id}/invite") + @Transactional + @Operation(summary = "Inviter des utilisateurs à un événement", description = "Envoie des invitations à des utilisateurs pour un événement.") + public Response inviteUsersToEvent(@PathParam("id") UUID eventId, Set userIds) { + LOG.info("[LOG] Invitation d'utilisateurs à l'événement : " + eventId); + + 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(); + } + + List invitedUsers = userIds.stream().map(usersRepository::findById).filter(u -> u != null).collect(Collectors.toList()); + invitedUsers.forEach(event::addParticipant); // Adapte pour ajouter en tant qu'invités, si nécessaire + eventsRepository.persist(event); + + LOG.info("[LOG] Utilisateurs invités avec succès à l'événement : " + event.getTitle()); + return Response.ok("Invitations envoyées avec succès.").build(); + } + + @GET + @Path("/{id}/participants") + @Operation(summary = "Récupérer la liste des participants d'un événement", description = "Retourne la liste des utilisateurs participant à un événement spécifique.") + public Response getParticipants(@PathParam("id") UUID eventId) { + // Log d'entrée de la méthode + LOG.info("[LOG] Récupération des participants de l'événement avec l'ID : " + eventId); + + // Recherche de l'événement + 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(); + } + + // Récupération de la liste des participants + Set participantsSet = event.getParticipants(); + if (participantsSet == null || participantsSet.isEmpty()) { + LOG.warn("[LOG] Aucun participant trouvé pour l'événement avec l'ID : " + eventId); + return Response.status(Response.Status.NO_CONTENT).entity("Aucun participant trouvé.").build(); + } + + // Conversion des participants en List + List participantsList = new ArrayList<>(participantsSet); + + // Conversion des participants en DTO pour la réponse + List responseDTOs = participantsList.stream() + .map(UserResponseDTO::new) // Conversion de chaque utilisateur en UserResponseDTO + .collect(Collectors.toList()); + + // Log de la taille de la liste des participants pour la traçabilité + LOG.info("[LOG] Nombre de participants récupérés pour l'événement avec l'ID : " + eventId + " : " + responseDTOs.size()); + + // Retourner la réponse avec les participants + return Response.ok(responseDTOs).build(); + } + + @POST + @Path("/{id}/favorite") + @Transactional + @Operation(summary = "Marquer un événement comme favori", description = "Permet à un utilisateur de marquer un événement comme favori.") + public Response favoriteEvent(@PathParam("id") UUID eventId, @QueryParam("userId") UUID userId) { + LOG.info("[LOG] Marquage de l'événement comme favori pour l'utilisateur ID : " + userId); + + Events event = eventsRepository.findById(eventId); + Users user = usersRepository.findById(userId); + if (event == null || user == null) { + LOG.warn("[LOG] Événement ou utilisateur non trouvé."); + return Response.status(Response.Status.NOT_FOUND).entity("Événement ou utilisateur non trouvé.").build(); + } + + user.addFavoriteEvent(event); + usersRepository.persist(user); + return Response.ok("Événement marqué comme favori.").build(); + } + + @GET + @Path("/user/{userId}/favorites") + @Operation(summary = "Récupérer les événements favoris d'un utilisateur", description = "Retourne les événements marqués comme favoris par un utilisateur.") + public Response getFavoriteEvents(@PathParam("userId") UUID userId) { + LOG.info("[LOG] Récupération des événements favoris pour l'utilisateur ID : " + userId); + + 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(); + } + + // Convertir Set en List + List favoriteEvents = new ArrayList<>(user.getFavoriteEvents()); + + // Mapper les événements en DTO + List responseDTOs = favoriteEvents.stream().map(EventCreateResponseDTO::new).toList(); + + return Response.ok(responseDTOs).build(); + } + + @GET + @Path("/{id}/comments") + @Operation(summary = "Récupérer les commentaires d'un événement", description = "Retourne la liste des commentaires associés à un événement.") + public Response getComments(@PathParam("id") UUID eventId) { + LOG.info("[LOG] Récupération des commentaires pour l'événement ID : " + eventId); + + // Recherche de l'événement + 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(); + } + + // Récupération des commentaires associés à l'événement + List comments = event.getComments(); + List responseDTOs = comments.stream() + .map(CommentResponseDTO::new) // Conversion de chaque commentaire en CommentResponseDTO + .collect(Collectors.toList()); + + LOG.info("[LOG] Nombre de commentaires récupérés pour l'événement avec l'ID : " + eventId + " : " + responseDTOs.size()); + + // Retourner la réponse avec les commentaires sous forme de DTO + return Response.ok(responseDTOs).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.") + public Response getEventRecommendations(@PathParam("userId") UUID userId) { + LOG.info("[LOG] Récupération des recommandations d'événements pour l'utilisateur ID : " + userId); + + 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(); + } + + List recommendedEvents = eventService.recommendEventsForUser(user); + List responseDTOs = recommendedEvents.stream().map(EventCreateResponseDTO::new).toList(); + + return Response.ok(responseDTOs).build(); + } + + @GET + @Path("/{id}/share-link") + @Operation(summary = "Partager un événement via un lien", description = "Génère un lien de partage pour un événement.") + public Response getShareLink(@PathParam("id") UUID eventId) { + LOG.info("[LOG] Génération du lien de partage pour l'événement ID : " + eventId); + + 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(); + } + + String shareLink = "https://lions.dev /events/" + eventId; + return Response.ok(Map.of("shareLink", shareLink)).build(); + } + + /** + * Endpoint pour fermer un événement. + * + * @param eventId L'ID de l'événement. + * @return Une réponse HTTP indiquant le succès de la fermeture. + */ + @PATCH + @Path("/{id}/close") + @Transactional + @Operation( + summary = "Fermer un événement", + description = "Ferme un événement et empêche les nouvelles participations" + ) + public Response closeEvent(@PathParam("id") UUID eventId) { + LOG.info("Tentative de fermeture de l'événement avec l'ID : " + eventId); + + // Recherche de l'événement par ID + Events event = eventsRepository.findById(eventId); + if (event == null) { + LOG.warn("Événement non trouvé avec l'ID : " + eventId); + return Response.status(Response.Status.NOT_FOUND) + .entity("Événement non trouvé.") + .build(); + } + + // Marquer l'événement comme fermé + event.setStatus("fermé"); // Modification du statut de l'événement + eventsRepository.persist(event); // Persister les modifications dans la base + LOG.info("Événement fermé avec succès : " + event.getTitle()); + + // Retourner une réponse HTTP 200 OK avec le DTO de l'événement fermé + return Response.ok(new EventCreateResponseDTO(event)).build(); + } + + /** + * Endpoint pour réouvrir un événement. + * + * @param eventId L'ID de l'événement à rouvrir. + * @return Une réponse HTTP indiquant le succès ou l'échec de la réouverture. + */ + @PATCH + @Path("{eventId}/reopen") + @Transactional + @Operation( + summary = "Rouvrir un événement", + description = "Rouvre un événement existant qui est actuellement fermé" + ) + public Response reopenEvent(@PathParam("eventId") UUID eventId) { + LOG.info("Tentative de réouverture de l'événement avec l'ID : " + eventId); + + // Recherche de l'événement par ID + Events event = eventsRepository.findById(eventId); + if (event == null) { + LOG.warn("Événement non trouvé avec l'ID : " + eventId); + return Response.status(Response.Status.NOT_FOUND) + .entity("Événement non trouvé.") + .build(); + } + + // Vérifier si l'événement est déjà ouvert + if ("ouvert".equals(event.getStatus())) { + LOG.warn("L'événement est déjà ouvert : " + eventId); + return Response.status(Response.Status.BAD_REQUEST) + .entity("L'événement est déjà ouvert.") + .build(); + } + + // Vérifier si l'événement est fermé avant de tenter la réouverture + if (!"fermé".equals(event.getStatus())) { + LOG.warn("L'événement n'est pas fermé, donc il ne peut pas être rouvert : " + eventId); + return Response.status(Response.Status.BAD_REQUEST) + .entity("L'événement n'est pas fermé et ne peut pas être rouvert.") + .build(); + } + + // Réouvrir l'événement en mettant à jour son statut + event.setStatus("ouvert"); // Changer le statut à "Ouvert" + eventsRepository.persist(event); // Persister les modifications dans la base + LOG.info("Événement rouvert avec succès : " + event.getTitle()); + + // Retourner une réponse HTTP 200 OK avec un message de succès + return Response.ok("L'événement a été réouvert avec succès.").build(); + } + } + diff --git a/src/main/java/com/lions/dev/resource/FileUploadResource.java b/src/main/java/com/lions/dev/resource/FileUploadResource.java new file mode 100644 index 0000000..3451b8c --- /dev/null +++ b/src/main/java/com/lions/dev/resource/FileUploadResource.java @@ -0,0 +1,36 @@ +package com.lions.dev.resource; + +import com.lions.dev.service.FileService; +import jakarta.ws.rs.Consumes; +import jakarta.ws.rs.POST; +import jakarta.ws.rs.Path; +import jakarta.ws.rs.core.MediaType; +import jakarta.ws.rs.core.Response; +import org.jboss.logging.Logger; +import org.jboss.resteasy.reactive.RestForm; +import org.jboss.resteasy.reactive.multipart.FileUpload; +import jakarta.inject.Inject; +import java.io.IOException; + +@Path("/upload") +public class FileUploadResource { + + private static final Logger LOG = Logger.getLogger(FileUploadResource.class); + + @Inject + FileService fileService; + + @POST + @Consumes(MediaType.MULTIPART_FORM_DATA) + public Response uploadFile(@RestForm("file") FileUpload file) { + String uploadDir = "/tmp/uploads/"; + + try { + Path savedFilePath = (jakarta.ws.rs.Path) fileService.saveFile(file.uploadedFile(), uploadDir, file.fileName()); + return Response.ok("Fichier uploadé avec succès : " + savedFilePath).build(); + } catch (IOException e) { + LOG.error("Erreur lors de l'upload du fichier", e); + return Response.serverError().entity("Erreur lors de l'upload du fichier.").build(); + } + } +} diff --git a/src/main/java/com/lions/dev/resource/FriendshipResource.java b/src/main/java/com/lions/dev/resource/FriendshipResource.java new file mode 100644 index 0000000..6e89765 --- /dev/null +++ b/src/main/java/com/lions/dev/resource/FriendshipResource.java @@ -0,0 +1,348 @@ +package com.lions.dev.resource; + +import com.lions.dev.dto.request.friends.FriendshipCreateOneRequestDTO; +import com.lions.dev.dto.request.friends.FriendshipReadFriendDetailsRequestDTO; +import com.lions.dev.dto.request.friends.FriendshipReadStatusRequestDTO; +import com.lions.dev.dto.response.friends.FriendshipCreateOneResponseDTO; +import com.lions.dev.dto.response.friends.FriendshipReadFriendDetailsResponseDTO; +import com.lions.dev.dto.response.friends.FriendshipReadStatusResponseDTO; +import com.lions.dev.exception.UserNotFoundException; +import com.lions.dev.service.FriendshipService; +import jakarta.inject.Inject; +import jakarta.validation.Valid; +import jakarta.validation.constraints.NotNull; +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 org.eclipse.microprofile.openapi.annotations.Operation; +import org.eclipse.microprofile.openapi.annotations.media.Content; +import org.eclipse.microprofile.openapi.annotations.media.Schema; +import org.eclipse.microprofile.openapi.annotations.responses.APIResponse; +import org.eclipse.microprofile.openapi.annotations.responses.APIResponses; +import org.eclipse.microprofile.openapi.annotations.tags.Tag; +import org.jboss.logging.Logger; + +/** + * Ressource REST pour gérer les amitiés. Ce contrôleur expose des endpoints pour envoyer, accepter, + * rejeter et supprimer des demandes d'amitié. Toutes les opérations sont loguées pour faciliter le + * suivi en temps réel. + */ +@Path("/friends") +@Produces(MediaType.APPLICATION_JSON) // Assure que la réponse sera en JSON +@Consumes(MediaType.APPLICATION_JSON) // Assure que la requête attend du JSON +@Tag(name = "Friendship", description = "Opérations liées à la gestion des amis") +public class FriendshipResource { + + @Inject FriendshipService friendshipService; // Injection du service d'amitié + + private static final Logger logger = Logger.getLogger(FriendshipResource.class); + + /** + * Envoie une demande d'amitié. + * + * @param request DTO contenant l'ID de l'utilisateur qui envoie la demande et l'utilisateur qui + * la reçoit. + * @return La relation d'amitié créée. + */ + @POST + @Path("/send") + @Operation( + summary = "Envoyer une demande d'amitié", + description = "Permet à un utilisateur d'envoyer une demande d'amitié") + @APIResponses({ + @APIResponse( + responseCode = "200", + description = "Demande d'amitié envoyée avec succès", + content = + @Content( + mediaType = MediaType.APPLICATION_JSON, + schema = @Schema(implementation = FriendshipCreateOneResponseDTO.class))), + @APIResponse(responseCode = "400", description = "Requête invalide"), + @APIResponse( + responseCode = "500", + description = "Erreur serveur lors de l'envoi de la demande d'amitié") + }) + public Response sendFriendRequest(@Valid @NotNull FriendshipCreateOneRequestDTO request) { + logger.info( + "[LOG] Reçu une demande pour envoyer une demande d'amitié de l'utilisateur " + + request.getUserId() + + " à l'utilisateur " + + request.getFriendId()); + + try { + // Appel du service pour envoyer la demande d'amitié + FriendshipCreateOneResponseDTO friendshipResponse = + friendshipService.sendFriendRequest(request); + logger.info( + "[LOG] Demande d'amitié envoyée avec succès entre les utilisateurs " + + friendshipResponse.getUserId() + + " et " + + friendshipResponse.getFriendId()); + return Response.ok(friendshipResponse).build(); + } catch (Exception e) { + logger.error("[ERROR] Erreur lors de l'envoi de la demande d'amitié : " + e.getMessage(), e); + return Response.status(Response.Status.INTERNAL_SERVER_ERROR) + .entity("{\"message\": \"Erreur lors de l'envoi de la demande d'amitié.\"}") + .build(); + } + } + + /** + * Accepte une demande d'amitié. + * + * @param friendshipId L'ID de la relation d'amitié à accepter. + * @return La relation d'amitié acceptée. + */ + @PATCH + @Path("/{friendshipId}/accept") + @Operation( + summary = "Accepter une demande d'amitié", + description = "Accepte une demande d'amitié en attente") + @APIResponses({ + @APIResponse( + responseCode = "200", + description = "Demande d'amitié acceptée", + content = + @Content( + mediaType = MediaType.APPLICATION_JSON, + schema = @Schema(implementation = FriendshipCreateOneResponseDTO.class))), + @APIResponse(responseCode = "404", description = "Demande d'amitié non trouvée"), + @APIResponse( + responseCode = "500", + description = "Erreur lors de l'acceptation de la demande d'amitié") + }) + public Response acceptFriendRequest(@PathParam("friendshipId") UUID friendshipId) { + logger.info( + "[LOG] Reçu une demande pour accepter la demande d'amitié avec l'ID : " + friendshipId); + + try { + FriendshipCreateOneResponseDTO friendshipResponse = + friendshipService.acceptFriendRequest(friendshipId); + logger.info( + "[LOG] Demande d'amitié acceptée avec succès entre les utilisateurs " + + friendshipResponse.getUserId() + + " et " + + friendshipResponse.getFriendId()); + return Response.ok(friendshipResponse).build(); + } catch (Exception e) { + logger.error( + "[ERROR] Erreur lors de l'acceptation de la demande d'amitié : " + e.getMessage(), e); + return Response.status(Response.Status.INTERNAL_SERVER_ERROR) + .entity("{\"message\": \"Erreur lors de l'acceptation de la demande d'amitié.\"}") + .build(); + } + } + + /** + * Rejette une demande d'amitié. + * + * @param friendshipId L'ID de la relation d'amitié à rejeter. + * @return Confirmation de la demande rejetée. + */ + @PATCH + @Path("/{friendshipId}/reject") + @Operation( + summary = "Rejeter une demande d'amitié", + description = "Rejette une demande d'amitié en attente") + @APIResponses({ + @APIResponse(responseCode = "204", description = "Demande d'amitié rejetée"), + @APIResponse(responseCode = "404", description = "Demande d'amitié non trouvée"), + @APIResponse(responseCode = "500", description = "Erreur lors du rejet de la demande d'amitié") + }) + public Response rejectFriendRequest(@PathParam("friendshipId") UUID friendshipId) { + logger.info( + "[LOG] Reçu une demande pour rejeter la demande d'amitié avec l'ID : " + friendshipId); + + try { + friendshipService.rejectFriendRequest(friendshipId); + logger.info("[LOG] Demande d'amitié rejetée avec succès."); + return Response.noContent().build(); + } catch (Exception e) { + logger.error("[ERROR] Erreur lors du rejet de la demande d'amitié : " + e.getMessage(), e); + return Response.status(Response.Status.INTERNAL_SERVER_ERROR) + .entity("{\"message\": \"Erreur lors du rejet de la demande d'amitié.\"}") + .build(); + } + } + + /** + * Supprime une relation d'amitié. + * + * @param friendshipId L'ID de la relation d'amitié à supprimer. + * @return Confirmation de la suppression. + */ + @DELETE + @Path("/{friendshipId}") + @Operation( + summary = "Supprimer une relation d'amitié", + description = "Supprime une relation d'amitié existante") + @APIResponses({ + @APIResponse(responseCode = "204", description = "Relation d'amitié supprimée"), + @APIResponse(responseCode = "404", description = "Relation d'amitié non trouvée"), + @APIResponse( + responseCode = "500", + description = "Erreur lors de la suppression de la relation d'amitié") + }) + public Response removeFriend(@PathParam("friendshipId") UUID friendshipId) { + logger.info( + "[LOG] Reçu une demande pour supprimer la relation d'amitié avec l'ID : " + friendshipId); + + try { + friendshipService.removeFriend(friendshipId); + logger.info("[LOG] Relation d'amitié supprimée avec succès."); + return Response.noContent().build(); + } catch (Exception e) { + logger.error( + "[ERROR] Erreur lors de la suppression de la relation d'amitié : " + e.getMessage(), e); + return Response.status(Response.Status.INTERNAL_SERVER_ERROR) + .entity("{\"message\": \"Erreur lors de la suppression de la relation d'amitié.\"}") + .build(); + } + } + + /** + * Récupère la liste des amis d'un utilisateur. + * + * @param userId L'ID de l'utilisateur + * @param page Numéro de la page pour la pagination + * @param size Nombre d'éléments par page + * @return Liste des amis de l'utilisateur avec pagination + */ + @GET + @Path("/list/{userId}") + @Operation( + summary = "Récupérer la liste des amis", + description = "Retourne la liste des amis d'un utilisateur avec pagination") + @APIResponses({ + @APIResponse( + responseCode = "200", + description = "Liste des amis récupérée avec succès", + content = @Content( + mediaType = MediaType.APPLICATION_JSON, + schema = @Schema(implementation = FriendshipReadFriendDetailsResponseDTO.class))), + @APIResponse(responseCode = "404", description = "Utilisateur non trouvé"), + @APIResponse(responseCode = "500", description = "Erreur lors de la récupération des amis") + }) + public Response listFriends( + @PathParam("userId") UUID userId, + @QueryParam("page") @DefaultValue("0") int page, + @QueryParam("size") @DefaultValue("10") int size) { + logger.info("[LOG] Reçu une demande pour récupérer la liste des amis de l'utilisateur avec l'ID : " + userId); + + try { + List friendships = friendshipService.listFriends(userId, page, size) + .stream() + .distinct() // Assure qu'il n'y a pas de doublons + .toList(); + + logger.info("[LOG] Liste des amis récupérée avec succès, nombre d'amis : " + friendships.size()); + return Response.ok(friendships).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 de la liste des amis : " + e.getMessage(), e); + return Response.status(Response.Status.INTERNAL_SERVER_ERROR) + .entity("{\"message\": \"Erreur lors de la récupération des amis.\"}") + .build(); + } + } + + /** + * Récupérer les demandes d'amitié avec un statut spécifique. + * + * @param request DTO contenant les informations de filtrage (statut). + * @return Liste des demandes d'amitié avec le statut spécifié. + */ + @POST + @Path("/status") + @Operation( + summary = "Récupérer les demandes d'amitié par statut", + description = "Retourne la liste des demandes d'amitié avec un statut particulier") + @APIResponses({ + @APIResponse( + responseCode = "200", + description = "Demandes d'amitié récupérées", + content = + @Content( + mediaType = MediaType.APPLICATION_JSON, + schema = @Schema(implementation = FriendshipReadStatusResponseDTO.class))), + @APIResponse(responseCode = "404", description = "Utilisateur non trouvé"), + @APIResponse( + responseCode = "500", + description = "Erreur lors de la récupération des demandes d'amitié") + }) + public Response listFriendRequestsByStatus( + @Valid @NotNull FriendshipReadStatusRequestDTO request) { + logger.info("[LOG] Récupération des demandes d'amitié avec le statut : " + request.getStatus()); + + try { + List friendships = + friendshipService.listFriendRequestsByStatus(request); + logger.info("[LOG] " + friendships.size() + " demandes d'amitié récupérées avec succès."); + return Response.ok(friendships).build(); + } catch (Exception e) { + logger.error( + "[ERROR] Erreur lors de la récupération des demandes d'amitié : " + e.getMessage(), e); + return Response.status(Response.Status.INTERNAL_SERVER_ERROR) + .entity("{\"message\": \"Erreur lors de la récupération des demandes d'amitié.\"}") + .build(); + } + } + + /** + * Récupère les détails complets d'un ami. + * + * @param request DTO contenant l'ID de l'utilisateur et de l'ami dont les détails sont requis. + * @return Les détails complets de l'ami. + */ + @POST + @Path("/details") + @Operation( + summary = "Récupérer les détails d'un ami", + description = "Permet de récupérer toutes les informations disponibles sur un ami spécifique") + @APIResponses({ + @APIResponse( + responseCode = "200", + description = "Détails de l'ami récupérés avec succès", + content = + @Content( + mediaType = MediaType.APPLICATION_JSON, + schema = @Schema(implementation = FriendshipReadFriendDetailsResponseDTO.class))), + @APIResponse(responseCode = "404", description = "Ami non trouvé"), + @APIResponse(responseCode = "500", description = "Erreur serveur lors de la récupération des détails de l'ami") + }) + public Response getFriendDetails(@Valid @NotNull FriendshipReadFriendDetailsRequestDTO request) { + logger.info( + "[LOG] Reçu une demande pour récupérer les détails de l'ami avec l'ID : " + + request.getFriendId() + " pour l'utilisateur : " + request.getUserId()); + + try { + // Appel du service pour récupérer les détails de l'ami + FriendshipReadFriendDetailsResponseDTO friendDetails = + friendshipService.getFriendDetails(request); + logger.info( + "[LOG] Détails de l'ami récupérés avec succès pour l'utilisateur : " + + request.getUserId() + ", ami ID : " + request.getFriendId()); + return Response.ok(friendDetails).build(); + } catch (NotFoundException e) { + logger.warn( + "[WARN] Aucun ami trouvé pour l'utilisateur : " + request.getUserId() + + " avec l'ID de l'ami : " + request.getFriendId()); + return Response.status(Response.Status.NOT_FOUND) + .entity("{\"message\": \"Ami non trouvé.\"}") + .build(); + } catch (Exception e) { + logger.error( + "[ERROR] Erreur lors de la récupération des détails de l'ami : " + + e.getMessage(), e); + return Response.status(Response.Status.INTERNAL_SERVER_ERROR) + .entity("{\"message\": \"Erreur lors de la récupération des détails de l'ami.\"}") + .build(); + } + } +} diff --git a/src/main/java/com/lions/dev/resource/UsersResource.java b/src/main/java/com/lions/dev/resource/UsersResource.java index 408e637..934a1a5 100644 --- a/src/main/java/com/lions/dev/resource/UsersResource.java +++ b/src/main/java/com/lions/dev/resource/UsersResource.java @@ -1,40 +1,46 @@ package com.lions.dev.resource; import com.lions.dev.dto.request.users.UserAuthenticateRequestDTO; -import com.lions.dev.dto.request.users.UserRequestDTO; +import com.lions.dev.dto.request.users.UserCreateRequestDTO; import com.lions.dev.dto.response.users.UserAuthenticateResponseDTO; -import com.lions.dev.dto.response.users.UserResponseDTO; +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.service.UserService; +import com.lions.dev.service.UsersService; import jakarta.inject.Inject; import jakarta.transaction.Transactional; +import jakarta.validation.Valid; +import jakarta.validation.constraints.NotNull; import jakarta.ws.rs.*; +import jakarta.ws.rs.core.MediaType; import jakarta.ws.rs.core.Response; +import java.io.File; +import java.util.List; import java.util.UUID; 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 utilisateurs dans le système AfterWork. Cette classe expose - * des endpoints pour créer, authentifier, récupérer et supprimer des utilisateurs. - * - *

Tous les logs nécessaires pour la traçabilité sont intégrés. + * Ressource REST pour la gestion des utilisateurs dans le système AfterWork. + * Cette classe expose des endpoints pour créer, authentifier, récupérer et supprimer des utilisateurs. + * Tous les logs nécessaires pour la traçabilité sont intégrés. */ @Path("/users") -@Produces("application/json") -@Consumes("application/json") +@Produces(MediaType.APPLICATION_JSON) +@Consumes(MediaType.APPLICATION_JSON) @Tag(name = "Users", description = "Opérations liées à la gestion des utilisateurs") public class UsersResource { - @Inject UserService userService; + @Inject + UsersService userService; private static final Logger LOG = Logger.getLogger(UsersResource.class); /** * Endpoint pour créer un nouvel utilisateur. * - * @param userRequestDTO Le DTO contenant les informations de l'utilisateur à créer. + * @param userCreateRequestDTO Le DTO contenant les informations de l'utilisateur à créer. * @return Une réponse HTTP contenant l'utilisateur créé ou un message d'erreur. */ @POST @@ -42,15 +48,13 @@ public class UsersResource { @Operation( summary = "Créer un nouvel utilisateur", description = "Crée un nouvel utilisateur et retourne les détails") - public Response createUser(UserRequestDTO userRequestDTO) { + public Response createUser(@Valid @NotNull UserCreateRequestDTO userCreateRequestDTO) { LOG.info( "Tentative de création d'un nouvel utilisateur avec l'email : " - + userRequestDTO.getEmail()); + + userCreateRequestDTO.getEmail()); - // Utilisation de UserService pour créer l'utilisateur - Users user = userService.createUser(userRequestDTO); - - UserResponseDTO responseDTO = new UserResponseDTO(user); + Users user = userService.createUser(userCreateRequestDTO); + UserCreateResponseDTO responseDTO = new UserCreateResponseDTO(user); return Response.status(Response.Status.CREATED).entity(responseDTO).build(); } @@ -65,25 +69,14 @@ public class UsersResource { @Operation( summary = "Authentifier un utilisateur", description = "Vérifie les informations de connexion de l'utilisateur") - public Response authenticateUser(UserAuthenticateRequestDTO userAuthenticateRequestDTO) { - LOG.info( - "Tentative d'authentification pour l'utilisateur avec l'email : " - + userAuthenticateRequestDTO.getEmail()); - - // Utilisation de UserService pour authentifier l'utilisateur - Users user = - userService.authenticateUser( - userAuthenticateRequestDTO.getEmail(), userAuthenticateRequestDTO.getMotDePasse()); + public Response authenticateUser(@Valid @NotNull UserAuthenticateRequestDTO userAuthenticateRequestDTO) { + LOG.info("Tentative d'authentification pour l'utilisateur avec l'email : " + userAuthenticateRequestDTO.getEmail()); + Users user = userService.authenticateUser(userAuthenticateRequestDTO.getEmail(), userAuthenticateRequestDTO.getMotDePasse()); LOG.info("Authentification réussie pour l'utilisateur : " + user.getEmail()); - // Création du DTO de réponse avec les informations supplémentaires de l'utilisateur - UserAuthenticateResponseDTO responseDTO = - new UserAuthenticateResponseDTO( - user.getId(), user.getPrenoms(), user.getNom(), user.getEmail(), user.getRole()); - + UserAuthenticateResponseDTO responseDTO = new UserAuthenticateResponseDTO(user.getId(), user.getPrenoms(), user.getNom(), user.getEmail(), user.getRole()); responseDTO.logResponseDetails(); - return Response.ok(responseDTO).build(); } @@ -101,19 +94,36 @@ public class UsersResource { public Response getUserById(@PathParam("id") UUID id) { LOG.info("Récupération de l'utilisateur avec l'ID : " + id); - // Utilisation de UserService pour récupérer l'utilisateur Users user = userService.getUserById(id); - - UserResponseDTO responseDTO = new UserResponseDTO(user); + UserCreateResponseDTO responseDTO = new UserCreateResponseDTO(user); LOG.info("Utilisateur trouvé : " + user.getEmail()); return Response.ok(responseDTO).build(); } + /** + * Endpoint pour récupérer tous les utilisateurs avec pagination. + * + * @param page Le numéro de la page à récupérer. + * @param size Le nombre d'utilisateurs par page. + * @return Une réponse HTTP contenant la liste des utilisateurs paginée. + */ + @GET + @Operation( + summary = "Récupérer tous les utilisateurs avec pagination", + description = "Retourne la liste paginée des utilisateurs") + public Response listUsers(@QueryParam("page") @DefaultValue("1") int page, @QueryParam("size") @DefaultValue("10") int size) { + LOG.info("Récupération de la liste des utilisateurs - page : " + page + ", taille : " + size); + + List users = userService.listUsers(page, size); + LOG.info("Liste des utilisateurs récupérée avec succès, taille : " + users.size()); + return Response.ok(users).build(); + } + /** * Endpoint pour supprimer un utilisateur par ID. * * @param id L'ID de l'utilisateur à supprimer. - * @return Une réponse HTTP indiquant le succès ou l'échec de la suppression. + * @return Une réponse HTTP avec le statut de suppression. */ @DELETE @Path("/{id}") @@ -124,15 +134,95 @@ public class UsersResource { public Response deleteUser(@PathParam("id") UUID id) { LOG.info("Tentative de suppression de l'utilisateur avec l'ID : " + id); - // Utilisation de UserService pour supprimer l'utilisateur boolean deleted = userService.deleteUser(id); + UserDeleteResponseDto responseDTO = new UserDeleteResponseDto(); if (deleted) { LOG.info("Utilisateur supprimé avec succès."); - return Response.noContent().build(); + responseDTO.setSuccess(true); + responseDTO.setMessage("Utilisateur supprimé avec succès."); + responseDTO.logResponseDetails(); + return Response.ok(responseDTO).build(); } else { LOG.warn("Échec de la suppression : utilisateur introuvable avec l'ID : " + id); - return Response.status(Response.Status.NOT_FOUND).entity("Utilisateur non trouvé.").build(); + responseDTO.setSuccess(false); + responseDTO.setMessage("Utilisateur non trouvé."); + responseDTO.logResponseDetails(); + return Response.status(Response.Status.NOT_FOUND).entity(responseDTO).build(); } } + + /** + * Endpoint pour mettre à jour un utilisateur. + * + * @param id L'ID de l'utilisateur à mettre à jour. + * @param userCreateRequestDTO Les informations mises à jour de l'utilisateur. + * @return Les informations de l'utilisateur mis à jour. + */ + @PUT + @Path("/{id}") + @Transactional + @Operation( + summary = "Mettre à jour un utilisateur", + description = "Met à jour les informations d'un utilisateur existant") + public Response updateUser(@PathParam("id") UUID id, @Valid UserCreateRequestDTO userCreateRequestDTO) { + LOG.info("Tentative de mise à jour de l'utilisateur avec l'ID : " + id); + + // Appel au service avec l'ID et les nouvelles informations + Users updatedUser = userService.updateUser(id, userCreateRequestDTO); + + LOG.info("Utilisateur mis à jour avec succès : " + updatedUser.getEmail()); + UserCreateResponseDTO responseDTO = new UserCreateResponseDTO(updatedUser); + return Response.ok(responseDTO).build(); + } + + /** + * Endpoint pour réinitialiser le mot de passe d'un utilisateur. + * + * @param id L'ID de l'utilisateur. + * @param nouveauMotDePasse Le nouveau mot de passe. + * @return Un message indiquant si la réinitialisation a réussi. + */ + @PATCH + @Path("/{id}/reset-password") + @Transactional + @Operation( + summary = "Réinitialiser le mot de passe d'un utilisateur", + description = "Réinitialise le mot de passe de l'utilisateur et le met à jour dans la base de données") + public Response resetPassword(@PathParam("id") UUID id, @QueryParam("newPassword") String nouveauMotDePasse) { + LOG.info("Réinitialisation du mot de passe pour l'utilisateur avec l'ID : " + id); + + userService.resetPassword(id, nouveauMotDePasse); + return Response.ok("{\"message\": \"Mot de passe réinitialisé avec succès.\"}").build(); + } + + /** + * Endpoint pour mettre à jour l'image de profil de l'utilisateur. + * + * @param id L'identifiant de l'utilisateur. + * @param imageFilePath Le chemin vers l'image de profil. + * @return Un message indiquant si la mise à jour a réussi. + */ + @PUT + @Path("/{id}/profile-image") + @Operation(summary = "Mettre à jour l'image de profil d'un utilisateur", description = "Met à jour l'image de profil d'un utilisateur.") + public String updateUserProfileImage(@PathParam("id") UUID id, String imageFilePath) { + try { + File file = new File(imageFilePath); + if (!file.exists()) { + LOG.error("[ERROR] Le fichier spécifié n'existe pas : " + imageFilePath); + return "Le fichier spécifié n'existe pas."; + } + + String profileImageUrl = file.getAbsolutePath(); + userService.updateUserProfileImage(id, profileImageUrl); // Appel à la méthode correcte + + LOG.info("[LOG] Image de profil mise à jour pour l'utilisateur avec l'ID : " + id); + return "Image de profil mise à jour avec succès."; + } catch (Exception e) { + LOG.error("[ERROR] Erreur lors de la mise à jour de l'image de profil : " + e.getMessage()); + return "Erreur lors de la mise à jour de l'image de profil."; + } + } + } diff --git a/src/main/java/com/lions/dev/service/EventService.java b/src/main/java/com/lions/dev/service/EventService.java index 4b0d18b..329270c 100644 --- a/src/main/java/com/lions/dev/service/EventService.java +++ b/src/main/java/com/lions/dev/service/EventService.java @@ -1,9 +1,12 @@ package com.lions.dev.service; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import jakarta.transaction.Transactional; +import com.lions.dev.dto.request.events.EventCreateRequestDTO; import com.lions.dev.entity.events.Events; import com.lions.dev.entity.users.Users; import com.lions.dev.repository.EventsRepository; -import com.lions.dev.dto.request.events.EventRequestDTO; import com.lions.dev.exception.EventNotFoundException; import jakarta.enterprise.context.ApplicationScoped; import jakarta.inject.Inject; @@ -13,7 +16,8 @@ import java.util.UUID; /** * Service de gestion des événements. - * Ce service contient la logique métier pour la création, récupération et suppression des événements. + * Ce service contient la logique métier pour la création, récupération, mise à jour et suppression des événements. + * Chaque méthode est loguée pour assurer une traçabilité exhaustive des actions effectuées. */ @ApplicationScoped public class EventService { @@ -21,21 +25,32 @@ public class EventService { @Inject EventsRepository eventsRepository; + private static final Logger logger = LoggerFactory.getLogger(EventService.class); + /** * Crée un nouvel événement dans le système. * - * @param eventRequestDTO Le DTO contenant les informations de l'événement à créer. + * @param eventCreateRequestDTO Le DTO contenant les informations de l'événement à créer. * @param creator L'utilisateur créateur de l'événement. * @return L'événement créé. */ - public Events createEvent(EventRequestDTO eventRequestDTO, Users creator) { + public Events createEvent(EventCreateRequestDTO eventCreateRequestDTO, Users creator) { + // Initialisation de l'entité Event avec les détails fournis Events event = new Events(); - event.setTitle(eventRequestDTO.getTitle()); - event.setStartDate(eventRequestDTO.getStartDate()); - event.setEndDate(eventRequestDTO.getEndDate()); + event.setTitle(eventCreateRequestDTO.getTitle()); + event.setDescription(eventCreateRequestDTO.getDescription()); + event.setStartDate(eventCreateRequestDTO.getStartDate()); + event.setEndDate(eventCreateRequestDTO.getEndDate()); + event.setLocation(eventCreateRequestDTO.getLocation()); + event.setCategory(eventCreateRequestDTO.getCategory()); + event.setLink(eventCreateRequestDTO.getLink()); + event.setImageUrl(eventCreateRequestDTO.getImageUrl()); event.setCreator(creator); + event.setStatus("ouvert"); + + // Persiste l'événement dans la base de données eventsRepository.persist(event); - System.out.println("[LOG] Événement créé : " + event.getTitle()); + logger.info("[logger] Événement créé avec succès : {}", event.getTitle()); return event; } @@ -47,24 +62,28 @@ public class EventService { * @throws EventNotFoundException Si l'événement n'est pas trouvé. */ public Events getEventById(UUID id) { + logger.info("[logger] Tentative de récupération de l'événement avec l'ID : {}", id); Events event = eventsRepository.findById(id); + if (event == null) { - System.out.println("[ERROR] Événement non trouvé avec l'ID : " + id); - throw new EventNotFoundException("Événement non trouvé avec l'ID : " + id); + logger.error("[ERROR] Événement non trouvé avec l'ID : {}", id); + throw new EventNotFoundException(id); } - System.out.println("[LOG] Événement trouvé avec l'ID : " + id); + logger.info("[logger] Événement trouvé avec l'ID : {}", id); return event; } /** * Récupère tous les événements après une date donnée. * - * @param startDate La date de début de filtre. - * @return Une liste d'événements. + * @param startDate La date de début pour filtrer les événements. + * @return Une liste d'événements après cette date. */ public List getEventsAfterDate(LocalDateTime startDate) { + logger.info("[logger] Récupération des événements après la date : {}", startDate); + List events = eventsRepository.findEventsAfterDate(startDate); - System.out.println("[LOG] Nombre d'événements trouvés après la date " + startDate + " : " + events.size()); + logger.info("[logger] Nombre d'événements trouvés après la date {} : {}", startDate, events.size()); return events; } @@ -73,14 +92,194 @@ public class EventService { * * @param id L'ID de l'événement à supprimer. * @return true si l'événement a été supprimé, false sinon. + * @throws EventNotFoundException Si l'événement n'est pas trouvé. */ + @Transactional public boolean deleteEvent(UUID id) { + logger.info("[logger] Tentative de suppression de l'événement avec l'ID : {}", id); + boolean deleted = eventsRepository.deleteById(id); if (deleted) { - System.out.println("[LOG] Événement supprimé avec succès : " + id); + logger.info("[logger] Événement avec l'ID {} supprimé avec succès.", id); } else { - System.out.println("[ERROR] Échec de la suppression de l'événement avec l'ID : " + id); + logger.warn("[logger] Échec de la suppression : événement avec l'ID {} introuvable.", id); + throw new EventNotFoundException(id); } return deleted; } + + /** + * Met à jour un événement dans le système. + * + * @param event L'événement contenant les détails mis à jour. + * @return L'événement mis à jour. + * @throws EventNotFoundException Si l'événement n'est pas trouvé. + */ + @Transactional + public Events updateEvent(Events event) { + logger.info("[logger] Tentative de mise à jour de l'événement avec l'ID : {}", event.getId()); + + Events existingEvent = eventsRepository.findById(event.getId()); + if (existingEvent == null) { + logger.error("[ERROR] Événement non trouvé avec l'ID : {}", event.getId()); + throw new EventNotFoundException(event.getId()); + } + + // Mettre à jour les détails de l'événement + existingEvent.setTitle(event.getTitle()); + existingEvent.setDescription(event.getDescription()); + existingEvent.setStartDate(event.getStartDate()); + existingEvent.setEndDate(event.getEndDate()); + existingEvent.setLocation(event.getLocation()); + existingEvent.setCategory(event.getCategory()); + existingEvent.setLink(event.getLink()); + existingEvent.setImageUrl(event.getImageUrl()); + existingEvent.setStatus(event.getStatus()); + + // Persiste les modifications dans la base de données + eventsRepository.persist(existingEvent); + logger.info("[logger] Événement mis à jour avec succès : {}", existingEvent.getTitle()); + return existingEvent; + } + + /** + * Récupère les événements par catégorie. + * + * @param category La catégorie des événements. + * @return La liste des événements dans cette catégorie. + */ + public List findEventsByCategory(String category) { + logger.info("[logger] Récupération des événements dans la catégorie : {}", category); + List events = eventsRepository.find("category", category).list(); + logger.info("[logger] Nombre d'événements trouvés dans la catégorie '{}' : {}", category, events.size()); + return events; + } + + /** + * Recherche des événements par mot-clé dans le titre ou la description. + * + * @param keyword Le mot-clé à rechercher. + * @return La liste des événements correspondant au mot-clé. + */ + public List searchEvents(String keyword) { + logger.info("[logger] Recherche d'événements avec le mot-clé : {}", keyword); + List events = eventsRepository.find("title like ?1 or description like ?1", "%" + keyword + "%").list(); + logger.info("[logger] Nombre d'événements trouvés pour le mot-clé '{}' : {}", keyword, events.size()); + return events; + } + + /** + * Récupère les événements auxquels un utilisateur participe. + * + * @param user L'utilisateur pour lequel récupérer les événements. + * @return La liste des événements auxquels l'utilisateur participe. + */ + public List findEventsByUser(Users user) { + logger.info("[logger] Récupération des événements pour l'utilisateur avec l'ID : {}", user.getId()); + List events = eventsRepository.find("participants", user).list(); + logger.info("[logger] Nombre d'événements pour l'utilisateur avec l'ID {} : {}", user.getId(), events.size()); + return events; + } + + /** + * Récupère les événements par statut. + * + * @param status Le statut des événements (en cours, fermé, etc.). + * @return La liste des événements ayant ce statut. + */ + public List findEventsByStatus(String status) { + logger.info("[logger] Récupération des événements avec le statut : {}", status); + List events = eventsRepository.find("status", status).list(); + logger.info("[logger] Nombre d'événements avec le statut '{}' : {}", status, events.size()); + return events; + } + + /** + * Récupère les événements qui se déroulent entre deux dates spécifiques. + * + * @param startDate La date de début. + * @param endDate La date de fin. + * @return La liste des événements entre ces deux dates. + */ + public List findEventsBetweenDates(LocalDateTime startDate, LocalDateTime endDate) { + logger.info("[logger] Récupération des événements entre les dates : {} et {}", startDate, endDate); + + // Vérifie la validité des dates fournies + if (startDate == null || endDate == null || endDate.isBefore(startDate)) { + logger.error("[ERROR] Dates invalides fournies : startDate={}, endDate={}", startDate, endDate); + throw new IllegalArgumentException("Les dates sont invalides ou mal formatées."); + } + + List events = eventsRepository.findEventsBetweenDates(startDate, endDate); + logger.info("[logger] Nombre d'événements trouvés entre les dates : {}", events.size()); + return events; + } + + + /** + * Récupère les événements futurs. + * + * @return Une liste d'événements à venir. + */ + public List findUpcomingEvents() { + logger.info("[logger] Récupération des événements futurs."); + LocalDateTime now = LocalDateTime.now(); + List events = eventsRepository.find("startDate > ?1", now).list(); + logger.info("[logger] Nombre d'événements futurs trouvés : " + events.size()); + return events; + } + + /** + * Récupère les événements passés. + * + * @return Une liste d'événements passés. + */ + public List findPastEvents() { + logger.info("[logger] Récupération des événements passés."); + LocalDateTime now = LocalDateTime.now(); + List events = eventsRepository.find("endDate < ?1", now).list(); + logger.info("[logger] Nombre d'événements passés trouvés : " + events.size()); + return events; + } + + /** + * Récupère les événements par localisation. + * + * @param location La localisation des événements. + * @return La liste des événements situés à cette localisation. + */ + public List findEventsByLocation(String location) { + logger.info("[logger] Récupération des événements pour la localisation : " + location); + List events = eventsRepository.find("location", location).list(); + logger.info("[logger] Nombre d'événements trouvés pour la localisation '" + location + "' : " + events.size()); + return events; + } + + /** + * Récupère les événements populaires en fonction du nombre de participants. + * + * @return Une liste d'événements populaires. + */ + public List findPopularEvents() { + logger.info("[logger] Récupération des événements populaires."); + List events = eventsRepository.listAll().stream() + .sorted((e1, e2) -> Integer.compare(e2.getNumberOfParticipants(), e1.getNumberOfParticipants())) + .limit(10) + .toList(); + logger.info("[logger] Nombre d'événements populaires trouvés : " + events.size()); + return events; + } + + /** + * Recommande des événements pour un utilisateur spécifique. + * + * @param user L'utilisateur pour lequel recommander des événements. + * @return La liste des événements recommandés. + */ + public List recommendEventsForUser(Users user) { + logger.info("[logger] Recommandation d'événements pour l'utilisateur : " + user.getEmail()); + List events = eventsRepository.find("category", user.getPreferredCategory()).list(); + logger.info("[logger] Nombre d'événements recommandés pour l'utilisateur : " + events.size()); + return events; + } } diff --git a/src/main/java/com/lions/dev/service/FileService.java b/src/main/java/com/lions/dev/service/FileService.java new file mode 100644 index 0000000..1f0d52e --- /dev/null +++ b/src/main/java/com/lions/dev/service/FileService.java @@ -0,0 +1,68 @@ +package com.lions.dev.service; + +import com.lions.dev.repository.EventsRepository; +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.inject.Inject; +import java.io.IOException; +import java.nio.file.FileAlreadyExistsException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.nio.file.StandardCopyOption; +import org.jboss.logging.Logger; + +/** + * Service pour la gestion des fichiers uploadés. + * Ce service permet de sauvegarder et gérer les fichiers uploadés sur le serveur. + * + *

Toutes les actions sont loguées pour assurer une traçabilité complète. + */ +@ApplicationScoped +public class FileService { + private static final Logger LOG = Logger.getLogger(FileService.class); + + @Inject + EventsRepository eventsRepository; + + /** + * Sauvegarde le fichier uploadé sur le serveur, avec création du répertoire de destination + * si nécessaire et gestion des erreurs de manière contrôlée. + * + * @param uploadedFilePath Le chemin temporaire du fichier uploadé. + * @param destinationDir Le répertoire de destination où sauvegarder le fichier. + * @param fileName Le nom du fichier. + * @return Le chemin complet du fichier sauvegardé. + * @throws IOException Si une erreur survient lors de la sauvegarde. + */ + public Path saveFile(Path uploadedFilePath, String destinationDir, String fileName) throws IOException { + Path destinationPath = Paths.get(destinationDir, fileName); + LOG.info("[LOG] Tentative de sauvegarde du fichier vers : " + destinationPath); + + if (Files.notExists(uploadedFilePath)) { + LOG.error("[ERROR] Le fichier uploadé n'existe pas : " + uploadedFilePath); + throw new IOException("Le fichier uploadé n'existe pas : " + uploadedFilePath); + } + + try { + Files.createDirectories(Paths.get(destinationDir)); + LOG.info("[LOG] Répertoire de destination créé ou déjà existant : " + destinationDir); + } catch (IOException e) { + LOG.error("[ERROR] Impossible de créer le répertoire de destination : " + destinationDir, e); + throw new IOException("Impossible de créer le répertoire de destination : " + destinationDir, e); + } + + try { + Files.copy(uploadedFilePath, destinationPath, StandardCopyOption.REPLACE_EXISTING); + LOG.info("[LOG] Fichier sauvegardé avec succès à l'emplacement : " + destinationPath); + } catch (FileAlreadyExistsException e) { + LOG.warn("[WARNING] Le fichier existe déjà, il sera remplacé : " + destinationPath); + Files.copy(uploadedFilePath, destinationPath, StandardCopyOption.REPLACE_EXISTING); + } catch (IOException e) { + LOG.error("[ERROR] Erreur lors de la copie du fichier vers : " + destinationPath, e); + throw new IOException("Erreur lors de la sauvegarde du fichier : " + destinationPath, e); + } + + return destinationPath; + } + +} diff --git a/src/main/java/com/lions/dev/service/FriendshipService.java b/src/main/java/com/lions/dev/service/FriendshipService.java new file mode 100644 index 0000000..ac9589f --- /dev/null +++ b/src/main/java/com/lions/dev/service/FriendshipService.java @@ -0,0 +1,258 @@ +package com.lions.dev.service; + +import com.lions.dev.dto.request.friends.FriendshipCreateOneRequestDTO; +import com.lions.dev.dto.request.friends.FriendshipReadFriendDetailsRequestDTO; +import com.lions.dev.dto.request.friends.FriendshipReadStatusRequestDTO; +import com.lions.dev.dto.response.friends.FriendshipCreateOneResponseDTO; +import com.lions.dev.dto.response.friends.FriendshipReadFriendDetailsResponseDTO; +import com.lions.dev.dto.response.friends.FriendshipReadStatusResponseDTO; +import com.lions.dev.entity.friends.Friendship; +import com.lions.dev.entity.friends.FriendshipStatus; +import com.lions.dev.entity.users.Users; +import com.lions.dev.exception.FriendshipNotFoundException; +import com.lions.dev.exception.UserNotFoundException; +import com.lions.dev.repository.FriendshipRepository; +import com.lions.dev.repository.UsersRepository; +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.inject.Inject; +import jakarta.transaction.Transactional; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.UUID; +import org.jboss.logging.Logger; + +/** + * Service pour gérer les relations d'amitié. + * Contient la logique métier pour envoyer, accepter, rejeter, et supprimer des relations d'amitié. + */ +@ApplicationScoped +public class FriendshipService { + + @Inject + FriendshipRepository friendshipRepository; // Injecte le repository des amitiés + @Inject + UsersRepository usersRepository; // Injecte le repository des utilisateurs + + private static final Logger logger = Logger.getLogger(FriendshipService.class); + + /** + * Envoie une demande d'amitié entre deux utilisateurs. + * + * @param request DTO contenant les informations sur l'utilisateur et l'ami. + * @return Le DTO de la relation d'amitié créée. + */ + @Transactional + public FriendshipCreateOneResponseDTO sendFriendRequest(FriendshipCreateOneRequestDTO request) { + logger.info("[LOG] Envoi d'une demande d'amitié de l'utilisateur " + request.getUserId() + " à l'utilisateur " + request.getFriendId()); + + // Récupérer les utilisateurs concernés + Users user = usersRepository.findById(request.getUserId()); + Users friend = usersRepository.findById(request.getFriendId()); + + if (user == null || friend == null) { + String notFoundId = user == null ? request.getUserId().toString() : request.getFriendId().toString(); + logger.error("[ERROR] Utilisateur non trouvé pour l'ID : " + notFoundId); + throw new UserNotFoundException("Utilisateur avec l'ID " + notFoundId + " introuvable."); + } + + // Vérifier s'il existe déjà une relation d'amitié + Friendship existingFriendship = friendshipRepository.findByUsers(user, friend).orElse(null); + if (existingFriendship != null) { + logger.error("[ERROR] Relation d'amitié déjà existante entre les utilisateurs."); + throw new IllegalArgumentException("Relation d'amitié déjà existante."); + } + + // Créer et persister une nouvelle relation d'amitié + Friendship friendship = new Friendship(user, friend, FriendshipStatus.PENDING); + friendshipRepository.persist(friendship); + + logger.info("[LOG] Demande d'amitié envoyée avec succès."); + return new FriendshipCreateOneResponseDTO(friendship); + } + + /** + * Accepter une demande d'amitié. + * + * @param friendshipId ID de la demande à accepter. + * @return Le DTO de la relation d'amitié acceptée. + */ + @Transactional + public FriendshipCreateOneResponseDTO acceptFriendRequest(UUID friendshipId) { + // Vérification de l'ID de la demande d'amitié + if (friendshipId == null) { + logger.error(String.format("[ERROR] L'ID de la demande d'amitié est nul.")); + throw new IllegalArgumentException("L'ID de la demande d'amitié est nul."); + } + + // Rechercher l'amitié dans la base de données + Friendship friendship = friendshipRepository.findById(friendshipId); + + // Si l'amitié n'est pas trouvée, lever une exception + if (friendship == null) { + logger.error(String.format("[ERROR] Demande d'amitié introuvable pour l'ID: %s", friendshipId)); // Correctement formaté + throw new FriendshipNotFoundException("Demande d'amitié introuvable."); + } + + // Vérifier que la demande n'est pas déjà acceptée + if (friendship.getStatus() == FriendshipStatus.ACCEPTED) { + logger.error(String.format("[ERROR] Demande d'amitié déjà acceptée pour l'ID: %s", friendshipId)); // Correctement formaté + throw new IllegalArgumentException("Demande d'amitié déjà acceptée."); + } + + // Accepter la demande + friendship.setStatus(FriendshipStatus.ACCEPTED); + friendshipRepository.persist(friendship); + + // Log de succès + logger.info(String.format("[LOG] Demande d'amitié acceptée avec succès pour l'ID: %s", friendshipId)); // Correctement formaté + + // Retourner la réponse avec les informations de la relation d'amitié + return new FriendshipCreateOneResponseDTO(friendship); + } + + /** + * Rejeter une demande d'amitié. + * + * @param friendshipId ID de la demande à rejeter. + */ + @Transactional + public void rejectFriendRequest(UUID friendshipId) { + Friendship friendship = friendshipRepository.findById(friendshipId); + if (friendship == null) { + throw new FriendshipNotFoundException("Demande d'amitié introuvable."); + } + + friendship.setStatus(FriendshipStatus.REJECTED); + friendshipRepository.persist(friendship); + + logger.info("[LOG] Demande d'amitié rejetée."); + } + + /** + * Supprimer une relation d'amitié. + * + * @param friendshipId ID de la relation à supprimer. + */ + @Transactional + public void removeFriend(UUID friendshipId) { + Friendship friendship = friendshipRepository.findById(friendshipId); + if (friendship == null) { + throw new FriendshipNotFoundException("Relation d'amitié introuvable."); + } + + friendshipRepository.delete(friendship); + logger.info("[LOG] Relation d'amitié supprimée."); + } + + /** + * Récupère les détails d'un ami spécifique pour un utilisateur donné. + * + * @param request DTO contenant l'ID de l'utilisateur et de l'ami. + * @return Le DTO des détails de l'ami. + */ + @Transactional + public FriendshipReadFriendDetailsResponseDTO getFriendDetails( + FriendshipReadFriendDetailsRequestDTO request) { + logger.info("[LOG] Tentative de récupération des détails de l'ami avec l'ID : " + + request.getFriendId() + " pour l'utilisateur : " + request.getUserId()); + + // Récupération de l'utilisateur et de l'ami + Users user = usersRepository.findById(request.getUserId()); + Users friend = usersRepository.findById(request.getFriendId()); + + if (user == null) { + logger.error("[ERROR] Utilisateur introuvable avec l'ID : " + request.getUserId()); + throw new UserNotFoundException("Utilisateur introuvable avec l'ID " + request.getUserId()); + } + + if (friend == null) { + logger.error("[ERROR] Ami introuvable avec l'ID : " + request.getFriendId()); + throw new UserNotFoundException("Ami introuvable avec l'ID " + request.getFriendId()); + } + + // Récupérer la relation d'amitié entre les deux utilisateurs + Friendship friendship = friendshipRepository.findByUsers(user, friend).orElse(null); + if (friendship == null) { + logger.error("[ERROR] Aucune relation d'amitié trouvée entre l'utilisateur et l'ami."); + throw new FriendshipNotFoundException("Relation d'amitié introuvable."); + } + + logger.info("[LOG] Détails de l'ami récupérés avec succès pour l'utilisateur : " + + user.getId() + ", ami ID : " + friend.getId()); + + // Création du DTO de réponse à partir des informations de l'ami et de la relation + return new FriendshipReadFriendDetailsResponseDTO( + user.getId(), // ID de l'utilisateur + friend.getId(), // ID de l'ami + friend.getNom(), // Nom de l'ami + friend.getPrenoms(), + friend.getEmail(), // Email de l'ami + friend.getProfileImageUrl(), // URL de l'image de profil de l'ami + friendship.getStatus(), // Statut de la relation + friendship.getCreatedAt(), // Date de création de la relation + friendship.getUpdatedAt() // Date de mise à jour de la relation + ); + } + + /** + * Récupérer la liste des amis d'un utilisateur. + * + * @param userId ID de l'utilisateur. + * @param page Numéro de la page. + * @param size Taille de la page. + * @return Liste paginée des relations d'amitié. + */ + public List listFriends(UUID userId, int page, int size) { + Users user = usersRepository.findById(userId); + if (user == null) { + logger.error("[ERROR] Utilisateur non trouvé."); + throw new UserNotFoundException("Utilisateur introuvable."); + } + + List friendships = friendshipRepository.findFriendsByUser(user, page, size); + logger.info("[LOG] " + friendships.size() + " amis récupérés (avant filtrage des doublons)."); + + // Utilisation d'un ensemble pour stocker des clés uniques basées sur les IDs des amis + Set uniqueFriendKeys = new HashSet<>(); + + return friendships.stream() + .map(friendship -> { + Users friend = friendship.getUser().equals(user) ? friendship.getFriend() : friendship.getUser(); + return new FriendshipReadFriendDetailsResponseDTO( + user.getId(), + friend.getId(), + friend.getNom(), + friend.getPrenoms(), + friend.getEmail(), + friend.getProfileImageUrl(), + friendship.getStatus(), + friendship.getCreatedAt(), + friendship.getUpdatedAt() + ); + }) + .filter(dto -> uniqueFriendKeys.add(dto.getUserId().toString() + "-" + dto.getFriendId().toString())) + .limit(size) // Limite la taille au paramètre 'size' requis + .toList(); + } + + /** + * Récupérer les demandes d'amitié avec un statut spécifique. + * + * @param request DTO contenant les informations de filtrage (statut). + * @return Liste des demandes d'amitié avec le statut spécifié. + */ + public List listFriendRequestsByStatus(FriendshipReadStatusRequestDTO request) { + Users user = usersRepository.findById(request.getUserId()); + if (user == null) { + logger.error("[ERROR] Utilisateur non trouvé."); + throw new UserNotFoundException("Utilisateur introuvable."); + } + + // Récupérer les demandes d'amitié selon le statut + List friendships = friendshipRepository.findByUserAndStatus(user, request.getStatus(), request.getPage() - 1, request.getSize()); + logger.info("[LOG] " + friendships.size() + " demandes d'amitié récupérées."); + + return friendships.stream().map(FriendshipReadStatusResponseDTO::new).toList(); + } +} diff --git a/src/main/java/com/lions/dev/service/UserService.java b/src/main/java/com/lions/dev/service/UserService.java deleted file mode 100644 index 9a0d46a..0000000 --- a/src/main/java/com/lions/dev/service/UserService.java +++ /dev/null @@ -1,97 +0,0 @@ -package com.lions.dev.service; - -import com.lions.dev.entity.users.Users; -import com.lions.dev.repository.UsersRepository; -import com.lions.dev.dto.request.users.UserRequestDTO; -import com.lions.dev.exception.UserNotFoundException; -import jakarta.enterprise.context.ApplicationScoped; -import jakarta.inject.Inject; -import java.util.Optional; -import java.util.UUID; - -/** - * Service de gestion des utilisateurs. - * Ce service contient la logique métier pour la création, récupération et suppression des utilisateurs. - */ -@ApplicationScoped -public class UserService { - - @Inject - UsersRepository usersRepository; - - /** - * Crée un nouvel utilisateur dans le système. - * - * @param userRequestDTO Le DTO contenant les informations de l'utilisateur à créer. - * @return L'utilisateur créé. - */ - public Users createUser(UserRequestDTO userRequestDTO) { - Users user = new Users(); - user.setNom(userRequestDTO.getNom()); - user.setPrenoms(userRequestDTO.getPrenoms()); - user.setEmail(userRequestDTO.getEmail()); - user.setMotDePasse(userRequestDTO.getMotDePasse()); // Hachage automatique - - // Vérifier si le rôle est défini, sinon attribuer un rôle par défaut - if (userRequestDTO.getRole() == null || userRequestDTO.getRole().isEmpty()) { - user.setRole("USER"); // Assigner un rôle par défaut, par exemple "USER" - } else { - user.setRole(userRequestDTO.getRole()); - } - - usersRepository.persist(user); - System.out.println("[LOG] Utilisateur créé : " + user.getEmail()); - return user; - } - - /** - * Authentifie un utilisateur avec son email et son mot de passe. - * - * @param email L'email de l'utilisateur. - * @param motDePasse Le mot de passe de l'utilisateur. - * @return L'utilisateur authentifié. - * @throws UserNotFoundException Si l'utilisateur n'est pas trouvé ou si le mot de passe est incorrect. - */ - public Users authenticateUser(String email, String motDePasse) { - Optional userOptional = usersRepository.findByEmail(email); - if (userOptional.isEmpty() || !userOptional.get().verifierMotDePasse(motDePasse)) { - System.out.println("[ERROR] Échec de l'authentification pour l'email : " + email); - throw new UserNotFoundException("Utilisateur ou mot de passe incorrect."); - } - System.out.println("[LOG] Utilisateur authentifié : " + email); - return userOptional.get(); - } - - /** - * Récupère un utilisateur par son ID. - * - * @param id L'ID de l'utilisateur. - * @return L'utilisateur trouvé. - * @throws UserNotFoundException Si l'utilisateur n'est pas trouvé. - */ - public Users getUserById(UUID id) { - Users user = usersRepository.findById(id); - if (user == null) { - System.out.println("[ERROR] Utilisateur non trouvé avec l'ID : " + id); - throw new UserNotFoundException("Utilisateur non trouvé avec l'ID : " + id); - } - System.out.println("[LOG] Utilisateur trouvé avec l'ID : " + id); - return user; - } - - /** - * Supprime un utilisateur par son ID. - * - * @param id L'ID de l'utilisateur à supprimer. - * @return true si l'utilisateur a été supprimé, false sinon. - */ - public boolean deleteUser(UUID id) { - boolean deleted = usersRepository.deleteById(id); - if (deleted) { - System.out.println("[LOG] Utilisateur supprimé avec succès : " + id); - } else { - System.out.println("[ERROR] Échec de la suppression de l'utilisateur avec l'ID : " + id); - } - return deleted; - } -} diff --git a/src/main/java/com/lions/dev/service/UsersService.java b/src/main/java/com/lions/dev/service/UsersService.java new file mode 100644 index 0000000..9480448 --- /dev/null +++ b/src/main/java/com/lions/dev/service/UsersService.java @@ -0,0 +1,194 @@ +package com.lions.dev.service; + +import com.lions.dev.dto.request.users.UserCreateRequestDTO; +import com.lions.dev.entity.users.Users; +import com.lions.dev.exception.UserNotFoundException; +import com.lions.dev.repository.UsersRepository; +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.inject.Inject; +import jakarta.transaction.Transactional; + +import java.util.List; +import java.util.Optional; +import java.util.UUID; + +/** + * Service de gestion des utilisateurs. + * Ce service contient la logique métier pour la création, récupération et suppression des utilisateurs. + */ +@ApplicationScoped +public class UsersService { + + @Inject + UsersRepository usersRepository; + + /** + * Crée un nouvel utilisateur dans le système. + * + * @param userCreateRequestDTO Le DTO contenant les informations de l'utilisateur à créer. + * @return L'utilisateur créé. + */ + public Users createUser(UserCreateRequestDTO userCreateRequestDTO) { + // Vérification si l'email existe déjà + Optional existingUser = usersRepository.findByEmail(userCreateRequestDTO.getEmail()); + if (existingUser.isPresent()) { + throw new IllegalArgumentException("Un utilisateur avec cet email existe déjà."); + } + + Users user = new Users(); + user.setNom(userCreateRequestDTO.getNom()); + user.setPrenoms(userCreateRequestDTO.getPrenoms()); + user.setEmail(userCreateRequestDTO.getEmail()); + user.setMotDePasse(userCreateRequestDTO.getMotDePasse()); // Hachage automatique + + // Logique pour l'image et le rôle par défaut. + user.setProfileImageUrl( + userCreateRequestDTO.getProfileImageUrl() != null + ? userCreateRequestDTO.getProfileImageUrl() + : "https://via.placeholder.com/150" + ); + user.setRole( + userCreateRequestDTO.getRole() != null + ? userCreateRequestDTO.getRole() + : "USER" + ); + + usersRepository.persist(user); + System.out.println("[LOG] Utilisateur créé : " + user.getEmail()); + return user; + } + + /** + * Met à jour un utilisateur existant dans le système. + * + * @param id L'ID de l'utilisateur à mettre à jour. + * @param userCreateRequestDTO Les nouvelles informations de l'utilisateur. + * @return L'utilisateur mis à jour. + * @throws UserNotFoundException Si l'utilisateur n'est pas trouvé. + */ + @Transactional + public Users updateUser(UUID id, UserCreateRequestDTO userCreateRequestDTO) { + Users existingUser = usersRepository.findById(id); + if (existingUser == null) { + System.out.println("[ERROR] Utilisateur non trouvé avec l'ID : " + id); + throw new UserNotFoundException("Utilisateur non trouvé avec l'ID : " + id); + } + + // Mettre à jour les champs de l'utilisateur existant + existingUser.setNom(userCreateRequestDTO.getNom()); + existingUser.setPrenoms(userCreateRequestDTO.getPrenoms()); + existingUser.setEmail(userCreateRequestDTO.getEmail()); + existingUser.setMotDePasse(userCreateRequestDTO.getMotDePasse()); // Hachage automatique si nécessaire + existingUser.setRole(userCreateRequestDTO.getRole()); + existingUser.setProfileImageUrl(userCreateRequestDTO.getProfileImageUrl()); + + usersRepository.persist(existingUser); + System.out.println("[LOG] Utilisateur mis à jour avec succès : " + existingUser.getEmail()); + return existingUser; + } + /** + * Met à jour l'image de profil d'un utilisateur existant dans le système. + * + * @param id L'ID de l'utilisateur à mettre à jour. + * @param profileImageUrl Les nouvelles informations de l'utilisateur. + * @return L'utilisateur mis à jour. + * @throws UserNotFoundException Si l'utilisateur n'est pas trouvé. + */ + @Transactional + public Users updateUserProfileImage(UUID id, String profileImageUrl) { + Users existingUser = usersRepository.findById(id); + if (existingUser == null) { + System.out.println("[ERROR] Utilisateur non trouvé avec l'ID : " + id); + throw new UserNotFoundException("Utilisateur non trouvé avec l'ID : " + id); + } + + // Mettre à jour les champs de l'utilisateur existant + existingUser.setProfileImageUrl(profileImageUrl); + + usersRepository.persist(existingUser); + System.out.println("[LOG] L'image de profile de l\'Utilisateur mis à jour avec succès : " + existingUser.getEmail()); + return existingUser; + } + + /** + * Liste tous les utilisateurs avec pagination. + * + * @param page Le numéro de la page à récupérer. + * @param size Le nombre d'utilisateurs par page. + * @return La liste des utilisateurs paginée. + */ + public List listUsers(int page, int size) { + return usersRepository.findAll().page(page - 1, size).list(); + } + + /** + * Authentifie un utilisateur avec son email et son mot de passe. + * + * @param email L'email de l'utilisateur. + * @param motDePasse Le mot de passe de l'utilisateur. + * @return L'utilisateur authentifié. + * @throws UserNotFoundException Si l'utilisateur n'est pas trouvé ou si le mot de passe est incorrect. + */ + public Users authenticateUser(String email, String motDePasse) { + Optional userOptional = usersRepository.findByEmail(email); + if (userOptional.isEmpty() || !userOptional.get().verifierMotDePasse(motDePasse)) { + System.out.println("[ERROR] Échec de l'authentification pour l'email : " + email); + throw new UserNotFoundException("Utilisateur ou mot de passe incorrect."); + } + System.out.println("[LOG] Utilisateur authentifié : " + email); + return userOptional.get(); + } + + /** + * Récupère un utilisateur par son ID. + * + * @param id L'ID de l'utilisateur. + * @return L'utilisateur trouvé. + * @throws UserNotFoundException Si l'utilisateur n'est pas trouvé. + */ + public Users getUserById(UUID id) { + Users user = usersRepository.findById(id); + if (user == null) { + System.out.println("[ERROR] Utilisateur non trouvé avec l'ID : " + id); + throw new UserNotFoundException("Utilisateur non trouvé avec l'ID : " + id); + } + System.out.println("[LOG] Utilisateur trouvé avec l'ID : " + id); + return user; + } + + /** + * Réinitialise le mot de passe d'un utilisateur. + * + * @param id L'ID de l'utilisateur. + * @param newPassword Le nouveau mot de passe à définir. + * @throws UserNotFoundException Si l'utilisateur n'est pas trouvé. + */ + @Transactional + public void resetPassword(UUID id, String newPassword) { + Users user = usersRepository.findById(id); + if (user == null) { + System.out.println("[ERROR] Utilisateur non trouvé avec l'ID : " + id); + throw new UserNotFoundException("Utilisateur non trouvé."); + } + + user.setMotDePasse(newPassword); // Hachage automatique + usersRepository.persist(user); + System.out.println("[LOG] Mot de passe réinitialisé pour l'utilisateur : " + user.getEmail()); + } + + /** + * Supprime un utilisateur par son ID. + * + * @param id L'ID de l'utilisateur à supprimer. + * @return true si l'utilisateur a été supprimé, false sinon. + */ + public boolean deleteUser(UUID id) { + boolean deleted = usersRepository.deleteById(id); + if (deleted) { + System.out.println("[LOG] Utilisateur supprimé avec succès : " + id); + } else { + System.out.println("[ERROR] Échec de la suppression de l'utilisateur avec l'ID : " + id); + } + return deleted; + } +} diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index 4fc0968..48f0219 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -1,25 +1,35 @@ -# Configuration Quarkus -quarkus.http.port=8085 - # Configuration Swagger UI quarkus.swagger-ui.always-include=true quarkus.swagger-ui.path=/q/swagger-ui quarkus.smallrye-openapi.path=/openapi -# Configuration de la base de donnes -quarkus.datasource.db-kind=oracle -quarkus.datasource.jdbc.url=jdbc:oracle:thin:@localhost:1522:ORCLCDB -quarkus.datasource.username=C##AFTERWORK -quarkus.datasource.password=afterwork -quarkus.datasource.jdbc.driver=oracle.jdbc.OracleDriver -quarkus.hibernate-orm.database.generation=drop-and-create -quarkus.hibernate-orm.log.sql=true -quarkus.datasource.devservices.enabled=false +# Configuration de la base de donnes PostgreSQL pour Quarkus en dveloppement +%dev.quarkus.datasource.db-kind=postgresql +%dev.quarkus.datasource.jdbc.url=jdbc:postgresql://localhost:5432/afterwork_db +%dev.quarkus.datasource.username=${DB_USERNAME} +%dev.quarkus.datasource.password=${DB_PASSWORD} +%dev.quarkus.datasource.jdbc.driver=org.postgresql.Driver +%dev.quarkus.hibernate-orm.database.generation=update +%dev.quarkus.hibernate-orm.log.sql=true +%dev.quarkus.datasource.devservices.enabled=false -# Niveau de logging -quarkus.log.level=INFO +# Configuration de la base de donnes PostgreSQL pour Quarkus en production +%prod.quarkus.datasource.db-kind=postgresql +%prod.quarkus.datasource.jdbc.url=jdbc:postgresql://${DB_HOST:localhost}:${DB_PORT:5432}/${DB_NAME:afterwork_db} +%prod.quarkus.datasource.username=${DB_USERNAME} +%prod.quarkus.datasource.password=${DB_PASSWORD} +%prod.quarkus.datasource.jdbc.driver=org.postgresql.Driver +%prod.quarkus.hibernate-orm.database.generation=update +%prod.quarkus.hibernate-orm.log.sql=false +%prod.quarkus.datasource.devservices.enabled=false -# Configuration la cl de signature JWT +# Niveau de logging pour Quarkus en dveloppement +%dev.quarkus.log.level=DEBUG + +# Niveau de logging pour Quarkus en production +%prod.quarkus.log.level=INFO + +# Configuration de la signature JWT # mp.jwt.verify.publickey.location=META-INF/resources/publicKey.pem # mp.jwt.verify.issuer=https://issuer.example.com # mp.jwt.token.header=Authorization @@ -27,3 +37,12 @@ quarkus.log.level=INFO # smallrye.jwt.sign.key.location=META-INF/resources/privateKey.pem # smallrye.jwt.sign.key.algorithm=RS256 # smallrye.jwt.token.lifetime=3600 + +# Activer le support multipart pour l'upload de fichiers +quarkus.http.body.uploads-directory=/tmp/uploads +# Taille maximale pour la requte multipart (en octets) +quarkus.http.body.multipart.max-request-size=10M + +# Taille maximale pour un fichier multipart (en octets) +quarkus.http.body.multipart.max-file-size=5M +