From 4beb053421246fdf2a15843dfa343c2c4076b762 Mon Sep 17 00:00:00 2001 From: Alberto Miorin <32617+amiorin@users.noreply.github.com> Date: Wed, 15 Dec 2021 20:04:30 +0100 Subject: [PATCH] Fix #1694: Add parameter team to filter the list of users (#1695) --- .../catalog/jdbi3/CollectionDAO.java | 59 +++++++++++++++++++ .../catalog/jdbi3/UserRepository.java | 4 +- .../catalog/resources/teams/UserResource.java | 7 ++- .../resources/teams/UserResourceTest.java | 39 ++++++++++++ 4 files changed, 105 insertions(+), 4 deletions(-) diff --git a/catalog-rest-service/src/main/java/org/openmetadata/catalog/jdbi3/CollectionDAO.java b/catalog-rest-service/src/main/java/org/openmetadata/catalog/jdbi3/CollectionDAO.java index d8ab9d1cdfb..6236f48be6a 100644 --- a/catalog-rest-service/src/main/java/org/openmetadata/catalog/jdbi3/CollectionDAO.java +++ b/catalog-rest-service/src/main/java/org/openmetadata/catalog/jdbi3/CollectionDAO.java @@ -842,6 +842,65 @@ public interface CollectionDAO { @SqlQuery("SELECT json FROM user_entity WHERE email = :email") String findByEmail(@Bind("email") String email); + + default int listCount(String team) { + return listCount(getTableName(), getNameColumn(), team, Relationship.CONTAINS.ordinal()); + } + + @Override + default List listBefore(String team, int limit, String before) { + return listBefore(getTableName(), getNameColumn(), team, limit, before, Relationship.CONTAINS.ordinal()); + } + + @Override + default List listAfter(String team, int limit, String after) { + return listAfter(getTableName(), getNameColumn(), team, limit, after, Relationship.CONTAINS.ordinal()); + } + + @SqlQuery("SELECT count(id) FROM (" + + "SELECT ue.id " + + "FROM user_entity ue " + + "LEFT JOIN entity_relationship er on ue.id = er.toId " + + "LEFT JOIN team_entity te on te.id = er.fromId and er.relation = :relation " + + "WHERE (te.name = :team OR :team IS NULL) " + + "GROUP BY ue.id) subquery") + int listCount(@Define("table") String table, @Define("nameColumn") String nameColumn, + @Bind("team") String team, + @Bind("relation") int relation); + + @SqlQuery("SELECT json FROM (" + + "SELECT ue., ue.json " + + "FROM user_entity ue " + + "LEFT JOIN entity_relationship er on ue.id = er.toId " + + "LEFT JOIN team_entity te on te.id = er.fromId and er.relation = :relation " + + "WHERE (te.name = :team OR :team IS NULL) AND " + + "ue. < :before " + + "GROUP BY ue., ue.json " + + "ORDER BY ue. DESC " + + "LIMIT :limit" + + ") last_rows_subquery ORDER BY ") + List listBefore(@Define("table") String table, + @Define("nameColumn") String nameColumn, + @Bind("team") String team, + @Bind("limit") int limit, + @Bind("before") String before, + @Bind("relation") int relation); + + @SqlQuery("SELECT ue.json " + + "FROM user_entity ue " + + "LEFT JOIN entity_relationship er on ue.id = er.toId " + + "LEFT JOIN team_entity te on te.id = er.fromId and er.relation = :relation " + + "WHERE (te.name = :team OR :team IS NULL) AND " + + "ue. > :after " + + "GROUP BY ue.json " + + "ORDER BY ue. " + + "LIMIT :limit") + List listAfter(@Define("table") String table, + @Define("nameColumn") String nameColumn, + @Bind("team") String team, + @Bind("limit") int limit, + @Bind("after") String after, + @Bind("relation") int relation); } interface ChangeEventDAO { diff --git a/catalog-rest-service/src/main/java/org/openmetadata/catalog/jdbi3/UserRepository.java b/catalog-rest-service/src/main/java/org/openmetadata/catalog/jdbi3/UserRepository.java index 04970acf5fd..e52c510200a 100644 --- a/catalog-rest-service/src/main/java/org/openmetadata/catalog/jdbi3/UserRepository.java +++ b/catalog-rest-service/src/main/java/org/openmetadata/catalog/jdbi3/UserRepository.java @@ -252,10 +252,10 @@ public class UserRepository extends EntityRepository { public void setId(UUID id) { entity.setId(id); } @Override - public void setDescription(String description) { entity.setDescription(description);} + public void setDescription(String description) { entity.setDescription(description); } @Override - public void setDisplayName(String displayName) { entity.setDisplayName(displayName);} + public void setDisplayName(String displayName) { entity.setDisplayName(displayName); } @Override public void setUpdateDetails(String updatedBy, Date updatedAt) { diff --git a/catalog-rest-service/src/main/java/org/openmetadata/catalog/resources/teams/UserResource.java b/catalog-rest-service/src/main/java/org/openmetadata/catalog/resources/teams/UserResource.java index 7eb41111dce..5e66acbe7b1 100644 --- a/catalog-rest-service/src/main/java/org/openmetadata/catalog/resources/teams/UserResource.java +++ b/catalog-rest-service/src/main/java/org/openmetadata/catalog/resources/teams/UserResource.java @@ -128,6 +128,9 @@ public class UserResource { @Parameter(description = "Fields requested in the returned resource", schema = @Schema(type = "string", example = FIELDS)) @QueryParam("fields") String fieldsParam, + @Parameter(description = "Filter users by team", + schema = @Schema(type = "string", example = "Legal")) + @QueryParam("team") String teamParam, @Parameter(description = "Limit the number users returned. (1 to 1000000, default = 10)") @DefaultValue("10") @Min(1) @@ -145,9 +148,9 @@ public class UserResource { ResultList users; if (before != null) { // Reverse paging - users = dao.listBefore(uriInfo, fields, null, limitParam, before); + users = dao.listBefore(uriInfo, fields, teamParam, limitParam, before); } else { // Forward paging or first page - users = dao.listAfter(uriInfo, fields, null, limitParam, after); + users = dao.listAfter(uriInfo, fields, teamParam, limitParam, after); } Optional.ofNullable(users.getData()).orElse(Collections.emptyList()).forEach(u -> addHref(uriInfo, u)); return users; diff --git a/catalog-rest-service/src/test/java/org/openmetadata/catalog/resources/teams/UserResourceTest.java b/catalog-rest-service/src/test/java/org/openmetadata/catalog/resources/teams/UserResourceTest.java index 85730010865..a9b1efb6801 100644 --- a/catalog-rest-service/src/test/java/org/openmetadata/catalog/resources/teams/UserResourceTest.java +++ b/catalog-rest-service/src/test/java/org/openmetadata/catalog/resources/teams/UserResourceTest.java @@ -38,6 +38,7 @@ import org.openmetadata.catalog.type.Profile; import org.openmetadata.catalog.util.EntityInterface; import org.openmetadata.catalog.util.EntityUtil; import org.openmetadata.catalog.util.JsonUtils; +import org.openmetadata.catalog.util.ResultList; import org.openmetadata.catalog.util.TestUtils; import org.openmetadata.catalog.util.TestUtils.UpdateType; import org.openmetadata.common.utils.JsonSchemaUtil; @@ -50,10 +51,12 @@ import java.net.URISyntaxException; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; +import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Optional; import java.util.UUID; +import java.util.function.Predicate; import static javax.ws.rs.core.Response.Status.BAD_REQUEST; import static javax.ws.rs.core.Response.Status.CREATED; @@ -196,6 +199,42 @@ public class UserResourceTest extends EntityResourceTest { assertEquals(user.getId(), team2.getUsers().get(0).getId()); } + @Test + public void get_listUsersWithTeams_200_ok(TestInfo test) throws IOException { + TeamResourceTest teamResourceTest = new TeamResourceTest(); + Team team1 = createTeam(teamResourceTest.create(test, 1), adminAuthHeaders()); + Team team2 = createTeam(teamResourceTest.create(test, 2), adminAuthHeaders()); + List teams = List.of(team1.getId(), team2.getId()); + List team = List.of(team1.getId()); + + CreateUser create = create(test, 0); + User user0 = createAndCheckEntity(create, adminAuthHeaders()); + create = create(test, 1).withTeams(team); + User user1 = createAndCheckEntity(create, adminAuthHeaders()); + create = create(test, 2).withTeams(teams); + User user2 = createAndCheckEntity(create, adminAuthHeaders()); + + Predicate isUser0 = u -> u.getId().equals(user0.getId()); + Predicate isUser1 = u -> u.getId().equals(user1.getId()); + Predicate isUser2 = u -> u.getId().equals(user2.getId()); + + Map queryParams = new HashMap<>() {{put("team", team1.getName()); }}; + ResultList users = listEntities(queryParams, 100_000, null, null, adminAuthHeaders()); + assertEquals(2, users.getData().size()); + assertTrue(users.getData().stream().anyMatch(isUser1)); + assertTrue(users.getData().stream().anyMatch(isUser2)); + + queryParams = new HashMap<>() {{put("team", team2.getName()); }}; + users = listEntities(queryParams, 100_000, null, null, adminAuthHeaders()); + assertEquals(1, users.getData().size()); + assertTrue(users.getData().stream().anyMatch(isUser2)); + + users = listEntities(null, 100_000, null, null, adminAuthHeaders()); + assertTrue(users.getData().stream().anyMatch(isUser0)); + assertTrue(users.getData().stream().anyMatch(isUser1)); + assertTrue(users.getData().stream().anyMatch(isUser2)); + } + @Test public void get_userWithInvalidFields_400_BadRequest(TestInfo test) throws HttpResponseException { User user = createUser(create(test), adminAuthHeaders());