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
|
||||
public Set<RoleModel> getRoles() {
|
||||
return cacheSession.getClientRoles(cachedRealm, this);
|
||||
public Stream<RoleModel> getRolesStream() {
|
||||
return cacheSession.getClientRolesStream(cachedRealm, this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<RoleModel> getRoles(Integer first, Integer max) {
|
||||
return cacheSession.getClientRoles(cachedRealm, this, first, max);
|
||||
public Stream<RoleModel> getRolesStream(Integer first, Integer max) {
|
||||
return cacheSession.getClientRolesStream(cachedRealm, this, first, max);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<RoleModel> searchForRoles(String search, Integer first, Integer max) {
|
||||
return cacheSession.searchForClientRoles(cachedRealm, this, search, first, max);
|
||||
public Stream<RoleModel> searchForRolesStream(String search, Integer first, Integer max) {
|
||||
return cacheSession.searchForClientRolesStream(cachedRealm, this, search, first, max);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -29,6 +29,7 @@ import org.keycloak.storage.client.ClientStorageProvider;
|
|||
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
|
@ -755,13 +756,13 @@ public class RealmAdapter implements CachedRealmModel {
|
|||
}
|
||||
|
||||
@Override
|
||||
public List<ClientModel> getClients() {
|
||||
return cacheSession.getClients(this);
|
||||
public Stream<ClientModel> getClientsStream() {
|
||||
return cacheSession.getClientsStream(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ClientModel> getAlwaysDisplayInConsoleClients() {
|
||||
return cacheSession.getAlwaysDisplayInConsoleClients(this);
|
||||
public Stream<ClientModel> getAlwaysDisplayInConsoleClientsStream() {
|
||||
return cacheSession.getAlwaysDisplayInConsoleClientsStream(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -791,13 +792,13 @@ public class RealmAdapter implements CachedRealmModel {
|
|||
}
|
||||
|
||||
@Override
|
||||
public List<ClientModel> searchClientByClientId(String clientId, Integer firstResult, Integer maxResults) {
|
||||
return cacheSession.searchClientsByClientId(this, clientId, firstResult, maxResults);
|
||||
public Stream<ClientModel> searchClientByClientIdStream(String clientId, Integer firstResult, Integer maxResults) {
|
||||
return cacheSession.searchClientsByClientIdStream(this, clientId, firstResult, maxResults);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ClientModel> getClients(Integer firstResult, Integer maxResults) {
|
||||
return cacheSession.getClients(this, firstResult, maxResults);
|
||||
public Stream<ClientModel> getClientsStream(Integer firstResult, Integer maxResults) {
|
||||
return cacheSession.getClientsStream(this, firstResult, maxResults);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -1022,18 +1023,18 @@ public class RealmAdapter implements CachedRealmModel {
|
|||
}
|
||||
|
||||
@Override
|
||||
public Set<RoleModel> getRoles() {
|
||||
return cacheSession.getRealmRoles(this);
|
||||
public Stream<RoleModel> getRolesStream() {
|
||||
return cacheSession.getRealmRolesStream(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<RoleModel> getRoles(Integer first, Integer max) {
|
||||
return cacheSession.getRealmRoles(this, first, max);
|
||||
public Stream<RoleModel> getRolesStream(Integer first, Integer max) {
|
||||
return cacheSession.getRealmRolesStream(this, first, max);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<RoleModel> searchForRoles(String search, Integer first, Integer max) {
|
||||
return cacheSession.searchForRoles(this, search, first, max);
|
||||
public Stream<RoleModel> searchForRolesStream(String search, Integer first, Integer max) {
|
||||
return cacheSession.searchForRolesStream(this, search, first, max);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -31,6 +31,8 @@ import org.keycloak.storage.StorageId;
|
|||
import org.keycloak.storage.client.ClientStorageProviderModel;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
|
||||
/**
|
||||
|
@ -538,18 +540,18 @@ public class RealmCacheSession implements CacheRealmProvider {
|
|||
}
|
||||
|
||||
@Override
|
||||
public List<ClientModel> getClients(RealmModel realm, Integer firstResult, Integer maxResults) {
|
||||
return getClientDelegate().getClients(realm, firstResult, maxResults);
|
||||
public Stream<ClientModel> getClientsStream(RealmModel realm, Integer firstResult, Integer maxResults) {
|
||||
return getClientDelegate().getClientsStream(realm, firstResult, maxResults);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ClientModel> getClients(RealmModel realm) {
|
||||
return getClientDelegate().getClients(realm);
|
||||
public Stream<ClientModel> getClientsStream(RealmModel realm) {
|
||||
return getClientDelegate().getClientsStream(realm);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ClientModel> getAlwaysDisplayInConsoleClients(RealmModel realm) {
|
||||
return getClientDelegate().getAlwaysDisplayInConsoleClients(realm);
|
||||
public Stream<ClientModel> getAlwaysDisplayInConsoleClientsStream(RealmModel realm) {
|
||||
return getClientDelegate().getAlwaysDisplayInConsoleClientsStream(realm);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -604,11 +606,11 @@ public class RealmCacheSession implements CacheRealmProvider {
|
|||
}
|
||||
|
||||
@Override
|
||||
public Set<RoleModel> getRealmRoles(RealmModel realm) {
|
||||
public Stream<RoleModel> getRealmRolesStream(RealmModel realm) {
|
||||
String cacheKey = getRolesCacheKey(realm.getId());
|
||||
boolean queryDB = invalidations.contains(cacheKey) || listInvalidations.contains(realm.getId());
|
||||
if (queryDB) {
|
||||
return getRealmDelegate().getRealmRoles(realm);
|
||||
return getRealmDelegate().getRealmRolesStream(realm);
|
||||
}
|
||||
|
||||
RoleListQuery query = cache.get(cacheKey, RoleListQuery.class);
|
||||
|
@ -618,33 +620,33 @@ public class RealmCacheSession implements CacheRealmProvider {
|
|||
|
||||
if (query == null) {
|
||||
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);
|
||||
if (model == null) return null;
|
||||
Set<String> ids = new HashSet<>();
|
||||
for (RoleModel role : model) ids.add(role.getId());
|
||||
Set<String> ids = model.stream().map(RoleModel::getId).collect(Collectors.toSet());
|
||||
query = new RoleListQuery(loaded, cacheKey, realm, ids);
|
||||
logger.tracev("adding realm roles cache miss: realm {0} key {1}", realm.getName(), cacheKey);
|
||||
cache.addRevisioned(query, startupRevision);
|
||||
return model;
|
||||
return model.stream();
|
||||
}
|
||||
Set<RoleModel> list = new HashSet<>();
|
||||
for (String id : query.getRoles()) {
|
||||
RoleModel role = session.realms().getRoleById(id, realm);
|
||||
if (role == null) {
|
||||
invalidations.add(cacheKey);
|
||||
return getRealmDelegate().getRealmRoles(realm);
|
||||
return getRealmDelegate().getRealmRolesStream(realm);
|
||||
}
|
||||
list.add(role);
|
||||
}
|
||||
return list;
|
||||
return list.stream();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<RoleModel> getClientRoles(RealmModel realm, ClientModel client) {
|
||||
public Stream<RoleModel> getClientRolesStream(RealmModel realm, ClientModel client) {
|
||||
String cacheKey = getRolesCacheKey(client.getId());
|
||||
boolean queryDB = invalidations.contains(cacheKey) || listInvalidations.contains(client.getId()) || listInvalidations.contains(realm.getId());
|
||||
if (queryDB) {
|
||||
return getRealmDelegate().getClientRoles(realm, client);
|
||||
return getRealmDelegate().getClientRolesStream(realm, client, null, null);
|
||||
}
|
||||
|
||||
RoleListQuery query = cache.get(cacheKey, RoleListQuery.class);
|
||||
|
@ -654,46 +656,46 @@ public class RealmCacheSession implements CacheRealmProvider {
|
|||
|
||||
if (query == null) {
|
||||
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;
|
||||
Set<String> ids = new HashSet<>();
|
||||
for (RoleModel role : model) ids.add(role.getId());
|
||||
Set<String> ids = model.stream().map(RoleModel::getId).collect(Collectors.toSet());
|
||||
query = new RoleListQuery(loaded, cacheKey, realm, ids, client.getClientId());
|
||||
logger.tracev("adding client roles cache miss: client {0} key {1}", client.getClientId(), cacheKey);
|
||||
cache.addRevisioned(query, startupRevision);
|
||||
return model;
|
||||
return model.stream();
|
||||
}
|
||||
Set<RoleModel> list = new HashSet<>();
|
||||
for (String id : query.getRoles()) {
|
||||
RoleModel role = session.realms().getRoleById(id, realm);
|
||||
if (role == null) {
|
||||
invalidations.add(cacheKey);
|
||||
return getRealmDelegate().getClientRoles(realm, client);
|
||||
return getRealmDelegate().getClientRolesStream(realm, client, null, null);
|
||||
}
|
||||
list.add(role);
|
||||
}
|
||||
return list;
|
||||
return list.stream();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<RoleModel> getRealmRoles(RealmModel realm, Integer first, Integer max) {
|
||||
return getRealmDelegate().getRealmRoles(realm, first, max);
|
||||
public Stream<RoleModel> getRealmRolesStream(RealmModel realm, Integer first, Integer max) {
|
||||
return getRealmDelegate().getRealmRolesStream(realm, first, max);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<RoleModel> getClientRoles(RealmModel realm, ClientModel client, Integer first, Integer max) {
|
||||
return getRealmDelegate().getClientRoles(realm, client, first, max);
|
||||
public Stream<RoleModel> getClientRolesStream(RealmModel realm, ClientModel client, Integer first, Integer max) {
|
||||
return getRealmDelegate().getClientRolesStream(realm, client, first, max);
|
||||
}
|
||||
|
||||
@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) {
|
||||
return getRealmDelegate().searchForClientRoles(realm, client, search, first, max);
|
||||
return getRealmDelegate().searchForClientRolesStream(realm, client, search, first, max);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<RoleModel> searchForRoles(RealmModel realm, String search, Integer first, Integer max) {
|
||||
return getRealmDelegate().searchForRoles(realm, search, first, max);
|
||||
public Stream<RoleModel> searchForRolesStream(RealmModel realm, String search, Integer first, Integer max) {
|
||||
return getRealmDelegate().searchForRolesStream(realm, search, first, max);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -1128,8 +1130,8 @@ public class RealmCacheSession implements CacheRealmProvider {
|
|||
}
|
||||
|
||||
@Override
|
||||
public List<ClientModel> searchClientsByClientId(RealmModel realm, String clientId, Integer firstResult, Integer maxResults) {
|
||||
return getClientDelegate().searchClientsByClientId(realm, clientId, firstResult, maxResults);
|
||||
public Stream<ClientModel> searchClientsByClientIdStream(RealmModel realm, String clientId, Integer firstResult, Integer maxResults) {
|
||||
return getClientDelegate().searchClientsByClientIdStream(realm, clientId, firstResult, maxResults);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -671,18 +671,18 @@ public class ClientAdapter implements ClientModel, JpaModel<ClientEntity> {
|
|||
}
|
||||
|
||||
@Override
|
||||
public Set<RoleModel> getRoles() {
|
||||
return session.realms().getClientRoles(realm, this);
|
||||
public Stream<RoleModel> getRolesStream() {
|
||||
return session.realms().getClientRolesStream(realm, this, null, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<RoleModel> getRoles(Integer first, Integer max) {
|
||||
return session.realms().getClientRoles(realm, this, first, max);
|
||||
public Stream<RoleModel> getRolesStream(Integer first, Integer max) {
|
||||
return session.realms().getClientRolesStream(realm, this, first, max);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<RoleModel> searchForRoles(String search, Integer first, Integer max) {
|
||||
return session.realms().searchForClientRoles(realm, this, search, first, max);
|
||||
public Stream<RoleModel> searchForRolesStream(String search, Integer first, Integer max) {
|
||||
return session.realms().searchForClientRolesStream(realm, this, search, first, max);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -46,6 +46,8 @@ import javax.persistence.TypedQuery;
|
|||
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import org.keycloak.models.ModelException;
|
||||
import static org.keycloak.common.util.StackUtil.getShortStackTrace;
|
||||
|
||||
|
@ -253,17 +255,12 @@ public class JpaRealmProvider implements RealmProvider, ClientProvider {
|
|||
}
|
||||
|
||||
@Override
|
||||
public Set<RoleModel> getRealmRoles(RealmModel realm) {
|
||||
public Stream<RoleModel> getRealmRolesStream(RealmModel realm) {
|
||||
TypedQuery<String> query = em.createNamedQuery("getRealmRoleIds", String.class);
|
||||
query.setParameter("realm", realm.getId());
|
||||
List<String> roles = query.getResultList();
|
||||
Stream<String> roles = query.getResultStream();
|
||||
|
||||
if (roles.isEmpty()) return Collections.EMPTY_SET;
|
||||
Set<RoleModel> list = new HashSet<>();
|
||||
for (String id : roles) {
|
||||
list.add(session.realms().getRoleById(id, realm));
|
||||
}
|
||||
return Collections.unmodifiableSet(list);
|
||||
return roles.map(realm::getRoleById);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -276,65 +273,49 @@ public class JpaRealmProvider implements RealmProvider, ClientProvider {
|
|||
return session.realms().getRoleById(roles.get(0), realm);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Set<RoleModel> getClientRoles(RealmModel realm, ClientModel client) {
|
||||
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) {
|
||||
public Stream<RoleModel> getRealmRolesStream(RealmModel realm, Integer first, Integer max) {
|
||||
TypedQuery<RoleEntity> query = em.createNamedQuery("getRealmRoles", RoleEntity.class);
|
||||
query.setParameter("realm", realm.getId());
|
||||
|
||||
return getRoles(query, realm, first, max);
|
||||
return getRolesStream(query, realm, first, max);
|
||||
}
|
||||
|
||||
@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);
|
||||
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)
|
||||
&& first >= 0 && max >= 0) {
|
||||
query= query.setFirstResult(first).setMaxResults(max);
|
||||
}
|
||||
|
||||
List<RoleEntity> results = query.getResultList();
|
||||
Stream<RoleEntity> results = query.getResultStream();
|
||||
|
||||
return results.stream()
|
||||
.map(role -> new RoleAdapter(session, realm, em, role))
|
||||
.collect(Collectors.collectingAndThen(
|
||||
Collectors.toCollection(LinkedHashSet::new), Collections::unmodifiableSet));
|
||||
return results.map(role -> new RoleAdapter(session, realm, em, role));
|
||||
}
|
||||
|
||||
@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);
|
||||
query.setParameter("client", client.getId());
|
||||
return searchForRoles(query, realm, search, first, max);
|
||||
}
|
||||
|
||||
@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);
|
||||
query.setParameter("realm", realm.getId());
|
||||
|
||||
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() + "%");
|
||||
if(Objects.nonNull(first) && Objects.nonNull(max)
|
||||
|
@ -342,12 +323,9 @@ public class JpaRealmProvider implements RealmProvider, ClientProvider {
|
|||
query= query.setFirstResult(first).setMaxResults(max);
|
||||
}
|
||||
|
||||
List<RoleEntity> results = query.getResultList();
|
||||
Stream<RoleEntity> results = query.getResultStream();
|
||||
|
||||
return results.stream()
|
||||
.map(role -> new RoleAdapter(session, realm, em, role))
|
||||
.collect(Collectors.collectingAndThen(
|
||||
Collectors.toSet(), Collections::unmodifiableSet));
|
||||
return results.map(role -> new RoleAdapter(session, realm, em, role));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -364,7 +342,7 @@ public class JpaRealmProvider implements RealmProvider, ClientProvider {
|
|||
}
|
||||
String compositeRoleTable = JpaUtils.getTableNameForNativeQuery("COMPOSITE_ROLE", em);
|
||||
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();
|
||||
int val = em.createNamedQuery("deleteGroupRoleMappingsByRole").setParameter("roleId", roleEntity.getId()).executeUpdate();
|
||||
|
||||
|
@ -614,7 +592,12 @@ public class JpaRealmProvider implements RealmProvider, ClientProvider {
|
|||
}
|
||||
|
||||
@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);
|
||||
if (firstResult != null && firstResult > 0) {
|
||||
query.setFirstResult(firstResult);
|
||||
|
@ -623,28 +606,18 @@ public class JpaRealmProvider implements RealmProvider, ClientProvider {
|
|||
query.setMaxResults(maxResults);
|
||||
}
|
||||
query.setParameter("realm", realm.getId());
|
||||
List<String> clients = query.getResultList();
|
||||
if (clients.isEmpty()) return Collections.EMPTY_LIST;
|
||||
List<ClientModel> list = new LinkedList<>();
|
||||
for (String id : clients) {
|
||||
ClientModel client = session.clients().getClientById(realm, id);
|
||||
if (client != null) list.add(client);
|
||||
}
|
||||
return Collections.unmodifiableList(list);
|
||||
Stream<String> clients = query.getResultStream();
|
||||
|
||||
return clients.map(c -> session.clients().getClientById(realm, c)).filter(Objects::nonNull);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ClientModel> getAlwaysDisplayInConsoleClients(RealmModel realm) {
|
||||
public Stream<ClientModel> getAlwaysDisplayInConsoleClientsStream(RealmModel realm) {
|
||||
TypedQuery<String> query = em.createNamedQuery("getAlwaysDisplayInConsoleClients", String.class);
|
||||
query.setParameter("realm", realm.getId());
|
||||
List<String> clients = query.getResultList();
|
||||
if (clients.isEmpty()) return Collections.EMPTY_LIST;
|
||||
List<ClientModel> list = new LinkedList<>();
|
||||
for (String id : clients) {
|
||||
ClientModel client = session.clients().getClientById(realm, id);
|
||||
if (client != null) list.add(client);
|
||||
}
|
||||
return Collections.unmodifiableList(list);
|
||||
Stream<String> clientStream = query.getResultStream();
|
||||
|
||||
return clientStream.map(c -> session.clients().getClientById(realm, c)).filter(Objects::nonNull);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -673,7 +646,7 @@ public class JpaRealmProvider implements RealmProvider, ClientProvider {
|
|||
}
|
||||
|
||||
@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);
|
||||
if (firstResult != null && firstResult > 0) {
|
||||
query.setFirstResult(firstResult);
|
||||
|
@ -683,9 +656,8 @@ public class JpaRealmProvider implements RealmProvider, ClientProvider {
|
|||
}
|
||||
query.setParameter("clientId", clientId);
|
||||
query.setParameter("realm", realm.getId());
|
||||
List<String> results = query.getResultList();
|
||||
if (results.isEmpty()) return Collections.EMPTY_LIST;
|
||||
return results.stream().map(id -> session.clients().getClientById(realm, id)).collect(Collectors.toList());
|
||||
Stream<String> results = query.getResultStream();
|
||||
return results.map(c -> session.clients().getClientById(realm, c));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -34,6 +34,7 @@ import javax.persistence.TypedQuery;
|
|||
import java.util.*;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import static java.util.Objects.nonNull;
|
||||
|
||||
|
@ -829,18 +830,18 @@ public class RealmAdapter implements RealmModel, JpaModel<RealmEntity> {
|
|||
|
||||
}
|
||||
@Override
|
||||
public List<ClientModel> getClients() {
|
||||
return session.clients().getClients(this);
|
||||
public Stream<ClientModel> getClientsStream() {
|
||||
return session.clients().getClientsStream(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ClientModel> getClients(Integer firstResult, Integer maxResults) {
|
||||
return session.clients().getClients(this, firstResult, maxResults);
|
||||
public Stream<ClientModel> getClientsStream(Integer firstResult, Integer maxResults) {
|
||||
return session.clients().getClientsStream(this, firstResult, maxResults);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ClientModel> getAlwaysDisplayInConsoleClients() {
|
||||
return session.clients().getAlwaysDisplayInConsoleClients(this);
|
||||
public Stream<ClientModel> getAlwaysDisplayInConsoleClientsStream() {
|
||||
return session.clients().getAlwaysDisplayInConsoleClientsStream(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -872,8 +873,8 @@ public class RealmAdapter implements RealmModel, JpaModel<RealmEntity> {
|
|||
}
|
||||
|
||||
@Override
|
||||
public List<ClientModel> searchClientByClientId(String clientId, Integer firstResult, Integer maxResults) {
|
||||
return session.clients().searchClientsByClientId(this, clientId, firstResult, maxResults);
|
||||
public Stream<ClientModel> searchClientByClientIdStream(String clientId, Integer firstResult, Integer maxResults) {
|
||||
return session.clients().searchClientsByClientIdStream(this, clientId, firstResult, maxResults);
|
||||
}
|
||||
|
||||
private static final String BROWSER_HEADER_PREFIX = "_browser_header.";
|
||||
|
@ -933,18 +934,18 @@ public class RealmAdapter implements RealmModel, JpaModel<RealmEntity> {
|
|||
}
|
||||
|
||||
@Override
|
||||
public Set<RoleModel> getRoles() {
|
||||
return session.realms().getRealmRoles(this);
|
||||
public Stream<RoleModel> getRolesStream() {
|
||||
return session.realms().getRealmRolesStream(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<RoleModel> getRoles(Integer first, Integer max) {
|
||||
return session.realms().getRealmRoles(this, first, max);
|
||||
public Stream<RoleModel> getRolesStream(Integer first, Integer max) {
|
||||
return session.realms().getRealmRolesStream(this, first, max);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<RoleModel> searchForRoles(String search, Integer first, Integer max) {
|
||||
return session.realms().searchForRoles(this, search, first, max);
|
||||
public Stream<RoleModel> searchForRolesStream(String search, Integer first, Integer max) {
|
||||
return session.realms().searchForRolesStream(this, search, first, max);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -25,6 +25,7 @@ import org.keycloak.models.map.common.AbstractEntity;
|
|||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
/**
|
||||
*
|
||||
|
@ -81,18 +82,18 @@ public abstract class AbstractClientModel<E extends AbstractEntity> implements C
|
|||
}
|
||||
|
||||
@Override
|
||||
public Set<RoleModel> getRoles() {
|
||||
return session.realms().getClientRoles(realm, this);
|
||||
public Stream<RoleModel> getRolesStream() {
|
||||
return session.realms().getClientRolesStream(realm, this, null, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<RoleModel> getRoles(Integer firstResult, Integer maxResults) {
|
||||
return session.realms().getClientRoles(realm, this, firstResult, maxResults);
|
||||
public Stream<RoleModel> getRolesStream(Integer firstResult, Integer maxResults) {
|
||||
return session.realms().getClientRolesStream(realm, this, firstResult, maxResults);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<RoleModel> searchForRoles(String search, Integer first, Integer max) {
|
||||
return session.realms().searchForClientRoles(realm, this, search, first, max);
|
||||
public Stream<RoleModel> searchForRolesStream(String search, Integer first, Integer max) {
|
||||
return session.realms().searchForClientRolesStream(realm, this, search, first, max);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -29,9 +29,7 @@ import org.keycloak.models.RealmProvider;
|
|||
import org.keycloak.models.RoleModel;
|
||||
import org.keycloak.models.map.storage.MapKeycloakTransaction;
|
||||
import org.keycloak.models.map.common.Serialization;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.UUID;
|
||||
|
@ -134,15 +132,15 @@ public class MapClientProvider implements ClientProvider {
|
|||
}
|
||||
|
||||
@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);
|
||||
if (firstResult >= 0) {
|
||||
if (firstResult != null && firstResult >= 0) {
|
||||
s = s.skip(firstResult);
|
||||
}
|
||||
if (maxResults >= 0) {
|
||||
if (maxResults != null && maxResults >= 0) {
|
||||
s = s.limit(maxResults);
|
||||
}
|
||||
return s.collect(Collectors.toList());
|
||||
return s;
|
||||
}
|
||||
|
||||
private Stream<MapClientEntity> getNotRemovedUpdatedClientsStream() {
|
||||
|
@ -152,7 +150,7 @@ public class MapClientProvider implements ClientProvider {
|
|||
return Stream.concat(tx.createdValuesStream(clientStore.keySet()), updatedAndNotRemovedClientsStream);
|
||||
}
|
||||
|
||||
// @Override
|
||||
@Override
|
||||
public Stream<ClientModel> getClientsStream(RealmModel realm) {
|
||||
return getNotRemovedUpdatedClientsStream()
|
||||
.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
|
||||
public ClientModel addClient(RealmModel realm, String id, String clientId) {
|
||||
final UUID entityId = id == null ? UUID.randomUUID() : UUID.fromString(id);
|
||||
|
@ -194,10 +187,9 @@ public class MapClientProvider implements ClientProvider {
|
|||
}
|
||||
|
||||
@Override
|
||||
public List<ClientModel> getAlwaysDisplayInConsoleClients(RealmModel realm) {
|
||||
public Stream<ClientModel> getAlwaysDisplayInConsoleClientsStream(RealmModel realm) {
|
||||
return getClientsStream(realm)
|
||||
.filter(ClientModel::isAlwaysDisplayInConsole)
|
||||
.collect(Collectors.toList());
|
||||
.filter(ClientModel::isAlwaysDisplayInConsole);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -285,9 +277,9 @@ public class MapClientProvider implements ClientProvider {
|
|||
}
|
||||
|
||||
@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) {
|
||||
return Collections.EMPTY_LIST;
|
||||
return Stream.empty();
|
||||
}
|
||||
String clientIdLower = clientId.toLowerCase();
|
||||
Stream<MapClientEntity> s = getNotRemovedUpdatedClientsStream()
|
||||
|
@ -295,17 +287,14 @@ public class MapClientProvider implements ClientProvider {
|
|||
.filter(entity -> entity.getClientId() != null && entity.getClientId().toLowerCase().contains(clientIdLower))
|
||||
.sorted(COMPARE_BY_CLIENT_ID);
|
||||
|
||||
if (firstResult >= 0) {
|
||||
if (firstResult != null && firstResult >= 0) {
|
||||
s = s.skip(firstResult);
|
||||
}
|
||||
if (maxResults >= 0) {
|
||||
if (maxResults != null && maxResults >= 0) {
|
||||
s = s.limit(maxResults);
|
||||
}
|
||||
|
||||
return s
|
||||
.map(entityToAdapterFunc(realm))
|
||||
.collect(Collectors.toList())
|
||||
;
|
||||
return s.map(entityToAdapterFunc(realm));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -22,7 +22,7 @@ import org.keycloak.models.RoleModel;
|
|||
|
||||
import java.util.Collections;
|
||||
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.
|
||||
|
@ -52,18 +52,18 @@ public abstract class UnsupportedOperationsClientStorageAdapter implements Clien
|
|||
}
|
||||
|
||||
@Override
|
||||
public final Set<RoleModel> getRoles() {
|
||||
return Collections.EMPTY_SET;
|
||||
public final Stream<RoleModel> getRolesStream() {
|
||||
return Stream.empty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public final Set<RoleModel> getRoles(Integer first, Integer max) {
|
||||
return Collections.EMPTY_SET;
|
||||
public final Stream<RoleModel> getRolesStream(Integer first, Integer max) {
|
||||
return Stream.empty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public final Set<RoleModel> searchForRoles(String search, Integer first, Integer max) {
|
||||
return Collections.EMPTY_SET;
|
||||
public final Stream<RoleModel> searchForRolesStream(String search, Integer first, Integer max) {
|
||||
return Stream.empty();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -17,7 +17,6 @@
|
|||
|
||||
package org.keycloak.models;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
|
|
|
@ -20,6 +20,8 @@ import org.keycloak.provider.Provider;
|
|||
import org.keycloak.storage.client.ClientLookupProvider;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
/**
|
||||
* Provider of the client records.
|
||||
|
@ -31,21 +33,46 @@ public interface ClientProvider extends ClientLookupProvider, Provider {
|
|||
|
||||
/**
|
||||
* Returns the clients of the given realm.
|
||||
* @deprecated use the stream variant instead
|
||||
* @param realm Realm.
|
||||
* @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}.
|
||||
*/
|
||||
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.
|
||||
* @deprecated use the stream variant instead
|
||||
* Effectively the same as the call {@code getClients(realm, null, null)}.
|
||||
* @param realm Realm.
|
||||
* @return List of the clients. Never returns {@code null}.
|
||||
*/
|
||||
@Deprecated
|
||||
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.
|
||||
* @deprecated use the stream variant instead
|
||||
* @param realm Realm owning the clients.
|
||||
* @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.
|
||||
|
|
|
@ -26,6 +26,8 @@ import org.keycloak.storage.client.ClientStorageProvider;
|
|||
import org.keycloak.storage.client.ClientStorageProviderModel;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
|
@ -284,11 +286,28 @@ public interface RealmModel extends RoleContainerModel {
|
|||
|
||||
void removeDefaultGroup(GroupModel group);
|
||||
|
||||
List<ClientModel> getClients();
|
||||
List<ClientModel> getClients(Integer firstResult, Integer maxResults);
|
||||
@Deprecated
|
||||
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();
|
||||
|
||||
List<ClientModel> getAlwaysDisplayInConsoleClients();
|
||||
@Deprecated
|
||||
default List<ClientModel> getAlwaysDisplayInConsoleClients() {
|
||||
return getAlwaysDisplayInConsoleClientsStream().collect(Collectors.toList());
|
||||
}
|
||||
|
||||
Stream<ClientModel> getAlwaysDisplayInConsoleClientsStream();
|
||||
|
||||
ClientModel addClient(String name);
|
||||
|
||||
|
@ -298,7 +317,13 @@ public interface RealmModel extends RoleContainerModel {
|
|||
|
||||
ClientModel getClientById(String id);
|
||||
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);
|
||||
|
||||
|
|
|
@ -22,6 +22,8 @@ import org.keycloak.provider.Provider;
|
|||
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
/**
|
||||
* @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);
|
||||
|
||||
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,
|
||||
Integer max);
|
||||
Stream<RoleModel> getRealmRolesStream(RealmModel realm, Integer first, Integer max);
|
||||
|
||||
Set<RoleModel> searchForRoles(RealmModel realm, String search, 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);
|
||||
|
||||
@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);
|
||||
|
||||
|
@ -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}. */
|
||||
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}. */
|
||||
|
@ -151,16 +183,11 @@ public interface RealmProvider extends Provider /* TODO: Remove in future versio
|
|||
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}. */
|
||||
@Override
|
||||
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
|
||||
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}. */
|
||||
@Override
|
||||
|
@ -196,10 +218,4 @@ public interface RealmProvider extends Provider /* TODO: Remove in future versio
|
|||
/**
|
||||
* @deprecated Use the corresponding method from {@link ClientProvider}. */
|
||||
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.List;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
|
@ -47,11 +49,29 @@ public interface RoleContainerModel {
|
|||
|
||||
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();
|
||||
|
||||
|
|
|
@ -20,6 +20,8 @@ import org.keycloak.models.ClientModel;
|
|||
import org.keycloak.models.RealmModel;
|
||||
|
||||
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.
|
||||
|
@ -71,10 +73,14 @@ public interface ClientLookupProvider {
|
|||
* @param clientId Searched substring of the public client
|
||||
* identifier ({@code client_id} in OIDC or {@code entityID} in SAML.)
|
||||
* @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}.
|
||||
* @return Model of the client, or {@code null} if no client is found.
|
||||
* @param maxResults Maximum number of results to return. Ignored if negative or {@code null}.
|
||||
* @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.
|
||||
|
@ -82,11 +88,8 @@ public interface ClientLookupProvider {
|
|||
* @param clientId Searched substring of the public client
|
||||
* identifier ({@code client_id} in OIDC or {@code entityID} in SAML.)
|
||||
* @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}.
|
||||
* @return Models of the matching clients. Never returns {@code null}.
|
||||
* @deprecated Use {@link #searchClientsByClientId(org.keycloak.models.RealmModel, java.lang.String, java.lang.Integer, java.lang.Integer)} instead.
|
||||
* @param maxResults Maximum number of results to return. Ignored if negative or {@code null}.
|
||||
* @return Stream of ClientModel or an empty stream if no client is found.
|
||||
*/
|
||||
default List<ClientModel> searchClientsByClientId(String clientId, Integer firstResult, Integer maxResults, RealmModel realm) {
|
||||
return searchClientsByClientId(realm, clientId, firstResult, maxResults);
|
||||
}
|
||||
Stream<ClientModel> searchClientsByClientIdStream(RealmModel realm, String clientId, Integer firstResult, Integer maxResults);
|
||||
}
|
||||
|
|
|
@ -178,7 +178,9 @@ public class DefaultKeycloakSession implements KeycloakSession {
|
|||
|
||||
@Override
|
||||
public ClientProvider clientStorageManager() {
|
||||
if (clientStorageManager == null) clientStorageManager = new ClientStorageManager(this);
|
||||
if (clientStorageManager == null) {
|
||||
clientStorageManager = new ClientStorageManager(this, factory.getClientStorageProviderTimeout());
|
||||
}
|
||||
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
|
||||
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
|
||||
public void register(ProviderEventListener listener) {
|
||||
listeners.add(listener);
|
||||
|
@ -79,6 +85,8 @@ public class DefaultKeycloakSessionFactory implements KeycloakSessionFactory, Pr
|
|||
public void init() {
|
||||
serverStartupTimestamp = System.currentTimeMillis();
|
||||
|
||||
clientStorageProviderTimeout = Config.scope("client").getLong("storageProviderTimeout", 3000L);
|
||||
|
||||
ProviderManager pm = new ProviderManager(KeycloakDeploymentInfo.create().services(), getClass().getClassLoader(), Config.scope().getArray("providers"));
|
||||
spis.addAll(pm.loadSpis());
|
||||
factoriesMap = loadFactories(pm);
|
||||
|
@ -351,6 +359,10 @@ public class DefaultKeycloakSessionFactory implements KeycloakSessionFactory, Pr
|
|||
return packageName.startsWith("org.keycloak") && !packageName.startsWith("org.keycloak.examples");
|
||||
}
|
||||
|
||||
public long getClientStorageProviderTimeout() {
|
||||
return clientStorageProviderTimeout;
|
||||
}
|
||||
|
||||
/**
|
||||
* @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.ClientStorageProviderFactory;
|
||||
import org.keycloak.storage.client.ClientStorageProviderModel;
|
||||
import org.keycloak.utils.ServicesUtils;
|
||||
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
|
@ -41,6 +43,8 @@ public class ClientStorageManager implements ClientProvider {
|
|||
|
||||
protected KeycloakSession session;
|
||||
|
||||
private long clientStorageProviderTimeout;
|
||||
|
||||
public static boolean isStorageProviderEnabled(RealmModel realm, String providerId) {
|
||||
ClientStorageProviderModel model = getStorageProviderModel(realm, providerId);
|
||||
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.clientStorageProviderTimeout = clientStorageProviderTimeout;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -147,17 +152,22 @@ public class ClientStorageManager implements ClientProvider {
|
|||
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
|
||||
public List<ClientModel> searchClientsByClientId(RealmModel realm, String clientId, Integer firstResult, Integer maxResults) {
|
||||
List<ClientModel> clients = session.clientLocalStorage().searchClientsByClientId(realm, clientId, firstResult, maxResults);
|
||||
if (clients != null) {
|
||||
return clients;
|
||||
}
|
||||
for (ClientLookupProvider provider : getEnabledStorageProviders(session, realm, ClientLookupProvider.class)) {
|
||||
clients = provider.searchClientsByClientId(realm, clientId, firstResult, maxResults);
|
||||
if (clients != null) return clients;
|
||||
}
|
||||
return null;
|
||||
public Stream<ClientModel> searchClientsByClientIdStream(RealmModel realm, String clientId, Integer firstResult, Integer maxResults) {
|
||||
Stream<ClientModel> local = session.clientLocalStorage().searchClientsByClientIdStream(realm, clientId, firstResult, maxResults);
|
||||
Stream<ClientModel> ext = getEnabledStorageProviders(session, realm, ClientLookupProvider.class).stream()
|
||||
.flatMap(ServicesUtils.timeBound(session,
|
||||
clientStorageProviderTimeout,
|
||||
p -> ((ClientLookupProvider) p).searchClientsByClientIdStream(realm, clientId, firstResult, maxResults)));
|
||||
|
||||
return Stream.concat(local, ext);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -171,13 +181,13 @@ public class ClientStorageManager implements ClientProvider {
|
|||
}
|
||||
|
||||
@Override
|
||||
public List<ClientModel> getClients(RealmModel realm, Integer firstResult, Integer maxResults) {
|
||||
return session.clientLocalStorage().getClients(realm, firstResult, maxResults);
|
||||
public Stream<ClientModel> getClientsStream(RealmModel realm, Integer firstResult, Integer maxResults) {
|
||||
return session.clientLocalStorage().getClientsStream(realm, firstResult, maxResults);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ClientModel> getClients(RealmModel realm) {
|
||||
return session.clientLocalStorage().getClients(realm);
|
||||
public Stream<ClientModel> getClientsStream(RealmModel realm) {
|
||||
return session.clientLocalStorage().getClientsStream(realm);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -186,8 +196,8 @@ public class ClientStorageManager implements ClientProvider {
|
|||
}
|
||||
|
||||
@Override
|
||||
public List<ClientModel> getAlwaysDisplayInConsoleClients(RealmModel realm) {
|
||||
return session.clientLocalStorage().getAlwaysDisplayInConsoleClients(realm);
|
||||
public Stream<ClientModel> getAlwaysDisplayInConsoleClientsStream(RealmModel realm) {
|
||||
return session.clientLocalStorage().getAlwaysDisplayInConsoleClientsStream(realm);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -26,9 +26,8 @@ import org.keycloak.storage.StorageId;
|
|||
import org.keycloak.storage.client.ClientStorageProvider;
|
||||
import org.keycloak.storage.client.ClientStorageProviderModel;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
|
||||
|
@ -76,9 +75,9 @@ public class OpenshiftClientStorageProvider implements ClientStorageProvider {
|
|||
}
|
||||
|
||||
@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
|
||||
return Collections.singletonList(getClientByClientId(realm, clientId));
|
||||
return Stream.of(getClientByClientId(realm, clientId));
|
||||
}
|
||||
|
||||
@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.Map;
|
||||
import java.util.Set;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
|
@ -79,11 +78,11 @@ public class HardcodedClientStorageProvider implements ClientStorageProvider, Cl
|
|||
}
|
||||
|
||||
@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())) {
|
||||
return Collections.singletonList(new ClientAdapter(realm));
|
||||
return Stream.of(new ClientAdapter(realm));
|
||||
}
|
||||
return Collections.EMPTY_LIST;
|
||||
return Stream.empty();
|
||||
}
|
||||
|
||||
public class ClientAdapter extends AbstractReadOnlyClientStorageAdapter {
|
||||
|
|
Loading…
Reference in a new issue