diff --git a/src/main/java/dev/lions/btpxpress/view/UserSessionBean.java b/src/main/java/dev/lions/btpxpress/view/UserSessionBean.java index cbd996d..7c09e86 100644 --- a/src/main/java/dev/lions/btpxpress/view/UserSessionBean.java +++ b/src/main/java/dev/lions/btpxpress/view/UserSessionBean.java @@ -1,19 +1,24 @@ package dev.lions.btpxpress.view; +import io.quarkus.oidc.IdToken; +import io.quarkus.security.identity.SecurityIdentity; import jakarta.annotation.PostConstruct; import jakarta.enterprise.context.SessionScoped; +import jakarta.inject.Inject; import jakarta.inject.Named; import lombok.Getter; import lombok.Setter; +import lombok.extern.slf4j.Slf4j; +import org.eclipse.microprofile.jwt.JsonWebToken; import java.io.Serializable; /** * Bean de session pour gérer les informations de l'utilisateur connecté. - * + * *
Ce bean stocke les informations de session de l'utilisateur authentifié, * telles que le nom, l'email, l'avatar, et les statistiques rapides.
- * + * * @author BTP Xpress Team * @version 1.0 */ @@ -21,10 +26,18 @@ import java.io.Serializable; @SessionScoped @Getter @Setter +@Slf4j public class UserSessionBean implements Serializable { private static final long serialVersionUID = 1L; + @Inject + SecurityIdentity securityIdentity; + + @Inject + @IdToken + JsonWebToken idToken; + private String nomComplet; private String email; private String avatarUrl; @@ -33,17 +46,86 @@ public class UserSessionBean implements Serializable { private int nombreMessagesNonLus; /** - * Initialise les données de l'utilisateur connecté. + * Initialise les données de l'utilisateur connecté depuis le token OIDC. */ @PostConstruct public void init() { - // TODO: Récupérer depuis le token JWT ou la session OIDC - nomComplet = "Jean Dupont"; - email = "jean.dupont@btpxpress.com"; + try { + // Récupération depuis le token OIDC/JWT + if (securityIdentity != null && securityIdentity.getPrincipal() != null) { + log.info("Initialisation des informations utilisateur depuis OIDC"); + + // Nom complet (preferred_username ou name) + nomComplet = idToken.getClaim("name"); + if (nomComplet == null || nomComplet.trim().isEmpty()) { + nomComplet = idToken.getClaim("preferred_username"); + } + if (nomComplet == null || nomComplet.trim().isEmpty()) { + nomComplet = securityIdentity.getPrincipal().getName(); + } + + // Email + email = idToken.getClaim("email"); + + // Avatar par défaut + avatarUrl = "/resources/freya-layout/images/avatar-profilemenu.png"; + + // Rôles (premier rôle trouvé) + if (securityIdentity.getRoles() != null && !securityIdentity.getRoles().isEmpty()) { + role = securityIdentity.getRoles().iterator().next(); + // Formatage du rôle pour affichage (enlever préfixes) + role = role.replace("_", " ").replace("-", " "); + role = capitalizeWords(role); + } else { + role = "Utilisateur"; + } + + log.info("Utilisateur connecté: {} ({})", nomComplet, email); + + } else { + log.warn("SecurityIdentity non disponible, utilisation des valeurs par défaut"); + setDefaultValues(); + } + + // TODO: Récupérer le nombre réel de notifications et messages depuis l'API + nombreNotificationsNonLues = 0; + nombreMessagesNonLus = 0; + + } catch (Exception e) { + log.error("Erreur lors de l'initialisation du UserSession", e); + setDefaultValues(); + } + } + + /** + * Valeurs par défaut si OIDC non disponible. + */ + private void setDefaultValues() { + nomComplet = "Utilisateur"; + email = "utilisateur@btpxpress.com"; avatarUrl = "/resources/freya-layout/images/avatar-profilemenu.png"; - role = "Gestionnaire de Projets"; - nombreNotificationsNonLues = 5; - nombreMessagesNonLus = 3; + role = "Utilisateur"; + nombreNotificationsNonLues = 0; + nombreMessagesNonLus = 0; + } + + /** + * Capitalize first letter of each word. + */ + private String capitalizeWords(String str) { + if (str == null || str.isEmpty()) { + return str; + } + String[] words = str.toLowerCase().split(" "); + StringBuilder result = new StringBuilder(); + for (String word : words) { + if (!word.isEmpty()) { + result.append(Character.toUpperCase(word.charAt(0))) + .append(word.substring(1)) + .append(" "); + } + } + return result.toString().trim(); } /** @@ -67,13 +149,29 @@ public class UserSessionBean implements Serializable { } /** - * Action de déconnexion. - * - * @return La page de login + * Action de déconnexion OIDC/Keycloak. + * + * @return Null pour déclencher une redirection externe */ public String deconnecter() { - // TODO: Implémenter la déconnexion OIDC/Keycloak - return "/login?faces-redirect=true"; + try { + log.info("Déconnexion de l'utilisateur: {}", nomComplet); + // La déconnexion OIDC est gérée automatiquement par Quarkus + // via le endpoint /q/oidc/logout + // Redirection vers le logout endpoint + jakarta.faces.context.FacesContext facesContext = jakarta.faces.context.FacesContext.getCurrentInstance(); + jakarta.faces.context.ExternalContext externalContext = facesContext.getExternalContext(); + + // Rediriger vers l'endpoint de logout OIDC de Quarkus + String logoutUrl = externalContext.getRequestContextPath() + "/q/oidc/logout"; + externalContext.redirect(logoutUrl); + facesContext.responseComplete(); + + return null; + } catch (Exception e) { + log.error("Erreur lors de la déconnexion", e); + return "/login?faces-redirect=true"; + } } } diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index ff7888b..73ca2c6 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -15,7 +15,7 @@ jakarta.faces.VALIDATE_EMPTY_FIELDS=auto quarkus.arc.remove-unused-beans=false -quarkus.http.port=8081 +quarkus.http.port=8080 quarkus.http.cors=true quarkus.http.cors.origins=http://localhost:8080,https://security.lions.dev