diff --git a/pom.xml b/pom.xml index c10cde2..e3a65c2 100644 --- a/pom.xml +++ b/pom.xml @@ -7,7 +7,7 @@ com.gbcm gbcm-client-impl-quarkus 1.0.0-SNAPSHOT - war + jar GBCM Client Implementation - Quarkus Interface web GBCM avec Quarkus et PrimeFaces @@ -55,16 +55,14 @@ quarkus-oidc - + - org.apache.myfaces.core - myfaces-impl - 4.0.1 + io.quarkus + quarkus-resteasy-reactive - org.apache.myfaces.core - myfaces-api - 4.0.1 + io.quarkus + quarkus-qute @@ -75,13 +73,15 @@ jakarta - + + diff --git a/src/main/java/com/gbcm/client/beans/auth/AuthBean.java b/src/main/java/com/gbcm/client/beans/auth/AuthBean.java deleted file mode 100644 index 469d32c..0000000 --- a/src/main/java/com/gbcm/client/beans/auth/AuthBean.java +++ /dev/null @@ -1,195 +0,0 @@ -package com.gbcm.client.beans.auth; - -import com.gbcm.client.service.GBCMServerClient; -import com.gbcm.server.api.dto.UserDTO; -import com.gbcm.server.api.dto.LoginRequestDTO; -import com.gbcm.server.api.dto.LoginResponseDTO; - -import jakarta.enterprise.context.SessionScoped; -import jakarta.faces.application.FacesMessage; -import jakarta.faces.context.FacesContext; -import jakarta.inject.Inject; -import jakarta.inject.Named; -import java.io.Serializable; - -/** - * Managed Bean pour la gestion de l'authentification - */ -@Named("authBean") -@SessionScoped -public class AuthBean implements Serializable { - - private static final long serialVersionUID = 1L; - - @Inject - private GBCMServerClient serverClient; - - // Propriétés de connexion - private String email; - private String password; - private boolean rememberMe; - - // Utilisateur connecté - private UserDTO currentUser; - private String authToken; - private boolean authenticated = false; - - /** - * Tentative de connexion - */ - public String login() { - try { - LoginRequestDTO loginRequest = new LoginRequestDTO(); - loginRequest.setEmail(email); - loginRequest.setPassword(password); - loginRequest.setRememberMe(rememberMe); - - LoginResponseDTO response = serverClient.login(loginRequest); - - if (response.isSuccess()) { - this.currentUser = response.getUser(); - this.authToken = response.getToken(); - this.authenticated = true; - - // Message de succès - FacesContext.getCurrentInstance().addMessage(null, - new FacesMessage(FacesMessage.SEVERITY_INFO, - "Connexion réussie", - "Bienvenue " + currentUser.getFirstName())); - - // Redirection selon le rôle - return redirectAfterLogin(); - } else { - FacesContext.getCurrentInstance().addMessage(null, - new FacesMessage(FacesMessage.SEVERITY_ERROR, - "Erreur de connexion", - response.getMessage())); - return null; - } - - } catch (Exception e) { - FacesContext.getCurrentInstance().addMessage(null, - new FacesMessage(FacesMessage.SEVERITY_ERROR, - "Erreur système", - "Impossible de se connecter au serveur")); - return null; - } - } - - /** - * Déconnexion - */ - public String logout() { - try { - if (authToken != null) { - serverClient.logout(authToken); - } - } catch (Exception e) { - // Log l'erreur mais continue la déconnexion - } - - // Nettoyage de la session - this.currentUser = null; - this.authToken = null; - this.authenticated = false; - this.email = null; - this.password = null; - this.rememberMe = false; - - // Invalidation de la session JSF - FacesContext.getCurrentInstance().getExternalContext().invalidateSession(); - - return "/index?faces-redirect=true"; - } - - /** - * Redirection après connexion selon le rôle - */ - private String redirectAfterLogin() { - if (currentUser == null) { - return "/index?faces-redirect=true"; - } - - switch (currentUser.getRole()) { - case "ADMIN": - return "/pages/admin/dashboard?faces-redirect=true"; - case "COACH": - return "/pages/coaching/dashboard?faces-redirect=true"; - case "CLIENT": - return "/pages/dashboard/client?faces-redirect=true"; - default: - return "/pages/dashboard/home?faces-redirect=true"; - } - } - - /** - * Navigation vers le profil - */ - public String goToProfile() { - return "/pages/profile/edit?faces-redirect=true"; - } - - /** - * Navigation vers les paramètres - */ - public String goToSettings() { - return "/pages/settings/general?faces-redirect=true"; - } - - /** - * Vérification des permissions - */ - public boolean hasRole(String role) { - return authenticated && currentUser != null && - role.equals(currentUser.getRole()); - } - - public boolean isAdmin() { - return hasRole("ADMIN"); - } - - public boolean isCoach() { - return hasRole("COACH"); - } - - public boolean isClient() { - return hasRole("CLIENT"); - } - - // Getters et Setters - public String getEmail() { - return email; - } - - public void setEmail(String email) { - this.email = email; - } - - public String getPassword() { - return password; - } - - public void setPassword(String password) { - this.password = password; - } - - public boolean isRememberMe() { - return rememberMe; - } - - public void setRememberMe(boolean rememberMe) { - this.rememberMe = rememberMe; - } - - public UserDTO getCurrentUser() { - return currentUser; - } - - public String getAuthToken() { - return authToken; - } - - public boolean isAuthenticated() { - return authenticated; - } -} diff --git a/src/main/java/com/gbcm/client/service/GBCMServerClient.java b/src/main/java/com/gbcm/client/service/GBCMServerClient.java new file mode 100644 index 0000000..c4cbb7f --- /dev/null +++ b/src/main/java/com/gbcm/client/service/GBCMServerClient.java @@ -0,0 +1,140 @@ +package com.gbcm.client.service; + +import com.gbcm.server.api.dto.auth.LoginRequestDTO; +import com.gbcm.server.api.dto.auth.LoginResponseDTO; +import com.gbcm.server.api.dto.user.UserDTO; +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.ws.rs.client.Client; +import jakarta.ws.rs.client.ClientBuilder; +import jakarta.ws.rs.client.Entity; +import jakarta.ws.rs.core.MediaType; +import jakarta.ws.rs.core.Response; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Client REST pour communiquer avec l'API GBCM Server + * + * @author GBCM Team + * @version 1.0.0 + * @since 2025-01-01 + */ +@ApplicationScoped +public class GBCMServerClient { + + private static final Logger logger = LoggerFactory.getLogger(GBCMServerClient.class); + + private static final String BASE_URL = "http://localhost:8080/api"; + + private final Client client; + + public GBCMServerClient() { + this.client = ClientBuilder.newClient(); + } + + /** + * Authentification utilisateur + * + * @param loginRequest Données de connexion + * @return Réponse d'authentification + */ + public LoginResponseDTO login(LoginRequestDTO loginRequest) { + try { + logger.info("Tentative de connexion pour l'utilisateur: {}", loginRequest.getEmail()); + + Response response = client + .target(BASE_URL + "/auth/login") + .request(MediaType.APPLICATION_JSON) + .post(Entity.entity(loginRequest, MediaType.APPLICATION_JSON)); + + if (response.getStatus() == 200) { + LoginResponseDTO loginResponse = response.readEntity(LoginResponseDTO.class); + logger.info("Connexion réussie pour l'utilisateur: {}", loginRequest.getEmail()); + return loginResponse; + } else { + logger.error("Échec de la connexion pour l'utilisateur: {}. Status: {}", + loginRequest.getEmail(), response.getStatus()); + throw new RuntimeException("Échec de l'authentification: " + response.getStatus()); + } + } catch (Exception e) { + logger.error("Erreur lors de la connexion pour l'utilisateur: {}", loginRequest.getEmail(), e); + throw new RuntimeException("Erreur de communication avec le serveur", e); + } + } + + /** + * Déconnexion utilisateur + * + * @param token Token JWT + */ + public void logout(String token) { + try { + logger.info("Déconnexion de l'utilisateur"); + + Response response = client + .target(BASE_URL + "/auth/logout") + .request(MediaType.APPLICATION_JSON) + .header("Authorization", "Bearer " + token) + .post(Entity.text("")); + + if (response.getStatus() == 200) { + logger.info("Déconnexion réussie"); + } else { + logger.warn("Problème lors de la déconnexion. Status: {}", response.getStatus()); + } + } catch (Exception e) { + logger.error("Erreur lors de la déconnexion", e); + } + } + + /** + * Récupération du profil utilisateur + * + * @param token Token JWT + * @return Profil utilisateur + */ + public UserDTO getUserProfile(String token) { + try { + logger.info("Récupération du profil utilisateur"); + + Response response = client + .target(BASE_URL + "/users/profile") + .request(MediaType.APPLICATION_JSON) + .header("Authorization", "Bearer " + token) + .get(); + + if (response.getStatus() == 200) { + UserDTO user = response.readEntity(UserDTO.class); + logger.info("Profil utilisateur récupéré: {}", user.getEmail()); + return user; + } else { + logger.error("Échec de la récupération du profil. Status: {}", response.getStatus()); + throw new RuntimeException("Impossible de récupérer le profil utilisateur"); + } + } catch (Exception e) { + logger.error("Erreur lors de la récupération du profil utilisateur", e); + throw new RuntimeException("Erreur de communication avec le serveur", e); + } + } + + /** + * Validation d'un token JWT + * + * @param token Token à valider + * @return true si le token est valide + */ + public boolean validateToken(String token) { + try { + Response response = client + .target(BASE_URL + "/auth/validate") + .request(MediaType.APPLICATION_JSON) + .header("Authorization", "Bearer " + token) + .get(); + + return response.getStatus() == 200; + } catch (Exception e) { + logger.error("Erreur lors de la validation du token", e); + return false; + } + } +} diff --git a/src/main/java/com/gbcm/client/web/HomeController.java b/src/main/java/com/gbcm/client/web/HomeController.java new file mode 100644 index 0000000..89ea235 --- /dev/null +++ b/src/main/java/com/gbcm/client/web/HomeController.java @@ -0,0 +1,42 @@ +package com.gbcm.client.web; + +import jakarta.ws.rs.GET; +import jakarta.ws.rs.Path; +import jakarta.ws.rs.Produces; +import jakarta.ws.rs.core.MediaType; +import io.quarkus.qute.Template; +import io.quarkus.qute.TemplateInstance; +import jakarta.inject.Inject; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Contrôleur principal pour l'interface web GBCM + * + * @author GBCM Team + * @version 1.0.0 + * @since 2025-01-01 + */ +@Path("/") +public class HomeController { + + private static final Logger logger = LoggerFactory.getLogger(HomeController.class); + + @Inject + Template index; + + @GET + @Produces(MediaType.TEXT_HTML) + public TemplateInstance home() { + logger.info("Accès à la page d'accueil GBCM"); + return index.data("title", "GBCM - Global Business Consulting & Management") + .data("message", "Bienvenue dans l'interface web GBCM"); + } + + @GET + @Path("/health") + @Produces(MediaType.APPLICATION_JSON) + public String health() { + return "{\"status\":\"UP\",\"service\":\"gbcm-client-web\"}"; + } +} diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index fb6c0de..1112e49 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -12,8 +12,17 @@ quarkus.servlet.context-path=/gbcm # Security Configuration quarkus.security.auth.enabled=true +# Keycloak OIDC Configuration +quarkus.oidc.auth-server-url=http://localhost:8180/realms/gbcm-llc +quarkus.oidc.client-id=gbcm-web-client +quarkus.oidc.credentials.secret=gbcm-web-secret +quarkus.oidc.tls.verification=none +quarkus.oidc.application-type=web-app +quarkus.oidc.authentication.redirect-path=/gbcm/login +quarkus.oidc.authentication.restore-path-after-redirect=true + # REST Client Configuration - GBCM Server API -gbcm.server.api.url=http://localhost:8081/api/v1 +gbcm.server.api.url=http://localhost:8082/api quarkus.rest-client."com.gbcm.client.service.GBCMServerClient".url=${gbcm.server.api.url} # Database Configuration (for session storage) diff --git a/src/main/resources/templates/index.html b/src/main/resources/templates/index.html new file mode 100644 index 0000000..2895250 --- /dev/null +++ b/src/main/resources/templates/index.html @@ -0,0 +1,143 @@ + + + + + + {title} + + + +
+ +
Global Business Consulting & Management
+
{message}
+ +
+
+ Interface Web Active +
+ +
+
+

🏢 Gestion Clients

+

Suivi complet des prospects et clients

+
+
+

👨‍💼 Gestion Coaches

+

Planification et suivi des coaches

+
+
+

🎯 Ateliers

+

Organisation des workshops

+
+
+

💬 Sessions

+

Coaching individuel personnalisé

+
+
+ + +
+ + diff --git a/src/main/webapp/index.xhtml b/src/main/webapp/index.xhtml new file mode 100644 index 0000000..645e006 --- /dev/null +++ b/src/main/webapp/index.xhtml @@ -0,0 +1,59 @@ + + + + + GBCM - Global Business Consulting and Management + + + + + +
+
+
+
+
+
+

GBCM Client Web

+

Interface web pour la plateforme GBCM

+
+
+ +
+
+

Bienvenue sur GBCM

+

Global Business Consulting and Management - Plateforme de conseil en entreprise

+ + +
+
+
+

Authentification

+ +
+
+ +
+
+

Statut du serveur

+ + +
+
+
+
+
+
+
+
+
+
+
+