KEYCLOAK-14220 Complement methods for accessing clients with Stream variants
This commit is contained in:
parent
da6530471b
commit
feef5b4db2
21 changed files with 392 additions and 247 deletions
|
@ -612,18 +612,18 @@ public class ClientAdapter implements ClientModel, CachedObject {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Set<RoleModel> getRoles() {
|
public Stream<RoleModel> getRolesStream() {
|
||||||
return cacheSession.getClientRoles(cachedRealm, this);
|
return cacheSession.getClientRolesStream(cachedRealm, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Set<RoleModel> getRoles(Integer first, Integer max) {
|
public Stream<RoleModel> getRolesStream(Integer first, Integer max) {
|
||||||
return cacheSession.getClientRoles(cachedRealm, this, first, max);
|
return cacheSession.getClientRolesStream(cachedRealm, this, first, max);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Set<RoleModel> searchForRoles(String search, Integer first, Integer max) {
|
public Stream<RoleModel> searchForRolesStream(String search, Integer first, Integer max) {
|
||||||
return cacheSession.searchForClientRoles(cachedRealm, this, search, first, max);
|
return cacheSession.searchForClientRolesStream(cachedRealm, this, search, first, max);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -29,6 +29,7 @@ import org.keycloak.storage.client.ClientStorageProvider;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||||
|
@ -755,13 +756,13 @@ public class RealmAdapter implements CachedRealmModel {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<ClientModel> getClients() {
|
public Stream<ClientModel> getClientsStream() {
|
||||||
return cacheSession.getClients(this);
|
return cacheSession.getClientsStream(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<ClientModel> getAlwaysDisplayInConsoleClients() {
|
public Stream<ClientModel> getAlwaysDisplayInConsoleClientsStream() {
|
||||||
return cacheSession.getAlwaysDisplayInConsoleClients(this);
|
return cacheSession.getAlwaysDisplayInConsoleClientsStream(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -791,13 +792,13 @@ public class RealmAdapter implements CachedRealmModel {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<ClientModel> searchClientByClientId(String clientId, Integer firstResult, Integer maxResults) {
|
public Stream<ClientModel> searchClientByClientIdStream(String clientId, Integer firstResult, Integer maxResults) {
|
||||||
return cacheSession.searchClientsByClientId(this, clientId, firstResult, maxResults);
|
return cacheSession.searchClientsByClientIdStream(this, clientId, firstResult, maxResults);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<ClientModel> getClients(Integer firstResult, Integer maxResults) {
|
public Stream<ClientModel> getClientsStream(Integer firstResult, Integer maxResults) {
|
||||||
return cacheSession.getClients(this, firstResult, maxResults);
|
return cacheSession.getClientsStream(this, firstResult, maxResults);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -1022,18 +1023,18 @@ public class RealmAdapter implements CachedRealmModel {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Set<RoleModel> getRoles() {
|
public Stream<RoleModel> getRolesStream() {
|
||||||
return cacheSession.getRealmRoles(this);
|
return cacheSession.getRealmRolesStream(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Set<RoleModel> getRoles(Integer first, Integer max) {
|
public Stream<RoleModel> getRolesStream(Integer first, Integer max) {
|
||||||
return cacheSession.getRealmRoles(this, first, max);
|
return cacheSession.getRealmRolesStream(this, first, max);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Set<RoleModel> searchForRoles(String search, Integer first, Integer max) {
|
public Stream<RoleModel> searchForRolesStream(String search, Integer first, Integer max) {
|
||||||
return cacheSession.searchForRoles(this, search, first, max);
|
return cacheSession.searchForRolesStream(this, search, first, max);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -31,6 +31,8 @@ import org.keycloak.storage.StorageId;
|
||||||
import org.keycloak.storage.client.ClientStorageProviderModel;
|
import org.keycloak.storage.client.ClientStorageProviderModel;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -538,18 +540,18 @@ public class RealmCacheSession implements CacheRealmProvider {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<ClientModel> getClients(RealmModel realm, Integer firstResult, Integer maxResults) {
|
public Stream<ClientModel> getClientsStream(RealmModel realm, Integer firstResult, Integer maxResults) {
|
||||||
return getClientDelegate().getClients(realm, firstResult, maxResults);
|
return getClientDelegate().getClientsStream(realm, firstResult, maxResults);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<ClientModel> getClients(RealmModel realm) {
|
public Stream<ClientModel> getClientsStream(RealmModel realm) {
|
||||||
return getClientDelegate().getClients(realm);
|
return getClientDelegate().getClientsStream(realm);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<ClientModel> getAlwaysDisplayInConsoleClients(RealmModel realm) {
|
public Stream<ClientModel> getAlwaysDisplayInConsoleClientsStream(RealmModel realm) {
|
||||||
return getClientDelegate().getAlwaysDisplayInConsoleClients(realm);
|
return getClientDelegate().getAlwaysDisplayInConsoleClientsStream(realm);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -604,11 +606,11 @@ public class RealmCacheSession implements CacheRealmProvider {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Set<RoleModel> getRealmRoles(RealmModel realm) {
|
public Stream<RoleModel> getRealmRolesStream(RealmModel realm) {
|
||||||
String cacheKey = getRolesCacheKey(realm.getId());
|
String cacheKey = getRolesCacheKey(realm.getId());
|
||||||
boolean queryDB = invalidations.contains(cacheKey) || listInvalidations.contains(realm.getId());
|
boolean queryDB = invalidations.contains(cacheKey) || listInvalidations.contains(realm.getId());
|
||||||
if (queryDB) {
|
if (queryDB) {
|
||||||
return getRealmDelegate().getRealmRoles(realm);
|
return getRealmDelegate().getRealmRolesStream(realm);
|
||||||
}
|
}
|
||||||
|
|
||||||
RoleListQuery query = cache.get(cacheKey, RoleListQuery.class);
|
RoleListQuery query = cache.get(cacheKey, RoleListQuery.class);
|
||||||
|
@ -618,33 +620,33 @@ public class RealmCacheSession implements CacheRealmProvider {
|
||||||
|
|
||||||
if (query == null) {
|
if (query == null) {
|
||||||
Long loaded = cache.getCurrentRevision(cacheKey);
|
Long loaded = cache.getCurrentRevision(cacheKey);
|
||||||
|
// intentionally using deprecated method here because role ids needs to be collected for cashing while the stream returned
|
||||||
Set<RoleModel> model = getRealmDelegate().getRealmRoles(realm);
|
Set<RoleModel> model = getRealmDelegate().getRealmRoles(realm);
|
||||||
if (model == null) return null;
|
if (model == null) return null;
|
||||||
Set<String> ids = new HashSet<>();
|
Set<String> ids = model.stream().map(RoleModel::getId).collect(Collectors.toSet());
|
||||||
for (RoleModel role : model) ids.add(role.getId());
|
|
||||||
query = new RoleListQuery(loaded, cacheKey, realm, ids);
|
query = new RoleListQuery(loaded, cacheKey, realm, ids);
|
||||||
logger.tracev("adding realm roles cache miss: realm {0} key {1}", realm.getName(), cacheKey);
|
logger.tracev("adding realm roles cache miss: realm {0} key {1}", realm.getName(), cacheKey);
|
||||||
cache.addRevisioned(query, startupRevision);
|
cache.addRevisioned(query, startupRevision);
|
||||||
return model;
|
return model.stream();
|
||||||
}
|
}
|
||||||
Set<RoleModel> list = new HashSet<>();
|
Set<RoleModel> list = new HashSet<>();
|
||||||
for (String id : query.getRoles()) {
|
for (String id : query.getRoles()) {
|
||||||
RoleModel role = session.realms().getRoleById(id, realm);
|
RoleModel role = session.realms().getRoleById(id, realm);
|
||||||
if (role == null) {
|
if (role == null) {
|
||||||
invalidations.add(cacheKey);
|
invalidations.add(cacheKey);
|
||||||
return getRealmDelegate().getRealmRoles(realm);
|
return getRealmDelegate().getRealmRolesStream(realm);
|
||||||
}
|
}
|
||||||
list.add(role);
|
list.add(role);
|
||||||
}
|
}
|
||||||
return list;
|
return list.stream();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Set<RoleModel> getClientRoles(RealmModel realm, ClientModel client) {
|
public Stream<RoleModel> getClientRolesStream(RealmModel realm, ClientModel client) {
|
||||||
String cacheKey = getRolesCacheKey(client.getId());
|
String cacheKey = getRolesCacheKey(client.getId());
|
||||||
boolean queryDB = invalidations.contains(cacheKey) || listInvalidations.contains(client.getId()) || listInvalidations.contains(realm.getId());
|
boolean queryDB = invalidations.contains(cacheKey) || listInvalidations.contains(client.getId()) || listInvalidations.contains(realm.getId());
|
||||||
if (queryDB) {
|
if (queryDB) {
|
||||||
return getRealmDelegate().getClientRoles(realm, client);
|
return getRealmDelegate().getClientRolesStream(realm, client, null, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
RoleListQuery query = cache.get(cacheKey, RoleListQuery.class);
|
RoleListQuery query = cache.get(cacheKey, RoleListQuery.class);
|
||||||
|
@ -654,46 +656,46 @@ public class RealmCacheSession implements CacheRealmProvider {
|
||||||
|
|
||||||
if (query == null) {
|
if (query == null) {
|
||||||
Long loaded = cache.getCurrentRevision(cacheKey);
|
Long loaded = cache.getCurrentRevision(cacheKey);
|
||||||
Set<RoleModel> model = getRealmDelegate().getClientRoles(realm, client);
|
// intentionally using deprecated method here because role ids needs to be collected for cashing while the stream returned
|
||||||
|
Set<RoleModel> model = getRealmDelegate().getClientRoles(realm, client, null, null);
|
||||||
if (model == null) return null;
|
if (model == null) return null;
|
||||||
Set<String> ids = new HashSet<>();
|
Set<String> ids = model.stream().map(RoleModel::getId).collect(Collectors.toSet());
|
||||||
for (RoleModel role : model) ids.add(role.getId());
|
|
||||||
query = new RoleListQuery(loaded, cacheKey, realm, ids, client.getClientId());
|
query = new RoleListQuery(loaded, cacheKey, realm, ids, client.getClientId());
|
||||||
logger.tracev("adding client roles cache miss: client {0} key {1}", client.getClientId(), cacheKey);
|
logger.tracev("adding client roles cache miss: client {0} key {1}", client.getClientId(), cacheKey);
|
||||||
cache.addRevisioned(query, startupRevision);
|
cache.addRevisioned(query, startupRevision);
|
||||||
return model;
|
return model.stream();
|
||||||
}
|
}
|
||||||
Set<RoleModel> list = new HashSet<>();
|
Set<RoleModel> list = new HashSet<>();
|
||||||
for (String id : query.getRoles()) {
|
for (String id : query.getRoles()) {
|
||||||
RoleModel role = session.realms().getRoleById(id, realm);
|
RoleModel role = session.realms().getRoleById(id, realm);
|
||||||
if (role == null) {
|
if (role == null) {
|
||||||
invalidations.add(cacheKey);
|
invalidations.add(cacheKey);
|
||||||
return getRealmDelegate().getClientRoles(realm, client);
|
return getRealmDelegate().getClientRolesStream(realm, client, null, null);
|
||||||
}
|
}
|
||||||
list.add(role);
|
list.add(role);
|
||||||
}
|
}
|
||||||
return list;
|
return list.stream();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Set<RoleModel> getRealmRoles(RealmModel realm, Integer first, Integer max) {
|
public Stream<RoleModel> getRealmRolesStream(RealmModel realm, Integer first, Integer max) {
|
||||||
return getRealmDelegate().getRealmRoles(realm, first, max);
|
return getRealmDelegate().getRealmRolesStream(realm, first, max);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Set<RoleModel> getClientRoles(RealmModel realm, ClientModel client, Integer first, Integer max) {
|
public Stream<RoleModel> getClientRolesStream(RealmModel realm, ClientModel client, Integer first, Integer max) {
|
||||||
return getRealmDelegate().getClientRoles(realm, client, first, max);
|
return getRealmDelegate().getClientRolesStream(realm, client, first, max);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Set<RoleModel> searchForClientRoles(RealmModel realm, ClientModel client, String search, Integer first,
|
public Stream<RoleModel> searchForClientRolesStream(RealmModel realm, ClientModel client, String search, Integer first,
|
||||||
Integer max) {
|
Integer max) {
|
||||||
return getRealmDelegate().searchForClientRoles(realm, client, search, first, max);
|
return getRealmDelegate().searchForClientRolesStream(realm, client, search, first, max);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Set<RoleModel> searchForRoles(RealmModel realm, String search, Integer first, Integer max) {
|
public Stream<RoleModel> searchForRolesStream(RealmModel realm, String search, Integer first, Integer max) {
|
||||||
return getRealmDelegate().searchForRoles(realm, search, first, max);
|
return getRealmDelegate().searchForRolesStream(realm, search, first, max);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -1128,8 +1130,8 @@ public class RealmCacheSession implements CacheRealmProvider {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<ClientModel> searchClientsByClientId(RealmModel realm, String clientId, Integer firstResult, Integer maxResults) {
|
public Stream<ClientModel> searchClientsByClientIdStream(RealmModel realm, String clientId, Integer firstResult, Integer maxResults) {
|
||||||
return getClientDelegate().searchClientsByClientId(realm, clientId, firstResult, maxResults);
|
return getClientDelegate().searchClientsByClientIdStream(realm, clientId, firstResult, maxResults);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -671,18 +671,18 @@ public class ClientAdapter implements ClientModel, JpaModel<ClientEntity> {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Set<RoleModel> getRoles() {
|
public Stream<RoleModel> getRolesStream() {
|
||||||
return session.realms().getClientRoles(realm, this);
|
return session.realms().getClientRolesStream(realm, this, null, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Set<RoleModel> getRoles(Integer first, Integer max) {
|
public Stream<RoleModel> getRolesStream(Integer first, Integer max) {
|
||||||
return session.realms().getClientRoles(realm, this, first, max);
|
return session.realms().getClientRolesStream(realm, this, first, max);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Set<RoleModel> searchForRoles(String search, Integer first, Integer max) {
|
public Stream<RoleModel> searchForRolesStream(String search, Integer first, Integer max) {
|
||||||
return session.realms().searchForClientRoles(realm, this, search, first, max);
|
return session.realms().searchForClientRolesStream(realm, this, search, first, max);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -46,6 +46,8 @@ import javax.persistence.TypedQuery;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
import org.keycloak.models.ModelException;
|
import org.keycloak.models.ModelException;
|
||||||
import static org.keycloak.common.util.StackUtil.getShortStackTrace;
|
import static org.keycloak.common.util.StackUtil.getShortStackTrace;
|
||||||
|
|
||||||
|
@ -253,17 +255,12 @@ public class JpaRealmProvider implements RealmProvider, ClientProvider {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Set<RoleModel> getRealmRoles(RealmModel realm) {
|
public Stream<RoleModel> getRealmRolesStream(RealmModel realm) {
|
||||||
TypedQuery<String> query = em.createNamedQuery("getRealmRoleIds", String.class);
|
TypedQuery<String> query = em.createNamedQuery("getRealmRoleIds", String.class);
|
||||||
query.setParameter("realm", realm.getId());
|
query.setParameter("realm", realm.getId());
|
||||||
List<String> roles = query.getResultList();
|
Stream<String> roles = query.getResultStream();
|
||||||
|
|
||||||
if (roles.isEmpty()) return Collections.EMPTY_SET;
|
return roles.map(realm::getRoleById);
|
||||||
Set<RoleModel> list = new HashSet<>();
|
|
||||||
for (String id : roles) {
|
|
||||||
list.add(session.realms().getRoleById(id, realm));
|
|
||||||
}
|
|
||||||
return Collections.unmodifiableSet(list);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -276,65 +273,49 @@ public class JpaRealmProvider implements RealmProvider, ClientProvider {
|
||||||
return session.realms().getRoleById(roles.get(0), realm);
|
return session.realms().getRoleById(roles.get(0), realm);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Set<RoleModel> getClientRoles(RealmModel realm, ClientModel client) {
|
public Stream<RoleModel> getRealmRolesStream(RealmModel realm, Integer first, Integer max) {
|
||||||
Set<RoleModel> list = new HashSet<>();
|
|
||||||
TypedQuery<String> query = em.createNamedQuery("getClientRoleIds", String.class);
|
|
||||||
query.setParameter("client", client.getId());
|
|
||||||
List<String> roles = query.getResultList();
|
|
||||||
for (String id : roles) {
|
|
||||||
list.add(session.realms().getRoleById(id, realm));
|
|
||||||
}
|
|
||||||
return list;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Set<RoleModel> getRealmRoles(RealmModel realm, Integer first, Integer max) {
|
|
||||||
TypedQuery<RoleEntity> query = em.createNamedQuery("getRealmRoles", RoleEntity.class);
|
TypedQuery<RoleEntity> query = em.createNamedQuery("getRealmRoles", RoleEntity.class);
|
||||||
query.setParameter("realm", realm.getId());
|
query.setParameter("realm", realm.getId());
|
||||||
|
|
||||||
return getRoles(query, realm, first, max);
|
return getRolesStream(query, realm, first, max);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Set<RoleModel> getClientRoles(RealmModel realm, ClientModel client, Integer first, Integer max) {
|
public Stream<RoleModel> getClientRolesStream(RealmModel realm, ClientModel client, Integer first, Integer max) {
|
||||||
TypedQuery<RoleEntity> query = em.createNamedQuery("getClientRoles", RoleEntity.class);
|
TypedQuery<RoleEntity> query = em.createNamedQuery("getClientRoles", RoleEntity.class);
|
||||||
query.setParameter("client", client.getId());
|
query.setParameter("client", client.getId());
|
||||||
|
|
||||||
return getRoles(query, realm, first, max);
|
return getRolesStream(query, realm, first, max);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected Set<RoleModel> getRoles(TypedQuery<RoleEntity> query, RealmModel realm, Integer first, Integer max) {
|
protected Stream<RoleModel> getRolesStream(TypedQuery<RoleEntity> query, RealmModel realm, Integer first, Integer max) {
|
||||||
if(Objects.nonNull(first) && Objects.nonNull(max)
|
if(Objects.nonNull(first) && Objects.nonNull(max)
|
||||||
&& first >= 0 && max >= 0) {
|
&& first >= 0 && max >= 0) {
|
||||||
query= query.setFirstResult(first).setMaxResults(max);
|
query= query.setFirstResult(first).setMaxResults(max);
|
||||||
}
|
}
|
||||||
|
|
||||||
List<RoleEntity> results = query.getResultList();
|
Stream<RoleEntity> results = query.getResultStream();
|
||||||
|
|
||||||
return results.stream()
|
return results.map(role -> new RoleAdapter(session, realm, em, role));
|
||||||
.map(role -> new RoleAdapter(session, realm, em, role))
|
|
||||||
.collect(Collectors.collectingAndThen(
|
|
||||||
Collectors.toCollection(LinkedHashSet::new), Collections::unmodifiableSet));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Set<RoleModel> searchForClientRoles(RealmModel realm, ClientModel client, String search, Integer first, Integer max) {
|
public Stream<RoleModel> searchForClientRolesStream(RealmModel realm, ClientModel client, String search, Integer first, Integer max) {
|
||||||
TypedQuery<RoleEntity> query = em.createNamedQuery("searchForClientRoles", RoleEntity.class);
|
TypedQuery<RoleEntity> query = em.createNamedQuery("searchForClientRoles", RoleEntity.class);
|
||||||
query.setParameter("client", client.getId());
|
query.setParameter("client", client.getId());
|
||||||
return searchForRoles(query, realm, search, first, max);
|
return searchForRoles(query, realm, search, first, max);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Set<RoleModel> searchForRoles(RealmModel realm, String search, Integer first, Integer max) {
|
public Stream<RoleModel> searchForRolesStream(RealmModel realm, String search, Integer first, Integer max) {
|
||||||
TypedQuery<RoleEntity> query = em.createNamedQuery("searchForRealmRoles", RoleEntity.class);
|
TypedQuery<RoleEntity> query = em.createNamedQuery("searchForRealmRoles", RoleEntity.class);
|
||||||
query.setParameter("realm", realm.getId());
|
query.setParameter("realm", realm.getId());
|
||||||
|
|
||||||
return searchForRoles(query, realm, search, first, max);
|
return searchForRoles(query, realm, search, first, max);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected Set<RoleModel> searchForRoles(TypedQuery<RoleEntity> query, RealmModel realm, String search, Integer first, Integer max) {
|
protected Stream<RoleModel> searchForRoles(TypedQuery<RoleEntity> query, RealmModel realm, String search, Integer first, Integer max) {
|
||||||
|
|
||||||
query.setParameter("search", "%" + search.trim().toLowerCase() + "%");
|
query.setParameter("search", "%" + search.trim().toLowerCase() + "%");
|
||||||
if(Objects.nonNull(first) && Objects.nonNull(max)
|
if(Objects.nonNull(first) && Objects.nonNull(max)
|
||||||
|
@ -342,12 +323,9 @@ public class JpaRealmProvider implements RealmProvider, ClientProvider {
|
||||||
query= query.setFirstResult(first).setMaxResults(max);
|
query= query.setFirstResult(first).setMaxResults(max);
|
||||||
}
|
}
|
||||||
|
|
||||||
List<RoleEntity> results = query.getResultList();
|
Stream<RoleEntity> results = query.getResultStream();
|
||||||
|
|
||||||
return results.stream()
|
return results.map(role -> new RoleAdapter(session, realm, em, role));
|
||||||
.map(role -> new RoleAdapter(session, realm, em, role))
|
|
||||||
.collect(Collectors.collectingAndThen(
|
|
||||||
Collectors.toSet(), Collections::unmodifiableSet));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -364,7 +342,7 @@ public class JpaRealmProvider implements RealmProvider, ClientProvider {
|
||||||
}
|
}
|
||||||
String compositeRoleTable = JpaUtils.getTableNameForNativeQuery("COMPOSITE_ROLE", em);
|
String compositeRoleTable = JpaUtils.getTableNameForNativeQuery("COMPOSITE_ROLE", em);
|
||||||
em.createNativeQuery("delete from " + compositeRoleTable + " where CHILD_ROLE = :role").setParameter("role", roleEntity).executeUpdate();
|
em.createNativeQuery("delete from " + compositeRoleTable + " where CHILD_ROLE = :role").setParameter("role", roleEntity).executeUpdate();
|
||||||
realm.getClients().forEach(c -> c.deleteScopeMapping(role));
|
realm.getClientsStream().forEach(c -> c.deleteScopeMapping(role));
|
||||||
em.createNamedQuery("deleteClientScopeRoleMappingByRole").setParameter("role", roleEntity).executeUpdate();
|
em.createNamedQuery("deleteClientScopeRoleMappingByRole").setParameter("role", roleEntity).executeUpdate();
|
||||||
int val = em.createNamedQuery("deleteGroupRoleMappingsByRole").setParameter("roleId", roleEntity.getId()).executeUpdate();
|
int val = em.createNamedQuery("deleteGroupRoleMappingsByRole").setParameter("roleId", roleEntity.getId()).executeUpdate();
|
||||||
|
|
||||||
|
@ -614,7 +592,12 @@ public class JpaRealmProvider implements RealmProvider, ClientProvider {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<ClientModel> getClients(RealmModel realm, Integer firstResult, Integer maxResults) {
|
public Stream<ClientModel> getClientsStream(RealmModel realm) {
|
||||||
|
return getClientsStream(realm, null, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Stream<ClientModel> getClientsStream(RealmModel realm, Integer firstResult, Integer maxResults) {
|
||||||
TypedQuery<String> query = em.createNamedQuery("getClientIdsByRealm", String.class);
|
TypedQuery<String> query = em.createNamedQuery("getClientIdsByRealm", String.class);
|
||||||
if (firstResult != null && firstResult > 0) {
|
if (firstResult != null && firstResult > 0) {
|
||||||
query.setFirstResult(firstResult);
|
query.setFirstResult(firstResult);
|
||||||
|
@ -623,28 +606,18 @@ public class JpaRealmProvider implements RealmProvider, ClientProvider {
|
||||||
query.setMaxResults(maxResults);
|
query.setMaxResults(maxResults);
|
||||||
}
|
}
|
||||||
query.setParameter("realm", realm.getId());
|
query.setParameter("realm", realm.getId());
|
||||||
List<String> clients = query.getResultList();
|
Stream<String> clients = query.getResultStream();
|
||||||
if (clients.isEmpty()) return Collections.EMPTY_LIST;
|
|
||||||
List<ClientModel> list = new LinkedList<>();
|
return clients.map(c -> session.clients().getClientById(realm, c)).filter(Objects::nonNull);
|
||||||
for (String id : clients) {
|
|
||||||
ClientModel client = session.clients().getClientById(realm, id);
|
|
||||||
if (client != null) list.add(client);
|
|
||||||
}
|
|
||||||
return Collections.unmodifiableList(list);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<ClientModel> getAlwaysDisplayInConsoleClients(RealmModel realm) {
|
public Stream<ClientModel> getAlwaysDisplayInConsoleClientsStream(RealmModel realm) {
|
||||||
TypedQuery<String> query = em.createNamedQuery("getAlwaysDisplayInConsoleClients", String.class);
|
TypedQuery<String> query = em.createNamedQuery("getAlwaysDisplayInConsoleClients", String.class);
|
||||||
query.setParameter("realm", realm.getId());
|
query.setParameter("realm", realm.getId());
|
||||||
List<String> clients = query.getResultList();
|
Stream<String> clientStream = query.getResultStream();
|
||||||
if (clients.isEmpty()) return Collections.EMPTY_LIST;
|
|
||||||
List<ClientModel> list = new LinkedList<>();
|
return clientStream.map(c -> session.clients().getClientById(realm, c)).filter(Objects::nonNull);
|
||||||
for (String id : clients) {
|
|
||||||
ClientModel client = session.clients().getClientById(realm, id);
|
|
||||||
if (client != null) list.add(client);
|
|
||||||
}
|
|
||||||
return Collections.unmodifiableList(list);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -673,7 +646,7 @@ public class JpaRealmProvider implements RealmProvider, ClientProvider {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<ClientModel> searchClientsByClientId(RealmModel realm, String clientId, Integer firstResult, Integer maxResults) {
|
public Stream<ClientModel> searchClientsByClientIdStream(RealmModel realm, String clientId, Integer firstResult, Integer maxResults) {
|
||||||
TypedQuery<String> query = em.createNamedQuery("searchClientsByClientId", String.class);
|
TypedQuery<String> query = em.createNamedQuery("searchClientsByClientId", String.class);
|
||||||
if (firstResult != null && firstResult > 0) {
|
if (firstResult != null && firstResult > 0) {
|
||||||
query.setFirstResult(firstResult);
|
query.setFirstResult(firstResult);
|
||||||
|
@ -683,9 +656,8 @@ public class JpaRealmProvider implements RealmProvider, ClientProvider {
|
||||||
}
|
}
|
||||||
query.setParameter("clientId", clientId);
|
query.setParameter("clientId", clientId);
|
||||||
query.setParameter("realm", realm.getId());
|
query.setParameter("realm", realm.getId());
|
||||||
List<String> results = query.getResultList();
|
Stream<String> results = query.getResultStream();
|
||||||
if (results.isEmpty()) return Collections.EMPTY_LIST;
|
return results.map(c -> session.clients().getClientById(realm, c));
|
||||||
return results.stream().map(id -> session.clients().getClientById(realm, id)).collect(Collectors.toList());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -34,6 +34,7 @@ import javax.persistence.TypedQuery;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.function.Predicate;
|
import java.util.function.Predicate;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
import static java.util.Objects.nonNull;
|
import static java.util.Objects.nonNull;
|
||||||
|
|
||||||
|
@ -829,18 +830,18 @@ public class RealmAdapter implements RealmModel, JpaModel<RealmEntity> {
|
||||||
|
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
public List<ClientModel> getClients() {
|
public Stream<ClientModel> getClientsStream() {
|
||||||
return session.clients().getClients(this);
|
return session.clients().getClientsStream(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<ClientModel> getClients(Integer firstResult, Integer maxResults) {
|
public Stream<ClientModel> getClientsStream(Integer firstResult, Integer maxResults) {
|
||||||
return session.clients().getClients(this, firstResult, maxResults);
|
return session.clients().getClientsStream(this, firstResult, maxResults);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<ClientModel> getAlwaysDisplayInConsoleClients() {
|
public Stream<ClientModel> getAlwaysDisplayInConsoleClientsStream() {
|
||||||
return session.clients().getAlwaysDisplayInConsoleClients(this);
|
return session.clients().getAlwaysDisplayInConsoleClientsStream(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -872,8 +873,8 @@ public class RealmAdapter implements RealmModel, JpaModel<RealmEntity> {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<ClientModel> searchClientByClientId(String clientId, Integer firstResult, Integer maxResults) {
|
public Stream<ClientModel> searchClientByClientIdStream(String clientId, Integer firstResult, Integer maxResults) {
|
||||||
return session.clients().searchClientsByClientId(this, clientId, firstResult, maxResults);
|
return session.clients().searchClientsByClientIdStream(this, clientId, firstResult, maxResults);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final String BROWSER_HEADER_PREFIX = "_browser_header.";
|
private static final String BROWSER_HEADER_PREFIX = "_browser_header.";
|
||||||
|
@ -933,18 +934,18 @@ public class RealmAdapter implements RealmModel, JpaModel<RealmEntity> {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Set<RoleModel> getRoles() {
|
public Stream<RoleModel> getRolesStream() {
|
||||||
return session.realms().getRealmRoles(this);
|
return session.realms().getRealmRolesStream(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Set<RoleModel> getRoles(Integer first, Integer max) {
|
public Stream<RoleModel> getRolesStream(Integer first, Integer max) {
|
||||||
return session.realms().getRealmRoles(this, first, max);
|
return session.realms().getRealmRolesStream(this, first, max);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Set<RoleModel> searchForRoles(String search, Integer first, Integer max) {
|
public Stream<RoleModel> searchForRolesStream(String search, Integer first, Integer max) {
|
||||||
return session.realms().searchForRoles(this, search, first, max);
|
return session.realms().searchForRolesStream(this, search, first, max);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -25,6 +25,7 @@ import org.keycloak.models.map.common.AbstractEntity;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
|
@ -81,18 +82,18 @@ public abstract class AbstractClientModel<E extends AbstractEntity> implements C
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Set<RoleModel> getRoles() {
|
public Stream<RoleModel> getRolesStream() {
|
||||||
return session.realms().getClientRoles(realm, this);
|
return session.realms().getClientRolesStream(realm, this, null, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Set<RoleModel> getRoles(Integer firstResult, Integer maxResults) {
|
public Stream<RoleModel> getRolesStream(Integer firstResult, Integer maxResults) {
|
||||||
return session.realms().getClientRoles(realm, this, firstResult, maxResults);
|
return session.realms().getClientRolesStream(realm, this, firstResult, maxResults);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Set<RoleModel> searchForRoles(String search, Integer first, Integer max) {
|
public Stream<RoleModel> searchForRolesStream(String search, Integer first, Integer max) {
|
||||||
return session.realms().searchForClientRoles(realm, this, search, first, max);
|
return session.realms().searchForClientRolesStream(realm, this, search, first, max);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -29,9 +29,7 @@ import org.keycloak.models.RealmProvider;
|
||||||
import org.keycloak.models.RoleModel;
|
import org.keycloak.models.RoleModel;
|
||||||
import org.keycloak.models.map.storage.MapKeycloakTransaction;
|
import org.keycloak.models.map.storage.MapKeycloakTransaction;
|
||||||
import org.keycloak.models.map.common.Serialization;
|
import org.keycloak.models.map.common.Serialization;
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.Comparator;
|
import java.util.Comparator;
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
@ -134,15 +132,15 @@ public class MapClientProvider implements ClientProvider {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<ClientModel> getClients(RealmModel realm, Integer firstResult, Integer maxResults) {
|
public Stream<ClientModel> getClientsStream(RealmModel realm, Integer firstResult, Integer maxResults) {
|
||||||
Stream<ClientModel> s = getClientsStream(realm);
|
Stream<ClientModel> s = getClientsStream(realm);
|
||||||
if (firstResult >= 0) {
|
if (firstResult != null && firstResult >= 0) {
|
||||||
s = s.skip(firstResult);
|
s = s.skip(firstResult);
|
||||||
}
|
}
|
||||||
if (maxResults >= 0) {
|
if (maxResults != null && maxResults >= 0) {
|
||||||
s = s.limit(maxResults);
|
s = s.limit(maxResults);
|
||||||
}
|
}
|
||||||
return s.collect(Collectors.toList());
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Stream<MapClientEntity> getNotRemovedUpdatedClientsStream() {
|
private Stream<MapClientEntity> getNotRemovedUpdatedClientsStream() {
|
||||||
|
@ -152,7 +150,7 @@ public class MapClientProvider implements ClientProvider {
|
||||||
return Stream.concat(tx.createdValuesStream(clientStore.keySet()), updatedAndNotRemovedClientsStream);
|
return Stream.concat(tx.createdValuesStream(clientStore.keySet()), updatedAndNotRemovedClientsStream);
|
||||||
}
|
}
|
||||||
|
|
||||||
// @Override
|
@Override
|
||||||
public Stream<ClientModel> getClientsStream(RealmModel realm) {
|
public Stream<ClientModel> getClientsStream(RealmModel realm) {
|
||||||
return getNotRemovedUpdatedClientsStream()
|
return getNotRemovedUpdatedClientsStream()
|
||||||
.filter(entityRealmFilter(realm))
|
.filter(entityRealmFilter(realm))
|
||||||
|
@ -161,11 +159,6 @@ public class MapClientProvider implements ClientProvider {
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public List<ClientModel> getClients(RealmModel realm) {
|
|
||||||
return getClientsStream(realm).collect(Collectors.toList());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ClientModel addClient(RealmModel realm, String id, String clientId) {
|
public ClientModel addClient(RealmModel realm, String id, String clientId) {
|
||||||
final UUID entityId = id == null ? UUID.randomUUID() : UUID.fromString(id);
|
final UUID entityId = id == null ? UUID.randomUUID() : UUID.fromString(id);
|
||||||
|
@ -194,10 +187,9 @@ public class MapClientProvider implements ClientProvider {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<ClientModel> getAlwaysDisplayInConsoleClients(RealmModel realm) {
|
public Stream<ClientModel> getAlwaysDisplayInConsoleClientsStream(RealmModel realm) {
|
||||||
return getClientsStream(realm)
|
return getClientsStream(realm)
|
||||||
.filter(ClientModel::isAlwaysDisplayInConsole)
|
.filter(ClientModel::isAlwaysDisplayInConsole);
|
||||||
.collect(Collectors.toList());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -285,9 +277,9 @@ public class MapClientProvider implements ClientProvider {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<ClientModel> searchClientsByClientId(RealmModel realm, String clientId, Integer firstResult, Integer maxResults) {
|
public Stream<ClientModel> searchClientsByClientIdStream(RealmModel realm, String clientId, Integer firstResult, Integer maxResults) {
|
||||||
if (clientId == null) {
|
if (clientId == null) {
|
||||||
return Collections.EMPTY_LIST;
|
return Stream.empty();
|
||||||
}
|
}
|
||||||
String clientIdLower = clientId.toLowerCase();
|
String clientIdLower = clientId.toLowerCase();
|
||||||
Stream<MapClientEntity> s = getNotRemovedUpdatedClientsStream()
|
Stream<MapClientEntity> s = getNotRemovedUpdatedClientsStream()
|
||||||
|
@ -295,17 +287,14 @@ public class MapClientProvider implements ClientProvider {
|
||||||
.filter(entity -> entity.getClientId() != null && entity.getClientId().toLowerCase().contains(clientIdLower))
|
.filter(entity -> entity.getClientId() != null && entity.getClientId().toLowerCase().contains(clientIdLower))
|
||||||
.sorted(COMPARE_BY_CLIENT_ID);
|
.sorted(COMPARE_BY_CLIENT_ID);
|
||||||
|
|
||||||
if (firstResult >= 0) {
|
if (firstResult != null && firstResult >= 0) {
|
||||||
s = s.skip(firstResult);
|
s = s.skip(firstResult);
|
||||||
}
|
}
|
||||||
if (maxResults >= 0) {
|
if (maxResults != null && maxResults >= 0) {
|
||||||
s = s.limit(maxResults);
|
s = s.limit(maxResults);
|
||||||
}
|
}
|
||||||
|
|
||||||
return s
|
return s.map(entityToAdapterFunc(realm));
|
||||||
.map(entityToAdapterFunc(realm))
|
|
||||||
.collect(Collectors.toList())
|
|
||||||
;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -22,7 +22,7 @@ import org.keycloak.models.RoleModel;
|
||||||
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Base helper class. Unsupported operations are implemented here that throw exception on invocation.
|
* Base helper class. Unsupported operations are implemented here that throw exception on invocation.
|
||||||
|
@ -52,18 +52,18 @@ public abstract class UnsupportedOperationsClientStorageAdapter implements Clien
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public final Set<RoleModel> getRoles() {
|
public final Stream<RoleModel> getRolesStream() {
|
||||||
return Collections.EMPTY_SET;
|
return Stream.empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public final Set<RoleModel> getRoles(Integer first, Integer max) {
|
public final Stream<RoleModel> getRolesStream(Integer first, Integer max) {
|
||||||
return Collections.EMPTY_SET;
|
return Stream.empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public final Set<RoleModel> searchForRoles(String search, Integer first, Integer max) {
|
public final Stream<RoleModel> searchForRolesStream(String search, Integer first, Integer max) {
|
||||||
return Collections.EMPTY_SET;
|
return Stream.empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -17,7 +17,6 @@
|
||||||
|
|
||||||
package org.keycloak.models;
|
package org.keycloak.models;
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
|
|
|
@ -20,6 +20,8 @@ import org.keycloak.provider.Provider;
|
||||||
import org.keycloak.storage.client.ClientLookupProvider;
|
import org.keycloak.storage.client.ClientLookupProvider;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Provider of the client records.
|
* Provider of the client records.
|
||||||
|
@ -31,21 +33,46 @@ public interface ClientProvider extends ClientLookupProvider, Provider {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the clients of the given realm.
|
* Returns the clients of the given realm.
|
||||||
|
* @deprecated use the stream variant instead
|
||||||
* @param realm Realm.
|
* @param realm Realm.
|
||||||
* @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 Maximim 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 List of the clients. Never returns {@code null}.
|
* @return List of the clients. Never returns {@code null}.
|
||||||
*/
|
*/
|
||||||
List<ClientModel> getClients(RealmModel realm, Integer firstResult, Integer maxResults);
|
@Deprecated
|
||||||
|
default List<ClientModel> getClients(RealmModel realm, Integer firstResult, Integer maxResults) {
|
||||||
|
return getClientsStream(realm, firstResult, maxResults).collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the clients of the given realm as a stream.
|
||||||
|
* @param realm Realm.
|
||||||
|
* @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}.
|
||||||
|
* @return Stream of the clients. Never returns {@code null}.
|
||||||
|
*/
|
||||||
|
Stream<ClientModel> getClientsStream(RealmModel realm, Integer firstResult, Integer maxResults);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns all the clients of the given realm.
|
* Returns all the clients of the given realm.
|
||||||
|
* @deprecated use the stream variant instead
|
||||||
* Effectively the same as the call {@code getClients(realm, null, null)}.
|
* Effectively the same as the call {@code getClients(realm, null, null)}.
|
||||||
* @param realm Realm.
|
* @param realm Realm.
|
||||||
* @return List of the clients. Never returns {@code null}.
|
* @return List of the clients. Never returns {@code null}.
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
default List<ClientModel> getClients(RealmModel realm) {
|
default List<ClientModel> getClients(RealmModel realm) {
|
||||||
return this.getClients(realm, null, null);
|
return this.getClientsStream(realm, null, null).collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns all the clients of the given realm as a stream.
|
||||||
|
* Effectively the same as the call {@code getClientsStream(realm, null, null)}.
|
||||||
|
* @param realm Realm.
|
||||||
|
* @return Stream of the clients. Never returns {@code null}.
|
||||||
|
*/
|
||||||
|
default Stream<ClientModel> getClientsStream(RealmModel realm) {
|
||||||
|
return this.getClientsStream(realm, null, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -81,10 +108,21 @@ public interface ClientProvider extends ClientLookupProvider, Provider {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a list of clients that are expected to always show up in account console.
|
* Returns a list of clients that are expected to always show up in account console.
|
||||||
|
* @deprecated use the stream variant instead
|
||||||
* @param realm Realm owning the clients.
|
* @param realm Realm owning the clients.
|
||||||
* @return List of the clients. Never returns {@code null}.
|
* @return List of the clients. Never returns {@code null}.
|
||||||
*/
|
*/
|
||||||
List<ClientModel> getAlwaysDisplayInConsoleClients(RealmModel realm);
|
@Deprecated
|
||||||
|
default List<ClientModel> getAlwaysDisplayInConsoleClients(RealmModel realm) {
|
||||||
|
return getAlwaysDisplayInConsoleClientsStream(realm).collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a stream of clients that are expected to always show up in account console.
|
||||||
|
* @param realm Realm owning the clients.
|
||||||
|
* @return Stream of the clients. Never returns {@code null}.
|
||||||
|
*/
|
||||||
|
Stream<ClientModel> getAlwaysDisplayInConsoleClientsStream(RealmModel realm);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Removes given client from the given realm.
|
* Removes given client from the given realm.
|
||||||
|
|
|
@ -26,6 +26,8 @@ import org.keycloak.storage.client.ClientStorageProvider;
|
||||||
import org.keycloak.storage.client.ClientStorageProviderModel;
|
import org.keycloak.storage.client.ClientStorageProviderModel;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||||
|
@ -284,11 +286,28 @@ public interface RealmModel extends RoleContainerModel {
|
||||||
|
|
||||||
void removeDefaultGroup(GroupModel group);
|
void removeDefaultGroup(GroupModel group);
|
||||||
|
|
||||||
List<ClientModel> getClients();
|
@Deprecated
|
||||||
List<ClientModel> getClients(Integer firstResult, Integer maxResults);
|
default List<ClientModel> getClients() {
|
||||||
|
return getClientsStream(null, null).collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
|
||||||
|
Stream<ClientModel> getClientsStream();
|
||||||
|
|
||||||
|
@Deprecated
|
||||||
|
default List<ClientModel> getClients(Integer firstResult, Integer maxResults) {
|
||||||
|
return getClientsStream(firstResult, maxResults).collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
|
||||||
|
Stream<ClientModel> getClientsStream(Integer firstResult, Integer maxResults);
|
||||||
|
|
||||||
Long getClientsCount();
|
Long getClientsCount();
|
||||||
|
|
||||||
List<ClientModel> getAlwaysDisplayInConsoleClients();
|
@Deprecated
|
||||||
|
default List<ClientModel> getAlwaysDisplayInConsoleClients() {
|
||||||
|
return getAlwaysDisplayInConsoleClientsStream().collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
|
||||||
|
Stream<ClientModel> getAlwaysDisplayInConsoleClientsStream();
|
||||||
|
|
||||||
ClientModel addClient(String name);
|
ClientModel addClient(String name);
|
||||||
|
|
||||||
|
@ -298,7 +317,13 @@ public interface RealmModel extends RoleContainerModel {
|
||||||
|
|
||||||
ClientModel getClientById(String id);
|
ClientModel getClientById(String id);
|
||||||
ClientModel getClientByClientId(String clientId);
|
ClientModel getClientByClientId(String clientId);
|
||||||
List<ClientModel> searchClientByClientId(String clientId, Integer firstResult, Integer maxResults);
|
|
||||||
|
@Deprecated
|
||||||
|
default List<ClientModel> searchClientByClientId(String clientId, Integer firstResult, Integer maxResults) {
|
||||||
|
return searchClientByClientIdStream(clientId, firstResult, maxResults).collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
|
||||||
|
Stream<ClientModel> searchClientByClientIdStream(String clientId, Integer firstResult, Integer maxResults);
|
||||||
|
|
||||||
void updateRequiredCredentials(Set<String> creds);
|
void updateRequiredCredentials(Set<String> creds);
|
||||||
|
|
||||||
|
|
|
@ -22,6 +22,8 @@ import org.keycloak.provider.Provider;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||||
|
@ -81,16 +83,44 @@ public interface RealmProvider extends Provider /* TODO: Remove in future versio
|
||||||
|
|
||||||
RoleModel getRealmRole(RealmModel realm, String name);
|
RoleModel getRealmRole(RealmModel realm, String name);
|
||||||
|
|
||||||
Set<RoleModel> getRealmRoles(RealmModel realm);
|
// TODO switch all usages to the stream variant
|
||||||
|
@Deprecated
|
||||||
|
default Set<RoleModel> getRealmRoles(RealmModel realm) {
|
||||||
|
return getRealmRolesStream(realm).collect(Collectors.toSet());
|
||||||
|
}
|
||||||
|
|
||||||
Set<RoleModel> getRealmRoles(RealmModel realm, Integer first, Integer max);
|
Stream<RoleModel> getRealmRolesStream(RealmModel realm);
|
||||||
|
|
||||||
Set<RoleModel> getClientRoles(RealmModel realm, ClientModel client, Integer first, Integer max);
|
@Deprecated
|
||||||
|
default Set<RoleModel> getRealmRoles(RealmModel realm, Integer first, Integer max) {
|
||||||
|
return getRealmRolesStream(realm, first, max).collect(Collectors.toSet());
|
||||||
|
}
|
||||||
|
|
||||||
Set<RoleModel> searchForClientRoles(RealmModel realm, ClientModel client, String search, Integer first,
|
Stream<RoleModel> getRealmRolesStream(RealmModel realm, Integer first, Integer max);
|
||||||
|
|
||||||
|
// TODO switch all usages to the stream variant
|
||||||
|
@Deprecated
|
||||||
|
default Set<RoleModel> getClientRoles(RealmModel realm, ClientModel client, Integer first, Integer max) {
|
||||||
|
return getClientRolesStream(realm, client, first, max).collect(Collectors.toSet());
|
||||||
|
}
|
||||||
|
|
||||||
|
Stream<RoleModel> getClientRolesStream(RealmModel realm, ClientModel client, Integer first, Integer max);
|
||||||
|
|
||||||
|
@Deprecated
|
||||||
|
default Set<RoleModel> searchForClientRoles(RealmModel realm, ClientModel client, String search, Integer first,
|
||||||
|
Integer max) {
|
||||||
|
return searchForClientRolesStream(realm, client, search, first, max).collect(Collectors.toSet());
|
||||||
|
}
|
||||||
|
|
||||||
|
Stream<RoleModel> searchForClientRolesStream(RealmModel realm, ClientModel client, String search, Integer first,
|
||||||
Integer max);
|
Integer max);
|
||||||
|
|
||||||
Set<RoleModel> searchForRoles(RealmModel realm, String search, Integer first, Integer max);
|
@Deprecated
|
||||||
|
default Set<RoleModel> searchForRoles(RealmModel realm, String search, Integer first, Integer max) {
|
||||||
|
return searchForRolesStream(realm, search, first, max).collect(Collectors.toSet());
|
||||||
|
}
|
||||||
|
|
||||||
|
Stream<RoleModel> searchForRolesStream(RealmModel realm, String search, Integer first, Integer max);
|
||||||
|
|
||||||
boolean removeRole(RealmModel realm, RoleModel role);
|
boolean removeRole(RealmModel realm, RoleModel role);
|
||||||
|
|
||||||
|
@ -114,7 +144,9 @@ public interface RealmProvider extends Provider /* TODO: Remove in future versio
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* TODO: To be @deprecated Use the corresponding method from {@link ??RoleProvider}. */
|
* TODO: To be @deprecated Use the corresponding method from {@link ??RoleProvider}. */
|
||||||
public Set<RoleModel> getClientRoles(RealmModel realm, ClientModel client);
|
default public Stream<RoleModel> getClientRolesStream(RealmModel realm, ClientModel client) {
|
||||||
|
return getClientRolesStream(realm, client, null, null);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* TODO: To be @deprecated Use the corresponding method from {@link ??RoleProvider}. */
|
* TODO: To be @deprecated Use the corresponding method from {@link ??RoleProvider}. */
|
||||||
|
@ -151,16 +183,11 @@ public interface RealmProvider extends Provider /* TODO: Remove in future versio
|
||||||
return this.getClients(realm, null, null);
|
return this.getClients(realm, null, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @deprecated Use the corresponding method from {@link ClientProvider}. */
|
|
||||||
@Override
|
|
||||||
public List<ClientModel> getClients(RealmModel realm, Integer firstResult, Integer maxResults);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @deprecated Use the corresponding method from {@link ClientProvider}. */
|
* @deprecated Use the corresponding method from {@link ClientProvider}. */
|
||||||
@Override
|
@Override
|
||||||
default List<ClientModel> searchClientsByClientId(String clientId, Integer firstResult, Integer maxResults, RealmModel realm) {
|
default List<ClientModel> searchClientsByClientId(String clientId, Integer firstResult, Integer maxResults, RealmModel realm) {
|
||||||
return searchClientsByClientId(realm, clientId, firstResult, maxResults);
|
return searchClientsByClientId(clientId, firstResult, maxResults, realm);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -173,11 +200,6 @@ public interface RealmProvider extends Provider /* TODO: Remove in future versio
|
||||||
@Override
|
@Override
|
||||||
default ClientModel getClientById(String id, RealmModel realm) { return getClientById(realm, id); }
|
default ClientModel getClientById(String id, RealmModel realm) { return getClientById(realm, id); }
|
||||||
|
|
||||||
/**
|
|
||||||
* @deprecated Use the corresponding method from {@link ClientProvider}. */
|
|
||||||
@Override
|
|
||||||
public List<ClientModel> searchClientsByClientId(RealmModel realm, String clientId, Integer firstResult, Integer maxResults);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @deprecated Use the corresponding method from {@link ClientProvider}. */
|
* @deprecated Use the corresponding method from {@link ClientProvider}. */
|
||||||
@Override
|
@Override
|
||||||
|
@ -196,10 +218,4 @@ public interface RealmProvider extends Provider /* TODO: Remove in future versio
|
||||||
/**
|
/**
|
||||||
* @deprecated Use the corresponding method from {@link ClientProvider}. */
|
* @deprecated Use the corresponding method from {@link ClientProvider}. */
|
||||||
default boolean removeClient(String id, RealmModel realm) { return this.removeClient(realm, id); }
|
default boolean removeClient(String id, RealmModel realm) { return this.removeClient(realm, id); }
|
||||||
|
|
||||||
/**
|
|
||||||
* @deprecated Use the corresponding method from {@link ClientProvider}. */
|
|
||||||
@Override
|
|
||||||
public List<ClientModel> getAlwaysDisplayInConsoleClients(RealmModel realm);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,6 +25,8 @@ import java.util.Collection;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||||
|
@ -47,11 +49,29 @@ public interface RoleContainerModel {
|
||||||
|
|
||||||
boolean removeRole(RoleModel role);
|
boolean removeRole(RoleModel role);
|
||||||
|
|
||||||
Set<RoleModel> getRoles();
|
// TODO switch all usages to the stream variant
|
||||||
|
@Deprecated
|
||||||
|
default Set<RoleModel> getRoles() {
|
||||||
|
return getRolesStream().collect(Collectors.toSet());
|
||||||
|
}
|
||||||
|
|
||||||
Set<RoleModel> getRoles(Integer firstResult, Integer maxResults);
|
Stream<RoleModel> getRolesStream();
|
||||||
|
|
||||||
Set<RoleModel> searchForRoles(String search, Integer first, Integer max);
|
// TODO switch all usages to the stream variant
|
||||||
|
@Deprecated
|
||||||
|
default Set<RoleModel> getRoles(Integer firstResult, Integer maxResults) {
|
||||||
|
return getRolesStream(firstResult, maxResults).collect(Collectors.toSet());
|
||||||
|
}
|
||||||
|
|
||||||
|
Stream<RoleModel> getRolesStream(Integer firstResult, Integer maxResults);
|
||||||
|
|
||||||
|
// TODO switch all usages to the stream variant
|
||||||
|
@Deprecated
|
||||||
|
default Set<RoleModel> searchForRoles(String search, Integer first, Integer max) {
|
||||||
|
return searchForRolesStream(search, first, max).collect(Collectors.toSet());
|
||||||
|
}
|
||||||
|
|
||||||
|
Stream<RoleModel> searchForRolesStream(String search, Integer first, Integer max);
|
||||||
|
|
||||||
List<String> getDefaultRoles();
|
List<String> getDefaultRoles();
|
||||||
|
|
||||||
|
|
|
@ -20,6 +20,8 @@ import org.keycloak.models.ClientModel;
|
||||||
import org.keycloak.models.RealmModel;
|
import org.keycloak.models.RealmModel;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Abstraction interface for lookoup of clients by id and clientId. These methods required for participating in login flows.
|
* Abstraction interface for lookoup of clients by id and clientId. These methods required for participating in login flows.
|
||||||
|
@ -71,10 +73,14 @@ public interface ClientLookupProvider {
|
||||||
* @param clientId Searched substring of the public client
|
* @param clientId Searched substring of the public client
|
||||||
* identifier ({@code client_id} in OIDC or {@code entityID} in SAML.)
|
* identifier ({@code client_id} in OIDC or {@code entityID} in SAML.)
|
||||||
* @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 Maximim 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 Model of the client, or {@code null} if no client is found.
|
* @return List of ClientModel or an empty list if no client is found.
|
||||||
|
* @deprecated Use {@link #searchClientsByClientIdStream(org.keycloak.models.RealmModel, java.lang.String, java.lang.Integer, java.lang.Integer)} instead.
|
||||||
*/
|
*/
|
||||||
List<ClientModel> searchClientsByClientId(RealmModel realm, String clientId, Integer firstResult, Integer maxResults);
|
@Deprecated
|
||||||
|
default List<ClientModel> searchClientsByClientId(String clientId, Integer firstResult, Integer maxResults, RealmModel realm) {
|
||||||
|
return searchClientsByClientIdStream(realm, clientId, firstResult, maxResults).collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Case-insensitive search for clients that contain the given string in their public client identifier.
|
* Case-insensitive search for clients that contain the given string in their public client identifier.
|
||||||
|
@ -82,11 +88,8 @@ public interface ClientLookupProvider {
|
||||||
* @param clientId Searched substring of the public client
|
* @param clientId Searched substring of the public client
|
||||||
* identifier ({@code client_id} in OIDC or {@code entityID} in SAML.)
|
* identifier ({@code client_id} in OIDC or {@code entityID} in SAML.)
|
||||||
* @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 Maximim 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 Models of the matching clients. Never returns {@code null}.
|
* @return Stream of ClientModel or an empty stream if no client is found.
|
||||||
* @deprecated Use {@link #searchClientsByClientId(org.keycloak.models.RealmModel, java.lang.String, java.lang.Integer, java.lang.Integer)} instead.
|
|
||||||
*/
|
*/
|
||||||
default List<ClientModel> searchClientsByClientId(String clientId, Integer firstResult, Integer maxResults, RealmModel realm) {
|
Stream<ClientModel> searchClientsByClientIdStream(RealmModel realm, String clientId, Integer firstResult, Integer maxResults);
|
||||||
return searchClientsByClientId(realm, clientId, firstResult, maxResults);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -178,7 +178,9 @@ public class DefaultKeycloakSession implements KeycloakSession {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ClientProvider clientStorageManager() {
|
public ClientProvider clientStorageManager() {
|
||||||
if (clientStorageManager == null) clientStorageManager = new ClientStorageManager(this);
|
if (clientStorageManager == null) {
|
||||||
|
clientStorageManager = new ClientStorageManager(this, factory.getClientStorageProviderTimeout());
|
||||||
|
}
|
||||||
return clientStorageManager;
|
return clientStorageManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -59,6 +59,12 @@ public class DefaultKeycloakSessionFactory implements KeycloakSessionFactory, Pr
|
||||||
// TODO: Likely should be changed to int and use Time.currentTime() to be compatible with all our "time" reps
|
// TODO: Likely should be changed to int and use Time.currentTime() to be compatible with all our "time" reps
|
||||||
protected long serverStartupTimestamp;
|
protected long serverStartupTimestamp;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Timeout is used as time boundary for obtaining clients from an external client storage. Default value is set
|
||||||
|
* to 3000 milliseconds and it's configurable.
|
||||||
|
*/
|
||||||
|
private long clientStorageProviderTimeout;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void register(ProviderEventListener listener) {
|
public void register(ProviderEventListener listener) {
|
||||||
listeners.add(listener);
|
listeners.add(listener);
|
||||||
|
@ -79,6 +85,8 @@ public class DefaultKeycloakSessionFactory implements KeycloakSessionFactory, Pr
|
||||||
public void init() {
|
public void init() {
|
||||||
serverStartupTimestamp = System.currentTimeMillis();
|
serverStartupTimestamp = System.currentTimeMillis();
|
||||||
|
|
||||||
|
clientStorageProviderTimeout = Config.scope("client").getLong("storageProviderTimeout", 3000L);
|
||||||
|
|
||||||
ProviderManager pm = new ProviderManager(KeycloakDeploymentInfo.create().services(), getClass().getClassLoader(), Config.scope().getArray("providers"));
|
ProviderManager pm = new ProviderManager(KeycloakDeploymentInfo.create().services(), getClass().getClassLoader(), Config.scope().getArray("providers"));
|
||||||
spis.addAll(pm.loadSpis());
|
spis.addAll(pm.loadSpis());
|
||||||
factoriesMap = loadFactories(pm);
|
factoriesMap = loadFactories(pm);
|
||||||
|
@ -351,6 +359,10 @@ public class DefaultKeycloakSessionFactory implements KeycloakSessionFactory, Pr
|
||||||
return packageName.startsWith("org.keycloak") && !packageName.startsWith("org.keycloak.examples");
|
return packageName.startsWith("org.keycloak") && !packageName.startsWith("org.keycloak.examples");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public long getClientStorageProviderTimeout() {
|
||||||
|
return clientStorageProviderTimeout;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return timestamp of Keycloak server startup
|
* @return timestamp of Keycloak server startup
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -28,9 +28,11 @@ import org.keycloak.storage.client.ClientLookupProvider;
|
||||||
import org.keycloak.storage.client.ClientStorageProvider;
|
import org.keycloak.storage.client.ClientStorageProvider;
|
||||||
import org.keycloak.storage.client.ClientStorageProviderFactory;
|
import org.keycloak.storage.client.ClientStorageProviderFactory;
|
||||||
import org.keycloak.storage.client.ClientStorageProviderModel;
|
import org.keycloak.storage.client.ClientStorageProviderModel;
|
||||||
|
import org.keycloak.utils.ServicesUtils;
|
||||||
|
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||||
|
@ -41,6 +43,8 @@ public class ClientStorageManager implements ClientProvider {
|
||||||
|
|
||||||
protected KeycloakSession session;
|
protected KeycloakSession session;
|
||||||
|
|
||||||
|
private long clientStorageProviderTimeout;
|
||||||
|
|
||||||
public static boolean isStorageProviderEnabled(RealmModel realm, String providerId) {
|
public static boolean isStorageProviderEnabled(RealmModel realm, String providerId) {
|
||||||
ClientStorageProviderModel model = getStorageProviderModel(realm, providerId);
|
ClientStorageProviderModel model = getStorageProviderModel(realm, providerId);
|
||||||
return model.isEnabled();
|
return model.isEnabled();
|
||||||
|
@ -118,8 +122,9 @@ public class ClientStorageManager implements ClientProvider {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public ClientStorageManager(KeycloakSession session) {
|
public ClientStorageManager(KeycloakSession session, long clientStorageProviderTimeout) {
|
||||||
this.session = session;
|
this.session = session;
|
||||||
|
this.clientStorageProviderTimeout = clientStorageProviderTimeout;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -147,17 +152,22 @@ public class ClientStorageManager implements ClientProvider {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Obtaining clients from an external client storage is time-bounded. In case the external client storage
|
||||||
|
* isn't available at least clients from a local storage are returned. For this purpose
|
||||||
|
* the {@link org.keycloak.services.DefaultKeycloakSessionFactory#getClientStorageProviderTimeout()} property is used.
|
||||||
|
* Default value is 3000 milliseconds and it's configurable.
|
||||||
|
* See {@link org.keycloak.services.DefaultKeycloakSessionFactory} for details.
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public List<ClientModel> searchClientsByClientId(RealmModel realm, String clientId, Integer firstResult, Integer maxResults) {
|
public Stream<ClientModel> searchClientsByClientIdStream(RealmModel realm, String clientId, Integer firstResult, Integer maxResults) {
|
||||||
List<ClientModel> clients = session.clientLocalStorage().searchClientsByClientId(realm, clientId, firstResult, maxResults);
|
Stream<ClientModel> local = session.clientLocalStorage().searchClientsByClientIdStream(realm, clientId, firstResult, maxResults);
|
||||||
if (clients != null) {
|
Stream<ClientModel> ext = getEnabledStorageProviders(session, realm, ClientLookupProvider.class).stream()
|
||||||
return clients;
|
.flatMap(ServicesUtils.timeBound(session,
|
||||||
}
|
clientStorageProviderTimeout,
|
||||||
for (ClientLookupProvider provider : getEnabledStorageProviders(session, realm, ClientLookupProvider.class)) {
|
p -> ((ClientLookupProvider) p).searchClientsByClientIdStream(realm, clientId, firstResult, maxResults)));
|
||||||
clients = provider.searchClientsByClientId(realm, clientId, firstResult, maxResults);
|
|
||||||
if (clients != null) return clients;
|
return Stream.concat(local, ext);
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -171,13 +181,13 @@ public class ClientStorageManager implements ClientProvider {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<ClientModel> getClients(RealmModel realm, Integer firstResult, Integer maxResults) {
|
public Stream<ClientModel> getClientsStream(RealmModel realm, Integer firstResult, Integer maxResults) {
|
||||||
return session.clientLocalStorage().getClients(realm, firstResult, maxResults);
|
return session.clientLocalStorage().getClientsStream(realm, firstResult, maxResults);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<ClientModel> getClients(RealmModel realm) {
|
public Stream<ClientModel> getClientsStream(RealmModel realm) {
|
||||||
return session.clientLocalStorage().getClients(realm);
|
return session.clientLocalStorage().getClientsStream(realm);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -186,8 +196,8 @@ public class ClientStorageManager implements ClientProvider {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<ClientModel> getAlwaysDisplayInConsoleClients(RealmModel realm) {
|
public Stream<ClientModel> getAlwaysDisplayInConsoleClientsStream(RealmModel realm) {
|
||||||
return session.clientLocalStorage().getAlwaysDisplayInConsoleClients(realm);
|
return session.clientLocalStorage().getAlwaysDisplayInConsoleClientsStream(realm);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -26,9 +26,8 @@ import org.keycloak.storage.StorageId;
|
||||||
import org.keycloak.storage.client.ClientStorageProvider;
|
import org.keycloak.storage.client.ClientStorageProvider;
|
||||||
import org.keycloak.storage.client.ClientStorageProviderModel;
|
import org.keycloak.storage.client.ClientStorageProviderModel;
|
||||||
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.regex.Matcher;
|
import java.util.regex.Matcher;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
|
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
|
||||||
|
@ -76,9 +75,9 @@ public class OpenshiftClientStorageProvider implements ClientStorageProvider {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<ClientModel> searchClientsByClientId(RealmModel realm, String clientId, Integer firstResult, Integer maxResults) {
|
public Stream<ClientModel> searchClientsByClientIdStream(RealmModel realm, String clientId, Integer firstResult, Integer maxResults) {
|
||||||
// TODO not sure about this, but I don't see this implementation using the search now
|
// TODO not sure about this, but I don't see this implementation using the search now
|
||||||
return Collections.singletonList(getClientByClientId(realm, clientId));
|
return Stream.of(getClientByClientId(realm, clientId));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
56
services/src/main/java/org/keycloak/utils/ServicesUtils.java
Normal file
56
services/src/main/java/org/keycloak/utils/ServicesUtils.java
Normal file
|
@ -0,0 +1,56 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2020 Red Hat, Inc. and/or its affiliates
|
||||||
|
* and other contributors as indicated by the @author tags.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.keycloak.utils;
|
||||||
|
|
||||||
|
import org.jboss.logging.Logger;
|
||||||
|
import org.keycloak.executors.ExecutorsProvider;
|
||||||
|
import org.keycloak.models.KeycloakSession;
|
||||||
|
|
||||||
|
import java.util.concurrent.Callable;
|
||||||
|
import java.util.concurrent.ExecutionException;
|
||||||
|
import java.util.concurrent.ExecutorService;
|
||||||
|
import java.util.concurrent.Future;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
import java.util.concurrent.TimeoutException;
|
||||||
|
import java.util.function.Function;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Utility class for general helper methods used across the keycloak-services.
|
||||||
|
*/
|
||||||
|
public class ServicesUtils {
|
||||||
|
|
||||||
|
private static final Logger logger = Logger.getLogger(ServicesUtils.class);
|
||||||
|
|
||||||
|
public static <T, R> Function<? super T,? extends Stream<? extends R>> timeBound(KeycloakSession session,
|
||||||
|
long timeout,
|
||||||
|
Function<T, ? extends Stream<R>> func) {
|
||||||
|
ExecutorService executor = session.getProvider(ExecutorsProvider.class).getExecutor("storage-provider-threads");
|
||||||
|
return p -> {
|
||||||
|
Callable<? extends Stream<R>> c = () -> func.apply(p);
|
||||||
|
Future<? extends Stream<R>> future = executor.submit(c);
|
||||||
|
try {
|
||||||
|
return future.get(timeout, TimeUnit.MILLISECONDS);
|
||||||
|
} catch (InterruptedException | ExecutionException | TimeoutException e) {
|
||||||
|
future.cancel(true);
|
||||||
|
logger.debug("Function failed to return on time.", e);
|
||||||
|
return Stream.empty();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
|
@ -36,7 +36,6 @@ import java.util.Collections;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.List;
|
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
|
@ -79,11 +78,11 @@ public class HardcodedClientStorageProvider implements ClientStorageProvider, Cl
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<ClientModel> searchClientsByClientId(RealmModel realm, String clientId, Integer firstResult, Integer maxResults) {
|
public Stream<ClientModel> searchClientsByClientIdStream(RealmModel realm, String clientId, Integer firstResult, Integer maxResults) {
|
||||||
if (clientId != null && this.clientId.toLowerCase().contains(clientId.toLowerCase())) {
|
if (clientId != null && this.clientId.toLowerCase().contains(clientId.toLowerCase())) {
|
||||||
return Collections.singletonList(new ClientAdapter(realm));
|
return Stream.of(new ClientAdapter(realm));
|
||||||
}
|
}
|
||||||
return Collections.EMPTY_LIST;
|
return Stream.empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
public class ClientAdapter extends AbstractReadOnlyClientStorageAdapter {
|
public class ClientAdapter extends AbstractReadOnlyClientStorageAdapter {
|
||||||
|
|
Loading…
Reference in a new issue