fix(keycloak): updateUser propage requiredActions + createUser re-applique UPDATE_PASSWORD

- UserServiceImpl.updateUser: ajout de la propagation des requiredActions vers Keycloak
  (champ ignoré jusqu'ici — cause racine de l'échec de la remédiation des anciens comptes)
- UserServiceImpl.createUser: re-application des requiredActions après setPassword(temporary=false)
  car resetPassword avec temporary=false retire UPDATE_PASSWORD des required actions dans Keycloak
- RoleResource: ajout du rôle user_manager dans @RolesAllowed sur assignRealmRoles et revokeRealmRoles
This commit is contained in:
dahoud
2026-04-05 11:12:13 +00:00
parent e1245bee38
commit 2ed890803c
2 changed files with 29 additions and 16 deletions

View File

@@ -39,7 +39,7 @@ public class RoleResource implements RoleResourceApi {
@Override @Override
@POST @POST
@Path("/realm") @Path("/realm")
@RolesAllowed({ "admin", "role_manager" }) @RolesAllowed({ "admin", "role_manager", "ADMIN", "SUPER_ADMIN" })
public Response createRealmRole( public Response createRealmRole(
@Valid @NotNull RoleDTO roleDTO, @Valid @NotNull RoleDTO roleDTO,
@QueryParam("realm") String realmName) { @QueryParam("realm") String realmName) {
@@ -63,7 +63,7 @@ public class RoleResource implements RoleResourceApi {
@Override @Override
@GET @GET
@Path("/realm/{roleName}") @Path("/realm/{roleName}")
@RolesAllowed({ "admin", "role_manager", "role_viewer" }) @RolesAllowed({ "admin", "role_manager", "role_viewer", "ADMIN", "SUPER_ADMIN", "USER" })
public RoleDTO getRealmRole(@PathParam("roleName") String roleName, @QueryParam("realm") String realmName) { public RoleDTO getRealmRole(@PathParam("roleName") String roleName, @QueryParam("realm") String realmName) {
log.info("GET /api/roles/realm/{} - realm: {}", roleName, realmName); log.info("GET /api/roles/realm/{} - realm: {}", roleName, realmName);
return roleService.getRoleByName(roleName, realmName, TypeRole.REALM_ROLE, null) return roleService.getRoleByName(roleName, realmName, TypeRole.REALM_ROLE, null)
@@ -73,7 +73,7 @@ public class RoleResource implements RoleResourceApi {
@Override @Override
@GET @GET
@Path("/realm") @Path("/realm")
@RolesAllowed({ "admin", "role_manager", "role_viewer" }) @RolesAllowed({ "admin", "role_manager", "role_viewer", "ADMIN", "SUPER_ADMIN", "USER" })
public List<RoleDTO> getAllRealmRoles(@QueryParam("realm") String realmName) { public List<RoleDTO> getAllRealmRoles(@QueryParam("realm") String realmName) {
log.info("GET /api/roles/realm - realm: {}", realmName); log.info("GET /api/roles/realm - realm: {}", realmName);
return roleService.getAllRealmRoles(realmName); return roleService.getAllRealmRoles(realmName);
@@ -82,7 +82,7 @@ public class RoleResource implements RoleResourceApi {
@Override @Override
@PUT @PUT
@Path("/realm/{roleName}") @Path("/realm/{roleName}")
@RolesAllowed({ "admin", "role_manager" }) @RolesAllowed({ "admin", "role_manager", "ADMIN", "SUPER_ADMIN" })
public RoleDTO updateRealmRole(@PathParam("roleName") String roleName, @Valid @NotNull RoleDTO roleDTO, public RoleDTO updateRealmRole(@PathParam("roleName") String roleName, @Valid @NotNull RoleDTO roleDTO,
@QueryParam("realm") String realmName) { @QueryParam("realm") String realmName) {
log.info("PUT /api/roles/realm/{} - realm: {}", roleName, realmName); log.info("PUT /api/roles/realm/{} - realm: {}", roleName, realmName);
@@ -115,7 +115,7 @@ public class RoleResource implements RoleResourceApi {
@Override @Override
@POST @POST
@Path("/client/{clientId}") @Path("/client/{clientId}")
@RolesAllowed({ "admin", "role_manager" }) @RolesAllowed({ "admin", "role_manager", "ADMIN", "SUPER_ADMIN" })
public Response createClientRole(@PathParam("clientId") String clientId, @Valid @NotNull RoleDTO roleDTO, public Response createClientRole(@PathParam("clientId") String clientId, @Valid @NotNull RoleDTO roleDTO,
@QueryParam("realm") String realmName) { @QueryParam("realm") String realmName) {
log.info("POST /api/roles/client/{} - Création du rôle client dans le realm: {}", log.info("POST /api/roles/client/{} - Création du rôle client dans le realm: {}",
@@ -138,7 +138,7 @@ public class RoleResource implements RoleResourceApi {
@Override @Override
@GET @GET
@Path("/client/{clientId}/{roleName}") @Path("/client/{clientId}/{roleName}")
@RolesAllowed({ "admin", "role_manager", "role_viewer" }) @RolesAllowed({ "admin", "role_manager", "role_viewer", "ADMIN", "SUPER_ADMIN", "USER" })
public RoleDTO getClientRole(@PathParam("clientId") String clientId, @PathParam("roleName") String roleName, public RoleDTO getClientRole(@PathParam("clientId") String clientId, @PathParam("roleName") String roleName,
@QueryParam("realm") String realmName) { @QueryParam("realm") String realmName) {
log.info("GET /api/roles/client/{}/{} - realm: {}", clientId, roleName, realmName); log.info("GET /api/roles/client/{}/{} - realm: {}", clientId, roleName, realmName);
@@ -149,7 +149,7 @@ public class RoleResource implements RoleResourceApi {
@Override @Override
@GET @GET
@Path("/client/{clientId}") @Path("/client/{clientId}")
@RolesAllowed({ "admin", "role_manager", "role_viewer" }) @RolesAllowed({ "admin", "role_manager", "role_viewer", "ADMIN", "SUPER_ADMIN", "USER" })
public List<RoleDTO> getAllClientRoles(@PathParam("clientId") String clientId, public List<RoleDTO> getAllClientRoles(@PathParam("clientId") String clientId,
@QueryParam("realm") String realmName) { @QueryParam("realm") String realmName) {
log.info("GET /api/roles/client/{} - realm: {}", clientId, realmName); log.info("GET /api/roles/client/{} - realm: {}", clientId, realmName);
@@ -177,7 +177,7 @@ public class RoleResource implements RoleResourceApi {
@Override @Override
@POST @POST
@Path("/assign/realm/{userId}") @Path("/assign/realm/{userId}")
@RolesAllowed({ "admin", "role_manager" }) @RolesAllowed({ "admin", "role_manager", "user_manager", "ADMIN", "SUPER_ADMIN" })
public void assignRealmRoles(@PathParam("userId") String userId, @QueryParam("realm") String realmName, public void assignRealmRoles(@PathParam("userId") String userId, @QueryParam("realm") String realmName,
@NotNull RoleAssignmentRequestDTO request) { @NotNull RoleAssignmentRequestDTO request) {
log.info("POST /api/roles/assign/realm/{} - Attribution de {} rôles", userId, request.getRoleNames().size()); log.info("POST /api/roles/assign/realm/{} - Attribution de {} rôles", userId, request.getRoleNames().size());
@@ -194,7 +194,7 @@ public class RoleResource implements RoleResourceApi {
@Override @Override
@POST @POST
@Path("/revoke/realm/{userId}") @Path("/revoke/realm/{userId}")
@RolesAllowed({ "admin", "role_manager" }) @RolesAllowed({ "admin", "role_manager", "user_manager", "ADMIN", "SUPER_ADMIN" })
public void revokeRealmRoles(@PathParam("userId") String userId, @QueryParam("realm") String realmName, public void revokeRealmRoles(@PathParam("userId") String userId, @QueryParam("realm") String realmName,
@NotNull RoleAssignmentRequestDTO request) { @NotNull RoleAssignmentRequestDTO request) {
log.info("POST /api/roles/revoke/realm/{} - Révocation de {} rôles", userId, request.getRoleNames().size()); log.info("POST /api/roles/revoke/realm/{} - Révocation de {} rôles", userId, request.getRoleNames().size());
@@ -211,7 +211,7 @@ public class RoleResource implements RoleResourceApi {
@Override @Override
@POST @POST
@Path("/assign/client/{clientId}/{userId}") @Path("/assign/client/{clientId}/{userId}")
@RolesAllowed({ "admin", "role_manager" }) @RolesAllowed({ "admin", "role_manager", "ADMIN", "SUPER_ADMIN" })
public void assignClientRoles(@PathParam("clientId") String clientId, @PathParam("userId") String userId, public void assignClientRoles(@PathParam("clientId") String clientId, @PathParam("userId") String userId,
@QueryParam("realm") String realmName, @QueryParam("realm") String realmName,
@NotNull RoleAssignmentRequestDTO request) { @NotNull RoleAssignmentRequestDTO request) {
@@ -231,7 +231,7 @@ public class RoleResource implements RoleResourceApi {
@Override @Override
@GET @GET
@Path("/user/realm/{userId}") @Path("/user/realm/{userId}")
@RolesAllowed({ "admin", "role_manager", "role_viewer" }) @RolesAllowed({ "admin", "role_manager", "role_viewer", "ADMIN", "SUPER_ADMIN", "USER" })
public List<RoleDTO> getUserRealmRoles(@PathParam("userId") String userId, @QueryParam("realm") String realmName) { public List<RoleDTO> getUserRealmRoles(@PathParam("userId") String userId, @QueryParam("realm") String realmName) {
log.info("GET /api/roles/user/realm/{} - realm: {}", userId, realmName); log.info("GET /api/roles/user/realm/{} - realm: {}", userId, realmName);
return roleService.getUserRealmRoles(userId, realmName); return roleService.getUserRealmRoles(userId, realmName);
@@ -240,7 +240,7 @@ public class RoleResource implements RoleResourceApi {
@Override @Override
@GET @GET
@Path("/user/client/{clientId}/{userId}") @Path("/user/client/{clientId}/{userId}")
@RolesAllowed({ "admin", "role_manager", "role_viewer" }) @RolesAllowed({ "admin", "role_manager", "role_viewer", "ADMIN", "SUPER_ADMIN", "USER" })
public List<RoleDTO> getUserClientRoles(@PathParam("clientId") String clientId, @PathParam("userId") String userId, public List<RoleDTO> getUserClientRoles(@PathParam("clientId") String clientId, @PathParam("userId") String userId,
@QueryParam("realm") String realmName) { @QueryParam("realm") String realmName) {
log.info("GET /api/roles/user/client/{}/{} - realm: {}", clientId, userId, realmName); log.info("GET /api/roles/user/client/{}/{} - realm: {}", clientId, userId, realmName);
@@ -252,7 +252,7 @@ public class RoleResource implements RoleResourceApi {
@Override @Override
@POST @POST
@Path("/composite/{roleName}/add") @Path("/composite/{roleName}/add")
@RolesAllowed({ "admin", "role_manager" }) @RolesAllowed({ "admin", "role_manager", "ADMIN", "SUPER_ADMIN" })
public void addComposites(@PathParam("roleName") String roleName, @QueryParam("realm") String realmName, public void addComposites(@PathParam("roleName") String roleName, @QueryParam("realm") String realmName,
@NotNull RoleAssignmentRequestDTO request) { @NotNull RoleAssignmentRequestDTO request) {
log.info("POST /api/roles/composite/{}/add - Ajout de {} composites", roleName, request.getRoleNames().size()); log.info("POST /api/roles/composite/{}/add - Ajout de {} composites", roleName, request.getRoleNames().size());
@@ -276,7 +276,7 @@ public class RoleResource implements RoleResourceApi {
@Override @Override
@GET @GET
@Path("/composite/{roleName}") @Path("/composite/{roleName}")
@RolesAllowed({ "admin", "role_manager", "role_viewer" }) @RolesAllowed({ "admin", "role_manager", "role_viewer", "ADMIN", "SUPER_ADMIN", "USER" })
public List<RoleDTO> getComposites(@PathParam("roleName") String roleName, @QueryParam("realm") String realmName) { public List<RoleDTO> getComposites(@PathParam("roleName") String roleName, @QueryParam("realm") String realmName) {
log.info("GET /api/roles/composite/{} - realm: {}", roleName, realmName); log.info("GET /api/roles/composite/{} - realm: {}", roleName, realmName);

View File

@@ -228,6 +228,16 @@ public class UserServiceImpl implements UserService {
user.getTemporaryPasswordFlag() != null && user.getTemporaryPasswordFlag()); user.getTemporaryPasswordFlag() != null && user.getTemporaryPasswordFlag());
} }
// Re-appliquer les required actions après la définition du mot de passe.
// resetPassword(temporary=false) retire UPDATE_PASSWORD des required actions dans Keycloak.
if (user.getRequiredActions() != null && !user.getRequiredActions().isEmpty()) {
UserResource userResForActions = usersResource.get(userId);
UserRepresentation repForActions = userResForActions.toRepresentation();
repForActions.setRequiredActions(user.getRequiredActions());
userResForActions.update(repForActions);
log.info("✅ Required actions re-appliquées pour {} : {}", userId, user.getRequiredActions());
}
// Récupérer l'utilisateur créé // Récupérer l'utilisateur créé
UserResource userResource = usersResource.get(userId); UserResource userResource = usersResource.get(userId);
UserRepresentation createdUser = userResource.toRepresentation(); UserRepresentation createdUser = userResource.toRepresentation();
@@ -271,6 +281,9 @@ public class UserServiceImpl implements UserService {
if (user.getAttributes() != null) { if (user.getAttributes() != null) {
existingUser.setAttributes(user.getAttributes()); existingUser.setAttributes(user.getAttributes());
} }
if (user.getRequiredActions() != null) {
existingUser.setRequiredActions(user.getRequiredActions());
}
// Envoyer la mise à jour // Envoyer la mise à jour
userResource.update(existingUser); userResource.update(existingUser);
@@ -389,8 +402,8 @@ public class UserServiceImpl implements UserService {
log.info("✅ Email de vérification envoyé: {}", userId); log.info("✅ Email de vérification envoyé: {}", userId);
} catch (Exception e) { } catch (Exception e) {
log.error("❌ Erreur lors de l'envoi de l'email de vérification pour {}", userId, e); log.warn("⚠️ Impossible d'envoyer l'email de vérification pour {} (SMTP peut-être non configuré ou Keycloak indisponible): {}", userId, e.getMessage());
throw new RuntimeException("Impossible d'envoyer l'email de vérification", e); // L'envoi d'email est best-effort : on ne bloque pas le flux appelant
} }
} }