diff --git a/model/jpa/src/main/java/org/keycloak/models/jpa/JpaRealmProvider.java b/model/jpa/src/main/java/org/keycloak/models/jpa/JpaRealmProvider.java index 2e15fd04af..17f629fd14 100755 --- a/model/jpa/src/main/java/org/keycloak/models/jpa/JpaRealmProvider.java +++ b/model/jpa/src/main/java/org/keycloak/models/jpa/JpaRealmProvider.java @@ -18,6 +18,7 @@ package org.keycloak.models.jpa; import com.sun.org.apache.xpath.internal.operations.Bool; +import org.apache.commons.codec.binary.StringUtils; import org.jboss.logging.Logger; import org.keycloak.common.util.Time; import org.keycloak.connections.jpa.util.JpaUtils; @@ -335,6 +336,7 @@ public class JpaRealmProvider implements RealmProvider { return ref.getGroups().stream() .map(g -> session.realms().getGroupById(g.getId(), realm)) + .sorted(Comparator.comparing(GroupModel::getName)) .collect(Collectors.collectingAndThen( Collectors.toList(), Collections::unmodifiableList)); } @@ -354,12 +356,7 @@ public class JpaRealmProvider implements RealmProvider { @Override public Long getGroupsCountByNameContaining(RealmModel realm, String search) { - Long count = em.createNamedQuery("getGroupCountByNameContaining", Long.class) - .setParameter("realm", realm.getId()) - .setParameter("name", search) - .getSingleResult(); - - return count; + return (long) searchForGroupByName(realm, search, null, null).size(); } @Override @@ -369,6 +366,7 @@ public class JpaRealmProvider implements RealmProvider { return ref.getGroups().stream() .filter(g -> g.getParent() == null) .map(g -> session.realms().getGroupById(g.getId(), realm)) + .sorted(Comparator.comparing(GroupModel::getName)) .collect(Collectors.collectingAndThen( Collectors.toList(), Collections::unmodifiableList)); } @@ -388,6 +386,8 @@ public class JpaRealmProvider implements RealmProvider { } } + list.sort(Comparator.comparing(GroupModel::getName)); + return Collections.unmodifiableList(list); } @@ -582,7 +582,7 @@ public class JpaRealmProvider implements RealmProvider { @Override public List searchForGroupByName(RealmModel realm, String search, Integer first, Integer max) { - TypedQuery query = em.createNamedQuery("getTopLevelGroupIdsByNameContaining", String.class) + TypedQuery query = em.createNamedQuery("getGroupIdsByNameContaining", String.class) .setParameter("realm", realm.getId()) .setParameter("search", search); if(Objects.nonNull(first) && Objects.nonNull(max)) { @@ -590,10 +590,18 @@ public class JpaRealmProvider implements RealmProvider { } List groups = query.getResultList(); if (Objects.isNull(groups)) return Collections.EMPTY_LIST; - List list = new LinkedList<>(); + List list = new ArrayList<>(); for (String id : groups) { - list.add(session.realms().getGroupById(id, realm)); + GroupModel groupById = session.realms().getGroupById(id, realm); + while(Objects.nonNull(groupById.getParentId())) { + groupById = session.realms().getGroupById(groupById.getParentId(), realm); + } + if(!list.contains(groupById)) { + list.add(groupById); + } } + list.sort(Comparator.comparing(GroupModel::getName)); + return Collections.unmodifiableList(list); } @@ -645,7 +653,7 @@ public class JpaRealmProvider implements RealmProvider { List entities = query.getResultList(); return entities.stream() - .map(entity -> entityToModel(entity)) + .map(this::entityToModel) .collect(Collectors.toList()); } diff --git a/model/jpa/src/main/java/org/keycloak/models/jpa/entities/GroupEntity.java b/model/jpa/src/main/java/org/keycloak/models/jpa/entities/GroupEntity.java index eff0340704..e01ad0c11e 100755 --- a/model/jpa/src/main/java/org/keycloak/models/jpa/entities/GroupEntity.java +++ b/model/jpa/src/main/java/org/keycloak/models/jpa/entities/GroupEntity.java @@ -27,11 +27,10 @@ import java.util.Collection; */ @NamedQueries({ @NamedQuery(name="getGroupIdsByParent", query="select u.id from GroupEntity u where u.parent = :parent"), - @NamedQuery(name="getTopLevelGroupIdsByNameContaining", query="select u.id from GroupEntity u where u.realm.id = :realm and u.name like concat('%',:search,'%') and u.parent is null order by u.name ASC"), + @NamedQuery(name="getGroupIdsByNameContaining", query="select u.id from GroupEntity u where u.realm.id = :realm and u.name like concat('%',:search,'%') order by u.name ASC"), @NamedQuery(name="getTopLevelGroupIds", query="select u.id from GroupEntity u where u.parent is null and u.realm.id = :realm"), @NamedQuery(name="getGroupCount", query="select count(u) from GroupEntity u where u.realm.id = :realm"), - @NamedQuery(name="getTopLevelGroupCount", query="select count(u) from GroupEntity u where u.realm.id = :realm and u.parent is null"), - @NamedQuery(name="getGroupCountByNameContaining", query="select count(u) from GroupEntity u where u.realm.id = :realm and u.name like concat('%',:name,'%')"), + @NamedQuery(name="getTopLevelGroupCount", query="select count(u) from GroupEntity u where u.realm.id = :realm and u.parent is null") }) @Entity @Table(name="KEYCLOAK_GROUP") diff --git a/server-spi/src/main/java/org/keycloak/models/RealmProvider.java b/server-spi/src/main/java/org/keycloak/models/RealmProvider.java index e1a5d5f7f7..d14f2d6256 100755 --- a/server-spi/src/main/java/org/keycloak/models/RealmProvider.java +++ b/server-spi/src/main/java/org/keycloak/models/RealmProvider.java @@ -48,7 +48,7 @@ public interface RealmProvider extends Provider { List getTopLevelGroups(RealmModel realm, Integer first, Integer max); - List searchForGroupByName(RealmModel realm, String search, Integer first, Integer max); + List searchForGroupByName(RealmModel realm, String search, Integer first, Integer max); boolean removeGroup(RealmModel realm, GroupModel group); 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 fed4d94078..23edb675d5 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 @@ -65,7 +65,7 @@ module.controller('GroupListCtrl', function($scope, $route, $q, realm, groups, g $scope.$watch('currentPage', function(newValue, oldValue) { if(newValue !== oldValue) { - refreshGroups(); + refreshGroups($scope.searchTerms); } });