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 e704c399d6..6c92204cca 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 Bill Burke @@ -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 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 count(@QueryParam("search") String search); /** * Counts groups by name search. - * @param search max number of occurrences * @param onlyTopGroups true or false 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 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 bcff0ba591..318bb539c5 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); diff --git a/model/jpa/pom.xml b/model/jpa/pom.xml index 5994089985..54166f5445 100755 --- a/model/jpa/pom.xml +++ b/model/jpa/pom.xml @@ -111,11 +111,6 @@ junit test - - org.mockito - mockito-all - test - diff --git a/model/jpa/src/test/java/org/keycloak/models/jpa/JpaRealmProviderTest.java b/model/jpa/src/test/java/org/keycloak/models/jpa/JpaRealmProviderTest.java deleted file mode 100644 index fc8ffa4ae1..0000000000 --- a/model/jpa/src/test/java/org/keycloak/models/jpa/JpaRealmProviderTest.java +++ /dev/null @@ -1,218 +0,0 @@ -/* - * Copyright 2016 Red Hat, Inc. and/or its affiliates - * and other contributors as indicated by the @author tags. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.keycloak.models.jpa; - -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.keycloak.models.GroupModel; -import org.keycloak.models.KeycloakSession; -import org.keycloak.models.RealmModel; -import org.keycloak.models.RealmProvider; -import org.keycloak.models.jpa.entities.GroupEntity; -import org.mockito.Mockito; -import org.mockito.invocation.InvocationOnMock; -import org.mockito.runners.MockitoJUnitRunner; -import org.mockito.stubbing.Answer; - -import javax.persistence.EntityManager; -import javax.persistence.Query; -import javax.persistence.TypedQuery; -import java.util.*; - -import static org.junit.Assert.assertEquals; -import static org.mockito.Mockito.*; - -/** - * @author NAGY Léventé - * @version $Revision: 1 $ - */ -@RunWith(MockitoJUnitRunner.class) -public class JpaRealmProviderTest { - - private JpaRealmProvider subject; - - private RealmModel realmModelMock; - private RealmProvider realmProviderMock; - private KeycloakSession sessionMock; - private EntityManager entityManagerMock; - - @Before - public void setup() { - realmModelMock = mock(RealmModel.class); - realmProviderMock = mock(RealmProvider.class); - sessionMock = mock(KeycloakSession.class); - entityManagerMock = mock(EntityManager.class); - - subject = new JpaRealmProvider(sessionMock, entityManagerMock); - - // Common behaviours - when(realmProviderMock.getGroupById(anyString(), any(RealmModel.class))).thenAnswer((Answer) invocationOnMock -> { - GroupEntity entity = new GroupEntity(); - entity.setId((String) invocationOnMock.getArguments()[0]); - entity.setName((String) invocationOnMock.getArguments()[0]); - return new GroupAdapter(realmModelMock, entityManagerMock, entity); - }); - } - - @Test - public void testGetGroupsCountAllGroups() { - // Given - Long result = 10L; - String idRealm = "idGroup"; - TypedQuery query = mock(TypedQuery.class); - - // When - when(entityManagerMock.createNamedQuery("getGroupCount", Long.class)).thenReturn(query); - when(realmModelMock.getId()).thenReturn(idRealm); - when(query.setParameter("realm", idRealm)).thenReturn(query); - when(query.getSingleResult()).thenReturn(result); - - // Then - Long countResult = subject.getGroupsCount(realmModelMock, false); - - assertEquals(result, countResult); - } - - @Test - public void testGetGroupsCountOnlyTopLevelGroups() { - // Given - Long result = 10L; - String idRealm = "idGroup"; - TypedQuery query = mock(TypedQuery.class); - - // When - when(entityManagerMock.createNamedQuery("getTopLevelGroupCount", Long.class)).thenReturn(query); - when(realmModelMock.getId()).thenReturn(idRealm); - when(query.setParameter("realm", idRealm)).thenReturn(query); - when(query.getSingleResult()).thenReturn(result); - - // Then - Long countResult = subject.getGroupsCount(realmModelMock, true); - - assertEquals(result, countResult); - } - - @Test - public void testSearchForGroupByNameWithAllParams() { - // Given - List result = Arrays.asList("idGroup1", "idGroup2", "idGroup3"); - String idRealm = "idGroup"; - TypedQuery query = mock(TypedQuery.class); - String search = "findMe"; - Integer first = 0; - Integer max = 10; - - // When - when(entityManagerMock.createNamedQuery("getGroupIdsByNameContaining", String.class)).thenReturn(query); - when(realmModelMock.getId()).thenReturn(idRealm); - when(query.setParameter("realm", idRealm)).thenReturn(query); - when(query.setParameter("search", search)).thenReturn(query); - when(query.setFirstResult(first)).thenReturn(query); - when(query.setMaxResults(max)).thenReturn(query); - when(query.getResultList()).thenReturn(result); - when(sessionMock.realms()).thenReturn(realmProviderMock); - - // Then - List searchResult = subject.searchForGroupByName(realmModelMock, search, first, max); - - assertEquals(result.size(), searchResult.size()); - } - - @Test - public void testSearchForGroupByNameWithNullQueryResult() { - // Given - String idRealm = "idGroup"; - TypedQuery query = mock(TypedQuery.class); - String search = "findMe"; - - // When - when(entityManagerMock.createNamedQuery("getGroupIdsByNameContaining", String.class)).thenReturn(query); - when(realmModelMock.getId()).thenReturn(idRealm); - when(query.setParameter("realm", idRealm)).thenReturn(query); - when(query.setParameter("search", search)).thenReturn(query); - when(query.getResultList()).thenReturn(null); - when(sessionMock.realms()).thenReturn(realmProviderMock); - - // Then - List searchResult = subject.searchForGroupByName(realmModelMock, search, null, null); - - assertEquals(Collections.EMPTY_LIST, searchResult); - } - - @Test - public void testSearchForGroupByNameWithNonTopLevelGroupInQueryResult() { - // Given - List result = Arrays.asList("idGroup1", "idGroup2", "idGroup3", "idGroup4"); - String idRealm = "idGroup"; - TypedQuery query = mock(TypedQuery.class); - String search = "findMe"; - Integer first = 0; - Integer max = 10; - - // When - when(entityManagerMock.createNamedQuery("getGroupIdsByNameContaining", String.class)).thenReturn(query); - when(realmModelMock.getId()).thenReturn(idRealm); - when(query.setParameter("realm", idRealm)).thenReturn(query); - when(query.setParameter("search", search)).thenReturn(query); - when(query.setFirstResult(first)).thenReturn(query); - when(query.setMaxResults(max)).thenReturn(query); - when(query.getResultList()).thenReturn(result); - when(sessionMock.realms()).thenReturn(realmProviderMock); - when(realmProviderMock.getGroupById(anyString(), any(RealmModel.class))).thenAnswer((Answer) invocationOnMock -> { - GroupEntity entity = new GroupEntity(); - entity.setId((String) invocationOnMock.getArguments()[0]); - entity.setName((String) invocationOnMock.getArguments()[0]); - if(Arrays.asList("idGroup2", "idGroup4").contains(invocationOnMock.getArguments()[0])) { - entity.setParent(new GroupEntity()); - entity.getParent().setId("idGroup5"); - entity.getParent().setName("idGroup5"); - } - return new GroupAdapter(realmModelMock, entityManagerMock, entity); - }); - - // Then - List searchResult = subject.searchForGroupByName(realmModelMock, search, first, max); - - assertEquals(3,searchResult.size()); - } - - @Test - public void testGetGroupsCountByNameContaining() { - // Given - List result = Arrays.asList("idGroup1", "idGroup2", "idGroup3", "idGroup4"); - String idRealm = "idGroup"; - TypedQuery query = mock(TypedQuery.class); - String search = "findMe"; - - // When - when(entityManagerMock.createNamedQuery("getGroupIdsByNameContaining", String.class)).thenReturn(query); - when(realmModelMock.getId()).thenReturn(idRealm); - when(query.setParameter("realm", idRealm)).thenReturn(query); - when(query.setParameter("search", search)).thenReturn(query); - when(query.getResultList()).thenReturn(result); - when(sessionMock.realms()).thenReturn(realmProviderMock); - - // Then - Long countResult = subject.getGroupsCountByNameContaining(realmModelMock, search); - - verify(query, never()).setFirstResult(anyInt()); - verify(query, never()).setFirstResult(anyInt()); - assertEquals(result.size(), countResult.intValue()); - } -} diff --git a/pom.xml b/pom.xml index e437123938..8b216dcbef 100755 --- a/pom.xml +++ b/pom.xml @@ -108,7 +108,6 @@ 1.3 2.10 4.12 - 1.9.5 2.7.0.Final 2.35.0 1.4.01 @@ -368,12 +367,6 @@ ${junit.version} test - - org.mockito - mockito-all - test - ${mockito.version} - org.hamcrest hamcrest-all diff --git a/services/pom.xml b/services/pom.xml index cbbf3da206..733b81277e 100755 --- a/services/pom.xml +++ b/services/pom.xml @@ -180,11 +180,6 @@ - - org.mockito - mockito-all - test - 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 958b995786..15be7ae029 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 getGroupCount(@QueryParam("search") String search, + @QueryParam("top") @DefaultValue("false") boolean onlyTopGroups) { Long results; - JSONObject response = new JSONObject(); + Map 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/services/src/test/java/org/keycloak/services/resources/admin/GroupsResourceTest.java b/services/src/test/java/org/keycloak/services/resources/admin/GroupsResourceTest.java deleted file mode 100644 index 9783bbb065..0000000000 --- a/services/src/test/java/org/keycloak/services/resources/admin/GroupsResourceTest.java +++ /dev/null @@ -1,230 +0,0 @@ -/* - * Copyright 2016 Red Hat, Inc. and/or its affiliates - * and other contributors as indicated by the @author tags. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.keycloak.services.resources.admin; - - -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; -import org.keycloak.events.admin.ResourceType; -import org.keycloak.models.GroupModel; -import org.keycloak.models.KeycloakSession; -import org.keycloak.models.RealmModel; -import org.keycloak.representations.idm.GroupRepresentation; -import org.keycloak.services.resources.admin.permissions.AdminPermissionEvaluator; -import org.keycloak.services.resources.admin.permissions.GroupPermissionEvaluator; -import twitter4j.JSONException; -import twitter4j.JSONObject; - -import javax.ws.rs.core.MediaType; -import javax.ws.rs.core.Response; -import java.util.Collections; -import java.util.List; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.fail; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - -/** - * @author NAGY Léventé - * @version $Revision: 1 $ - */ -public class GroupsResourceTest { - - private GroupsResource subject; - - private RealmModel realmMock; - private KeycloakSession sessionMock; - private AdminPermissionEvaluator authMock; - private AdminEventBuilder adminEventBuilderMock; - - @Before - public void setup() { - realmMock = mock(RealmModel.class); - sessionMock = mock(KeycloakSession.class); - authMock = mock(AdminPermissionEvaluator.class); - when(authMock.groups()).thenReturn(mock(GroupPermissionEvaluator.class)); - - adminEventBuilderMock = mock(AdminEventBuilder.class); - when(adminEventBuilderMock.resource(ResourceType.GROUP)).thenReturn(adminEventBuilderMock); - - subject= new GroupsResource(realmMock, sessionMock, authMock, adminEventBuilderMock); - } - - @Test - public void testGetGroupWithAllParams() { - // Given - String search = "hello"; - Integer first = 0; - Integer max = 20; - String groupId = "groupId"; - String groupName = "groupName"; - GroupModel groupMock = mock(GroupModel.class); - List groupsList = Collections.singletonList(groupMock); - - // When - when(realmMock.searchForGroupByName(search, first, max)).thenReturn(groupsList); - when(groupMock.getSubGroups()).thenReturn(Collections.EMPTY_SET); - when(groupMock.getId()).thenReturn(groupId); - when(groupMock.getName()).thenReturn(groupName); - when(groupMock.getParent()).thenReturn(null); - - //Then - List result = subject.getGroups(search, first,max); - - Assert.assertEquals(groupsList.size(), result.size()); - Assert.assertEquals(groupId, result.get(0).getId()); - Assert.assertEquals(groupName, result.get(0).getName()); - Assert.assertTrue(result.get(0).getSubGroups().isEmpty()); - } - - @Test - public void testGetGroupWithoutSearch() { - // Given - Integer first = 0; - Integer max = 20; - String groupId = "groupId"; - String groupName = "groupName"; - GroupModel groupMock = mock(GroupModel.class); - List groupsList = Collections.singletonList(groupMock); - - // When - when(realmMock.getTopLevelGroups(first, max)).thenReturn(groupsList); - when(groupMock.getSubGroups()).thenReturn(Collections.EMPTY_SET); - when(groupMock.getId()).thenReturn(groupId); - when(groupMock.getName()).thenReturn(groupName); - when(groupMock.getParent()).thenReturn(null); - - //Then - List result = subject.getGroups(null, first,max); - - Assert.assertEquals(groupsList.size(), result.size()); - Assert.assertEquals(groupId, result.get(0).getId()); - Assert.assertEquals(groupName, result.get(0).getName()); - Assert.assertTrue(result.get(0).getSubGroups().isEmpty()); - } - - @Test - public void testGetGroupWithoutSearchAndPagination() { - // Given - String groupId = "groupId"; - String groupName = "groupName"; - GroupModel groupMock = mock(GroupModel.class); - List groupsList = Collections.singletonList(groupMock); - - // When - when(realmMock.getTopLevelGroups()).thenReturn(groupsList); - when(groupMock.getSubGroups()).thenReturn(Collections.EMPTY_SET); - when(groupMock.getId()).thenReturn(groupId); - when(groupMock.getName()).thenReturn(groupName); - when(groupMock.getParent()).thenReturn(null); - - //Then - List result = subject.getGroups(null, null, null); - - Assert.assertEquals(groupsList.size(), result.size()); - Assert.assertEquals(groupId, result.get(0).getId()); - Assert.assertEquals(groupName, result.get(0).getName()); - Assert.assertTrue(result.get(0).getSubGroups().isEmpty()); - } - - @Test - public void testGetGroupCountWithSearchAndTopLevelFlagTrue() { - // Given - String search = "search"; - Long countResult = 5L; - JSONObject response = new JSONObject(); - try { - response.put("count", countResult); - } catch (JSONException e) { - fail(e.getMessage()); - } - - // When - when(realmMock.getGroupsCountByNameContaining(search)).thenReturn(countResult); - - //Then - Response restResponse = subject.getGroupCount(search, "true"); - - assertEquals(response.toString(), restResponse.getEntity()); - assertEquals(MediaType.APPLICATION_JSON, restResponse.getMediaType().toString()); - } - - @Test - public void testGetGroupCountWithoutSearchAndTopLevelFlagTrue() { - // Given - Long countResult = 5L; - JSONObject response = new JSONObject(); - try { - response.put("count", countResult); - } catch (JSONException e) { - fail(e.getMessage()); - } - - // When - when(realmMock.getGroupsCount(true)).thenReturn(countResult); - - //Then - Response restResponse = subject.getGroupCount(null, "true"); - - assertEquals(response.toString(), restResponse.getEntity()); - assertEquals(MediaType.APPLICATION_JSON, restResponse.getMediaType().toString()); - } - - @Test - public void testGetGroupCountWithoutSearchAndTopLevelFlagFalse() { - // Given - Long countResult = 5L; - JSONObject response = new JSONObject(); - try { - response.put("count", countResult); - } catch (JSONException e) { - fail(e.getMessage()); - } - - // When - when(realmMock.getGroupsCount(false)).thenReturn(countResult); - - //Then - Response restResponse = subject.getGroupCount(null, "false"); - - assertEquals(response.toString(), restResponse.getEntity()); - assertEquals(MediaType.APPLICATION_JSON, restResponse.getMediaType().toString()); - } - - @Test - public void testGetGroupCountWithoutSearchAndTopLevelFlagNull() { - // Given - Long countResult = 5L; - JSONObject response = new JSONObject(); - try { - response.put("count", countResult); - } catch (JSONException e) { - fail(e.getMessage()); - } - - // When - when(realmMock.getGroupsCount(false)).thenReturn(countResult); - - //Then - Response restResponse = subject.getGroupCount(null, null); - - assertEquals(response.toString(), restResponse.getEntity()); - assertEquals(MediaType.APPLICATION_JSON, restResponse.getMediaType().toString()); - } -} 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 b7274ecbe3..fd58f7590a 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 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 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 allGroups = realm.groups().groups(); + assertEquals(20, allGroups.size()); + + List slice = realm.groups().groups(5, 7); + assertEquals(7, slice.size()); + + List search = realm.groups().groups("group1",0,20); + assertEquals(11, search.size()); + for(GroupRepresentation group : search) { + assertTrue(group.getName().contains("group1")); + } + + List 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 23edb675d5..bc3691f9df 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 9b7bab3bda..fb49c64f10 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 } }); });