Files
unionflow-server-impl-quarkus/src/main/java/dev/lions/unionflow/server/resource/AdminUserResource.java
2026-04-24 16:19:25 +00:00

163 lines
6.7 KiB
Java

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<RoleDTO> 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<RoleDTO> 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<String> 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();
}
}
}