From 860c3fbbd30a7949fbe4bcc0ae21d2a8a93a0dc4 Mon Sep 17 00:00:00 2001 From: Sergey Ch Date: Thu, 1 Sep 2022 23:27:24 +0600 Subject: [PATCH] KEYCLOAK-17263 Add exact searching for users (#8059) Co-authored-by: Stian Thorgersen --- .../admin/client/resource/UsersResource.java | 28 +++++++ .../keycloak/testsuite/admin/UserTest.java | 84 ++++++++++++++++++- 2 files changed, 111 insertions(+), 1 deletion(-) diff --git a/integration/admin-client/src/main/java/org/keycloak/admin/client/resource/UsersResource.java b/integration/admin-client/src/main/java/org/keycloak/admin/client/resource/UsersResource.java index adff9c7bef..481516293c 100755 --- a/integration/admin-client/src/main/java/org/keycloak/admin/client/resource/UsersResource.java +++ b/integration/admin-client/src/main/java/org/keycloak/admin/client/resource/UsersResource.java @@ -143,6 +143,34 @@ public interface UsersResource { @Produces(MediaType.APPLICATION_JSON) List searchByLastName(@QueryParam("lastName") String email, @QueryParam("exact") Boolean exact); + /** + * Search for users based on the given filters. + * + * @param username a value contained in username + * @param firstName a value contained in first name + * @param lastName a value contained in last name + * @param email a value contained in email + * @param firstResult the position of the first result to retrieve + * @param maxResults the maximum number of results to retrieve + * @param enabled only return enabled or disabled users + * @param briefRepresentation Only return basic information (only guaranteed to return id, username, created, first + * and last name, email, enabled state, email verification state, federation link, and access. + * Note that it means that namely user attributes, required actions, and not before are not returned.) + * @param exact search with exact matching by filters (username, email, firstName, lastName) + * @return a list of {@link UserRepresentation} + */ + @GET + @Produces(MediaType.APPLICATION_JSON) + List search(@QueryParam("username") String username, + @QueryParam("firstName") String firstName, + @QueryParam("lastName") String lastName, + @QueryParam("email") String email, + @QueryParam("first") Integer firstResult, + @QueryParam("max") Integer maxResults, + @QueryParam("enabled") Boolean enabled, + @QueryParam("briefRepresentation") Boolean briefRepresentation, + @QueryParam("exact") Boolean exact); + /** * Search for users whose username or email matches the value provided by {@code search}. The {@code search} * argument also allows finding users by specific attributes as follows: diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/UserTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/UserTest.java index 51d0fed322..8c10d5544c 100755 --- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/UserTest.java +++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/UserTest.java @@ -1134,6 +1134,88 @@ public class UserTest extends AbstractAdminTest { assertThat(userIds.get(0), equalTo(users.get(0).getId())); } + @Test + public void searchWithExactMatch() { + UserRepresentation user = new UserRepresentation(); + user.setUsername("test_username"); + user.setFirstName("test_first_name"); + user.setLastName("test_last_name"); + user.setEmail("test_email@test.com"); + user.setEnabled(true); + user.setEmailVerified(true); + createUser(user); + + UserRepresentation user2 = new UserRepresentation(); + user2.setUsername("test_username2"); + user2.setFirstName("test_first_name2"); + user2.setLastName("test_last_name"); + user2.setEmail("test_email@test.com2"); + user2.setEnabled(true); + user2.setEmailVerified(true); + createUser(user2); + + UserRepresentation user3 = new UserRepresentation(); + user3.setUsername("test_username3"); + user3.setFirstName("test_first_name"); + user3.setLastName("test_last_name3"); + user3.setEmail("test_email@test.com3"); + user3.setEnabled(true); + user3.setEmailVerified(true); + createUser(user3); + + List users = realm.users().search( + null, null, null, "test_email@test.co", + 0, 10, null, null, true + ); + assertEquals(0, users.size()); + users = realm.users().search( + null, null, null, "test_email@test.com", + 0, 10, null, null, true + ); + assertEquals(1, users.size()); + users = realm.users().search( + null, null, "test_last", "test_email@test.com", + 0, 10, null, null, true + ); + assertEquals(0, users.size()); + users = realm.users().search( + null, null, "test_last_name", "test_email@test.com", + 0, 10, null, null, true + ); + assertEquals(1, users.size()); + users = realm.users().search( + null, "test_first", "test_last_name", "test_email@test.com", + 0, 10, null, null, true + ); + assertEquals(0, users.size()); + users = realm.users().search( + null, "test_first_name", "test_last_name", "test_email@test.com", + 0, 10, null, null, true + ); + assertEquals(1, users.size()); + users = realm.users().search( + "test_usernam", "test_first_name", "test_last_name", "test_email@test.com", + 0, 10, null, null, true + ); + assertEquals(0, users.size()); + users = realm.users().search( + "test_username", "test_first_name", "test_last_name", "test_email@test.com", + 0, 10, null, null, true + ); + assertEquals(1, users.size()); + + users = realm.users().search( + null, null, "test_last_name", null, + 0, 10, null, null, true + ); + assertEquals(2, users.size()); + users = realm.users().search( + null, "test_first_name", null, null, + 0, 10, null, null, true + ); + assertEquals(2, users.size()); + } + @Test public void countUsersNotServiceAccount() { createUsers(); @@ -2958,4 +3040,4 @@ public class UserTest extends AbstractAdminTest { testRealm().roles().get("realm-role").remove(); } } -} +} \ No newline at end of file