mirror of
https://github.com/keycloak/keycloak.git
synced 2026-01-10 15:32:05 -03:30
Allow returning attributes when querying organizations
Closes #34590 Signed-off-by: Himanshi Gupta <higupta@redhat.com> Signed-off-by: Pedro Igor <pigor.craveiro@gmail.com> Co-authored-by: Himanshi Gupta <higupta@redhat.com>
This commit is contained in:
parent
17863d1d4f
commit
cc64375c88
@ -83,6 +83,28 @@ public interface OrganizationsResource {
|
||||
@QueryParam("max") Integer max
|
||||
);
|
||||
|
||||
/**
|
||||
* Returns all organizations that match the specified filters.
|
||||
*
|
||||
* @param search a {@code String} representing either an organization name or domain.
|
||||
* @param exact if {@code true}, the organizations will be searched using exact match for the {@code search} param - i.e.
|
||||
* either the organization name or one of its domains must match exactly the {@code search} param. If false,
|
||||
* the method returns all organizations whose name or (domains) partially match the {@code search} param.
|
||||
* @param first the position of the first result to be processed (pagination offset). Ignored if negative or {@code null}.
|
||||
* @param max the maximum number of results to be returned. Ignored if negative or {@code null}.
|
||||
* @param briefRepresentation if {@code true} the full representation is to be returned. Otherwise, only the basic fields are returned.
|
||||
* @return a list containing the matched organizations.
|
||||
*/
|
||||
@GET
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
List<OrganizationRepresentation> search(
|
||||
@QueryParam("search") String search,
|
||||
@QueryParam("exact") Boolean exact,
|
||||
@QueryParam("first") Integer first,
|
||||
@QueryParam("max") Integer max,
|
||||
@QueryParam("briefRepresentation") Boolean briefRepresentation
|
||||
);
|
||||
|
||||
/**
|
||||
* Returns all organizations that contain attributes matching the specified query.
|
||||
*
|
||||
|
||||
@ -1296,7 +1296,7 @@ public class ModelToRepresentation {
|
||||
}
|
||||
|
||||
public static OrganizationRepresentation toRepresentation(OrganizationModel model) {
|
||||
OrganizationRepresentation rep = toBriefRepresentation(model);
|
||||
OrganizationRepresentation rep = toBriefRepresentation(model,false);
|
||||
if (rep == null) {
|
||||
return null;
|
||||
}
|
||||
@ -1304,7 +1304,7 @@ public class ModelToRepresentation {
|
||||
return rep;
|
||||
}
|
||||
|
||||
public static OrganizationRepresentation toBriefRepresentation(OrganizationModel model) {
|
||||
public static OrganizationRepresentation toBriefRepresentation(OrganizationModel model, Boolean briefRepresentation) {
|
||||
if (model == null) {
|
||||
return null;
|
||||
}
|
||||
@ -1312,6 +1312,9 @@ public class ModelToRepresentation {
|
||||
rep.setId(model.getId());
|
||||
rep.setName(model.getName());
|
||||
rep.setAlias(model.getAlias());
|
||||
if (briefRepresentation) {
|
||||
rep.setAttributes(model.getAttributes());
|
||||
}
|
||||
rep.setEnabled(model.isEnabled());
|
||||
rep.setRedirectUrl(model.getRedirectUrl());
|
||||
rep.setDescription(model.getDescription());
|
||||
|
||||
@ -127,23 +127,24 @@ public class OrganizationsResource {
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
@NoCache
|
||||
@Tag(name = KeycloakOpenAPI.Admin.Tags.ORGANIZATIONS)
|
||||
@Operation( summary = "Returns a paginated list of organizations filtered according to the specified parameters")
|
||||
@Operation(summary = "Returns a paginated list of organizations filtered according to the specified parameters")
|
||||
public Stream<OrganizationRepresentation> search(
|
||||
@Parameter(description = "A String representing either an organization name or domain") @QueryParam("search") String search,
|
||||
@Parameter(description = "A query to search for custom attributes, in the format 'key1:value2 key2:value2'") @QueryParam("q") String searchQuery,
|
||||
@Parameter(description = "Boolean which defines whether the param 'search' must match exactly or not") @QueryParam("exact") Boolean exact,
|
||||
@Parameter(description = "The position of the first result to be processed (pagination offset)") @QueryParam("first") @DefaultValue("0") Integer first,
|
||||
@Parameter(description = "The maximum number of results to be returned - defaults to 10") @QueryParam("max") @DefaultValue("10") Integer max
|
||||
) {
|
||||
@Parameter(description = "The maximum number of results to be returned - defaults to 10") @QueryParam("max") @DefaultValue("10") Integer max,
|
||||
@Parameter(description = "if true, return the full representation. Otherwise, only the basic fields are returned.") @QueryParam("briefRepresentation") @DefaultValue("false") boolean briefRepresentation
|
||||
) {
|
||||
auth.realm().requireManageRealm();
|
||||
Organizations.checkEnabled(provider);
|
||||
|
||||
// check if are searching orgs by attribute.
|
||||
if (StringUtil.isNotBlank(searchQuery)) {
|
||||
Map<String, String> attributes = SearchQueryUtils.getFields(searchQuery);
|
||||
return provider.getAllStream(attributes, first, max).map(ModelToRepresentation::toBriefRepresentation);
|
||||
return provider.getAllStream(attributes, first, max).map(model -> ModelToRepresentation.toBriefRepresentation(model, briefRepresentation));
|
||||
} else {
|
||||
return provider.getAllStream(search, exact, first, max).map(ModelToRepresentation::toBriefRepresentation);
|
||||
return provider.getAllStream(search, exact, first, max).map(model -> ModelToRepresentation.toBriefRepresentation(model, briefRepresentation));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -21,6 +21,7 @@ import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static org.hamcrest.Matchers.containsInAnyOrder;
|
||||
import static org.hamcrest.Matchers.empty;
|
||||
import static org.hamcrest.Matchers.equalTo;
|
||||
import static org.hamcrest.Matchers.hasEntry;
|
||||
import static org.hamcrest.Matchers.hasSize;
|
||||
import static org.hamcrest.Matchers.is;
|
||||
import static org.hamcrest.Matchers.not;
|
||||
@ -43,6 +44,7 @@ import java.util.stream.Collectors;
|
||||
import jakarta.ws.rs.NotFoundException;
|
||||
import jakarta.ws.rs.core.Response;
|
||||
import jakarta.ws.rs.core.Response.Status;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.stream.IntStream;
|
||||
|
||||
@ -147,6 +149,15 @@ public class OrganizationTest extends AbstractOrganizationTest {
|
||||
assertThat(orgRep.getDomain("gtbank.net"), not(nullValue()));
|
||||
assertThat(orgRep.getAttributes(), nullValue());
|
||||
|
||||
orgRep.singleAttribute("foo", "bar");
|
||||
orgRep.singleAttribute("bar", "foo");
|
||||
testRealm().organizations().get(orgRep.getId()).update(orgRep).close();
|
||||
existing = testRealm().organizations().search("gtbank.net", true, 0, 10, true);
|
||||
assertThat(existing, hasSize(1));
|
||||
orgRep = existing.get(0);
|
||||
assertThat(orgRep.getAttributes(), notNullValue());
|
||||
assertThat(2, is(orgRep.getAttributes().size()));
|
||||
|
||||
existing = testRealm().organizations().search("nonexistent.org", true, 0, 10);
|
||||
assertThat(existing, is(empty()));
|
||||
|
||||
@ -268,7 +279,8 @@ public class OrganizationTest extends AbstractOrganizationTest {
|
||||
try {
|
||||
organization.toRepresentation();
|
||||
fail("should be deleted");
|
||||
} catch (NotFoundException ignore) {}
|
||||
} catch (NotFoundException ignore) {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -414,15 +426,18 @@ public class OrganizationTest extends AbstractOrganizationTest {
|
||||
try {
|
||||
testRealm().organizations().getAll();
|
||||
fail("Expected NotFoundException");
|
||||
} catch (NotFoundException expected) {}
|
||||
} catch (NotFoundException expected) {
|
||||
}
|
||||
try {
|
||||
testRealm().organizations().search("*");
|
||||
fail("Expected NotFoundException");
|
||||
} catch (NotFoundException expected) {}
|
||||
} catch (NotFoundException expected) {
|
||||
}
|
||||
try {
|
||||
testRealm().organizations().get(existing.getId()).toRepresentation();
|
||||
fail("Expected NotFoundException");
|
||||
} catch (NotFoundException expected) {}
|
||||
} catch (NotFoundException expected) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -461,8 +476,8 @@ public class OrganizationTest extends AbstractOrganizationTest {
|
||||
@Test
|
||||
public void testCount() {
|
||||
List<String> orgIds = IntStream.range(0, 10)
|
||||
.mapToObj(i -> createOrganization("kc.org." + i).getId())
|
||||
.collect(Collectors.toList());
|
||||
.mapToObj(i -> createOrganization("kc.org." + i).getId())
|
||||
.collect(Collectors.toList());
|
||||
|
||||
getTestingClient().server(TEST_REALM_NAME).run((RunOnServer) session -> {
|
||||
OrganizationProvider orgProvider = session.getProvider(OrganizationProvider.class);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user