package dev.lions.unionflow.server.resource; import dev.lions.unionflow.server.service.AdminUserService; import dev.lions.user.manager.dto.role.RoleDTO; import dev.lions.user.manager.dto.user.UserDTO; import dev.lions.user.manager.dto.user.UserSearchResultDTO; import jakarta.annotation.security.RolesAllowed; import jakarta.inject.Inject; import jakarta.ws.rs.*; import jakarta.ws.rs.core.MediaType; import jakarta.ws.rs.core.Response; import org.eclipse.microprofile.openapi.annotations.Operation; import org.eclipse.microprofile.openapi.annotations.tags.Tag; import org.jboss.logging.Logger; import java.util.List; import java.util.Map; /** * API admin pour la gestion des utilisateurs Keycloak (proxy vers lions-user-manager). * Réservé au rôle SUPER_ADMIN — la vérification est faite par @RolesAllowed au niveau classe. */ @Path("/api/admin/users") @Produces(MediaType.APPLICATION_JSON) @Consumes(MediaType.APPLICATION_JSON) @Tag(name = "Admin - Utilisateurs", description = "Gestion des utilisateurs Keycloak (SUPER_ADMIN)") @RolesAllowed("SUPER_ADMIN") public class AdminUserResource { private static final Logger LOG = Logger.getLogger(AdminUserResource.class); @Inject AdminUserService adminUserService; @GET @Operation(summary = "Lister les utilisateurs", description = "Liste paginée des utilisateurs du realm") public Response list( @QueryParam("page") @DefaultValue("0") int page, @QueryParam("size") @DefaultValue("20") int size, @QueryParam("search") String search ) { try { UserSearchResultDTO result = adminUserService.searchUsers(page, size, search); return Response.ok(result).build(); } catch (Exception e) { LOG.errorf(e, "Erreur liste utilisateurs: %s", e.getMessage()); return Response.status(Response.Status.INTERNAL_SERVER_ERROR) .entity(Map.of("error", "Erreur serveur", "message", e.getMessage())) .build(); } } @GET @Path("/{id}") @Operation(summary = "Détail utilisateur") public Response getById(@PathParam("id") String id) { try { UserDTO user = adminUserService.getUserById(id); if (user == null) { return Response.status(Response.Status.NOT_FOUND).build(); } return Response.ok(user).build(); } catch (Exception e) { LOG.errorf(e, "Erreur détail utilisateur %s: %s", id, e.getMessage()); return Response.status(Response.Status.INTERNAL_SERVER_ERROR) .entity(Map.of("error", "Erreur serveur", "message", e.getMessage())) .build(); } } @GET @Path("/roles") @Operation(summary = "Liste des rôles realm") public Response listRoles() { try { List roles = adminUserService.getRealmRoles(); return Response.ok(roles).build(); } catch (Exception e) { LOG.errorf(e, "Erreur liste rôles: %s", e.getMessage()); return Response.status(Response.Status.INTERNAL_SERVER_ERROR) .entity(Map.of("error", "Erreur serveur", "message", e.getMessage())) .build(); } } @GET @Path("/{id}/roles") @Operation(summary = "Rôles d'un utilisateur") public Response getUserRoles(@PathParam("id") String id) { try { List roles = adminUserService.getUserRoles(id); return Response.ok(roles).build(); } catch (Exception e) { LOG.errorf(e, "Erreur rôles utilisateur %s: %s", id, e.getMessage()); return Response.status(Response.Status.INTERNAL_SERVER_ERROR) .entity(Map.of("error", "Erreur serveur", "message", e.getMessage())) .build(); } } @PUT @Path("/{id}/roles") @Operation(summary = "Mettre à jour les rôles d'un utilisateur") public Response setUserRoles(@PathParam("id") String id, List roleNames) { try { adminUserService.setUserRoles(id, roleNames); return Response.ok(Map.of("success", true, "userId", id)).build(); } catch (Exception e) { LOG.errorf(e, "Erreur mise à jour rôles %s: %s", id, e.getMessage()); return Response.status(Response.Status.INTERNAL_SERVER_ERROR) .entity(Map.of("error", "Erreur serveur", "message", e.getMessage())) .build(); } } @POST @Operation(summary = "Créer un utilisateur", description = "Crée un nouvel utilisateur Keycloak (proxy lions-user-manager)") public Response createUser(UserDTO user) { try { UserDTO created = adminUserService.createUser(user); return Response.status(Response.Status.CREATED).entity(created).build(); } catch (IllegalArgumentException e) { LOG.warnf("Création utilisateur refusée: %s", e.getMessage()); return Response.status(Response.Status.CONFLICT) .entity(Map.of("error", "Conflit", "message", e.getMessage())) .build(); } catch (Exception e) { LOG.errorf(e, "Erreur création utilisateur: %s", e.getMessage()); return Response.status(Response.Status.INTERNAL_SERVER_ERROR) .entity(Map.of("error", "Erreur serveur", "message", e.getMessage())) .build(); } } @PUT @Path("/{id}") @Operation(summary = "Mettre à jour un utilisateur", description = "Met à jour un utilisateur (au minimum enabled)") public Response updateUser(@PathParam("id") String id, UserDTO user) { try { if (user.getEnabled() != null) { UserDTO updated = adminUserService.updateUserEnabled(id, user.getEnabled()); return Response.ok(updated).build(); } UserDTO updated = adminUserService.updateUser(id, user); return Response.ok(updated).build(); } catch (IllegalArgumentException e) { if (e.getMessage() != null && e.getMessage().contains("non trouvé")) { return Response.status(Response.Status.NOT_FOUND) .entity(Map.of("error", "Non trouvé", "message", e.getMessage())) .build(); } return Response.status(Response.Status.BAD_REQUEST) .entity(Map.of("error", "Requête invalide", "message", e.getMessage())) .build(); } catch (Exception e) { LOG.errorf(e, "Erreur mise à jour utilisateur %s: %s", id, e.getMessage()); return Response.status(Response.Status.INTERNAL_SERVER_ERROR) .entity(Map.of("error", "Erreur serveur", "message", e.getMessage())) .build(); } } }