keycloak-memoizeit
Changes
integration/admin-client/src/main/java/org/keycloak/admin/client/resource/UsersResource.java 33(+33 -0)
testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/UserTest.java 34(+26 -8)
Details
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 ca80245..dfac03f 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
@@ -44,6 +44,16 @@ public interface UsersResource {
@GET
@Produces(MediaType.APPLICATION_JSON)
+ List<UserRepresentation> 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("briefRepresentation") Boolean briefRepresentation);
+
+ @GET
+ @Produces(MediaType.APPLICATION_JSON)
List<UserRepresentation> search(@QueryParam("username") String username);
/**
@@ -65,6 +75,29 @@ public interface UsersResource {
@QueryParam("first") Integer firstResult,
@QueryParam("max") Integer maxResults);
+ /**
+ * 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:
+ *
+ * <ul>
+ * <li><i>id:</i> - Find users by identifier. For instance, <i>id:aa497859-bbf5-44ac-bf1a-74dbffcaf197</i></li>
+ * </ul>
+ *
+ * @param search the value to search. It can be the username, email or any of the supported options to query based on user attributes
+ * @param firstResult the position of the first result to retrieve
+ * @param maxResults the maximum number of results to retreive
+ * @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.)
+ * @return a list of {@link UserRepresentation}
+ */
+ @GET
+ @Produces(MediaType.APPLICATION_JSON)
+ List<UserRepresentation> search(@QueryParam("search") String search,
+ @QueryParam("first") Integer firstResult,
+ @QueryParam("max") Integer maxResults,
+ @QueryParam("briefRepresentation") Boolean briefRepresentation);
+
@GET
@Produces(MediaType.APPLICATION_JSON)
List<UserRepresentation> list(@QueryParam("first") Integer firstResult,
diff --git a/server-spi-private/src/main/java/org/keycloak/models/utils/ModelToRepresentation.java b/server-spi-private/src/main/java/org/keycloak/models/utils/ModelToRepresentation.java
index 17e8c1e..48bd73d 100755
--- a/server-spi-private/src/main/java/org/keycloak/models/utils/ModelToRepresentation.java
+++ b/server-spi-private/src/main/java/org/keycloak/models/utils/ModelToRepresentation.java
@@ -166,6 +166,21 @@ public class ModelToRepresentation {
return rep;
}
+ public static UserRepresentation toBriefRepresentation(UserModel user) {
+ UserRepresentation rep = new UserRepresentation();
+ rep.setId(user.getId());
+ rep.setUsername(user.getUsername());
+ rep.setCreatedTimestamp(user.getCreatedTimestamp());
+ rep.setLastName(user.getLastName());
+ rep.setFirstName(user.getFirstName());
+ rep.setEmail(user.getEmail());
+ rep.setEnabled(user.isEnabled());
+ rep.setEmailVerified(user.isEmailVerified());
+ rep.setFederationLink(user.getFederationLink());
+
+ return rep;
+ }
+
public static EventRepresentation toRepresentation(Event event) {
EventRepresentation rep = new EventRepresentation();
rep.setTime(event.getTime());
diff --git a/services/src/main/java/org/keycloak/services/resources/admin/UsersResource.java b/services/src/main/java/org/keycloak/services/resources/admin/UsersResource.java
index 6c15f68..e8a57c7 100755
--- a/services/src/main/java/org/keycloak/services/resources/admin/UsersResource.java
+++ b/services/src/main/java/org/keycloak/services/resources/admin/UsersResource.java
@@ -179,7 +179,8 @@ public class UsersResource {
@QueryParam("email") String email,
@QueryParam("username") String username,
@QueryParam("first") Integer firstResult,
- @QueryParam("max") Integer maxResults) {
+ @QueryParam("max") Integer maxResults,
+ @QueryParam("briefRepresentation") Boolean briefRepresentation) {
auth.users().requireQuery();
firstResult = firstResult != null ? firstResult : -1;
@@ -216,9 +217,12 @@ public class UsersResource {
}
boolean canViewGlobal = auth.users().canView();
+ boolean briefRepresentationB = briefRepresentation != null && briefRepresentation;
for (UserModel user : userModels) {
if (!canViewGlobal && !auth.users().canView(user)) continue;
- UserRepresentation userRep = ModelToRepresentation.toRepresentation(session, realm, user);
+ UserRepresentation userRep = briefRepresentationB
+ ? ModelToRepresentation.toBriefRepresentation(user)
+ : ModelToRepresentation.toRepresentation(session, realm, user);
userRep.setAccess(auth.users().getAccess(user));
results.add(userRep);
}
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 2ea2122..266499d 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
@@ -86,12 +86,8 @@ import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
+import static org.hamcrest.Matchers.is;
+import static org.junit.Assert.*;
import static org.keycloak.testsuite.Assert.assertNames;
/**
@@ -1407,14 +1403,36 @@ public class UserTest extends AbstractAdminTest {
UsersResource users = adminClient.realms().realm("test").users();
for (int i = 0; i < 110; i++) {
- users.create(UserBuilder.create().username("test-" + i).build()).close();
+ users.create(UserBuilder.create().username("test-" + i).addAttribute("aName", "aValue").build()).close();
+ }
+
+ List<UserRepresentation> result = users.search("test", null, null);
+ assertEquals(100, result.size());
+ for (UserRepresentation user : result) {
+ assertThat(user.getAttributes(), Matchers.notNullValue());
+ assertThat(user.getAttributes().keySet(), Matchers.hasSize(1));
+ assertThat(user.getAttributes(), Matchers.hasEntry(is("aName"), Matchers.contains("aValue")));
}
- assertEquals(100, users.search("test", null, null).size());
assertEquals(105, users.search("test", 0, 105).size());
assertEquals(111, users.search("test", 0, 1000).size());
}
+ @Test
+ public void defaultMaxResultsBrief() {
+ UsersResource users = adminClient.realms().realm("test").users();
+
+ for (int i = 0; i < 110; i++) {
+ users.create(UserBuilder.create().username("test-" + i).addAttribute("aName", "aValue").build()).close();
+ }
+
+ List<UserRepresentation> result = users.search("test", null, null, true);
+ assertEquals(100, result.size());
+ for (UserRepresentation user : result) {
+ assertThat(user.getAttributes(), Matchers.nullValue());
+ }
+ }
+
private void switchEditUsernameAllowedOn(boolean enable) {
RealmRepresentation rep = realm.toRepresentation();
rep.setEditUsernameAllowed(enable);
diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/util/UserBuilder.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/util/UserBuilder.java
index fd3ebbc..e27e97b 100644
--- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/util/UserBuilder.java
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/util/UserBuilder.java
@@ -82,6 +82,15 @@ public class UserBuilder {
return this;
}
+ public UserBuilder addAttribute(String name, String... values) {
+ if (rep.getAttributes() == null) {
+ rep.setAttributes(new HashMap<>());
+ }
+
+ rep.getAttributes().put(name, Arrays.asList(values));
+ return this;
+ }
+
/**
* This method makes sure that there is one single password for the user.
*/
diff --git a/themes/src/main/resources/theme/base/admin/resources/js/controllers/users.js b/themes/src/main/resources/theme/base/admin/resources/js/controllers/users.js
index 43d45b3..c51b9d5 100755
--- a/themes/src/main/resources/theme/base/admin/resources/js/controllers/users.js
+++ b/themes/src/main/resources/theme/base/admin/resources/js/controllers/users.js
@@ -235,6 +235,7 @@ module.controller('UserListCtrl', function($scope, realm, User, UserSearchState,
UserSearchState.query.realm = realm.realm;
$scope.query = UserSearchState.query;
+ $scope.query.briefRepresentation = 'true';
if (!UserSearchState.isFirstSearch) $scope.searchQuery();
};