Ensure identity providers returned to the org IDP selection are IDPs not associated with any orgs.
Closes #32238 Signed-off-by: Stefan Guilhen <sguilhen@redhat.com>
This commit is contained in:
parent
be766c751a
commit
585d179fe0
8 changed files with 38 additions and 44 deletions
|
@ -47,7 +47,15 @@ public interface IdentityProvidersResource {
|
|||
@GET
|
||||
@Path("instances")
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
List<IdentityProviderRepresentation> find(@QueryParam("search") String search, @QueryParam("briefRepresentation") Boolean briefRepresentation, @QueryParam("first") Integer firstResult, @QueryParam("max") Integer maxResults);
|
||||
List<IdentityProviderRepresentation> find(@QueryParam("search") String search, @QueryParam("briefRepresentation") Boolean briefRepresentation,
|
||||
@QueryParam("first") Integer firstResult, @QueryParam("max") Integer maxResults);
|
||||
|
||||
@GET
|
||||
@Path("instances")
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
List<IdentityProviderRepresentation> find(@QueryParam("search") String search, @QueryParam("briefRepresentation") Boolean briefRepresentation,
|
||||
@QueryParam("first") Integer firstResult, @QueryParam("max") Integer maxResults,
|
||||
@QueryParam("realmOnly") Boolean realmOnly);
|
||||
|
||||
@POST
|
||||
@Path("instances")
|
||||
|
|
|
@ -63,13 +63,14 @@ export const IdentityProviderSelect = ({
|
|||
async () => {
|
||||
const params: IdentityProvidersQuery = {
|
||||
max: 20,
|
||||
realmOnly: true,
|
||||
};
|
||||
if (search) {
|
||||
params.search = search;
|
||||
}
|
||||
|
||||
const idps = await adminClient.identityProviders.find(params);
|
||||
return idps.filter((i) => !i.config?.["kc.org"]);
|
||||
return idps;
|
||||
},
|
||||
setIdps,
|
||||
[search],
|
||||
|
|
|
@ -12,6 +12,7 @@ export interface PaginatedQuery {
|
|||
|
||||
export interface IdentityProvidersQuery extends PaginatedQuery {
|
||||
search?: string;
|
||||
realmOnly?: boolean;
|
||||
}
|
||||
|
||||
export class IdentityProviders extends Resource<{ realm?: string }> {
|
||||
|
|
|
@ -137,11 +137,6 @@ public class InfinispanIDPProvider implements IDPProvider {
|
|||
return idpDelegate.getByFlow(flowId, search, first, max);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Stream<IdentityProviderModel> getAllStream(String search, Integer first, Integer max) {
|
||||
return idpDelegate.getAllStream(search, first, max);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Stream<IdentityProviderModel> getAllStream(Map<String, String> attrs, Integer first, Integer max) {
|
||||
return idpDelegate.getAllStream(attrs, first, max);
|
||||
|
|
|
@ -54,6 +54,7 @@ import static org.keycloak.models.IdentityProviderModel.HIDE_ON_LOGIN;
|
|||
import static org.keycloak.models.IdentityProviderModel.LINK_ONLY;
|
||||
import static org.keycloak.models.IdentityProviderModel.ORGANIZATION_ID;
|
||||
import static org.keycloak.models.IdentityProviderModel.POST_BROKER_LOGIN_FLOW_ID;
|
||||
import static org.keycloak.models.IdentityProviderModel.SEARCH;
|
||||
import static org.keycloak.models.jpa.PaginationUtils.paginateQuery;
|
||||
import static org.keycloak.utils.StreamsUtil.closing;
|
||||
|
||||
|
@ -205,24 +206,6 @@ public class JpaIDPProvider implements IDPProvider {
|
|||
return toModel(getEntityByAlias(alias));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Stream<IdentityProviderModel> getAllStream(String search, Integer first, Integer max) {
|
||||
CriteriaBuilder builder = em.getCriteriaBuilder();
|
||||
CriteriaQuery<IdentityProviderEntity> query = builder.createQuery(IdentityProviderEntity.class);
|
||||
Root<IdentityProviderEntity> idp = query.from(IdentityProviderEntity.class);
|
||||
|
||||
List<Predicate> predicates = new ArrayList<>();
|
||||
predicates.add(builder.equal(idp.get("realmId"), getRealm().getId()));
|
||||
|
||||
if (StringUtil.isNotBlank(search)) {
|
||||
predicates.add(this.getAliasSearchPredicate(search, builder, idp));
|
||||
}
|
||||
|
||||
query.orderBy(builder.asc(idp.get(ALIAS)));
|
||||
TypedQuery<IdentityProviderEntity> typedQuery = em.createQuery(query.select(idp).where(predicates.toArray(Predicate[]::new)));
|
||||
return closing(paginateQuery(typedQuery, first, max).getResultStream()).map(this::toModel);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Stream<IdentityProviderModel> getAllStream(Map<String, String> attrs, Integer first, Integer max) {
|
||||
CriteriaBuilder builder = em.getCriteriaBuilder();
|
||||
|
@ -259,6 +242,12 @@ public class JpaIDPProvider implements IDPProvider {
|
|||
predicates.add(builder.equal(idp.get(key), value));
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SEARCH: {
|
||||
if (StringUtil.isNotBlank(value)) {
|
||||
predicates.add(this.getAliasSearchPredicate(value, builder, idp));
|
||||
}
|
||||
break;
|
||||
} default: {
|
||||
String dbProductName = em.unwrap(Session.class).doReturningWork(connection -> connection.getMetaData().getDatabaseProductName());
|
||||
MapJoin<IdentityProviderEntity, String, String> configJoin = idp.joinMap("config");
|
||||
|
|
|
@ -16,7 +16,6 @@
|
|||
*/
|
||||
package org.keycloak.models;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
|
@ -99,22 +98,9 @@ public interface IDPProvider extends Provider {
|
|||
* @return a non-null stream of {@link IdentityProviderModel}s.
|
||||
*/
|
||||
default Stream<IdentityProviderModel> getAllStream() {
|
||||
return getAllStream("", null, null);
|
||||
return getAllStream(Map.of(), null, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns all identity providers in the realm filtered according to the specified parameters.
|
||||
*
|
||||
* @param search a {@link String} representing an identity provider alias (partial or exact). If the value is enclosed
|
||||
* in double quotes, the method treats it as an exact search (e.g. {@code "name"}). If the value is enclosed in
|
||||
* wildcards, the method treats it as an infix search (e.g. {@code *name*}). Otherwise, the method treats it as a
|
||||
* prefix search (i.e. {@code name*} and {@code name} return the same results).
|
||||
* @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}.
|
||||
* @return a non-null stream of {@link IdentityProviderModel}s that match the search criteria.
|
||||
*/
|
||||
Stream<IdentityProviderModel> getAllStream(String search, Integer first, Integer max);
|
||||
|
||||
/**
|
||||
* Returns all identity providers in the realm filtered according to the specified parameters.
|
||||
*
|
||||
|
@ -134,7 +120,7 @@ public interface IDPProvider extends Provider {
|
|||
* @return a non-null stream of {@link IdentityProviderModel}s that match the search criteria.
|
||||
*/
|
||||
default Stream<IdentityProviderModel> getByOrganization(String orgId, Integer first, Integer max) {
|
||||
return getAllStream(Map.of(IdentityProviderModel.ORGANIZATION_ID, orgId), first, max);
|
||||
return getAllStream(Map.of(IdentityProviderModel.ORGANIZATION_ID, orgId != null ? orgId : ""), first, max);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -50,6 +50,7 @@ public class IdentityProviderModel implements Serializable {
|
|||
public static final String ORGANIZATION_ID = "organizationId";
|
||||
public static final String PASS_MAX_AGE = "passMaxAge";
|
||||
public static final String POST_BROKER_LOGIN_FLOW_ID = "postBrokerLoginFlowId";
|
||||
public static final String SEARCH = "search";
|
||||
public static final String SYNC_MODE = "syncMode";
|
||||
|
||||
private String internalId;
|
||||
|
|
|
@ -55,7 +55,10 @@ import jakarta.ws.rs.QueryParam;
|
|||
import jakarta.ws.rs.core.MediaType;
|
||||
import jakarta.ws.rs.core.MultivaluedMap;
|
||||
import jakarta.ws.rs.core.Response;
|
||||
import org.keycloak.utils.StringUtil;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
|
@ -180,18 +183,28 @@ public class IdentityProvidersResource {
|
|||
@Parameter(description = "Filter specific providers by name. Search can be prefix (name*), contains (*name*) or exact (\"name\"). Default prefixed.") @QueryParam("search") String search,
|
||||
@Parameter(description = "Boolean which defines whether brief representations are returned (default: false)") @QueryParam("briefRepresentation") Boolean briefRepresentation,
|
||||
@Parameter(description = "Pagination offset") @QueryParam("first") Integer firstResult,
|
||||
@Parameter(description = "Maximum results size (defaults to 100)") @QueryParam("max") Integer maxResults) {
|
||||
@Parameter(description = "Maximum results size (defaults to 100)") @QueryParam("max") Integer maxResults,
|
||||
@Parameter(description = "Boolean which defines if only realm-level IDPs (not associated with orgs) should be returned (default: false)") @QueryParam("realmOnly") Boolean realmOnly) {
|
||||
this.auth.realm().requireViewIdentityProviders();
|
||||
|
||||
if (maxResults == null) {
|
||||
maxResults = 100; // always set a maximum of 100 by default
|
||||
}
|
||||
|
||||
Function<IdentityProviderModel, IdentityProviderRepresentation> toRepresentation = Optional.<Boolean>ofNullable(briefRepresentation).orElse(false)
|
||||
Function<IdentityProviderModel, IdentityProviderRepresentation> toRepresentation = Optional.ofNullable(briefRepresentation).orElse(false)
|
||||
? m -> ModelToRepresentation.toBriefRepresentation(realm, m)
|
||||
: m -> StripSecretsUtils.stripSecrets(session, ModelToRepresentation.toRepresentation(realm, m));
|
||||
|
||||
return session.identityProviders().getAllStream(search, firstResult, maxResults).map(toRepresentation);
|
||||
boolean searchRealmOnlyIDPs = Optional.ofNullable(realmOnly).orElse(false);
|
||||
|
||||
Map<String, String> searchOptions = new HashMap<>();
|
||||
if (StringUtil.isNotBlank(search)) {
|
||||
searchOptions.put(IdentityProviderModel.SEARCH, search);
|
||||
}
|
||||
if (searchRealmOnlyIDPs) {
|
||||
searchOptions.put(IdentityProviderModel.ORGANIZATION_ID, null);
|
||||
}
|
||||
return session.identityProviders().getAllStream(searchOptions, firstResult, maxResults).map(toRepresentation);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
Loading…
Reference in a new issue