keycloak-aplcache
Changes
integration/admin-client/src/main/java/org/keycloak/admin/client/resource/GroupsResource.java 20(+10 -10)
model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/RealmCacheSession.java 18(+12 -6)
model/jpa/pom.xml 5(+0 -5)
pom.xml 7(+0 -7)
services/pom.xml 5(+0 -5)
Details
diff --git a/integration/admin-client/src/main/java/org/keycloak/admin/client/resource/GroupsResource.java b/integration/admin-client/src/main/java/org/keycloak/admin/client/resource/GroupsResource.java
index e704c39..6c92204 100755
--- a/integration/admin-client/src/main/java/org/keycloak/admin/client/resource/GroupsResource.java
+++ b/integration/admin-client/src/main/java/org/keycloak/admin/client/resource/GroupsResource.java
@@ -24,6 +24,7 @@ import javax.ws.rs.*;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import java.util.List;
+import java.util.Map;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
@@ -69,39 +70,38 @@ public interface GroupsResource {
/**
* Counts all groups.
- * @return The number of groups.
+ * @return A map containing key "count" with number of groups as value.
*/
@GET
@NoCache
- @Path("/count")
+ @Path("count")
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
- Response count();
+ Map<String, Long> count();
/**
* Counts groups by name search.
* @param search max number of occurrences
- * @return The number of group containing search therm.
+ * @return A map containing key "count" with number of groups as value which matching with search.
*/
@GET
@NoCache
- @Path("/count")
+ @Path("count")
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
- Response count(@QueryParam("search") String search);
+ Map<String, Long> count(@QueryParam("search") String search);
/**
* Counts groups by name search.
- * @param search max number of occurrences
* @param onlyTopGroups <code>true</code> or <code>false</code> for filter only top level groups count
- * @return The number of group containing search therm.
+ * @return A map containing key "count" with number of top level groups.
*/
@GET
@NoCache
- @Path("/count")
+ @Path("count")
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
- Response count(@QueryParam("search") String search, @QueryParam("top") String onlyTopGroups);
+ Map<String, Long> count(@QueryParam("top") @DefaultValue("true") boolean onlyTopGroups);
/**
* create or add a top level realm groupSet or create child. This will update the group and set the parent if it exists. Create it and set the parent
diff --git a/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/RealmCacheSession.java b/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/RealmCacheSession.java
index bcff0ba..318bb53 100755
--- a/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/RealmCacheSession.java
+++ b/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/RealmCacheSession.java
@@ -94,7 +94,6 @@ public class RealmCacheSession implements CacheRealmProvider {
protected static final Logger logger = Logger.getLogger(RealmCacheSession.class);
public static final String REALM_CLIENTS_QUERY_SUFFIX = ".realm.clients";
public static final String ROLES_QUERY_SUFFIX = ".roles";
- public static final String ROLE_BY_NAME_QUERY_SUFFIX = ".role.by-name";
protected RealmCacheManager cache;
protected KeycloakSession session;
protected RealmProvider delegate;
@@ -839,6 +838,9 @@ public class RealmCacheSession implements CacheRealmProvider {
}
list.add(group);
}
+
+ list.sort(Comparator.comparing(GroupModel::getName));
+
return list;
}
@@ -885,6 +887,9 @@ public class RealmCacheSession implements CacheRealmProvider {
}
list.add(group);
}
+
+ list.sort(Comparator.comparing(GroupModel::getName));
+
return list;
}
@@ -921,6 +926,9 @@ public class RealmCacheSession implements CacheRealmProvider {
}
list.add(group);
}
+
+ list.sort(Comparator.comparing(GroupModel::getName));
+
return list;
}
@@ -980,11 +988,9 @@ public class RealmCacheSession implements CacheRealmProvider {
String groupId = eventToAdd.getId();
// Check if we have existing event with bigger priority
- boolean eventAlreadyExists = invalidationEvents.stream().filter((InvalidationEvent event) -> {
-
- return (event.getId().equals(groupId)) && (event instanceof GroupAddedEvent || event instanceof GroupMovedEvent || event instanceof GroupRemovedEvent);
-
- }).findFirst().isPresent();
+ boolean eventAlreadyExists = invalidationEvents.stream()
+ .anyMatch((InvalidationEvent event) -> (event.getId().equals(groupId)) &&
+ (event instanceof GroupAddedEvent || event instanceof GroupMovedEvent || event instanceof GroupRemovedEvent));
if (!eventAlreadyExists) {
invalidationEvents.add(eventToAdd);
model/jpa/pom.xml 5(+0 -5)
diff --git a/model/jpa/pom.xml b/model/jpa/pom.xml
index 5994089..54166f5 100755
--- a/model/jpa/pom.xml
+++ b/model/jpa/pom.xml
@@ -111,11 +111,6 @@
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
- <dependency>
- <groupId>org.mockito</groupId>
- <artifactId>mockito-all</artifactId>
- <scope>test</scope>
- </dependency>
</dependencies>
<build>
<plugins>
pom.xml 7(+0 -7)
diff --git a/pom.xml b/pom.xml
index e437123..8b216dc 100755
--- a/pom.xml
+++ b/pom.xml
@@ -108,7 +108,6 @@
<hamcrest.version>1.3</hamcrest.version>
<jmeter.version>2.10</jmeter.version>
<junit.version>4.12</junit.version>
- <mockito.version>1.9.5</mockito.version>
<picketlink.version>2.7.0.Final</picketlink.version>
<selenium.version>2.35.0</selenium.version>
<xml-apis.version>1.4.01</xml-apis.version>
@@ -369,12 +368,6 @@
<scope>test</scope>
</dependency>
<dependency>
- <groupId>org.mockito</groupId>
- <artifactId>mockito-all</artifactId>
- <scope>test</scope>
- <version>${mockito.version}</version>
- </dependency>
- <dependency>
<groupId>org.hamcrest</groupId>
<artifactId>hamcrest-all</artifactId>
<version>${hamcrest.version}</version>
services/pom.xml 5(+0 -5)
diff --git a/services/pom.xml b/services/pom.xml
index cbbf3da..733b812 100755
--- a/services/pom.xml
+++ b/services/pom.xml
@@ -180,11 +180,6 @@
</exclusion>
</exclusions>
</dependency>
- <dependency>
- <groupId>org.mockito</groupId>
- <artifactId>mockito-all</artifactId>
- <scope>test</scope>
- </dependency>
</dependencies>
<build>
<plugins>
diff --git a/services/src/main/java/org/keycloak/services/resources/admin/GroupsResource.java b/services/src/main/java/org/keycloak/services/resources/admin/GroupsResource.java
index 958b995..15be7ae 100755
--- a/services/src/main/java/org/keycloak/services/resources/admin/GroupsResource.java
+++ b/services/src/main/java/org/keycloak/services/resources/admin/GroupsResource.java
@@ -35,7 +35,9 @@ import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriInfo;
import java.net.URI;
+import java.util.HashMap;
import java.util.List;
+import java.util.Map;
import java.util.Objects;
import org.keycloak.services.ErrorResponse;
import org.keycloak.services.resources.admin.permissions.AdminPermissionEvaluator;
@@ -113,22 +115,19 @@ public class GroupsResource {
*/
@GET
@NoCache
- @Path("/count")
+ @Path("count")
@Produces(MediaType.APPLICATION_JSON)
- public Response getGroupCount(@QueryParam("search") String search, @QueryParam("top") String onlyTopGroups) {
+ public Map<String, Long> getGroupCount(@QueryParam("search") String search,
+ @QueryParam("top") @DefaultValue("false") boolean onlyTopGroups) {
Long results;
- JSONObject response = new JSONObject();
+ Map<String, Long> map = new HashMap<>();
if (Objects.nonNull(search)) {
results = realm.getGroupsCountByNameContaining(search);
} else {
- results = realm.getGroupsCount(Objects.equals(onlyTopGroups, Boolean.TRUE.toString()));
+ results = realm.getGroupsCount(onlyTopGroups);
}
- try {
- response.put("count", results);
- } catch (JSONException e) {
- return ErrorResponse.error("Cannot create response object", Response.Status.INTERNAL_SERVER_ERROR);
- }
- return Response.ok(response.toString(), MediaType.APPLICATION_JSON).build();
+ map.put("count", results);
+ return map;
}
/**
diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/group/GroupTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/group/GroupTest.java
index b7274ec..fd58f75 100755
--- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/group/GroupTest.java
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/group/GroupTest.java
@@ -92,7 +92,6 @@ public class GroupTest extends AbstractGroupTest {
user.setCredentials(credentials);
users.add(user);
-
List<ClientRepresentation> clients = testRealmRep.getClients();
ClientRepresentation client = new ClientRepresentation();
@@ -155,16 +154,16 @@ public class GroupTest extends AbstractGroupTest {
@Test
public void doNotAllowSameGroupNameAtSameLevel() throws Exception {
RealmResource realm = adminClient.realms().realm("test");
-
+
GroupRepresentation topGroup = new GroupRepresentation();
topGroup.setName("top");
topGroup = createGroup(realm, topGroup);
-
+
GroupRepresentation anotherTopGroup = new GroupRepresentation();
anotherTopGroup.setName("top");
Response response = realm.groups().add(anotherTopGroup);
assertEquals(409, response.getStatus()); // conflict status 409 - same name not allowed
-
+
GroupRepresentation level2Group = new GroupRepresentation();
level2Group.setName("level2");
response = realm.groups().group(topGroup.getId()).subGroup(level2Group);
@@ -177,7 +176,7 @@ public class GroupTest extends AbstractGroupTest {
response.close();
assertEquals(409, response.getStatus()); // conflict status 409 - same name not allowed
}
-
+
@Test
public void createAndTestGroups() throws Exception {
RealmResource realm = adminClient.realms().realm("test");
@@ -206,7 +205,7 @@ public class GroupTest extends AbstractGroupTest {
GroupRepresentation topGroup = new GroupRepresentation();
topGroup.setName("top");
topGroup = createGroup(realm, topGroup);
-
+
List<RoleRepresentation> roles = new LinkedList<>();
roles.add(topRole);
realm.groups().group(topGroup.getId()).roles().realmLevel().add(roles);
@@ -634,4 +633,59 @@ public class GroupTest extends AbstractGroupTest {
assertEquals(110, group.members(0, 1000).size());
assertEquals(110, group.members(-1, -2).size());
}
+
+ @Test
+ public void searchAndCountGroups() throws Exception {
+ String firstGroupId = "";
+
+ RealmResource realm = adminClient.realms().realm("test");
+
+ // Clean up all test groups
+ for (GroupRepresentation group : realm.groups().groups()) {
+ GroupResource resource = realm.groups().group(group.getId());
+ resource.remove();
+ assertAdminEvents.assertEvent("test", OperationType.DELETE, AdminEventPaths.groupPath(group.getId()), ResourceType.GROUP);
+ }
+
+ // Add 20 new groups with known names
+ for (int i=0;i<20;i++) {
+ GroupRepresentation group = new GroupRepresentation();
+ group.setName("group"+i);
+ group = createGroup(realm, group);
+ if(i== 0) {
+ firstGroupId = group.getId();
+ }
+ }
+
+ // Get groups by search and pagination
+ List<GroupRepresentation> allGroups = realm.groups().groups();
+ assertEquals(20, allGroups.size());
+
+ List<GroupRepresentation> slice = realm.groups().groups(5, 7);
+ assertEquals(7, slice.size());
+
+ List<GroupRepresentation> search = realm.groups().groups("group1",0,20);
+ assertEquals(11, search.size());
+ for(GroupRepresentation group : search) {
+ assertTrue(group.getName().contains("group1"));
+ }
+
+ List<GroupRepresentation> noResultSearch = realm.groups().groups("abcd",0,20);
+ assertEquals(0, noResultSearch.size());
+
+ // Count
+ assertEquals(new Long(allGroups.size()), realm.groups().count().get("count"));
+ assertEquals(new Long(search.size()), realm.groups().count("group1").get("count"));
+ assertEquals(new Long(noResultSearch.size()), realm.groups().count("abcd").get("count"));
+
+ // Add a subgroup for onlyTopLevel flag testing
+ GroupRepresentation level2Group = new GroupRepresentation();
+ level2Group.setName("group1111");
+ Response response = realm.groups().group(firstGroupId).subGroup(level2Group);
+ response.close();
+ assertAdminEvents.assertEvent("test", OperationType.CREATE, AdminEventPaths.groupSubgroupsPath(firstGroupId), level2Group, ResourceType.GROUP);
+
+ assertEquals(new Long(allGroups.size()), realm.groups().count(true).get("count"));
+ assertEquals(new Long(allGroups.size() + 1), realm.groups().count(false).get("count"));
+ }
}
diff --git a/themes/src/main/resources/theme/base/admin/resources/js/controllers/groups.js b/themes/src/main/resources/theme/base/admin/resources/js/controllers/groups.js
index 23edb67..bc3691f 100755
--- a/themes/src/main/resources/theme/base/admin/resources/js/controllers/groups.js
+++ b/themes/src/main/resources/theme/base/admin/resources/js/controllers/groups.js
@@ -36,7 +36,7 @@ module.controller('GroupListCtrl', function($scope, $route, $q, realm, groups, g
Groups.query(queryParams, function(entry) {
promiseGetGroups.resolve(entry);
}, function() {
- promiseGetGroups.reject('Unable to fetch ' + i);
+ promiseGetGroups.reject('Unable to fetch ' + queryParams);
});
var promiseGetGroupsChain = promiseGetGroups.promise.then(function(entry) {
groups = entry;
@@ -53,14 +53,12 @@ module.controller('GroupListCtrl', function($scope, $route, $q, realm, groups, g
GroupsCount.query(countParams, function(entry) {
promiseCount.resolve(entry);
}, function() {
- promiseCount.reject('Unable to fetch ' + i);
+ promiseCount.reject('Unable to fetch ' + countParams);
});
var promiseCountChain = promiseCount.promise.then(function(entry) {
groupsCount = entry;
$scope.numberOfPages = Math.ceil(groupsCount.count/$scope.pageSize);
});
-
- $q.all([promiseGetGroupsChain, promiseCountChain]);
};
$scope.$watch('currentPage', function(newValue, oldValue) {
diff --git a/themes/src/main/resources/theme/base/admin/resources/js/loaders.js b/themes/src/main/resources/theme/base/admin/resources/js/loaders.js
index 9b7bab3..fb49c64 100755
--- a/themes/src/main/resources/theme/base/admin/resources/js/loaders.js
+++ b/themes/src/main/resources/theme/base/admin/resources/js/loaders.js
@@ -491,7 +491,7 @@ module.factory('GroupListLoader', function(Loader, Groups, $route, $q) {
return Loader.query(Groups, function() {
return {
realm : $route.current.params.realm,
- first : 1,
+ first : 0,
max : 20
}
});
@@ -501,7 +501,7 @@ module.factory('GroupCountLoader', function(Loader, GroupsCount, $route, $q) {
return Loader.query(GroupsCount, function() {
return {
realm : $route.current.params.realm,
- top : 'true'
+ top : true
}
});
});