From b1535d16cbe7e46580316abfba7f9079ccebaad3 Mon Sep 17 00:00:00 2001 From: DahoudG Date: Wed, 11 Sep 2024 19:24:39 +0000 Subject: [PATCH] =?UTF-8?q?Refactoring=20:=20Version=20Tr=C3=A8s=20Clean?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pom.xml | 5 + .../users/UserAuthenticateRequestDTO.java | 44 ++++ .../users/UserAuthenticateResponseDTO.java | 65 ++++++ .../dto/response/users/UserResponseDTO.java | 3 + .../com/lions/dev/resource/UsersResource.java | 220 +++++++++--------- .../com/lions/dev/service/UserService.java | 8 + src/main/resources/application.properties | 9 + 7 files changed, 242 insertions(+), 112 deletions(-) create mode 100644 src/main/java/com/lions/dev/dto/request/users/UserAuthenticateRequestDTO.java create mode 100644 src/main/java/com/lions/dev/dto/response/users/UserAuthenticateResponseDTO.java diff --git a/pom.xml b/pom.xml index 10d6e33..c2dedb7 100644 --- a/pom.xml +++ b/pom.xml @@ -30,6 +30,11 @@ + + io.quarkus + quarkus-smallrye-jwt + + org.springframework.security spring-security-core diff --git a/src/main/java/com/lions/dev/dto/request/users/UserAuthenticateRequestDTO.java b/src/main/java/com/lions/dev/dto/request/users/UserAuthenticateRequestDTO.java new file mode 100644 index 0000000..92a0895 --- /dev/null +++ b/src/main/java/com/lions/dev/dto/request/users/UserAuthenticateRequestDTO.java @@ -0,0 +1,44 @@ +package com.lions.dev.dto.request.users; + +import lombok.Getter; +import lombok.Setter; +import lombok.AllArgsConstructor; +import lombok.NoArgsConstructor; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * DTO pour la requête d'authentification de l'utilisateur. + * Utilisé pour encapsuler les informations nécessaires lors de l'authentification d'un utilisateur. + */ +@Getter +@Setter +@AllArgsConstructor +@NoArgsConstructor +public class UserAuthenticateRequestDTO { + + private static final Logger logger = LoggerFactory.getLogger(UserAuthenticateRequestDTO.class); + + /** + * Adresse email de l'utilisateur. Doit être validée côté front-end et back-end. + */ + private String email; + + /** + * Mot de passe de l'utilisateur en texte clair. + * Ce champ sera haché avant d'être utilisé pour l'authentification. + */ + private String motDePasse; + + /** + * Log de création de l'objet DTO. + */ + static { + logger.info("UserAuthenticateRequestDTO - DTO pour l'authentification initialisé"); + } + + // Méthode personnalisée pour loguer les détails de la requête + public void logRequestDetails() { + logger.info("Authentification demandée pour l'email: {}", email); + } +} 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 new file mode 100644 index 0000000..71bb156 --- /dev/null +++ b/src/main/java/com/lions/dev/dto/response/users/UserAuthenticateResponseDTO.java @@ -0,0 +1,65 @@ +package com.lions.dev.dto.response.users; + +import java.util.UUID; +import lombok.Getter; +import lombok.Setter; +import lombok.AllArgsConstructor; +import lombok.NoArgsConstructor; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * DTO pour la réponse d'authentification de l'utilisateur. + * Utilisé pour renvoyer les informations nécessaires après l'authentification réussie d'un utilisateur. + */ +@Getter +@Setter +@AllArgsConstructor +@NoArgsConstructor +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é. + */ + private UUID userId; + + /** + * Nom de l'utilisateur. + */ + private String nom; + + /** + * Prénom de l'utilisateur. + */ + private String prenoms; + + /** + * Adresse email de l'utilisateur. + */ + private String email; + + /** + * Rôle de l'utilisateur. + */ + private String role; + + /** + * Log de création de l'objet DTO. + */ + static { + logger.info("UserAuthenticateResponseDTO - DTO pour la réponse d'authentification initialisé"); + } + + // 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); + } +} 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 8591943..394b9b1 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,6 +1,7 @@ package com.lions.dev.dto.response.users; import com.lions.dev.entity.users.Users; +import java.util.UUID; import lombok.Getter; /** @@ -11,6 +12,7 @@ import lombok.Getter; @Getter 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 @@ -21,6 +23,7 @@ public class UserResponseDTO { * @param user L'utilisateur à convertir en DTO. */ public UserResponseDTO(Users user) { + this.uuid = user.getId(); this.nom = user.getNom(); this.prenoms = user.getPrenoms(); this.email = user.getEmail(); diff --git a/src/main/java/com/lions/dev/resource/UsersResource.java b/src/main/java/com/lions/dev/resource/UsersResource.java index bb180b1..408e637 100644 --- a/src/main/java/com/lions/dev/resource/UsersResource.java +++ b/src/main/java/com/lions/dev/resource/UsersResource.java @@ -1,25 +1,25 @@ package com.lions.dev.resource; -import com.lions.dev.entity.users.Users; -import com.lions.dev.repository.UsersRepository; +import com.lions.dev.dto.request.users.UserAuthenticateRequestDTO; import com.lions.dev.dto.request.users.UserRequestDTO; +import com.lions.dev.dto.response.users.UserAuthenticateResponseDTO; import com.lions.dev.dto.response.users.UserResponseDTO; -import com.lions.dev.exception.UserNotFoundException; +import com.lions.dev.entity.users.Users; +import com.lions.dev.service.UserService; import jakarta.inject.Inject; import jakarta.transaction.Transactional; import jakarta.ws.rs.*; import jakarta.ws.rs.core.Response; -import java.time.LocalDateTime; 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. + * 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. + *

Tous les logs nécessaires pour la traçabilité sont intégrés. */ @Path("/users") @Produces("application/json") @@ -27,116 +27,112 @@ import org.jboss.logging.Logger; @Tag(name = "Users", description = "Opérations liées à la gestion des utilisateurs") public class UsersResource { - @Inject - UsersRepository usersRepository; + @Inject UserService userService; - private static final Logger LOG = Logger.getLogger(UsersResource.class); + 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. - * @return Une réponse HTTP contenant l'utilisateur créé ou un message d'erreur. - */ - @POST - @Transactional - @Operation(summary = "Créer un nouvel utilisateur", description = "Crée un nouvel utilisateur et retourne les détails") - public Response createUser(UserRequestDTO userRequestDTO) { - LOG.info("Tentative de création d'un nouvel utilisateur avec l'email : " + userRequestDTO.getEmail()); + /** + * Endpoint pour créer un nouvel utilisateur. + * + * @param userRequestDTO 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 + @Transactional + @Operation( + summary = "Créer un nouvel utilisateur", + description = "Crée un nouvel utilisateur et retourne les détails") + public Response createUser(UserRequestDTO userRequestDTO) { + LOG.info( + "Tentative de création d'un nouvel utilisateur avec l'email : " + + userRequestDTO.getEmail()); - if (usersRepository.existsByEmail(userRequestDTO.getEmail())) { - LOG.warn("Un utilisateur avec cet email existe déjà : " + userRequestDTO.getEmail()); - return Response.status(Response.Status.CONFLICT) - .entity("Un utilisateur avec cet email existe déjà.").build(); - } + // Utilisation de UserService pour créer l'utilisateur + Users user = userService.createUser(userRequestDTO); - Users user = new Users(); - user.setNom(userRequestDTO.getNom()); - user.setPrenoms(userRequestDTO.getPrenoms()); - user.setEmail(userRequestDTO.getEmail()); - user.setMotDePasse(userRequestDTO.getMotDePasse()); // Hachage automatique dans l'entité - // Assigner un rôle par défaut si non fourni (par exemple : USER) - if (user.getRole() == null) { - user.setRole("USER"); // Définir le rôle par défaut - } + UserResponseDTO responseDTO = new UserResponseDTO(user); + return Response.status(Response.Status.CREATED).entity(responseDTO).build(); + } - usersRepository.persist(user); - LOG.info("Utilisateur créé avec succès : " + user.getEmail() + " à " + LocalDateTime.now()); + /** + * Endpoint pour authentifier un utilisateur. + * + * @param userAuthenticateRequestDTO Le DTO contenant les informations d'authentification. + * @return Une réponse HTTP indiquant si l'authentification a réussi ou échoué. + */ + @POST + @Path("/authenticate") + @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()); - UserResponseDTO responseDTO = new UserResponseDTO(user); - return Response.status(Response.Status.CREATED).entity(responseDTO).build(); - } - - /** - * Endpoint pour authentifier un utilisateur. - * - * @param userRequestDTO Le DTO contenant les informations d'authentification. - * @return Une réponse HTTP indiquant si l'authentification a réussi ou échoué. - */ - @POST - @Path("/authenticate") - @Operation(summary = "Authentifier un utilisateur", description = "Vérifie les informations de connexion de l'utilisateur") - public Response authenticateUser(UserRequestDTO userRequestDTO) { - LOG.info("Tentative d'authentification pour l'utilisateur avec l'email : " + userRequestDTO.getEmail()); - - Users user = usersRepository.findByEmail(userRequestDTO.getEmail()) - .orElseThrow(() -> new UserNotFoundException("Utilisateur non trouvé avec l'email : " + userRequestDTO.getEmail())); - - if (!user.verifierMotDePasse(userRequestDTO.getMotDePasse())) { - LOG.warn("Échec de l'authentification : mot de passe incorrect pour l'email : " + userRequestDTO.getEmail()); - return Response.status(Response.Status.UNAUTHORIZED).entity("Mot de passe incorrect.").build(); - } - - LOG.info("Authentification réussie pour l'utilisateur : " + user.getEmail()); - UserResponseDTO responseDTO = new UserResponseDTO(user); - return Response.ok(responseDTO).build(); - } - - /** - * Endpoint pour récupérer les détails d'un utilisateur par ID. - * - * @param id L'ID de l'utilisateur. - * @return Une réponse HTTP contenant les informations de l'utilisateur. - */ - @GET - @Path("/{id}") - @Operation(summary = "Récupérer un utilisateur par ID", description = "Retourne les détails de l'utilisateur demandé") - public Response getUserById(@PathParam("id") UUID id) { - LOG.info("Récupération de l'utilisateur avec l'ID : " + id); - - Users user = usersRepository.findById(id); - if (user == null) { - LOG.warn("Utilisateur non trouvé avec l'ID : " + id); - return Response.status(Response.Status.NOT_FOUND) - .entity("Utilisateur non trouvé.").build(); - } - - UserResponseDTO responseDTO = new UserResponseDTO(user); - LOG.info("Utilisateur trouvé : " + user.getEmail()); - return Response.ok(responseDTO).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. - */ - @DELETE - @Path("/{id}") - @Transactional - @Operation(summary = "Supprimer un utilisateur", description = "Supprime un utilisateur de la base de données") - public Response deleteUser(@PathParam("id") UUID id) { - LOG.info("Tentative de suppression de l'utilisateur avec l'ID : " + id); - - boolean deleted = usersRepository.deleteById(id); - if (deleted) { - LOG.info("Utilisateur supprimé avec succès."); - return Response.noContent().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(); - } + // Utilisation de UserService pour authentifier l'utilisateur + 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()); + + responseDTO.logResponseDetails(); + + return Response.ok(responseDTO).build(); + } + + /** + * Endpoint pour récupérer les détails d'un utilisateur par ID. + * + * @param id L'ID de l'utilisateur. + * @return Une réponse HTTP contenant les informations de l'utilisateur. + */ + @GET + @Path("/{id}") + @Operation( + summary = "Récupérer un utilisateur par ID", + description = "Retourne les détails de l'utilisateur demandé") + 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); + LOG.info("Utilisateur trouvé : " + user.getEmail()); + return Response.ok(responseDTO).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. + */ + @DELETE + @Path("/{id}") + @Transactional + @Operation( + summary = "Supprimer un utilisateur", + description = "Supprime un utilisateur de la base de données") + 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); + + if (deleted) { + LOG.info("Utilisateur supprimé avec succès."); + return Response.noContent().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(); } + } } diff --git a/src/main/java/com/lions/dev/service/UserService.java b/src/main/java/com/lions/dev/service/UserService.java index f7ad42c..9a0d46a 100644 --- a/src/main/java/com/lions/dev/service/UserService.java +++ b/src/main/java/com/lions/dev/service/UserService.java @@ -31,6 +31,14 @@ public class UserService { 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; diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index 880540b..4fc0968 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -18,3 +18,12 @@ quarkus.datasource.devservices.enabled=false # Niveau de logging quarkus.log.level=INFO + +# Configuration la clé de 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 +# mp.jwt.token.schemes=Bearer +# smallrye.jwt.sign.key.location=META-INF/resources/privateKey.pem +# smallrye.jwt.sign.key.algorithm=RS256 +# smallrye.jwt.token.lifetime=3600