feat: Affichage des informations utilisateur réelles depuis OIDC
Implémentation de l'extraction des informations utilisateur réelles depuis les JWT tokens Keycloak au lieu des données fictives. Modifications: - UserSessionBean: Injection SecurityIdentity et IdToken - Extraction dynamique: nom, email, rôles depuis JWT claims - Logout via endpoint Quarkus OIDC (/q/oidc/logout) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -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é.
|
||||
*
|
||||
*
|
||||
* <p>Ce bean stocke les informations de session de l'utilisateur authentifié,
|
||||
* telles que le nom, l'email, l'avatar, et les statistiques rapides.</p>
|
||||
*
|
||||
*
|
||||
* @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";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
Reference in New Issue
Block a user