Files
unionflow-server-impl-quarkus/src/test/java/dev/lions/unionflow/server/service/KeycloakServiceTest.java
dahoud c74ae25ad6 fix(tests): rôles @TestSecurity en majuscules + NPE Map.of() dans MembreResource
14 fichiers de tests : rôles passés en majuscules dans @TestSecurity(roles={...})
pour correspondre exactement aux valeurs @RolesAllowed du backend.
Mapping : "admin"→"ADMIN", "admin_organisation"→"ADMIN_ORGANISATION",
"membre_actif"→"MEMBRE", "tontine_resp"→"TONTINE_RESP", etc.
Un rôle en minuscules produit un 403 silencieux sans erreur Quarkus.

MembreResource : activerAdhesion/suspendrAdhesion/radierAdhesion/archiverAdhesion
remplacent Map.of() par HashMap pour accepter dateChangementStatut null
(Map.of() lève NullPointerException sur valeur null → HTTP 500).
2026-04-06 16:50:03 +00:00

610 lines
25 KiB
Java

package dev.lions.unionflow.server.service;
import static org.assertj.core.api.Assertions.assertThat;
import io.quarkus.test.junit.QuarkusTest;
import io.quarkus.test.security.TestSecurity;
import jakarta.inject.Inject;
import java.util.Set;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;
/**
* Tests du service KeycloakService — couvre les branches authentifiées et non authentifiées.
*/
@QuarkusTest
class KeycloakServiceTest {
@Inject
KeycloakService keycloakService;
// ================================================================
// NON AUTHENTIFIÉ
// ================================================================
@Nested
@DisplayName("Sans contexte d'authentification")
class SansContexte {
@Test
@DisplayName("isAuthenticated retourne false")
void isAuthenticated_returnsFalse() {
assertThat(keycloakService.isAuthenticated()).isFalse();
}
@Test
@DisplayName("getCurrentUserId retourne null")
void getCurrentUserId_returnsNull() {
assertThat(keycloakService.getCurrentUserId()).isNull();
}
@Test
@DisplayName("getCurrentUserEmail retourne null")
void getCurrentUserEmail_returnsNull() {
assertThat(keycloakService.getCurrentUserEmail()).isNull();
}
@Test
@DisplayName("getCurrentUserFullName retourne null")
void getCurrentUserFullName_returnsNull() {
assertThat(keycloakService.getCurrentUserFullName()).isNull();
}
@Test
@DisplayName("getCurrentUserRoles retourne set vide")
void getCurrentUserRoles_returnsEmpty() {
assertThat(keycloakService.getCurrentUserRoles()).isEmpty();
}
@Test
@DisplayName("hasRole retourne false")
void hasRole_returnsFalse() {
assertThat(keycloakService.hasRole("ADMIN")).isFalse();
}
@Test
@DisplayName("hasAnyRole retourne false")
void hasAnyRole_returnsFalse() {
assertThat(keycloakService.hasAnyRole("ADMIN", "TRESORIER")).isFalse();
}
@Test
@DisplayName("hasAllRoles retourne false")
void hasAllRoles_returnsFalse() {
assertThat(keycloakService.hasAllRoles("ADMIN", "TRESORIER")).isFalse();
}
@Test
@DisplayName("getClaim retourne null")
void getClaim_returnsNull() {
assertThat((Object) keycloakService.getClaim("email")).isNull();
}
@Test
@DisplayName("getAllClaimNames retourne set vide")
void getAllClaimNames_returnsEmpty() {
assertThat(keycloakService.getAllClaimNames()).isEmpty();
}
@Test
@DisplayName("getUserInfoForLogging retourne message non authentifié")
void getUserInfoForLogging_returnsNonAuthentifieMessage() {
assertThat(keycloakService.getUserInfoForLogging()).contains("non authentifié");
}
@Test
@DisplayName("isAdmin retourne false")
void isAdmin_returnsFalse() {
assertThat(keycloakService.isAdmin()).isFalse();
}
@Test
@DisplayName("canManageMembers retourne false")
void canManageMembers_returnsFalse() {
assertThat(keycloakService.canManageMembers()).isFalse();
}
@Test
@DisplayName("canManageFinances retourne false")
void canManageFinances_returnsFalse() {
assertThat(keycloakService.canManageFinances()).isFalse();
}
@Test
@DisplayName("canManageEvents retourne false")
void canManageEvents_returnsFalse() {
assertThat(keycloakService.canManageEvents()).isFalse();
}
@Test
@DisplayName("canManageOrganizations retourne false")
void canManageOrganizations_returnsFalse() {
assertThat(keycloakService.canManageOrganizations()).isFalse();
}
@Test
@DisplayName("getRawAccessToken retourne null")
void getRawAccessToken_returnsNull() {
assertThat(keycloakService.getRawAccessToken()).isNull();
}
@Test
@DisplayName("logSecurityInfo ne lève pas d'exception")
void logSecurityInfo_noException() {
keycloakService.logSecurityInfo();
// pas d'exception attendue
}
}
// ================================================================
// AUTHENTIFIÉ — UTILISATEUR SIMPLE
// ================================================================
@Nested
@DisplayName("Avec utilisateur authentifié simple")
class AvecUtilisateurSimple {
@Test
@TestSecurity(user = "alice@test.com", roles = {"MEMBRE"})
@DisplayName("isAuthenticated retourne true")
void isAuthenticated_returnsTrue() {
assertThat(keycloakService.isAuthenticated()).isTrue();
}
@Test
@TestSecurity(user = "alice@test.com", roles = {"MEMBRE"})
@DisplayName("getCurrentUserId retourne une valeur non null")
void getCurrentUserId_returnsValue() {
// Le sujet JWT peut être null en test sans JWT réel, mais isAuthenticated=true
// et la méthode ne doit pas lever d'exception
String userId = keycloakService.getCurrentUserId();
// Pas d'exception — valeur peut être null selon le contexte test
// (le try/catch dans la méthode gère le cas d'erreur)
assertThat(keycloakService.isAuthenticated()).isTrue();
}
@Test
@TestSecurity(user = "alice@test.com", roles = {"MEMBRE"})
@DisplayName("getCurrentUserEmail ne lève pas d'exception")
void getCurrentUserEmail_noException() {
// Le fallback sur securityIdentity.getPrincipal().getName() est couvert
String email = keycloakService.getCurrentUserEmail();
// Peut retourner le principal name comme fallback
assertThat(keycloakService.isAuthenticated()).isTrue();
}
@Test
@TestSecurity(user = "alice@test.com", roles = {"MEMBRE"})
@DisplayName("getCurrentUserFullName ne lève pas d'exception")
void getCurrentUserFullName_noException() {
String fullName = keycloakService.getCurrentUserFullName();
// Peut être null si les claims given_name/family_name/preferred_username ne sont pas présents
assertThat(keycloakService.isAuthenticated()).isTrue();
}
@Test
@TestSecurity(user = "alice@test.com", roles = {"MEMBRE"})
@DisplayName("getCurrentUserRoles retourne les rôles assignés")
void getCurrentUserRoles_returnsRoles() {
Set<String> roles = keycloakService.getCurrentUserRoles();
assertThat(roles).contains("MEMBRE");
}
@Test
@TestSecurity(user = "alice@test.com", roles = {"MEMBRE"})
@DisplayName("hasRole('MEMBRE') retourne true")
void hasRole_membreRole_returnsTrue() {
assertThat(keycloakService.hasRole("MEMBRE")).isTrue();
}
@Test
@TestSecurity(user = "alice@test.com", roles = {"MEMBRE"})
@DisplayName("hasRole('ADMIN') retourne false quand l'utilisateur n'a pas ce rôle")
void hasRole_adminRole_returnsFalse() {
assertThat(keycloakService.hasRole("ADMIN")).isFalse();
}
@Test
@TestSecurity(user = "alice@test.com", roles = {"MEMBRE"})
@DisplayName("hasAnyRole avec rôle correspondant retourne true")
void hasAnyRole_avecRoleCorrespondant_returnsTrue() {
assertThat(keycloakService.hasAnyRole("ADMIN", "MEMBRE", "TRESORIER")).isTrue();
}
@Test
@TestSecurity(user = "alice@test.com", roles = {"MEMBRE"})
@DisplayName("hasAnyRole sans rôle correspondant retourne false")
void hasAnyRole_sansRoleCorrespondant_returnsFalse() {
assertThat(keycloakService.hasAnyRole("ADMIN", "TRESORIER", "PRESIDENT")).isFalse();
}
@Test
@TestSecurity(user = "alice@test.com", roles = {"MEMBRE"})
@DisplayName("hasAllRoles avec tous les rôles présents retourne true")
void hasAllRoles_tousRolesPresents_returnsTrue() {
assertThat(keycloakService.hasAllRoles("MEMBRE")).isTrue();
}
@Test
@TestSecurity(user = "alice@test.com", roles = {"MEMBRE"})
@DisplayName("hasAllRoles avec un rôle manquant retourne false")
void hasAllRoles_roleManquant_returnsFalse() {
assertThat(keycloakService.hasAllRoles("MEMBRE", "ADMIN")).isFalse();
}
@Test
@TestSecurity(user = "alice@test.com", roles = {"MEMBRE"})
@DisplayName("getAllClaimNames ne lève pas d'exception")
void getAllClaimNames_noException() {
Set<String> claimNames = keycloakService.getAllClaimNames();
assertThat(claimNames).isNotNull();
}
@Test
@TestSecurity(user = "alice@test.com", roles = {"MEMBRE"})
@DisplayName("getUserInfoForLogging retourne une chaîne formatée")
void getUserInfoForLogging_returnsFormattedString() {
String info = keycloakService.getUserInfoForLogging();
assertThat(info).isNotNull();
assertThat(info).contains("Utilisateur:");
}
@Test
@TestSecurity(user = "alice@test.com", roles = {"MEMBRE"})
@DisplayName("getRawAccessToken ne lève pas d'exception")
void getRawAccessToken_noException() {
String token = keycloakService.getRawAccessToken();
// peut être null si jwt n'est pas un OidcJwtCallerPrincipal en mode test
assertThat(keycloakService.isAuthenticated()).isTrue();
}
@Test
@TestSecurity(user = "alice@test.com", roles = {"MEMBRE"})
@DisplayName("getClaim ne lève pas d'exception")
void getClaim_noException() {
Object claim = keycloakService.getClaim("sub");
assertThat(keycloakService.isAuthenticated()).isTrue();
}
@Test
@TestSecurity(user = "alice@test.com", roles = {"MEMBRE"})
@DisplayName("isAdmin retourne false pour un simple membre")
void isAdmin_membreRole_returnsFalse() {
assertThat(keycloakService.isAdmin()).isFalse();
}
@Test
@TestSecurity(user = "alice@test.com", roles = {"MEMBRE"})
@DisplayName("canManageMembers retourne false pour un simple membre")
void canManageMembers_membreRole_returnsFalse() {
assertThat(keycloakService.canManageMembers()).isFalse();
}
@Test
@TestSecurity(user = "alice@test.com", roles = {"MEMBRE"})
@DisplayName("canManageFinances retourne false pour un simple membre")
void canManageFinances_membreRole_returnsFalse() {
assertThat(keycloakService.canManageFinances()).isFalse();
}
@Test
@TestSecurity(user = "alice@test.com", roles = {"MEMBRE"})
@DisplayName("canManageEvents retourne false pour un simple membre")
void canManageEvents_membreRole_returnsFalse() {
assertThat(keycloakService.canManageEvents()).isFalse();
}
@Test
@TestSecurity(user = "alice@test.com", roles = {"MEMBRE"})
@DisplayName("canManageOrganizations retourne false pour un simple membre")
void canManageOrganizations_membreRole_returnsFalse() {
assertThat(keycloakService.canManageOrganizations()).isFalse();
}
}
// ================================================================
// AUTHENTIFIÉ — ADMIN
// ================================================================
@Nested
@DisplayName("Avec utilisateur ADMIN")
class AvecAdmin {
@Test
@TestSecurity(user = "admin@test.com", roles = {"ADMIN"})
@DisplayName("isAdmin avec rôle ADMIN retourne true")
void isAdmin_adminRole_returnsTrue() {
assertThat(keycloakService.isAdmin()).isTrue();
}
@Test
@TestSecurity(user = "admin@test.com", roles = {"ADMIN"})
@DisplayName("isAdmin avec rôle admin (minuscule) retourne true")
void isAdmin_adminLowercase_returnsTrue() {
assertThat(keycloakService.isAdmin()).isTrue();
}
@Test
@TestSecurity(user = "admin@test.com", roles = {"ADMIN"})
@DisplayName("canManageMembers avec rôle ADMIN retourne true")
void canManageMembers_adminRole_returnsTrue() {
assertThat(keycloakService.canManageMembers()).isTrue();
}
@Test
@TestSecurity(user = "admin@test.com", roles = {"ADMIN"})
@DisplayName("canManageFinances avec rôle ADMIN retourne true")
void canManageFinances_adminRole_returnsTrue() {
assertThat(keycloakService.canManageFinances()).isTrue();
}
@Test
@TestSecurity(user = "admin@test.com", roles = {"ADMIN"})
@DisplayName("canManageEvents avec rôle ADMIN retourne true")
void canManageEvents_adminRole_returnsTrue() {
assertThat(keycloakService.canManageEvents()).isTrue();
}
@Test
@TestSecurity(user = "admin@test.com", roles = {"ADMIN"})
@DisplayName("canManageOrganizations avec rôle ADMIN retourne true")
void canManageOrganizations_adminRole_returnsTrue() {
assertThat(keycloakService.canManageOrganizations()).isTrue();
}
@Test
@TestSecurity(user = "admin@test.com", roles = {"ADMIN"})
@DisplayName("hasAllRoles avec un seul rôle correct retourne true")
void hasAllRoles_singleRoleAdmin_returnsTrue() {
assertThat(keycloakService.hasAllRoles("ADMIN")).isTrue();
}
@Test
@TestSecurity(user = "admin@test.com", roles = {"ADMIN"})
@DisplayName("hasAnyRole avec ADMIN en premier retourne true immédiatement")
void hasAnyRole_adminFirst_returnsTrue() {
assertThat(keycloakService.hasAnyRole("ADMIN", "TRESORIER")).isTrue();
}
@Test
@TestSecurity(user = "admin@test.com", roles = {"ADMIN"})
@DisplayName("hasAnyRole avec ADMIN en dernier retourne true après itération complète")
void hasAnyRole_adminLast_returnsTrue() {
assertThat(keycloakService.hasAnyRole("TRESORIER", "GESTIONNAIRE_MEMBRE", "ADMIN")).isTrue();
}
}
// ================================================================
// AUTHENTIFIÉ — logSecurityInfo en mode debug
// ================================================================
@Nested
@DisplayName("logSecurityInfo")
class LogSecurityInfo {
@Test
@TestSecurity(user = "admin@test.com", roles = {"ADMIN"})
@DisplayName("logSecurityInfo ne lève pas d'exception quand authentifié")
void logSecurityInfo_authenticated_noException() {
keycloakService.logSecurityInfo();
// pas d'exception attendue — le debug peut être désactivé, ce qui est normal
}
@Test
@TestSecurity(user = "alice@test.com", roles = {"MEMBRE"})
@DisplayName("getUserInfoForLogging retourne les rôles de l'utilisateur authentifié")
void getUserInfoForLogging_authenticated_containsRoles() {
String info = keycloakService.getUserInfoForLogging();
assertThat(info).isNotNull();
assertThat(info).contains("Rôles:");
}
@Test
@TestSecurity(user = "alice@test.com", roles = {"MEMBRE"})
@DisplayName("getClaim avec claim existante retourne une valeur ou null sans exception")
void getClaim_existingClaim_noException() {
// En contexte test la JWT n'est pas une vraie OIDC JWT — pas de crash attendu
Object claim = keycloakService.getClaim("preferred_username");
// Le résultat peut être null ou une valeur selon le contexte test
assertThat(keycloakService.isAuthenticated()).isTrue();
}
@Test
@TestSecurity(user = "admin@test.com", roles = {"ADMIN", "TRESORIER"})
@DisplayName("hasAllRoles avec plusieurs rôles correspondants retourne true")
void hasAllRoles_multipleRolesPresent_returnsTrue() {
assertThat(keycloakService.hasAllRoles("ADMIN", "TRESORIER")).isTrue();
}
@Test
@TestSecurity(user = "admin@test.com", roles = {"ADMIN", "TRESORIER"})
@DisplayName("hasAnyRole avec plusieurs rôles dont l'un correspond retourne true")
void hasAnyRole_multipleRolesOneMatches_returnsTrue() {
assertThat(keycloakService.hasAnyRole("MEMBRE", "TRESORIER", "SECRETAIRE")).isTrue();
}
}
// ================================================================
// AUTHENTIFIÉ — RÔLES SPÉCIALISÉS
// ================================================================
@Nested
@DisplayName("Avec rôles spécialisés")
class AvecRolesSpecialises {
@Test
@TestSecurity(user = "gestionnaire@test.com", roles = {"GESTIONNAIRE_MEMBRE"})
@DisplayName("canManageMembers avec rôle GESTIONNAIRE_MEMBRE retourne true")
void canManageMembers_gestionnaireMembreRole_returnsTrue() {
assertThat(keycloakService.canManageMembers()).isTrue();
}
@Test
@TestSecurity(user = "tresorier@test.com", roles = {"TRESORIER"})
@DisplayName("canManageFinances avec rôle TRESORIER retourne true")
void canManageFinances_tresorierRole_returnsTrue() {
assertThat(keycloakService.canManageFinances()).isTrue();
}
@Test
@TestSecurity(user = "organisateur@test.com", roles = {"ORGANISATEUR_EVENEMENT"})
@DisplayName("canManageEvents avec rôle ORGANISATEUR_EVENEMENT retourne true")
void canManageEvents_organisateurRole_returnsTrue() {
assertThat(keycloakService.canManageEvents()).isTrue();
}
@Test
@TestSecurity(user = "president@test.com", roles = {"PRESIDENT"})
@DisplayName("canManageOrganizations avec rôle PRESIDENT retourne true")
void canManageOrganizations_presidentRole_returnsTrue() {
assertThat(keycloakService.canManageOrganizations()).isTrue();
}
@Test
@TestSecurity(user = "president@test.com", roles = {"PRESIDENT"})
@DisplayName("canManageMembers avec rôle PRESIDENT retourne true")
void canManageMembers_presidentRole_returnsTrue() {
assertThat(keycloakService.canManageMembers()).isTrue();
}
@Test
@TestSecurity(user = "president@test.com", roles = {"PRESIDENT"})
@DisplayName("canManageFinances avec rôle PRESIDENT retourne true")
void canManageFinances_presidentRole_returnsTrue() {
assertThat(keycloakService.canManageFinances()).isTrue();
}
@Test
@TestSecurity(user = "secretaire@test.com", roles = {"SECRETAIRE"})
@DisplayName("canManageMembers avec rôle SECRETAIRE retourne true")
void canManageMembers_secretaireRole_returnsTrue() {
assertThat(keycloakService.canManageMembers()).isTrue();
}
@Test
@TestSecurity(user = "secretaire@test.com", roles = {"SECRETAIRE"})
@DisplayName("canManageEvents avec rôle SECRETAIRE retourne true")
void canManageEvents_secretaireRole_returnsTrue() {
assertThat(keycloakService.canManageEvents()).isTrue();
}
@Test
@TestSecurity(user = "tresorier@test.com", roles = {"TRESORIER"})
@DisplayName("canManageFinances avec rôle tresorier (minuscule) retourne true")
void canManageFinances_tresorierLowercase_returnsTrue() {
assertThat(keycloakService.canManageFinances()).isTrue();
}
@Test
@TestSecurity(user = "gestionnaire@test.com", roles = {"GESTIONNAIRE_MEMBRE"})
@DisplayName("canManageMembers avec rôle gestionnaire_membre (minuscule) retourne true")
void canManageMembers_gestionnaireLowercase_returnsTrue() {
assertThat(keycloakService.canManageMembers()).isTrue();
}
@Test
@TestSecurity(user = "multi@test.com", roles = {"TRESORIER", "GESTIONNAIRE_MEMBRE"})
@DisplayName("hasAllRoles avec plusieurs rôles tous présents retourne true")
void hasAllRoles_multipleRolesAllPresent_returnsTrue() {
assertThat(keycloakService.hasAllRoles("TRESORIER", "GESTIONNAIRE_MEMBRE")).isTrue();
}
@Test
@TestSecurity(user = "multi@test.com", roles = {"TRESORIER", "GESTIONNAIRE_MEMBRE"})
@DisplayName("hasAllRoles avec un rôle absent retourne false")
void hasAllRoles_multipleRolesOneAbsent_returnsFalse() {
assertThat(keycloakService.hasAllRoles("TRESORIER", "GESTIONNAIRE_MEMBRE", "PRESIDENT")).isFalse();
}
@Test
@TestSecurity(user = "organisateur@test.com", roles = {"ORGANISATEUR_EVENEMENT"})
@DisplayName("canManageEvents avec rôle organisateur_evenement (minuscule) retourne true")
void canManageEvents_organisateurLowercase_returnsTrue() {
assertThat(keycloakService.canManageEvents()).isTrue();
}
@Test
@TestSecurity(user = "president@test.com", roles = {"PRESIDENT"})
@DisplayName("canManageOrganizations avec rôle president (minuscule) retourne true")
void canManageOrganizations_presidentLowercase_returnsTrue() {
assertThat(keycloakService.canManageOrganizations()).isTrue();
}
@Test
@TestSecurity(user = "secretaire@test.com", roles = {"SECRETAIRE"})
@DisplayName("canManageMembers avec rôle secretaire (minuscule) retourne true")
void canManageMembers_secretaireLowercase_returnsTrue() {
assertThat(keycloakService.canManageMembers()).isTrue();
}
@Test
@TestSecurity(user = "secretaire@test.com", roles = {"SECRETAIRE"})
@DisplayName("canManageEvents avec rôle secretaire (minuscule) retourne true")
void canManageEvents_secretaireLowercase_returnsTrue() {
assertThat(keycloakService.canManageEvents()).isTrue();
}
@Test
@TestSecurity(user = "president@test.com", roles = {"PRESIDENT"})
@DisplayName("canManageFinances avec rôle president (minuscule) retourne true")
void canManageFinances_presidentLowercase_returnsTrue() {
assertThat(keycloakService.canManageFinances()).isTrue();
}
@Test
@TestSecurity(user = "president@test.com", roles = {"PRESIDENT"})
@DisplayName("canManageMembers avec rôle president (minuscule) retourne true")
void canManageMembers_presidentLowercase_returnsTrue() {
assertThat(keycloakService.canManageMembers()).isTrue();
}
@Test
@TestSecurity(user = "admin@test.com", roles = {"ADMIN"})
@DisplayName("canManageMembers avec rôle admin (minuscule) retourne true")
void canManageMembers_adminLowercase_returnsTrue() {
assertThat(keycloakService.canManageMembers()).isTrue();
}
@Test
@TestSecurity(user = "admin@test.com", roles = {"ADMIN"})
@DisplayName("canManageFinances avec rôle admin (minuscule) retourne true")
void canManageFinances_adminLowercase_returnsTrue() {
assertThat(keycloakService.canManageFinances()).isTrue();
}
@Test
@TestSecurity(user = "admin@test.com", roles = {"ADMIN"})
@DisplayName("canManageEvents avec rôle admin (minuscule) retourne true")
void canManageEvents_adminLowercase_returnsTrue() {
assertThat(keycloakService.canManageEvents()).isTrue();
}
@Test
@TestSecurity(user = "admin@test.com", roles = {"ADMIN"})
@DisplayName("canManageOrganizations avec rôle admin (minuscule) retourne true")
void canManageOrganizations_adminLowercase_returnsTrue() {
assertThat(keycloakService.canManageOrganizations()).isTrue();
}
@Test
@TestSecurity(user = "alice@test.com", roles = {"MEMBRE"})
@DisplayName("getAllClaimNames avec authentification retourne set non-null")
void getAllClaimNames_authenticated_returnsNonNull() {
Set<String> claimNames = keycloakService.getAllClaimNames();
assertThat(claimNames).isNotNull();
}
@Test
@TestSecurity(user = "alice@test.com", roles = {"MEMBRE"})
@DisplayName("getRawAccessToken authentifié ne lève pas d'exception")
void getRawAccessToken_authenticated_noException() {
// En mode test, jwt.getRawToken() peut retourner null ou une valeur
// L'important est que la méthode ne lève pas d'exception
String token = keycloakService.getRawAccessToken();
assertThat(keycloakService.isAuthenticated()).isTrue();
}
}
}