Extend group search attribute functionality to account for use case where only the leaf group is required
This commit is contained in:
parent
9bc30f4705
commit
7e56938b74
4 changed files with 42 additions and 8 deletions
|
@ -146,4 +146,8 @@ public interface GroupsResource {
|
|||
@GET
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
List<GroupRepresentation> query(@QueryParam("q") String searchQuery);
|
||||
|
||||
@GET
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
List<GroupRepresentation> query(@QueryParam("q") String searchQuery, @QueryParam("populateHierarchy") boolean populateHierarchy);
|
||||
}
|
||||
|
|
|
@ -150,8 +150,10 @@ public class ModelToRepresentation {
|
|||
return rep;
|
||||
}
|
||||
|
||||
public static Stream<GroupRepresentation> searchGroupsByAttributes(KeycloakSession session, RealmModel realm, boolean full, Map<String,String> attributes, Integer first, Integer max) {
|
||||
return session.groups().searchGroupsByAttributes(realm, attributes, first, max)
|
||||
public static Stream<GroupRepresentation> searchGroupsByAttributes(KeycloakSession session, RealmModel realm, boolean full, boolean populateHierarchy, Map<String,String> attributes, Integer first, Integer max) {
|
||||
Stream<GroupModel> groups = session.groups().searchGroupsByAttributes(realm, attributes, first, max);
|
||||
if(populateHierarchy) {
|
||||
groups = groups
|
||||
// We need to return whole group hierarchy when any child group fulfills the attribute search,
|
||||
// therefore for each group from the result, we need to find root group
|
||||
.map(group -> {
|
||||
|
@ -162,10 +164,10 @@ public class ModelToRepresentation {
|
|||
})
|
||||
|
||||
// More child groups of one root can fulfill the search, so we need to filter duplicates
|
||||
.filter(StreamsUtil.distinctByKey(GroupModel::getId))
|
||||
|
||||
.filter(StreamsUtil.distinctByKey(GroupModel::getId));
|
||||
}
|
||||
// and then turn the result into GroupRepresentations creating whole hierarchy of child groups for each root group
|
||||
.map(g -> toGroupHierarchy(g, full, attributes));
|
||||
return groups.map(g -> toGroupHierarchy(g, full, attributes));
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
|
|
|
@ -79,12 +79,13 @@ public class GroupsResource {
|
|||
@QueryParam("exact") @DefaultValue("false") Boolean exact,
|
||||
@QueryParam("first") Integer firstResult,
|
||||
@QueryParam("max") Integer maxResults,
|
||||
@QueryParam("briefRepresentation") @DefaultValue("true") boolean briefRepresentation) {
|
||||
@QueryParam("briefRepresentation") @DefaultValue("true") boolean briefRepresentation,
|
||||
@QueryParam("populateHierarchy") @DefaultValue("true") boolean populateHierarchy) {
|
||||
auth.groups().requireList();
|
||||
|
||||
if (Objects.nonNull(searchQuery)) {
|
||||
Map<String, String> attributes = SearchQueryUtils.getFields(searchQuery);
|
||||
return ModelToRepresentation.searchGroupsByAttributes(session, realm, !briefRepresentation, attributes, firstResult, maxResults);
|
||||
return ModelToRepresentation.searchGroupsByAttributes(session, realm, !briefRepresentation, populateHierarchy, attributes, firstResult, maxResults);
|
||||
} else if (Objects.nonNull(search)) {
|
||||
return ModelToRepresentation.searchForGroupByName(session, realm, !briefRepresentation, search.trim(), exact, firstResult, maxResults);
|
||||
} else if(Objects.nonNull(firstResult) && Objects.nonNull(maxResults)) {
|
||||
|
|
|
@ -4,6 +4,7 @@ import static org.hamcrest.CoreMatchers.is;
|
|||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static org.hamcrest.Matchers.containsInAnyOrder;
|
||||
import static org.hamcrest.Matchers.equalTo;
|
||||
import static org.hamcrest.Matchers.hasSize;
|
||||
import static org.keycloak.testsuite.auth.page.AuthRealm.TEST;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
@ -143,11 +144,37 @@ public class GroupSearchTest extends AbstractGroupTest {
|
|||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNestedGroupQuerySearchNoHierarchy() throws Exception {
|
||||
configureSearchableAttributes(ATTR_URL_NAME, ATTR_ORG_NAME, ATTR_QUOTES_NAME);
|
||||
try (Creator<GroupResource> parentGroupCreator = Creator.create(testRealmResource(), parentGroup)) {
|
||||
parentGroupCreator.resource().subGroup(childGroup);
|
||||
|
||||
GroupRepresentation testGroup = new GroupRepresentation();
|
||||
testGroup.setName("test_child");
|
||||
parentGroupCreator.resource().subGroup(testGroup);
|
||||
|
||||
// query for the child group by org name
|
||||
GroupsResource search = testRealmResource().groups();
|
||||
String searchQuery = String.format("%s:%s", ATTR_ORG_NAME, "childOrg");
|
||||
List<GroupRepresentation> found = search.query(searchQuery, false);
|
||||
|
||||
assertThat(found.size(), is(1));
|
||||
assertThat(found.get(0).getName(), is(equalTo(CHILD_GROUP)));
|
||||
|
||||
String path = found.get(0).getPath();
|
||||
assertThat(path, is(String.format("/%s/%s", PARENT_GROUP, CHILD_GROUP)));
|
||||
} finally {
|
||||
resetSearchableAttributes();
|
||||
}
|
||||
}
|
||||
|
||||
private void search(String searchQuery, String... expectedGroupIds) {
|
||||
GroupsResource search = testRealmResource().groups();
|
||||
List<String> found = search.query(searchQuery).stream()
|
||||
.map(GroupRepresentation::getName)
|
||||
.collect(Collectors.toList());
|
||||
assertThat(found, hasSize(expectedGroupIds.length));
|
||||
assertThat(found, containsInAnyOrder(expectedGroupIds));
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue