Workaround to allow percent chars in getGroupByPath via PathSegment

Closes #25111

Signed-off-by: rmartinc <rmartinc@redhat.com>
This commit is contained in:
rmartinc 2023-12-05 08:47:12 +01:00 committed by Pedro Igor
parent 340eb99412
commit 522e8d2887
3 changed files with 58 additions and 1 deletions

View file

@ -716,6 +716,23 @@ public final class KeycloakModelUtils {
return getGroupModel(session.groups(), realm, null, split, 0);
}
/**
* Finds group by path. Variant when you have the path already separated by
* group names.
*
* @param session Keycloak session
* @param realm The realm
* @param path Path The path hierarchy of groups
*
* @return {@code GroupModel} corresponding to the given {@code path} or {@code null} if no group was found
*/
public static GroupModel findGroupByPath(KeycloakSession session, RealmModel realm, String[] path) {
if (path == null || path.length == 0) {
return null;
}
return getGroupModel(session.groups(), realm, null, path, 0);
}
private static GroupModel getGroupModel(GroupProvider groupProvider, RealmModel realm, GroupModel parent, String[] split, int index) {
StringBuilder nameBuilder = new StringBuilder();
for (int i = index; i < split.length; i++) {

View file

@ -49,6 +49,7 @@ import jakarta.ws.rs.Produces;
import jakarta.ws.rs.QueryParam;
import jakarta.ws.rs.core.HttpHeaders;
import jakarta.ws.rs.core.MediaType;
import jakarta.ws.rs.core.PathSegment;
import jakarta.ws.rs.core.Response;
import jakarta.ws.rs.core.Response.Status;
import jakarta.ws.rs.core.StreamingOutput;
@ -1080,7 +1081,8 @@ public class RealmAdminResource {
@Produces(MediaType.APPLICATION_JSON)
@Tag(name = KeycloakOpenAPI.Admin.Tags.REALMS_ADMIN)
@Operation()
public GroupRepresentation getGroupByPath(@PathParam("path") String path) {
public GroupRepresentation getGroupByPath(@PathParam("path") List<PathSegment> pathSegments) {
String[] path = pathSegments.stream().map(PathSegment::getPath).toArray(String[]::new);
GroupModel found = KeycloakModelUtils.findGroupByPath(session, realm, path);
if (found == null) {
throw new NotFoundException("Group path does not exist");

View file

@ -1299,6 +1299,44 @@ public class GroupTest extends AbstractGroupTest {
assertTrue(searchResultGroups.isEmpty());
}
@Test
public void testGroupsWithSpaces() {
RealmResource realm = adminClient.realms().realm("test");
GroupRepresentation parentGroup = new GroupRepresentation();
parentGroup.setName("parent space");
parentGroup = createGroup(realm, parentGroup);
GroupRepresentation childGroup = new GroupRepresentation();
childGroup.setName("child space");
try (Response response = realm.groups().group(parentGroup.getId()).subGroup(childGroup)) {
assertEquals(201, response.getStatus()); // created status
childGroup.setId(ApiUtil.getCreatedId(response));
}
assertAdminEvents.assertEvent(testRealmId, OperationType.CREATE,
AdminEventPaths.groupSubgroupsPath(parentGroup.getId()), childGroup, ResourceType.GROUP);
List<GroupRepresentation> groupsFound = realm.groups().groups("parent space", true, 0, 1, true);
Assert.assertEquals(1, groupsFound.size());
Assert.assertEquals(parentGroup.getId(), groupsFound.iterator().next().getId());
Assert.assertEquals(0, groupsFound.iterator().next().getSubGroups().size());
groupsFound = realm.groups().groups("child space", true, 0, 1, true);
Assert.assertEquals(1, groupsFound.size());
Assert.assertEquals(parentGroup.getId(), groupsFound.iterator().next().getId());
Assert.assertEquals(1, groupsFound.iterator().next().getSubGroups().size());
Assert.assertEquals(childGroup.getId(), groupsFound.iterator().next().getSubGroups().iterator().next().getId());
GroupRepresentation groupFound = realm.getGroupByPath(parentGroup.getName());
Assert.assertNotNull(groupFound);
Assert.assertEquals(parentGroup.getId(), groupFound.getId());
groupFound = realm.getGroupByPath("/" + parentGroup.getName() + "/" + childGroup.getName());
Assert.assertNotNull(groupFound);
Assert.assertEquals(childGroup.getId(), groupFound.getId());
realm.groups().group(childGroup.getId()).remove();
assertAdminEvents.assertEvent(testRealmId, OperationType.DELETE, AdminEventPaths.groupPath(childGroup.getId()), ResourceType.GROUP);
realm.groups().group(parentGroup.getId()).remove();
assertAdminEvents.assertEvent(testRealmId, OperationType.DELETE, AdminEventPaths.groupPath(parentGroup.getId()), ResourceType.GROUP);
}
/**
* Assert that when you create/move/update a group name, the response is not Http 409 Conflict and the message does not
* correspond to the returned user-friendly message in such cases