Refactoring - Version stable
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -73,4 +73,5 @@ public interface UserServiceClient {
|
|||||||
void sendVerificationEmail(
|
void sendVerificationEmail(
|
||||||
@PathParam("userId") String userId,
|
@PathParam("userId") String userId,
|
||||||
@QueryParam("realm") String realmName);
|
@QueryParam("realm") String realmName);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package dev.lions.unionflow.server.service;
|
package dev.lions.unionflow.server.service;
|
||||||
|
|
||||||
|
import dev.lions.unionflow.server.client.RoleServiceClient;
|
||||||
import dev.lions.unionflow.server.client.UserServiceClient;
|
import dev.lions.unionflow.server.client.UserServiceClient;
|
||||||
import dev.lions.unionflow.server.entity.Membre;
|
import dev.lions.unionflow.server.entity.Membre;
|
||||||
import dev.lions.unionflow.server.repository.MembreRepository;
|
import dev.lions.unionflow.server.repository.MembreRepository;
|
||||||
@@ -53,6 +54,10 @@ public class MembreKeycloakSyncService {
|
|||||||
@RestClient
|
@RestClient
|
||||||
UserServiceClient userServiceClient;
|
UserServiceClient userServiceClient;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
@RestClient
|
||||||
|
RoleServiceClient roleServiceClient;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Provisionne un compte Keycloak pour un Membre existant qui n'en a pas encore.
|
* Provisionne un compte Keycloak pour un Membre existant qui n'en a pas encore.
|
||||||
*
|
*
|
||||||
@@ -178,15 +183,12 @@ public class MembreKeycloakSyncService {
|
|||||||
userServiceClient.updateUser(keycloakUserId, user, DEFAULT_REALM);
|
userServiceClient.updateUser(keycloakUserId, user, DEFAULT_REALM);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ajouter le rôle MEMBRE_ACTIF s'il n'est pas déjà présent
|
// Assigner MEMBRE_ACTIF via l'endpoint dédié
|
||||||
List<String> roles = user.getRealmRoles() != null
|
roleServiceClient.assignRealmRoles(
|
||||||
? new java.util.ArrayList<>(user.getRealmRoles())
|
keycloakUserId,
|
||||||
: new java.util.ArrayList<>();
|
DEFAULT_REALM,
|
||||||
if (!roles.contains("MEMBRE_ACTIF")) {
|
new RoleServiceClient.RoleNamesRequest(List.of("MEMBRE_ACTIF"))
|
||||||
roles.add("MEMBRE_ACTIF");
|
);
|
||||||
user.setRealmRoles(roles);
|
|
||||||
userServiceClient.updateUser(keycloakUserId, user, DEFAULT_REALM);
|
|
||||||
}
|
|
||||||
|
|
||||||
LOGGER.info("✅ Rôle MEMBRE_ACTIF assigné dans Keycloak pour " + membre.getNomComplet());
|
LOGGER.info("✅ Rôle MEMBRE_ACTIF assigné dans Keycloak pour " + membre.getNomComplet());
|
||||||
|
|
||||||
@@ -230,19 +232,26 @@ public class MembreKeycloakSyncService {
|
|||||||
// S'assurer que le compte est activé
|
// S'assurer que le compte est activé
|
||||||
if (Boolean.FALSE.equals(user.getEnabled())) {
|
if (Boolean.FALSE.equals(user.getEnabled())) {
|
||||||
user.setEnabled(true);
|
user.setEnabled(true);
|
||||||
|
userServiceClient.updateUser(keycloakUserId, user, DEFAULT_REALM);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Construire la liste de rôles : ajouter ADMIN_ORGANISATION, retirer MEMBRE et MEMBRE_ACTIF
|
// Révoquer MEMBRE et MEMBRE_ACTIF (non bloquant — peuvent ne pas exister)
|
||||||
List<String> roles = user.getRealmRoles() != null
|
try {
|
||||||
? new java.util.ArrayList<>(user.getRealmRoles())
|
roleServiceClient.revokeRealmRoles(
|
||||||
: new java.util.ArrayList<>();
|
keycloakUserId,
|
||||||
roles.remove("MEMBRE");
|
DEFAULT_REALM,
|
||||||
roles.remove("MEMBRE_ACTIF");
|
new RoleServiceClient.RoleNamesRequest(List.of("MEMBRE", "MEMBRE_ACTIF"))
|
||||||
if (!roles.contains("ADMIN_ORGANISATION")) {
|
);
|
||||||
roles.add("ADMIN_ORGANISATION");
|
} catch (Exception e) {
|
||||||
|
LOGGER.warning("⚠️ Révocation MEMBRE/MEMBRE_ACTIF non bloquante: " + e.getMessage());
|
||||||
}
|
}
|
||||||
user.setRealmRoles(roles);
|
|
||||||
userServiceClient.updateUser(keycloakUserId, user, DEFAULT_REALM);
|
// Assigner ADMIN_ORGANISATION via l'endpoint dédié
|
||||||
|
roleServiceClient.assignRealmRoles(
|
||||||
|
keycloakUserId,
|
||||||
|
DEFAULT_REALM,
|
||||||
|
new RoleServiceClient.RoleNamesRequest(List.of("ADMIN_ORGANISATION"))
|
||||||
|
);
|
||||||
|
|
||||||
LOGGER.info("✅ Rôle ADMIN_ORGANISATION assigné dans Keycloak pour " + membre.getNomComplet());
|
LOGGER.info("✅ Rôle ADMIN_ORGANISATION assigné dans Keycloak pour " + membre.getNomComplet());
|
||||||
|
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import static org.mockito.ArgumentMatchers.any;
|
|||||||
import static org.mockito.ArgumentMatchers.anyString;
|
import static org.mockito.ArgumentMatchers.anyString;
|
||||||
import static org.mockito.Mockito.*;
|
import static org.mockito.Mockito.*;
|
||||||
|
|
||||||
|
import dev.lions.unionflow.server.client.RoleServiceClient;
|
||||||
import dev.lions.unionflow.server.client.UserServiceClient;
|
import dev.lions.unionflow.server.client.UserServiceClient;
|
||||||
import dev.lions.unionflow.server.entity.Membre;
|
import dev.lions.unionflow.server.entity.Membre;
|
||||||
import dev.lions.unionflow.server.repository.MembreRepository;
|
import dev.lions.unionflow.server.repository.MembreRepository;
|
||||||
@@ -36,6 +37,10 @@ class MembreKeycloakSyncServiceTest {
|
|||||||
@RestClient
|
@RestClient
|
||||||
UserServiceClient userServiceClient;
|
UserServiceClient userServiceClient;
|
||||||
|
|
||||||
|
@InjectMock
|
||||||
|
@RestClient
|
||||||
|
RoleServiceClient roleServiceClient;
|
||||||
|
|
||||||
// =========================================================================
|
// =========================================================================
|
||||||
// provisionKeycloakUser
|
// provisionKeycloakUser
|
||||||
// =========================================================================
|
// =========================================================================
|
||||||
@@ -232,8 +237,8 @@ class MembreKeycloakSyncServiceTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@DisplayName("promouvoirAdminOrganisation assigne ADMIN_ORGANISATION et retire MEMBRE/MEMBRE_ACTIF")
|
@DisplayName("promouvoirAdminOrganisation assigne ADMIN_ORGANISATION et révoque MEMBRE/MEMBRE_ACTIF")
|
||||||
void promouvoirAdminOrganisation_assignsAdminRoleAndRemovesMemberRoles() {
|
void promouvoirAdminOrganisation_assignsAdminRoleAndRevokesMemberRoles() {
|
||||||
UUID membreId = UUID.randomUUID();
|
UUID membreId = UUID.randomUUID();
|
||||||
UUID keycloakId = UUID.randomUUID();
|
UUID keycloakId = UUID.randomUUID();
|
||||||
|
|
||||||
@@ -249,16 +254,15 @@ class MembreKeycloakSyncServiceTest {
|
|||||||
UserDTO user = new UserDTO();
|
UserDTO user = new UserDTO();
|
||||||
user.setId(keycloakId.toString());
|
user.setId(keycloakId.toString());
|
||||||
user.setEnabled(true);
|
user.setEnabled(true);
|
||||||
user.setRealmRoles(new java.util.ArrayList<>(java.util.List.of("MEMBRE", "MEMBRE_ACTIF")));
|
|
||||||
user.setRealmName("unionflow");
|
user.setRealmName("unionflow");
|
||||||
when(userServiceClient.getUserById(eq(keycloakId.toString()), eq("unionflow"))).thenReturn(user);
|
when(userServiceClient.getUserById(eq(keycloakId.toString()), eq("unionflow"))).thenReturn(user);
|
||||||
when(userServiceClient.updateUser(anyString(), any(UserDTO.class), anyString())).thenReturn(user);
|
doNothing().when(roleServiceClient).revokeRealmRoles(anyString(), anyString(), any(RoleServiceClient.RoleNamesRequest.class));
|
||||||
|
doNothing().when(roleServiceClient).assignRealmRoles(anyString(), anyString(), any(RoleServiceClient.RoleNamesRequest.class));
|
||||||
|
|
||||||
syncService.promouvoirAdminOrganisationDansKeycloak(membreId);
|
syncService.promouvoirAdminOrganisationDansKeycloak(membreId);
|
||||||
|
|
||||||
verify(userServiceClient).updateUser(eq(keycloakId.toString()), any(UserDTO.class), eq("unionflow"));
|
verify(roleServiceClient).revokeRealmRoles(eq(keycloakId.toString()), eq("unionflow"), any(RoleServiceClient.RoleNamesRequest.class));
|
||||||
assertThat(user.getRealmRoles()).contains("ADMIN_ORGANISATION");
|
verify(roleServiceClient).assignRealmRoles(eq(keycloakId.toString()), eq("unionflow"), any(RoleServiceClient.RoleNamesRequest.class));
|
||||||
assertThat(user.getRealmRoles()).doesNotContain("MEMBRE", "MEMBRE_ACTIF");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -278,11 +282,12 @@ class MembreKeycloakSyncServiceTest {
|
|||||||
|
|
||||||
UserDTO user = new UserDTO();
|
UserDTO user = new UserDTO();
|
||||||
user.setId(keycloakId.toString());
|
user.setId(keycloakId.toString());
|
||||||
user.setEnabled(false); // désactivé
|
user.setEnabled(false);
|
||||||
user.setRealmRoles(new java.util.ArrayList<>());
|
|
||||||
user.setRealmName("unionflow");
|
user.setRealmName("unionflow");
|
||||||
when(userServiceClient.getUserById(anyString(), anyString())).thenReturn(user);
|
when(userServiceClient.getUserById(anyString(), anyString())).thenReturn(user);
|
||||||
when(userServiceClient.updateUser(anyString(), any(UserDTO.class), anyString())).thenReturn(user);
|
when(userServiceClient.updateUser(anyString(), any(UserDTO.class), anyString())).thenReturn(user);
|
||||||
|
doNothing().when(roleServiceClient).revokeRealmRoles(anyString(), anyString(), any(RoleServiceClient.RoleNamesRequest.class));
|
||||||
|
doNothing().when(roleServiceClient).assignRealmRoles(anyString(), anyString(), any(RoleServiceClient.RoleNamesRequest.class));
|
||||||
|
|
||||||
syncService.promouvoirAdminOrganisationDansKeycloak(membreId);
|
syncService.promouvoirAdminOrganisationDansKeycloak(membreId);
|
||||||
|
|
||||||
@@ -330,11 +335,13 @@ class MembreKeycloakSyncServiceTest {
|
|||||||
fetchedUser.setRealmName("unionflow");
|
fetchedUser.setRealmName("unionflow");
|
||||||
when(userServiceClient.getUserById(eq(newKeycloakId.toString()), anyString())).thenReturn(fetchedUser);
|
when(userServiceClient.getUserById(eq(newKeycloakId.toString()), anyString())).thenReturn(fetchedUser);
|
||||||
when(userServiceClient.updateUser(anyString(), any(UserDTO.class), anyString())).thenReturn(fetchedUser);
|
when(userServiceClient.updateUser(anyString(), any(UserDTO.class), anyString())).thenReturn(fetchedUser);
|
||||||
|
doNothing().when(roleServiceClient).revokeRealmRoles(anyString(), anyString(), any(RoleServiceClient.RoleNamesRequest.class));
|
||||||
|
doNothing().when(roleServiceClient).assignRealmRoles(anyString(), anyString(), any(RoleServiceClient.RoleNamesRequest.class));
|
||||||
|
|
||||||
syncService.promouvoirAdminOrganisationDansKeycloak(membreId);
|
syncService.promouvoirAdminOrganisationDansKeycloak(membreId);
|
||||||
|
|
||||||
verify(userServiceClient).createUser(any(UserDTO.class), eq("unionflow"));
|
verify(userServiceClient).createUser(any(UserDTO.class), eq("unionflow"));
|
||||||
verify(userServiceClient).updateUser(eq(newKeycloakId.toString()), any(UserDTO.class), eq("unionflow"));
|
verify(roleServiceClient).assignRealmRoles(eq(newKeycloakId.toString()), eq("unionflow"), any(RoleServiceClient.RoleNamesRequest.class));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -359,6 +366,78 @@ class MembreKeycloakSyncServiceTest {
|
|||||||
.hasMessageContaining("Impossible de promouvoir le compte Keycloak");
|
.hasMessageContaining("Impossible de promouvoir le compte Keycloak");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// =========================================================================
|
||||||
|
// activerMembreDansKeycloak
|
||||||
|
// =========================================================================
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("activerMembreDansKeycloak échoue si le membre n'existe pas")
|
||||||
|
void activerMembreDansKeycloak_failsIfMembreNotFound() {
|
||||||
|
UUID membreId = UUID.randomUUID();
|
||||||
|
when(membreRepository.findByIdOptional(membreId)).thenReturn(Optional.empty());
|
||||||
|
|
||||||
|
assertThatThrownBy(() -> syncService.activerMembreDansKeycloak(membreId))
|
||||||
|
.isInstanceOf(NotFoundException.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("activerMembreDansKeycloak assigne MEMBRE_ACTIF via roleServiceClient")
|
||||||
|
void activerMembreDansKeycloak_assignsMemberActifRole() {
|
||||||
|
UUID membreId = UUID.randomUUID();
|
||||||
|
UUID keycloakId = UUID.randomUUID();
|
||||||
|
|
||||||
|
Membre membre = new Membre();
|
||||||
|
membre.setId(membreId);
|
||||||
|
membre.setKeycloakId(keycloakId);
|
||||||
|
membre.setEmail("membre@unionflow.dev");
|
||||||
|
membre.setNom("Membre");
|
||||||
|
membre.setPrenom("Test");
|
||||||
|
|
||||||
|
when(membreRepository.findByIdOptional(membreId)).thenReturn(Optional.of(membre));
|
||||||
|
|
||||||
|
UserDTO user = new UserDTO();
|
||||||
|
user.setId(keycloakId.toString());
|
||||||
|
user.setEnabled(true);
|
||||||
|
user.setRealmName("unionflow");
|
||||||
|
when(userServiceClient.getUserById(eq(keycloakId.toString()), eq("unionflow"))).thenReturn(user);
|
||||||
|
doNothing().when(roleServiceClient).assignRealmRoles(anyString(), anyString(), any(RoleServiceClient.RoleNamesRequest.class));
|
||||||
|
|
||||||
|
syncService.activerMembreDansKeycloak(membreId);
|
||||||
|
|
||||||
|
verify(roleServiceClient).assignRealmRoles(
|
||||||
|
eq(keycloakId.toString()), eq("unionflow"), any(RoleServiceClient.RoleNamesRequest.class));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("activerMembreDansKeycloak active le compte s'il est désactivé")
|
||||||
|
void activerMembreDansKeycloak_enablesDisabledAccount() {
|
||||||
|
UUID membreId = UUID.randomUUID();
|
||||||
|
UUID keycloakId = UUID.randomUUID();
|
||||||
|
|
||||||
|
Membre membre = new Membre();
|
||||||
|
membre.setId(membreId);
|
||||||
|
membre.setKeycloakId(keycloakId);
|
||||||
|
membre.setEmail("disabled@unionflow.dev");
|
||||||
|
membre.setNom("Disabled");
|
||||||
|
membre.setPrenom("Membre");
|
||||||
|
|
||||||
|
when(membreRepository.findByIdOptional(membreId)).thenReturn(Optional.of(membre));
|
||||||
|
|
||||||
|
UserDTO user = new UserDTO();
|
||||||
|
user.setId(keycloakId.toString());
|
||||||
|
user.setEnabled(false);
|
||||||
|
user.setRealmName("unionflow");
|
||||||
|
when(userServiceClient.getUserById(anyString(), anyString())).thenReturn(user);
|
||||||
|
when(userServiceClient.updateUser(anyString(), any(UserDTO.class), anyString())).thenReturn(user);
|
||||||
|
doNothing().when(roleServiceClient).assignRealmRoles(anyString(), anyString(), any(RoleServiceClient.RoleNamesRequest.class));
|
||||||
|
|
||||||
|
syncService.activerMembreDansKeycloak(membreId);
|
||||||
|
|
||||||
|
assertThat(user.getEnabled()).isTrue();
|
||||||
|
verify(userServiceClient).updateUser(anyString(), any(UserDTO.class), anyString());
|
||||||
|
verify(roleServiceClient).assignRealmRoles(anyString(), anyString(), any(RoleServiceClient.RoleNamesRequest.class));
|
||||||
|
}
|
||||||
|
|
||||||
// =========================================================================
|
// =========================================================================
|
||||||
// syncMembreToKeycloak
|
// syncMembreToKeycloak
|
||||||
// =========================================================================
|
// =========================================================================
|
||||||
|
|||||||
Reference in New Issue
Block a user