package dev.lions.unionflow.server.service; import io.quarkus.oidc.runtime.OidcJwtCallerPrincipal; import io.quarkus.security.identity.SecurityIdentity; import jakarta.enterprise.context.ApplicationScoped; import jakarta.inject.Inject; import java.util.Set; import org.eclipse.microprofile.jwt.JsonWebToken; import org.jboss.logging.Logger; /** * Service pour l'intégration avec Keycloak * * @author UnionFlow Team * @version 1.0 * @since 2025-01-15 */ @ApplicationScoped public class KeycloakService { private static final Logger LOG = Logger.getLogger(KeycloakService.class); @Inject SecurityIdentity securityIdentity; @Inject JsonWebToken jwt; /** * Vérifie si l'utilisateur actuel est authentifié * * @return true si l'utilisateur est authentifié */ public boolean isAuthenticated() { return securityIdentity != null && !securityIdentity.isAnonymous(); } /** * Obtient l'ID de l'utilisateur actuel depuis Keycloak * * @return l'ID de l'utilisateur ou null si non authentifié */ public String getCurrentUserId() { if (!isAuthenticated()) { return null; } try { return jwt.getSubject(); } catch (Exception e) { LOG.warnf("Erreur lors de la récupération de l'ID utilisateur: %s", e.getMessage()); return null; } } /** * Obtient l'email de l'utilisateur actuel * * @return l'email de l'utilisateur ou null si non authentifié */ public String getCurrentUserEmail() { if (!isAuthenticated()) { return null; } try { return jwt.getClaim("email"); } catch (Exception e) { LOG.warnf("Erreur lors de la récupération de l'email utilisateur: %s", e.getMessage()); return securityIdentity.getPrincipal().getName(); } } /** * Obtient le nom complet de l'utilisateur actuel * * @return le nom complet ou null si non disponible */ public String getCurrentUserFullName() { if (!isAuthenticated()) { return null; } try { String firstName = jwt.getClaim("given_name"); String lastName = jwt.getClaim("family_name"); if (firstName != null && lastName != null) { return firstName + " " + lastName; } else if (firstName != null) { return firstName; } else if (lastName != null) { return lastName; } // Fallback sur le nom d'utilisateur return jwt.getClaim("preferred_username"); } catch (Exception e) { LOG.warnf("Erreur lors de la récupération du nom utilisateur: %s", e.getMessage()); return null; } } /** * Obtient tous les rôles de l'utilisateur actuel * * @return les rôles de l'utilisateur */ public Set getCurrentUserRoles() { if (!isAuthenticated()) { return Set.of(); } return securityIdentity.getRoles(); } /** * Vérifie si l'utilisateur actuel a un rôle spécifique * * @param role le rôle à vérifier * @return true si l'utilisateur a le rôle */ public boolean hasRole(String role) { if (!isAuthenticated()) { return false; } return securityIdentity.hasRole(role); } /** * Vérifie si l'utilisateur actuel a au moins un des rôles spécifiés * * @param roles les rôles à vérifier * @return true si l'utilisateur a au moins un des rôles */ public boolean hasAnyRole(String... roles) { if (!isAuthenticated()) { return false; } for (String role : roles) { if (securityIdentity.hasRole(role)) { return true; } } return false; } /** * Vérifie si l'utilisateur actuel a tous les rôles spécifiés * * @param roles les rôles à vérifier * @return true si l'utilisateur a tous les rôles */ public boolean hasAllRoles(String... roles) { if (!isAuthenticated()) { return false; } for (String role : roles) { if (!securityIdentity.hasRole(role)) { return false; } } return true; } /** * Obtient une claim spécifique du JWT * * @param claimName le nom de la claim * @return la valeur de la claim ou null si non trouvée */ public T getClaim(String claimName) { if (!isAuthenticated()) { return null; } try { return jwt.getClaim(claimName); } catch (Exception e) { LOG.warnf("Erreur lors de la récupération de la claim %s: %s", claimName, e.getMessage()); return null; } } /** * Obtient toutes les claims du JWT * * @return toutes les claims ou une map vide si non authentifié */ public Set getAllClaimNames() { if (!isAuthenticated()) { return Set.of(); } try { Set names = jwt.getClaimNames(); return names != null ? names : Set.of(); } catch (Exception e) { LOG.warnf("Erreur lors de la récupération des claims: %s", e.getMessage()); return Set.of(); } } /** * Obtient les informations utilisateur pour les logs * * @return informations utilisateur formatées */ public String getUserInfoForLogging() { if (!isAuthenticated()) { return "Utilisateur non authentifié"; } String email = getCurrentUserEmail(); String fullName = getCurrentUserFullName(); Set roles = getCurrentUserRoles(); return String.format( "Utilisateur: %s (%s), Rôles: %s", fullName != null ? fullName : "N/A", email != null ? email : "N/A", roles); } /** * Vérifie si l'utilisateur actuel est un administrateur * * @return true si l'utilisateur est administrateur */ public boolean isAdmin() { return hasRole("ADMIN") || hasRole("admin"); } /** * Vérifie si l'utilisateur actuel peut gérer les membres * * @return true si l'utilisateur peut gérer les membres */ public boolean canManageMembers() { return hasAnyRole( "ADMIN", "GESTIONNAIRE_MEMBRE", "PRESIDENT", "SECRETAIRE", "admin", "gestionnaire_membre", "president", "secretaire"); } /** * Vérifie si l'utilisateur actuel peut gérer les finances * * @return true si l'utilisateur peut gérer les finances */ public boolean canManageFinances() { return hasAnyRole("ADMIN", "TRESORIER", "PRESIDENT", "admin", "tresorier", "president"); } /** * Vérifie si l'utilisateur actuel peut gérer les événements * * @return true si l'utilisateur peut gérer les événements */ public boolean canManageEvents() { return hasAnyRole( "ADMIN", "ORGANISATEUR_EVENEMENT", "PRESIDENT", "SECRETAIRE", "admin", "organisateur_evenement", "president", "secretaire"); } /** * Vérifie si l'utilisateur actuel peut gérer les organisations * * @return true si l'utilisateur peut gérer les organisations */ public boolean canManageOrganizations() { return hasAnyRole("ADMIN", "PRESIDENT", "admin", "president"); } /** Log les informations de sécurité pour debug */ public void logSecurityInfo() { if (LOG.isDebugEnabled()) { LOG.debugf("Informations de sécurité: %s", getUserInfoForLogging()); } } /** * Obtient le token d'accès brut * * @return le token JWT brut ou null si non disponible */ public String getRawAccessToken() { if (!isAuthenticated()) { return null; } try { if (jwt instanceof OidcJwtCallerPrincipal) { return ((OidcJwtCallerPrincipal) jwt).getRawToken(); } return jwt.getRawToken(); } catch (Exception e) { LOG.warnf("Erreur lors de la récupération du token brut: %s", e.getMessage()); return null; } } }