From 2ed890803cde43289c1de606ea28258bbd0483d5 Mon Sep 17 00:00:00 2001 From: dahoud <41957584+DahoudG@users.noreply.github.com> Date: Sun, 5 Apr 2026 11:12:13 +0000 Subject: [PATCH] fix(keycloak): updateUser propage requiredActions + createUser re-applique UPDATE_PASSWORD MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 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 --- .../user/manager/resource/RoleResource.java | 28 +++++++++---------- .../manager/service/impl/UserServiceImpl.java | 17 +++++++++-- 2 files changed, 29 insertions(+), 16 deletions(-) diff --git a/src/main/java/dev/lions/user/manager/resource/RoleResource.java b/src/main/java/dev/lions/user/manager/resource/RoleResource.java index c1ed11f..47dffe0 100644 --- a/src/main/java/dev/lions/user/manager/resource/RoleResource.java +++ b/src/main/java/dev/lions/user/manager/resource/RoleResource.java @@ -39,7 +39,7 @@ public class RoleResource implements RoleResourceApi { @Override @POST @Path("/realm") - @RolesAllowed({ "admin", "role_manager" }) + @RolesAllowed({ "admin", "role_manager", "ADMIN", "SUPER_ADMIN" }) public Response createRealmRole( @Valid @NotNull RoleDTO roleDTO, @QueryParam("realm") String realmName) { @@ -63,7 +63,7 @@ public class RoleResource implements RoleResourceApi { @Override @GET @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) { log.info("GET /api/roles/realm/{} - realm: {}", roleName, realmName); return roleService.getRoleByName(roleName, realmName, TypeRole.REALM_ROLE, null) @@ -73,7 +73,7 @@ public class RoleResource implements RoleResourceApi { @Override @GET @Path("/realm") - @RolesAllowed({ "admin", "role_manager", "role_viewer" }) + @RolesAllowed({ "admin", "role_manager", "role_viewer", "ADMIN", "SUPER_ADMIN", "USER" }) public List getAllRealmRoles(@QueryParam("realm") String realmName) { log.info("GET /api/roles/realm - realm: {}", realmName); return roleService.getAllRealmRoles(realmName); @@ -82,7 +82,7 @@ public class RoleResource implements RoleResourceApi { @Override @PUT @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, @QueryParam("realm") String realmName) { log.info("PUT /api/roles/realm/{} - realm: {}", roleName, realmName); @@ -115,7 +115,7 @@ public class RoleResource implements RoleResourceApi { @Override @POST @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, @QueryParam("realm") String realmName) { 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 @GET @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, @QueryParam("realm") String realmName) { log.info("GET /api/roles/client/{}/{} - realm: {}", clientId, roleName, realmName); @@ -149,7 +149,7 @@ public class RoleResource implements RoleResourceApi { @Override @GET @Path("/client/{clientId}") - @RolesAllowed({ "admin", "role_manager", "role_viewer" }) + @RolesAllowed({ "admin", "role_manager", "role_viewer", "ADMIN", "SUPER_ADMIN", "USER" }) public List getAllClientRoles(@PathParam("clientId") String clientId, @QueryParam("realm") String realmName) { log.info("GET /api/roles/client/{} - realm: {}", clientId, realmName); @@ -177,7 +177,7 @@ public class RoleResource implements RoleResourceApi { @Override @POST @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, @NotNull RoleAssignmentRequestDTO request) { 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 @POST @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, @NotNull RoleAssignmentRequestDTO request) { 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 @POST @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, @QueryParam("realm") String realmName, @NotNull RoleAssignmentRequestDTO request) { @@ -231,7 +231,7 @@ public class RoleResource implements RoleResourceApi { @Override @GET @Path("/user/realm/{userId}") - @RolesAllowed({ "admin", "role_manager", "role_viewer" }) + @RolesAllowed({ "admin", "role_manager", "role_viewer", "ADMIN", "SUPER_ADMIN", "USER" }) public List getUserRealmRoles(@PathParam("userId") String userId, @QueryParam("realm") String realmName) { log.info("GET /api/roles/user/realm/{} - realm: {}", userId, realmName); return roleService.getUserRealmRoles(userId, realmName); @@ -240,7 +240,7 @@ public class RoleResource implements RoleResourceApi { @Override @GET @Path("/user/client/{clientId}/{userId}") - @RolesAllowed({ "admin", "role_manager", "role_viewer" }) + @RolesAllowed({ "admin", "role_manager", "role_viewer", "ADMIN", "SUPER_ADMIN", "USER" }) public List getUserClientRoles(@PathParam("clientId") String clientId, @PathParam("userId") String userId, @QueryParam("realm") String realmName) { log.info("GET /api/roles/user/client/{}/{} - realm: {}", clientId, userId, realmName); @@ -252,7 +252,7 @@ public class RoleResource implements RoleResourceApi { @Override @POST @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, @NotNull RoleAssignmentRequestDTO request) { log.info("POST /api/roles/composite/{}/add - Ajout de {} composites", roleName, request.getRoleNames().size()); @@ -276,7 +276,7 @@ public class RoleResource implements RoleResourceApi { @Override @GET @Path("/composite/{roleName}") - @RolesAllowed({ "admin", "role_manager", "role_viewer" }) + @RolesAllowed({ "admin", "role_manager", "role_viewer", "ADMIN", "SUPER_ADMIN", "USER" }) public List getComposites(@PathParam("roleName") String roleName, @QueryParam("realm") String realmName) { log.info("GET /api/roles/composite/{} - realm: {}", roleName, realmName); diff --git a/src/main/java/dev/lions/user/manager/service/impl/UserServiceImpl.java b/src/main/java/dev/lions/user/manager/service/impl/UserServiceImpl.java index b381747..6362d0a 100644 --- a/src/main/java/dev/lions/user/manager/service/impl/UserServiceImpl.java +++ b/src/main/java/dev/lions/user/manager/service/impl/UserServiceImpl.java @@ -228,6 +228,16 @@ public class UserServiceImpl implements UserService { 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éé UserResource userResource = usersResource.get(userId); UserRepresentation createdUser = userResource.toRepresentation(); @@ -271,6 +281,9 @@ public class UserServiceImpl implements UserService { if (user.getAttributes() != null) { existingUser.setAttributes(user.getAttributes()); } + if (user.getRequiredActions() != null) { + existingUser.setRequiredActions(user.getRequiredActions()); + } // Envoyer la mise à jour userResource.update(existingUser); @@ -389,8 +402,8 @@ public class UserServiceImpl implements UserService { log.info("✅ Email de vérification envoyé: {}", userId); } catch (Exception e) { - log.error("❌ Erreur lors de l'envoi de l'email de vérification pour {}", userId, e); - throw new RuntimeException("Impossible d'envoyer l'email de vérification", e); + log.warn("⚠️ Impossible d'envoyer l'email de vérification pour {} (SMTP peut-être non configuré ou Keycloak indisponible): {}", userId, e.getMessage()); + // L'envoi d'email est best-effort : on ne bloque pas le flux appelant } }