KEYCLOAK-18390 GroupProvider search implementation of JPA and Map delivers different results
This commit is contained in:
parent
c1168ea6ea
commit
ca6b78b730
3 changed files with 51 additions and 3 deletions
|
@ -178,8 +178,15 @@ public class MapGroupProvider<K> implements GroupProvider {
|
||||||
(ModelCriteriaBuilder<GroupModel> mcb) -> mcb.compare(SearchableFields.NAME, Operator.ILIKE, "%" + search + "%")
|
(ModelCriteriaBuilder<GroupModel> mcb) -> mcb.compare(SearchableFields.NAME, Operator.ILIKE, "%" + search + "%")
|
||||||
);
|
);
|
||||||
|
|
||||||
|
final Stream<String> groups = paginatedStream(groupModelStream.map(GroupModel::getId), firstResult, maxResults);
|
||||||
|
|
||||||
return paginatedStream(groupModelStream, firstResult, maxResults);
|
return groups.map(id -> {
|
||||||
|
GroupModel groupById = session.groups().getGroupById(realm,id);
|
||||||
|
while (Objects.nonNull(groupById.getParentId())) {
|
||||||
|
groupById = session.groups().getGroupById(realm, groupById.getParentId());
|
||||||
|
}
|
||||||
|
return groupById;
|
||||||
|
}).sorted(GroupModel.COMPARE_BY_NAME).distinct();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -50,13 +50,17 @@ public interface GroupLookupProvider {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns groups with the given string in name for the given realm.
|
* Returns the group hierarchy with the given string in name for the given realm.
|
||||||
|
*
|
||||||
|
* For a matching group node the parent group is fetched by id (with all children) and added to the result stream.
|
||||||
|
* This is done until the group node does not have a parent (root group)
|
||||||
*
|
*
|
||||||
* @param realm Realm.
|
* @param realm Realm.
|
||||||
* @param search Case sensitive searched string.
|
* @param search Case sensitive searched string.
|
||||||
* @param firstResult First result to return. Ignored if negative or {@code null}.
|
* @param firstResult First result to return. Ignored if negative or {@code null}.
|
||||||
* @param maxResults Maximum number of results to return. Ignored if negative or {@code null}.
|
* @param maxResults Maximum number of results to return. Ignored if negative or {@code null}.
|
||||||
* @return Stream of groups with the given string in name. Never returns {@code null}.
|
* @return Stream of root groups that have the given string in their name themself or a group in their child-collection has.
|
||||||
|
* The returned hierarchy contains siblings that do not necessarily have a matching name. Never returns {@code null}.
|
||||||
*/
|
*/
|
||||||
Stream<GroupModel> searchForGroupByNameStream(RealmModel realm, String search, Integer firstResult, Integer maxResults);
|
Stream<GroupModel> searchForGroupByNameStream(RealmModel realm, String search, Integer firstResult, Integer maxResults);
|
||||||
|
|
||||||
|
|
|
@ -1078,4 +1078,41 @@ public class GroupTest extends AbstractGroupTest {
|
||||||
user.remove();
|
user.remove();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Verifies that the group search works the same across group provider implementations for hierarchies
|
||||||
|
* @link https://issues.jboss.org/browse/KEYCLOAK-18390
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void searchGroupsOnGroupHierarchies() throws Exception {
|
||||||
|
final RealmResource realm = this.adminClient.realms().realm("test");
|
||||||
|
|
||||||
|
final String searchFor = UUID.randomUUID().toString();
|
||||||
|
|
||||||
|
final GroupRepresentation g1 = new GroupRepresentation();
|
||||||
|
g1.setName("g1");
|
||||||
|
final GroupRepresentation g1_1 = new GroupRepresentation();
|
||||||
|
g1_1.setName("g1.1-" + searchFor);
|
||||||
|
|
||||||
|
createGroup(realm, g1);
|
||||||
|
addSubGroup(realm, g1, g1_1);
|
||||||
|
|
||||||
|
final GroupRepresentation expectedRootGroup = realm.groups().group(g1.getId()).toRepresentation();
|
||||||
|
final GroupRepresentation expectedChildGroup = realm.groups().group(g1_1.getId()).toRepresentation();
|
||||||
|
|
||||||
|
final List<GroupRepresentation> searchResultGroups = realm.groups().groups(searchFor, 0, 10);
|
||||||
|
|
||||||
|
Assert.assertFalse(searchResultGroups.isEmpty());
|
||||||
|
Assert.assertEquals(expectedRootGroup.getId(), searchResultGroups.get(0).getId());
|
||||||
|
Assert.assertEquals(expectedRootGroup.getName(), searchResultGroups.get(0).getName());
|
||||||
|
|
||||||
|
List<GroupRepresentation> searchResultSubGroups = searchResultGroups.get(0).getSubGroups();
|
||||||
|
Assert.assertEquals(expectedChildGroup.getId(), searchResultSubGroups.get(0).getId());
|
||||||
|
Assert.assertEquals(expectedChildGroup.getName(), searchResultSubGroups.get(0).getName());
|
||||||
|
|
||||||
|
searchResultSubGroups.remove(0);
|
||||||
|
Assert.assertTrue(searchResultSubGroups.isEmpty());
|
||||||
|
searchResultGroups.remove(0);
|
||||||
|
Assert.assertTrue(searchResultGroups.isEmpty());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue