[KEYCLOAK-15200] Complement methods for accessing users with Stream variants
This commit is contained in:
parent
8d6577d66c
commit
aa46735173
36 changed files with 998 additions and 735 deletions
|
@ -21,12 +21,12 @@ import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.LinkedList;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.concurrent.atomic.AtomicReference;
|
import java.util.concurrent.atomic.AtomicReference;
|
||||||
import java.util.stream.Collectors;
|
import java.util.function.Predicate;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
import javax.naming.AuthenticationException;
|
import javax.naming.AuthenticationException;
|
||||||
|
|
||||||
|
@ -247,7 +247,7 @@ public class LDAPStorageProvider implements UserStorageProvider,
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<UserModel> searchForUserByUserAttribute(String attrName, String attrValue, RealmModel realm) {
|
public Stream<UserModel> searchForUserByUserAttributeStream(String attrName, String attrValue, RealmModel realm) {
|
||||||
try (LDAPQuery ldapQuery = LDAPUtils.createQueryForUserSearch(this, realm)) {
|
try (LDAPQuery ldapQuery = LDAPUtils.createQueryForUserSearch(this, realm)) {
|
||||||
LDAPQueryConditionsBuilder conditionsBuilder = new LDAPQueryConditionsBuilder();
|
LDAPQueryConditionsBuilder conditionsBuilder = new LDAPQueryConditionsBuilder();
|
||||||
|
|
||||||
|
@ -256,24 +256,15 @@ public class LDAPStorageProvider implements UserStorageProvider,
|
||||||
|
|
||||||
List<LDAPObject> ldapObjects = ldapQuery.getResultList();
|
List<LDAPObject> ldapObjects = ldapQuery.getResultList();
|
||||||
|
|
||||||
if (ldapObjects == null || ldapObjects.isEmpty()) {
|
return ldapObjects.stream().map(ldapUser -> {
|
||||||
return Collections.emptyList();
|
|
||||||
}
|
|
||||||
|
|
||||||
List<UserModel> searchResults = new LinkedList<>();
|
|
||||||
|
|
||||||
for (LDAPObject ldapUser : ldapObjects) {
|
|
||||||
String ldapUsername = LDAPUtils.getUsername(ldapUser, this.ldapIdentityStore.getConfig());
|
String ldapUsername = LDAPUtils.getUsername(ldapUser, this.ldapIdentityStore.getConfig());
|
||||||
UserModel localUser = session.userLocalStorage().getUserByUsername(ldapUsername, realm);
|
UserModel localUser = session.userLocalStorage().getUserByUsername(ldapUsername, realm);
|
||||||
if (localUser == null) {
|
if (localUser == null) {
|
||||||
UserModel imported = importUserFromLDAP(session, realm, ldapUser);
|
return importUserFromLDAP(session, realm, ldapUser);
|
||||||
searchResults.add(imported);
|
|
||||||
} else {
|
} else {
|
||||||
searchResults.add(proxy(realm, localUser, ldapUser, false));
|
return proxy(realm, localUser, ldapUser, false);
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
|
|
||||||
return searchResults;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -348,34 +339,34 @@ public class LDAPStorageProvider implements UserStorageProvider,
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<UserModel> getUsers(RealmModel realm) {
|
public Stream<UserModel> getUsersStream(RealmModel realm) {
|
||||||
return Collections.EMPTY_LIST;
|
return Stream.empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<UserModel> getUsers(RealmModel realm, int firstResult, int maxResults) {
|
public Stream<UserModel> getUsersStream(RealmModel realm, int firstResult, int maxResults) {
|
||||||
return Collections.EMPTY_LIST;
|
return Stream.empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<UserModel> searchForUser(String search, RealmModel realm) {
|
public Stream<UserModel> searchForUserStream(String search, RealmModel realm) {
|
||||||
return searchForUser(search, realm, 0, Integer.MAX_VALUE - 1);
|
return searchForUserStream(search, realm, 0, Integer.MAX_VALUE - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<UserModel> searchForUser(String search, RealmModel realm, int firstResult, int maxResults) {
|
public Stream<UserModel> searchForUserStream(String search, RealmModel realm, int firstResult, int maxResults) {
|
||||||
Map<String, String> attributes = new HashMap<String, String>();
|
Map<String, String> attributes = new HashMap<String, String>();
|
||||||
attributes.put(UserModel.SEARCH,search);
|
attributes.put(UserModel.SEARCH,search);
|
||||||
return searchForUser(attributes, realm, firstResult, maxResults);
|
return searchForUserStream(attributes, realm, firstResult, maxResults);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<UserModel> searchForUser(Map<String, String> params, RealmModel realm) {
|
public Stream<UserModel> searchForUserStream(Map<String, String> params, RealmModel realm) {
|
||||||
return searchForUser(params, realm, 0, Integer.MAX_VALUE - 1);
|
return searchForUserStream(params, realm, 0, Integer.MAX_VALUE - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<UserModel> searchForUser(Map<String, String> params, RealmModel realm, int firstResult, int maxResults) {
|
public Stream<UserModel> searchForUserStream(Map<String, String> params, RealmModel realm, int firstResult, int maxResults) {
|
||||||
String search = params.get(UserModel.SEARCH);
|
String search = params.get(UserModel.SEARCH);
|
||||||
if(search!=null) {
|
if(search!=null) {
|
||||||
int spaceIndex = search.lastIndexOf(' ');
|
int spaceIndex = search.lastIndexOf(' ');
|
||||||
|
@ -393,65 +384,47 @@ public class LDAPStorageProvider implements UserStorageProvider,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
List<UserModel> searchResults =new LinkedList<UserModel>();
|
Stream<LDAPObject> stream = searchLDAP(realm, params).stream()
|
||||||
|
.filter(ldapObject -> {
|
||||||
List<LDAPObject> ldapUsers = searchLDAP(realm, params, maxResults + firstResult);
|
String ldapUsername = LDAPUtils.getUsername(ldapObject, this.ldapIdentityStore.getConfig());
|
||||||
int counter = 0;
|
return (session.userLocalStorage().getUserByUsername(ldapUsername, realm) == null);
|
||||||
for (LDAPObject ldapUser : ldapUsers) {
|
});
|
||||||
if (counter++ < firstResult) continue;
|
if (firstResult > 0)
|
||||||
String ldapUsername = LDAPUtils.getUsername(ldapUser, this.ldapIdentityStore.getConfig());
|
stream = stream.skip(firstResult);
|
||||||
if (session.userLocalStorage().getUserByUsername(ldapUsername, realm) == null) {
|
if (maxResults >= 0)
|
||||||
UserModel imported = importUserFromLDAP(session, realm, ldapUser);
|
stream = stream.limit(maxResults);
|
||||||
searchResults.add(imported);
|
return stream.map(ldapObject -> importUserFromLDAP(session, realm, ldapObject));
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return searchResults;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<UserModel> getGroupMembers(RealmModel realm, GroupModel group) {
|
public Stream<UserModel> getGroupMembersStream(RealmModel realm, GroupModel group) {
|
||||||
return getGroupMembers(realm, group, 0, Integer.MAX_VALUE - 1);
|
return getGroupMembersStream(realm, group, 0, Integer.MAX_VALUE - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<UserModel> getGroupMembers(RealmModel realm, GroupModel group, int firstResult, int maxResults) {
|
public Stream<UserModel> getGroupMembersStream(RealmModel realm, GroupModel group, int firstResult, int maxResults) {
|
||||||
List<ComponentModel> sortedMappers = realm.getComponentsStream(model.getId(), LDAPStorageMapper.class.getName())
|
return realm.getComponentsStream(model.getId(), LDAPStorageMapper.class.getName())
|
||||||
|
.sorted(ldapMappersComparator.sortAsc())
|
||||||
|
.map(mapperModel ->
|
||||||
|
mapperManager.getMapper(mapperModel).getGroupMembers(realm, group, firstResult, maxResults))
|
||||||
|
.filter(((Predicate<List>) List::isEmpty).negate())
|
||||||
|
.map(List::stream)
|
||||||
|
.findFirst().orElse(Stream.empty());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Stream<UserModel> getRoleMembersStream(RealmModel realm, RoleModel role) {
|
||||||
|
return getRoleMembersStream(realm, role, 0, Integer.MAX_VALUE - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Stream<UserModel> getRoleMembersStream(RealmModel realm, RoleModel role, int firstResult, int maxResults) {
|
||||||
|
return realm.getComponentsStream(model.getId(), LDAPStorageMapper.class.getName())
|
||||||
.sorted(ldapMappersComparator.sortAsc())
|
.sorted(ldapMappersComparator.sortAsc())
|
||||||
.collect(Collectors.toList());
|
.map(mapperModel -> mapperManager.getMapper(mapperModel).getRoleMembers(realm, role, firstResult, maxResults))
|
||||||
|
.filter(((Predicate<List>) List::isEmpty).negate())
|
||||||
for (ComponentModel mapperModel : sortedMappers) {
|
.map(List::stream)
|
||||||
LDAPStorageMapper ldapMapper = mapperManager.getMapper(mapperModel);
|
.findFirst().orElse(Stream.empty());
|
||||||
List<UserModel> users = ldapMapper.getGroupMembers(realm, group, firstResult, maxResults);
|
|
||||||
|
|
||||||
// Sufficient for now
|
|
||||||
if (users.size() > 0) {
|
|
||||||
return users;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return Collections.emptyList();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public List<UserModel> getRoleMembers(RealmModel realm, RoleModel role) {
|
|
||||||
return getRoleMembers(realm, role, 0, Integer.MAX_VALUE - 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public List<UserModel> getRoleMembers(RealmModel realm, RoleModel role, int firstResult, int maxResults) {
|
|
||||||
List<ComponentModel> sortedMappers = realm.getComponentsStream(model.getId(), LDAPStorageMapper.class.getName())
|
|
||||||
.sorted(ldapMappersComparator.sortAsc())
|
|
||||||
.collect(Collectors.toList());
|
|
||||||
for (ComponentModel mapperModel : sortedMappers) {
|
|
||||||
LDAPStorageMapper ldapMapper = mapperManager.getMapper(mapperModel);
|
|
||||||
List<UserModel> users = ldapMapper.getRoleMembers(realm, role, firstResult, maxResults);
|
|
||||||
|
|
||||||
// Sufficient for now
|
|
||||||
if (users.size() > 0) {
|
|
||||||
return users;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return Collections.emptyList();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<UserModel> loadUsersByUsernames(List<String> usernames, RealmModel realm) {
|
public List<UserModel> loadUsersByUsernames(List<String> usernames, RealmModel realm) {
|
||||||
|
@ -469,7 +442,7 @@ public class LDAPStorageProvider implements UserStorageProvider,
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected List<LDAPObject> searchLDAP(RealmModel realm, Map<String, String> attributes, int maxResults) {
|
protected List<LDAPObject> searchLDAP(RealmModel realm, Map<String, String> attributes) {
|
||||||
|
|
||||||
List<LDAPObject> results = new ArrayList<LDAPObject>();
|
List<LDAPObject> results = new ArrayList<LDAPObject>();
|
||||||
if (attributes.containsKey(UserModel.USERNAME)) {
|
if (attributes.containsKey(UserModel.USERNAME)) {
|
||||||
|
|
|
@ -34,6 +34,7 @@ import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Mapper useful for the LDAP deployments when some attribute (usually CN) is mapped to full name of user
|
* Mapper useful for the LDAP deployments when some attribute (usually CN) is mapped to full name of user
|
||||||
|
@ -108,13 +109,13 @@ public class FullNameLDAPStorageMapper extends AbstractLDAPStorageMapper {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<String> getAttribute(String name) {
|
public Stream<String> getAttributeStream(String name) {
|
||||||
if (UserModel.FIRST_NAME.equals(name)) {
|
if (UserModel.FIRST_NAME.equals(name)) {
|
||||||
return firstName != null ? Collections.singletonList(firstName) : super.getAttribute(name);
|
return firstName != null ? Stream.of(firstName) : super.getAttributeStream(name);
|
||||||
} else if (UserModel.LAST_NAME.equals(name)) {
|
} else if (UserModel.LAST_NAME.equals(name)) {
|
||||||
return lastName != null ? Collections.singletonList(lastName) : super.getAttribute(name);
|
return lastName != null ? Stream.of(lastName) : super.getAttributeStream(name);
|
||||||
}
|
}
|
||||||
return super.getAttribute(name);
|
return super.getAttributeStream(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -18,8 +18,8 @@
|
||||||
package org.keycloak.storage.ldap.mappers;
|
package org.keycloak.storage.ldap.mappers;
|
||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
import org.jboss.logging.Logger;
|
import org.jboss.logging.Logger;
|
||||||
import org.keycloak.component.ComponentModel;
|
import org.keycloak.component.ComponentModel;
|
||||||
|
@ -73,11 +73,11 @@ public class HardcodedAttributeMapper extends AbstractLDAPStorageMapper {
|
||||||
delegate = new UserModelDelegate(delegate) {
|
delegate = new UserModelDelegate(delegate) {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<String> getAttribute(String name) {
|
public Stream<String> getAttributeStream(String name) {
|
||||||
if(userModelAttrName.equals(name)){
|
if(userModelAttrName.equals(name)){
|
||||||
return Arrays.asList(attributeValue);
|
return Stream.of(attributeValue);
|
||||||
}
|
}
|
||||||
return super.getAttribute(name);
|
return super.getAttributeStream(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -37,12 +37,12 @@ import org.keycloak.storage.ldap.idm.query.internal.LDAPQuery;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.LinkedHashSet;
|
import java.util.LinkedHashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
||||||
|
@ -338,16 +338,16 @@ public class UserAttributeLDAPStorageMapper extends AbstractLDAPStorageMapper {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<String> getAttribute(String name) {
|
public Stream<String> getAttributeStream(String name) {
|
||||||
if (name.equalsIgnoreCase(userModelAttrName)) {
|
if (name.equalsIgnoreCase(userModelAttrName)) {
|
||||||
Collection<String> ldapAttrValue = ldapUser.getAttributeAsSet(ldapAttrName);
|
Collection<String> ldapAttrValue = ldapUser.getAttributeAsSet(ldapAttrName);
|
||||||
if (ldapAttrValue == null) {
|
if (ldapAttrValue == null) {
|
||||||
return Collections.emptyList();
|
return Stream.empty();
|
||||||
} else {
|
} else {
|
||||||
return new ArrayList<>(ldapAttrValue);
|
return ldapAttrValue.stream();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return super.getAttribute(name);
|
return super.getAttributeStream(name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -38,6 +38,7 @@ import java.util.HashSet;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.regex.Matcher;
|
import java.util.regex.Matcher;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Mapper specific to MSAD. It's able to read the userAccountControl and pwdLastSet attributes and set actions in Keycloak based on that.
|
* Mapper specific to MSAD. It's able to read the userAccountControl and pwdLastSet attributes and set actions in Keycloak based on that.
|
||||||
|
@ -299,18 +300,14 @@ public class MSADUserAccountControlStorageMapper extends AbstractLDAPStorageMapp
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Set<String> getRequiredActions() {
|
public Stream<String> getRequiredActionsStream() {
|
||||||
Set<String> requiredActions = super.getRequiredActions();
|
|
||||||
|
|
||||||
if (ldapProvider.getEditMode() == UserStorageProvider.EditMode.WRITABLE) {
|
if (ldapProvider.getEditMode() == UserStorageProvider.EditMode.WRITABLE) {
|
||||||
if (getPwdLastSet() == 0 || getUserAccountControl(ldapUser).has(UserAccountControl.PASSWORD_EXPIRED)) {
|
if (getPwdLastSet() == 0 || getUserAccountControl(ldapUser).has(UserAccountControl.PASSWORD_EXPIRED)) {
|
||||||
requiredActions = new HashSet<>(requiredActions);
|
return Stream.concat(super.getRequiredActionsStream(), Stream.of(RequiredAction.UPDATE_PASSWORD.toString()))
|
||||||
requiredActions.add(RequiredAction.UPDATE_PASSWORD.toString());
|
.distinct();
|
||||||
return requiredActions;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return super.getRequiredActionsStream();
|
||||||
return requiredActions;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected long getPwdLastSet() {
|
protected long getPwdLastSet() {
|
||||||
|
|
|
@ -38,6 +38,7 @@ import java.util.HashSet;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.regex.Matcher;
|
import java.util.regex.Matcher;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Mapper specific to MSAD LDS. It's able to read the msDS-UserAccountDisabled, msDS-UserPasswordExpired and pwdLastSet attributes and set actions in Keycloak based on that.
|
* Mapper specific to MSAD LDS. It's able to read the msDS-UserAccountDisabled, msDS-UserPasswordExpired and pwdLastSet attributes and set actions in Keycloak based on that.
|
||||||
|
@ -257,17 +258,14 @@ public class MSADLDSUserAccountControlStorageMapper extends AbstractLDAPStorageM
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Set<String> getRequiredActions() {
|
public Stream<String> getRequiredActionsStream() {
|
||||||
Set<String> requiredActions = super.getRequiredActions();
|
Stream<String> requiredActions = super.getRequiredActionsStream();
|
||||||
|
|
||||||
if (ldapProvider.getEditMode() == UserStorageProvider.EditMode.WRITABLE) {
|
if (ldapProvider.getEditMode() == UserStorageProvider.EditMode.WRITABLE) {
|
||||||
if (getPwdLastSet() == 0 || Boolean.parseBoolean(ldapUser.getAttributeAsString(LDAPConstants.MSDS_USER_PASSWORD_EXPIRED))) {
|
if (getPwdLastSet() == 0 || Boolean.parseBoolean(ldapUser.getAttributeAsString(LDAPConstants.MSDS_USER_PASSWORD_EXPIRED))) {
|
||||||
requiredActions = new HashSet<>(requiredActions);
|
return Stream.concat(requiredActions, Stream.of(RequiredAction.UPDATE_PASSWORD.toString())).distinct();
|
||||||
requiredActions.add(RequiredAction.UPDATE_PASSWORD.toString());
|
|
||||||
return requiredActions;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return requiredActions;
|
return requiredActions;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -178,7 +178,7 @@ public class UserAdapter implements CachedUserModel {
|
||||||
getDelegateForUpdate();
|
getDelegateForUpdate();
|
||||||
if (UserModel.USERNAME.equals(name) || UserModel.EMAIL.equals(name)) {
|
if (UserModel.USERNAME.equals(name) || UserModel.EMAIL.equals(name)) {
|
||||||
String lowerCasedFirstValue = KeycloakModelUtils.toLowerCaseSafe((values != null && values.size() > 0) ? values.get(0) : null);
|
String lowerCasedFirstValue = KeycloakModelUtils.toLowerCaseSafe((values != null && values.size() > 0) ? values.get(0) : null);
|
||||||
if (lowerCasedFirstValue != null) values=Collections.singletonList(lowerCasedFirstValue);
|
if (lowerCasedFirstValue != null) values = Collections.singletonList(lowerCasedFirstValue);
|
||||||
}
|
}
|
||||||
updated.setAttribute(name, values);
|
updated.setAttribute(name, values);
|
||||||
}
|
}
|
||||||
|
@ -196,10 +196,10 @@ public class UserAdapter implements CachedUserModel {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<String> getAttribute(String name) {
|
public Stream<String> getAttributeStream(String name) {
|
||||||
if (updated != null) return updated.getAttribute(name);
|
if (updated != null) return updated.getAttributeStream(name);
|
||||||
List<String> result = cached.getAttributes(modelSupplier).get(name);
|
List<String> result = cached.getAttributes(modelSupplier).get(name);
|
||||||
return (result == null) ? Collections.emptyList() : result;
|
return (result == null) ? Stream.empty() : result.stream();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -209,9 +209,9 @@ public class UserAdapter implements CachedUserModel {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Set<String> getRequiredActions() {
|
public Stream<String> getRequiredActionsStream() {
|
||||||
if (updated != null) return updated.getRequiredActions();
|
if (updated != null) return updated.getRequiredActionsStream();
|
||||||
return cached.getRequiredActions(modelSupplier);
|
return cached.getRequiredActions(modelSupplier).stream();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -289,10 +289,9 @@ public class UserAdapter implements CachedUserModel {
|
||||||
@Override
|
@Override
|
||||||
public boolean hasRole(RoleModel role) {
|
public boolean hasRole(RoleModel role) {
|
||||||
if (updated != null) return updated.hasRole(role);
|
if (updated != null) return updated.hasRole(role);
|
||||||
if (cached.getRoleMappings(modelSupplier).contains(role.getId())) return true;
|
return cached.getRoleMappings(modelSupplier).contains(role.getId()) ||
|
||||||
|
getRoleMappingsStream().anyMatch(r -> r.hasRole(role)) ||
|
||||||
return getRoleMappingsStream().anyMatch(r -> r.hasRole(role)) ?
|
RoleUtils.hasRoleFromGroup(getGroupsStream(), role, true);
|
||||||
true : RoleUtils.hasRoleFromGroup(getGroupsStream(), role, true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -363,8 +362,7 @@ public class UserAdapter implements CachedUserModel {
|
||||||
@Override
|
@Override
|
||||||
public boolean isMemberOf(GroupModel group) {
|
public boolean isMemberOf(GroupModel group) {
|
||||||
if (updated != null) return updated.isMemberOf(group);
|
if (updated != null) return updated.isMemberOf(group);
|
||||||
if (cached.getGroups(modelSupplier).contains(group.getId())) return true;
|
return cached.getGroups(modelSupplier).contains(group.getId()) || RoleUtils.isMember(getGroupsStream(), group);
|
||||||
return RoleUtils.isMember(getGroupsStream(), group);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -60,10 +60,12 @@ import org.keycloak.storage.client.ClientStorageProvider;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.LinkedList;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Objects;
|
||||||
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>
|
||||||
|
@ -452,26 +454,25 @@ public class UserCacheSession implements UserCache {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<UserModel> getGroupMembers(RealmModel realm, GroupModel group, int firstResult, int maxResults) {
|
public Stream<UserModel> getGroupMembersStream(RealmModel realm, GroupModel group, int firstResult, int maxResults) {
|
||||||
return getDelegate().getGroupMembers(realm, group, firstResult, maxResults);
|
return getDelegate().getGroupMembersStream(realm, group, firstResult, maxResults);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<UserModel> getGroupMembers(RealmModel realm, GroupModel group) {
|
public Stream<UserModel> getGroupMembersStream(RealmModel realm, GroupModel group) {
|
||||||
return getDelegate().getGroupMembers(realm, group);
|
return getDelegate().getGroupMembersStream(realm, group);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<UserModel> getRoleMembers(RealmModel realm, RoleModel role, int firstResult, int maxResults) {
|
public Stream<UserModel> getRoleMembersStream(RealmModel realm, RoleModel role, int firstResult, int maxResults) {
|
||||||
return getDelegate().getRoleMembers(realm, role, firstResult, maxResults);
|
return getDelegate().getRoleMembersStream(realm, role, firstResult, maxResults);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<UserModel> getRoleMembers(RealmModel realm, RoleModel role) {
|
public Stream<UserModel> getRoleMembersStream(RealmModel realm, RoleModel role) {
|
||||||
return getDelegate().getRoleMembers(realm, role);
|
return getDelegate().getRoleMembersStream(realm, role);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public UserModel getServiceAccount(ClientModel client) {
|
public UserModel getServiceAccount(ClientModel client) {
|
||||||
// Just an attempt to find the user from cache by default serviceAccount username
|
// Just an attempt to find the user from cache by default serviceAccount username
|
||||||
|
@ -534,12 +535,9 @@ public class UserCacheSession implements UserCache {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<UserModel> getUsers(RealmModel realm, boolean includeServiceAccounts) {
|
public Stream<UserModel> getUsersStream(RealmModel realm, boolean includeServiceAccounts) {
|
||||||
return getDelegate().getUsers(realm, includeServiceAccounts);
|
return getDelegate().getUsersStream(realm, includeServiceAccounts);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -578,64 +576,65 @@ public class UserCacheSession implements UserCache {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<UserModel> getUsers(RealmModel realm, int firstResult, int maxResults, boolean includeServiceAccounts) {
|
public Stream<UserModel> getUsersStream(RealmModel realm, int firstResult, int maxResults, boolean includeServiceAccounts) {
|
||||||
return getDelegate().getUsers(realm, firstResult, maxResults, includeServiceAccounts);
|
return getDelegate().getUsersStream(realm, firstResult, maxResults, includeServiceAccounts);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<UserModel> getUsers(RealmModel realm) {
|
public Stream<UserModel> getUsersStream(RealmModel realm) {
|
||||||
return getUsers(realm, false);
|
return getUsersStream(realm, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<UserModel> getUsers(RealmModel realm, int firstResult, int maxResults) {
|
public Stream<UserModel> getUsersStream(RealmModel realm, int firstResult, int maxResults) {
|
||||||
return getUsers(realm, firstResult, maxResults, false);
|
return getUsersStream(realm, firstResult, maxResults, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<UserModel> searchForUser(String search, RealmModel realm) {
|
public Stream<UserModel> searchForUserStream(String search, RealmModel realm) {
|
||||||
return getDelegate().searchForUser(search, realm);
|
return getDelegate().searchForUserStream(search, realm);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<UserModel> searchForUser(String search, RealmModel realm, int firstResult, int maxResults) {
|
public Stream<UserModel> searchForUserStream(String search, RealmModel realm, int firstResult, int maxResults) {
|
||||||
return getDelegate().searchForUser(search, realm, firstResult, maxResults);
|
return getDelegate().searchForUserStream(search, realm, firstResult, maxResults);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<UserModel> searchForUser(Map<String, String> attributes, RealmModel realm) {
|
public Stream<UserModel> searchForUserStream(Map<String, String> attributes, RealmModel realm) {
|
||||||
return getDelegate().searchForUser(attributes, realm);
|
return getDelegate().searchForUserStream(attributes, realm);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<UserModel> searchForUser(Map<String, String> attributes, RealmModel realm, int firstResult, int maxResults) {
|
public Stream<UserModel> searchForUserStream(Map<String, String> attributes, RealmModel realm, int firstResult, int maxResults) {
|
||||||
return getDelegate().searchForUser(attributes, realm, firstResult, maxResults);
|
return getDelegate().searchForUserStream(attributes, realm, firstResult, maxResults);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<UserModel> searchForUserByUserAttribute(String attrName, String attrValue, RealmModel realm) {
|
public Stream<UserModel> searchForUserByUserAttributeStream(String attrName, String attrValue, RealmModel realm) {
|
||||||
return getDelegate().searchForUserByUserAttribute(attrName, attrValue, realm);
|
return getDelegate().searchForUserByUserAttributeStream(attrName, attrValue, realm);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Set<FederatedIdentityModel> getFederatedIdentities(UserModel user, RealmModel realm) {
|
public Stream<FederatedIdentityModel> getFederatedIdentitiesStream(UserModel user, RealmModel realm) {
|
||||||
logger.tracev("getFederatedIdentities: {0}", user.getUsername());
|
logger.tracev("getFederatedIdentities: {0}", user.getUsername());
|
||||||
|
|
||||||
String cacheKey = getFederatedIdentityLinksCacheKey(user.getId());
|
String cacheKey = getFederatedIdentityLinksCacheKey(user.getId());
|
||||||
if (realmInvalidations.contains(realm.getId()) || invalidations.contains(user.getId()) || invalidations.contains(cacheKey)) {
|
if (realmInvalidations.contains(realm.getId()) || invalidations.contains(user.getId()) || invalidations.contains(cacheKey)) {
|
||||||
return getDelegate().getFederatedIdentities(user, realm);
|
return getDelegate().getFederatedIdentitiesStream(user, realm);
|
||||||
}
|
}
|
||||||
|
|
||||||
CachedFederatedIdentityLinks cachedLinks = cache.get(cacheKey, CachedFederatedIdentityLinks.class);
|
CachedFederatedIdentityLinks cachedLinks = cache.get(cacheKey, CachedFederatedIdentityLinks.class);
|
||||||
|
|
||||||
if (cachedLinks == null) {
|
if (cachedLinks == null) {
|
||||||
Long loaded = cache.getCurrentRevision(cacheKey);
|
Long loaded = cache.getCurrentRevision(cacheKey);
|
||||||
Set<FederatedIdentityModel> federatedIdentities = getDelegate().getFederatedIdentities(user, realm);
|
Set<FederatedIdentityModel> federatedIdentities = getDelegate().getFederatedIdentitiesStream(user, realm)
|
||||||
|
.collect(Collectors.toSet());
|
||||||
cachedLinks = new CachedFederatedIdentityLinks(loaded, cacheKey, realm, federatedIdentities);
|
cachedLinks = new CachedFederatedIdentityLinks(loaded, cacheKey, realm, federatedIdentities);
|
||||||
cache.addRevisioned(cachedLinks, startupRevision);
|
cache.addRevisioned(cachedLinks, startupRevision);
|
||||||
return federatedIdentities;
|
return federatedIdentities.stream();
|
||||||
} else {
|
} else {
|
||||||
return new HashSet<>(cachedLinks.getFederatedIdentities());
|
return cachedLinks.getFederatedIdentities().stream();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -708,31 +707,25 @@ public class UserCacheSession implements UserCache {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<UserConsentModel> getConsents(RealmModel realm, String userId) {
|
public Stream<UserConsentModel> getConsentsStream(RealmModel realm, String userId) {
|
||||||
logger.tracev("getConsents: {0}", userId);
|
logger.tracev("getConsents: {0}", userId);
|
||||||
|
|
||||||
String cacheKey = getConsentCacheKey(userId);
|
String cacheKey = getConsentCacheKey(userId);
|
||||||
if (realmInvalidations.contains(realm.getId()) || invalidations.contains(userId) || invalidations.contains(cacheKey)) {
|
if (realmInvalidations.contains(realm.getId()) || invalidations.contains(userId) || invalidations.contains(cacheKey)) {
|
||||||
return getDelegate().getConsents(realm, userId);
|
return getDelegate().getConsentsStream(realm, userId);
|
||||||
}
|
}
|
||||||
|
|
||||||
CachedUserConsents cached = cache.get(cacheKey, CachedUserConsents.class);
|
CachedUserConsents cached = cache.get(cacheKey, CachedUserConsents.class);
|
||||||
|
|
||||||
if (cached == null) {
|
if (cached == null) {
|
||||||
Long loaded = cache.getCurrentRevision(cacheKey);
|
Long loaded = cache.getCurrentRevision(cacheKey);
|
||||||
List<UserConsentModel> consents = getDelegate().getConsents(realm, userId);
|
List<UserConsentModel> consents = getDelegate().getConsentsStream(realm, userId).collect(Collectors.toList());
|
||||||
cached = new CachedUserConsents(loaded, cacheKey, realm, consents);
|
cached = new CachedUserConsents(loaded, cacheKey, realm, consents);
|
||||||
cache.addRevisioned(cached, startupRevision);
|
cache.addRevisioned(cached, startupRevision);
|
||||||
return consents;
|
return consents.stream();
|
||||||
} else {
|
} else {
|
||||||
List<UserConsentModel> result = new LinkedList<>();
|
return cached.getConsents().values().stream().map(cachedConsent -> toConsentModel(realm, cachedConsent))
|
||||||
for (CachedUserConsent cachedConsent : cached.getConsents().values()) {
|
.filter(Objects::nonNull);
|
||||||
UserConsentModel consent = toConsentModel(realm, cachedConsent);
|
|
||||||
if (consent != null) {
|
|
||||||
result.add(consent);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -62,7 +62,7 @@ public class CachedUser extends AbstractExtendableRevisioned implements InRealm
|
||||||
this.federationLink = user.getFederationLink();
|
this.federationLink = user.getFederationLink();
|
||||||
this.serviceAccountClientLink = user.getServiceAccountClientLink();
|
this.serviceAccountClientLink = user.getServiceAccountClientLink();
|
||||||
this.notBefore = notBefore;
|
this.notBefore = notBefore;
|
||||||
this.requiredActions = new DefaultLazyLoader<>(UserModel::getRequiredActions, Collections::emptySet);
|
this.requiredActions = new DefaultLazyLoader<>(userModel -> userModel.getRequiredActionsStream().collect(Collectors.toSet()), Collections::emptySet);
|
||||||
this.attributes = new DefaultLazyLoader<>(userModel -> new MultivaluedHashMap<>(userModel.getAttributes()), MultivaluedHashMap::new);
|
this.attributes = new DefaultLazyLoader<>(userModel -> new MultivaluedHashMap<>(userModel.getAttributes()), MultivaluedHashMap::new);
|
||||||
this.roleMappings = new DefaultLazyLoader<>(userModel -> userModel.getRoleMappingsStream().map(RoleModel::getId).collect(Collectors.toSet()), Collections::emptySet);
|
this.roleMappings = new DefaultLazyLoader<>(userModel -> userModel.getRoleMappingsStream().map(RoleModel::getId).collect(Collectors.toSet()), Collections::emptySet);
|
||||||
this.groups = new DefaultLazyLoader<>(userModel -> userModel.getGroupsStream().map(GroupModel::getId).collect(Collectors.toCollection(LinkedHashSet::new)), LinkedHashSet::new);
|
this.groups = new DefaultLazyLoader<>(userModel -> userModel.getGroupsStream().map(GroupModel::getId).collect(Collectors.toCollection(LinkedHashSet::new)), LinkedHashSet::new);
|
||||||
|
|
|
@ -58,10 +58,25 @@ import javax.persistence.criteria.Join;
|
||||||
import javax.persistence.criteria.Predicate;
|
import javax.persistence.criteria.Predicate;
|
||||||
import javax.persistence.criteria.Root;
|
import javax.persistence.criteria.Root;
|
||||||
import javax.persistence.criteria.Subquery;
|
import javax.persistence.criteria.Subquery;
|
||||||
import java.util.*;
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Comparator;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.LinkedList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.Set;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
import javax.persistence.LockModeType;
|
import javax.persistence.LockModeType;
|
||||||
|
|
||||||
|
import static org.keycloak.utils.StreamsUtil.closing;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||||
* @version $Revision: 1 $
|
* @version $Revision: 1 $
|
||||||
|
@ -232,17 +247,10 @@ public class JpaUserProvider implements UserProvider, UserCredentialStore {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<UserConsentModel> getConsents(RealmModel realm, String userId) {
|
public Stream<UserConsentModel> getConsentsStream(RealmModel realm, String userId) {
|
||||||
TypedQuery<UserConsentEntity> query = em.createNamedQuery("userConsentsByUser", UserConsentEntity.class);
|
TypedQuery<UserConsentEntity> query = em.createNamedQuery("userConsentsByUser", UserConsentEntity.class);
|
||||||
query.setParameter("userId", userId);
|
query.setParameter("userId", userId);
|
||||||
List<UserConsentEntity> results = query.getResultList();
|
return closing(query.getResultStream().map(entity -> toConsentModel(realm, entity)));
|
||||||
|
|
||||||
List<UserConsentModel> consents = new ArrayList<UserConsentModel>();
|
|
||||||
for (UserConsentEntity entity : results) {
|
|
||||||
UserConsentModel model = toConsentModel(realm, entity);
|
|
||||||
consents.add(model);
|
|
||||||
}
|
|
||||||
return consents;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -369,7 +377,7 @@ public class JpaUserProvider implements UserProvider, UserCredentialStore {
|
||||||
@Override
|
@Override
|
||||||
public void grantToAllUsers(RealmModel realm, RoleModel role) {
|
public void grantToAllUsers(RealmModel realm, RoleModel role) {
|
||||||
if (realm.equals(role.isClientRole() ? ((ClientModel)role.getContainer()).getRealm() : (RealmModel)role.getContainer())) {
|
if (realm.equals(role.isClientRole() ? ((ClientModel)role.getContainer()).getRealm() : (RealmModel)role.getContainer())) {
|
||||||
int num = em.createNamedQuery("grantRoleToAllUsers")
|
em.createNamedQuery("grantRoleToAllUsers")
|
||||||
.setParameter("realmId", realm.getId())
|
.setParameter("realmId", realm.getId())
|
||||||
.setParameter("roleId", role.getId())
|
.setParameter("roleId", role.getId())
|
||||||
.executeUpdate();
|
.executeUpdate();
|
||||||
|
@ -378,61 +386,61 @@ public class JpaUserProvider implements UserProvider, UserCredentialStore {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void preRemove(RealmModel realm) {
|
public void preRemove(RealmModel realm) {
|
||||||
int num = em.createNamedQuery("deleteUserConsentClientScopesByRealm")
|
em.createNamedQuery("deleteUserConsentClientScopesByRealm")
|
||||||
.setParameter("realmId", realm.getId()).executeUpdate();
|
.setParameter("realmId", realm.getId()).executeUpdate();
|
||||||
num = em.createNamedQuery("deleteUserConsentsByRealm")
|
em.createNamedQuery("deleteUserConsentsByRealm")
|
||||||
.setParameter("realmId", realm.getId()).executeUpdate();
|
.setParameter("realmId", realm.getId()).executeUpdate();
|
||||||
num = em.createNamedQuery("deleteUserRoleMappingsByRealm")
|
em.createNamedQuery("deleteUserRoleMappingsByRealm")
|
||||||
.setParameter("realmId", realm.getId()).executeUpdate();
|
.setParameter("realmId", realm.getId()).executeUpdate();
|
||||||
num = em.createNamedQuery("deleteUserRequiredActionsByRealm")
|
em.createNamedQuery("deleteUserRequiredActionsByRealm")
|
||||||
.setParameter("realmId", realm.getId()).executeUpdate();
|
.setParameter("realmId", realm.getId()).executeUpdate();
|
||||||
num = em.createNamedQuery("deleteFederatedIdentityByRealm")
|
em.createNamedQuery("deleteFederatedIdentityByRealm")
|
||||||
.setParameter("realmId", realm.getId()).executeUpdate();
|
.setParameter("realmId", realm.getId()).executeUpdate();
|
||||||
num = em.createNamedQuery("deleteCredentialsByRealm")
|
em.createNamedQuery("deleteCredentialsByRealm")
|
||||||
.setParameter("realmId", realm.getId()).executeUpdate();
|
.setParameter("realmId", realm.getId()).executeUpdate();
|
||||||
num = em.createNamedQuery("deleteUserAttributesByRealm")
|
em.createNamedQuery("deleteUserAttributesByRealm")
|
||||||
.setParameter("realmId", realm.getId()).executeUpdate();
|
.setParameter("realmId", realm.getId()).executeUpdate();
|
||||||
num = em.createNamedQuery("deleteUserGroupMembershipByRealm")
|
em.createNamedQuery("deleteUserGroupMembershipByRealm")
|
||||||
.setParameter("realmId", realm.getId()).executeUpdate();
|
.setParameter("realmId", realm.getId()).executeUpdate();
|
||||||
num = em.createNamedQuery("deleteUsersByRealm")
|
em.createNamedQuery("deleteUsersByRealm")
|
||||||
.setParameter("realmId", realm.getId()).executeUpdate();
|
.setParameter("realmId", realm.getId()).executeUpdate();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void removeImportedUsers(RealmModel realm, String storageProviderId) {
|
public void removeImportedUsers(RealmModel realm, String storageProviderId) {
|
||||||
int num = em.createNamedQuery("deleteUserRoleMappingsByRealmAndLink")
|
em.createNamedQuery("deleteUserRoleMappingsByRealmAndLink")
|
||||||
.setParameter("realmId", realm.getId())
|
.setParameter("realmId", realm.getId())
|
||||||
.setParameter("link", storageProviderId)
|
.setParameter("link", storageProviderId)
|
||||||
.executeUpdate();
|
.executeUpdate();
|
||||||
num = em.createNamedQuery("deleteUserRequiredActionsByRealmAndLink")
|
em.createNamedQuery("deleteUserRequiredActionsByRealmAndLink")
|
||||||
.setParameter("realmId", realm.getId())
|
.setParameter("realmId", realm.getId())
|
||||||
.setParameter("link", storageProviderId)
|
.setParameter("link", storageProviderId)
|
||||||
.executeUpdate();
|
.executeUpdate();
|
||||||
num = em.createNamedQuery("deleteFederatedIdentityByRealmAndLink")
|
em.createNamedQuery("deleteFederatedIdentityByRealmAndLink")
|
||||||
.setParameter("realmId", realm.getId())
|
.setParameter("realmId", realm.getId())
|
||||||
.setParameter("link", storageProviderId)
|
.setParameter("link", storageProviderId)
|
||||||
.executeUpdate();
|
.executeUpdate();
|
||||||
num = em.createNamedQuery("deleteCredentialsByRealmAndLink")
|
em.createNamedQuery("deleteCredentialsByRealmAndLink")
|
||||||
.setParameter("realmId", realm.getId())
|
.setParameter("realmId", realm.getId())
|
||||||
.setParameter("link", storageProviderId)
|
.setParameter("link", storageProviderId)
|
||||||
.executeUpdate();
|
.executeUpdate();
|
||||||
num = em.createNamedQuery("deleteUserAttributesByRealmAndLink")
|
em.createNamedQuery("deleteUserAttributesByRealmAndLink")
|
||||||
.setParameter("realmId", realm.getId())
|
.setParameter("realmId", realm.getId())
|
||||||
.setParameter("link", storageProviderId)
|
.setParameter("link", storageProviderId)
|
||||||
.executeUpdate();
|
.executeUpdate();
|
||||||
num = em.createNamedQuery("deleteUserGroupMembershipsByRealmAndLink")
|
em.createNamedQuery("deleteUserGroupMembershipsByRealmAndLink")
|
||||||
.setParameter("realmId", realm.getId())
|
.setParameter("realmId", realm.getId())
|
||||||
.setParameter("link", storageProviderId)
|
.setParameter("link", storageProviderId)
|
||||||
.executeUpdate();
|
.executeUpdate();
|
||||||
num = em.createNamedQuery("deleteUserConsentClientScopesByRealmAndLink")
|
em.createNamedQuery("deleteUserConsentClientScopesByRealmAndLink")
|
||||||
.setParameter("realmId", realm.getId())
|
.setParameter("realmId", realm.getId())
|
||||||
.setParameter("link", storageProviderId)
|
.setParameter("link", storageProviderId)
|
||||||
.executeUpdate();
|
.executeUpdate();
|
||||||
num = em.createNamedQuery("deleteUserConsentsByRealmAndLink")
|
em.createNamedQuery("deleteUserConsentsByRealmAndLink")
|
||||||
.setParameter("realmId", realm.getId())
|
.setParameter("realmId", realm.getId())
|
||||||
.setParameter("link", storageProviderId)
|
.setParameter("link", storageProviderId)
|
||||||
.executeUpdate();
|
.executeUpdate();
|
||||||
num = em.createNamedQuery("deleteUsersByRealmAndLink")
|
em.createNamedQuery("deleteUsersByRealmAndLink")
|
||||||
.setParameter("realmId", realm.getId())
|
.setParameter("realmId", realm.getId())
|
||||||
.setParameter("link", storageProviderId)
|
.setParameter("link", storageProviderId)
|
||||||
.executeUpdate();
|
.executeUpdate();
|
||||||
|
@ -455,10 +463,10 @@ public class JpaUserProvider implements UserProvider, UserCredentialStore {
|
||||||
public void preRemove(RealmModel realm, ClientModel client) {
|
public void preRemove(RealmModel realm, ClientModel client) {
|
||||||
StorageId clientStorageId = new StorageId(client.getId());
|
StorageId clientStorageId = new StorageId(client.getId());
|
||||||
if (clientStorageId.isLocal()) {
|
if (clientStorageId.isLocal()) {
|
||||||
int num = em.createNamedQuery("deleteUserConsentClientScopesByClient")
|
em.createNamedQuery("deleteUserConsentClientScopesByClient")
|
||||||
.setParameter("clientId", client.getId())
|
.setParameter("clientId", client.getId())
|
||||||
.executeUpdate();
|
.executeUpdate();
|
||||||
num = em.createNamedQuery("deleteUserConsentsByClient")
|
em.createNamedQuery("deleteUserConsentsByClient")
|
||||||
.setParameter("clientId", client.getId())
|
.setParameter("clientId", client.getId())
|
||||||
.executeUpdate();
|
.executeUpdate();
|
||||||
} else {
|
} else {
|
||||||
|
@ -487,32 +495,19 @@ public class JpaUserProvider implements UserProvider, UserCredentialStore {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<UserModel> getGroupMembers(RealmModel realm, GroupModel group) {
|
public Stream<UserModel> getGroupMembersStream(RealmModel realm, GroupModel group) {
|
||||||
TypedQuery<UserEntity> query = em.createNamedQuery("groupMembership", UserEntity.class);
|
TypedQuery<UserEntity> query = em.createNamedQuery("groupMembership", UserEntity.class);
|
||||||
query.setParameter("groupId", group.getId());
|
query.setParameter("groupId", group.getId());
|
||||||
List<UserEntity> results = query.getResultList();
|
return closing(query.getResultStream().map(entity -> new UserAdapter(session, realm, em, entity)));
|
||||||
|
|
||||||
List<UserModel> users = new ArrayList<UserModel>();
|
|
||||||
for (UserEntity user : results) {
|
|
||||||
users.add(new UserAdapter(session, realm, em, user));
|
|
||||||
}
|
|
||||||
return users;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<UserModel> getRoleMembers(RealmModel realm, RoleModel role) {
|
public Stream<UserModel> getRoleMembersStream(RealmModel realm, RoleModel role) {
|
||||||
TypedQuery<UserEntity> query = em.createNamedQuery("usersInRole", UserEntity.class);
|
TypedQuery<UserEntity> query = em.createNamedQuery("usersInRole", UserEntity.class);
|
||||||
query.setParameter("roleId", role.getId());
|
query.setParameter("roleId", role.getId());
|
||||||
List<UserEntity> results = query.getResultList();
|
return closing(query.getResultStream().map(entity -> new UserAdapter(session, realm, em, entity)));
|
||||||
|
|
||||||
List<UserModel> users = new ArrayList<UserModel>();
|
|
||||||
for (UserEntity user : results) {
|
|
||||||
users.add(new UserAdapter(session, realm, em, user));
|
|
||||||
}
|
|
||||||
return users;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void preRemove(RealmModel realm, GroupModel group) {
|
public void preRemove(RealmModel realm, GroupModel group) {
|
||||||
em.createNamedQuery("deleteUserGroupMembershipsByGroup").setParameter("groupId", group.getId()).executeUpdate();
|
em.createNamedQuery("deleteUserGroupMembershipsByGroup").setParameter("groupId", group.getId()).executeUpdate();
|
||||||
|
@ -590,8 +585,8 @@ public class JpaUserProvider implements UserProvider, UserCredentialStore {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<UserModel> getUsers(RealmModel realm, boolean includeServiceAccounts) {
|
public Stream<UserModel> getUsersStream(RealmModel realm, boolean includeServiceAccounts) {
|
||||||
return getUsers(realm, -1, -1, includeServiceAccounts);
|
return getUsersStream(realm, -1, -1, includeServiceAccounts);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -746,17 +741,17 @@ public class JpaUserProvider implements UserProvider, UserCredentialStore {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<UserModel> getUsers(RealmModel realm) {
|
public Stream<UserModel> getUsersStream(RealmModel realm) {
|
||||||
return getUsers(realm, false);
|
return getUsersStream(realm, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<UserModel> getUsers(RealmModel realm, int firstResult, int maxResults) {
|
public Stream<UserModel> getUsersStream(RealmModel realm, int firstResult, int maxResults) {
|
||||||
return getUsers(realm, firstResult, maxResults, false);
|
return getUsersStream(realm, firstResult, maxResults, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<UserModel> getUsers(RealmModel realm, int firstResult, int maxResults, boolean includeServiceAccounts) {
|
public Stream<UserModel> getUsersStream(RealmModel realm, int firstResult, int maxResults, boolean includeServiceAccounts) {
|
||||||
String queryName = includeServiceAccounts ? "getAllUsersByRealm" : "getAllUsersByRealmExcludeServiceAccount" ;
|
String queryName = includeServiceAccounts ? "getAllUsersByRealm" : "getAllUsersByRealmExcludeServiceAccount" ;
|
||||||
|
|
||||||
TypedQuery<UserEntity> query = em.createNamedQuery(queryName, UserEntity.class);
|
TypedQuery<UserEntity> query = em.createNamedQuery(queryName, UserEntity.class);
|
||||||
|
@ -767,14 +762,11 @@ public class JpaUserProvider implements UserProvider, UserCredentialStore {
|
||||||
if (maxResults != -1) {
|
if (maxResults != -1) {
|
||||||
query.setMaxResults(maxResults);
|
query.setMaxResults(maxResults);
|
||||||
}
|
}
|
||||||
List<UserEntity> results = query.getResultList();
|
return closing(query.getResultStream().map(entity -> new UserAdapter(session, realm, em, entity)));
|
||||||
List<UserModel> users = new LinkedList<>();
|
|
||||||
for (UserEntity entity : results) users.add(new UserAdapter(session, realm, em, entity));
|
|
||||||
return users;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<UserModel> getGroupMembers(RealmModel realm, GroupModel group, int firstResult, int maxResults) {
|
public Stream<UserModel> getGroupMembersStream(RealmModel realm, GroupModel group, int firstResult, int maxResults) {
|
||||||
TypedQuery<UserEntity> query = em.createNamedQuery("groupMembership", UserEntity.class);
|
TypedQuery<UserEntity> query = em.createNamedQuery("groupMembership", UserEntity.class);
|
||||||
query.setParameter("groupId", group.getId());
|
query.setParameter("groupId", group.getId());
|
||||||
if (firstResult != -1) {
|
if (firstResult != -1) {
|
||||||
|
@ -783,17 +775,11 @@ public class JpaUserProvider implements UserProvider, UserCredentialStore {
|
||||||
if (maxResults != -1) {
|
if (maxResults != -1) {
|
||||||
query.setMaxResults(maxResults);
|
query.setMaxResults(maxResults);
|
||||||
}
|
}
|
||||||
List<UserEntity> results = query.getResultList();
|
return closing(query.getResultStream().map(user -> new UserAdapter(session, realm, em, user)));
|
||||||
|
|
||||||
List<UserModel> users = new LinkedList<>();
|
|
||||||
for (UserEntity user : results) {
|
|
||||||
users.add(new UserAdapter(session, realm, em, user));
|
|
||||||
}
|
|
||||||
return users;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<UserModel> getRoleMembers(RealmModel realm, RoleModel role, int firstResult, int maxResults) {
|
public Stream<UserModel> getRoleMembersStream(RealmModel realm, RoleModel role, int firstResult, int maxResults) {
|
||||||
TypedQuery<UserEntity> query = em.createNamedQuery("usersInRole", UserEntity.class);
|
TypedQuery<UserEntity> query = em.createNamedQuery("usersInRole", UserEntity.class);
|
||||||
query.setParameter("roleId", role.getId());
|
query.setParameter("roleId", role.getId());
|
||||||
if (firstResult != -1) {
|
if (firstResult != -1) {
|
||||||
|
@ -802,35 +788,29 @@ public class JpaUserProvider implements UserProvider, UserCredentialStore {
|
||||||
if (maxResults != -1) {
|
if (maxResults != -1) {
|
||||||
query.setMaxResults(maxResults);
|
query.setMaxResults(maxResults);
|
||||||
}
|
}
|
||||||
List<UserEntity> results = query.getResultList();
|
return closing(query.getResultStream().map(user -> new UserAdapter(session, realm, em, user)));
|
||||||
|
|
||||||
List<UserModel> users = new LinkedList<>();
|
|
||||||
for (UserEntity user : results) {
|
|
||||||
users.add(new UserAdapter(session, realm, em, user));
|
|
||||||
}
|
|
||||||
return users;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<UserModel> searchForUser(String search, RealmModel realm) {
|
public Stream<UserModel> searchForUserStream(String search, RealmModel realm) {
|
||||||
return searchForUser(search, realm, -1, -1);
|
return searchForUserStream(search, realm, -1, -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<UserModel> searchForUser(String search, RealmModel realm, int firstResult, int maxResults) {
|
public Stream<UserModel> searchForUserStream(String search, RealmModel realm, int firstResult, int maxResults) {
|
||||||
Map<String, String> attributes = new HashMap<>();
|
Map<String, String> attributes = new HashMap<>();
|
||||||
attributes.put(UserModel.SEARCH, search);
|
attributes.put(UserModel.SEARCH, search);
|
||||||
session.setAttribute(UserModel.INCLUDE_SERVICE_ACCOUNT, false);
|
session.setAttribute(UserModel.INCLUDE_SERVICE_ACCOUNT, false);
|
||||||
return searchForUser(attributes, realm, firstResult, maxResults);
|
return searchForUserStream(attributes, realm, firstResult, maxResults);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<UserModel> searchForUser(Map<String, String> attributes, RealmModel realm) {
|
public Stream<UserModel> searchForUserStream(Map<String, String> attributes, RealmModel realm) {
|
||||||
return searchForUser(attributes, realm, -1, -1);
|
return searchForUserStream(attributes, realm, -1, -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<UserModel> searchForUser(Map<String, String> attributes, RealmModel realm, int firstResult, int maxResults) {
|
public Stream<UserModel> searchForUserStream(Map<String, String> attributes, RealmModel realm, int firstResult, int maxResults) {
|
||||||
CriteriaBuilder builder = em.getCriteriaBuilder();
|
CriteriaBuilder builder = em.getCriteriaBuilder();
|
||||||
CriteriaQuery<UserEntity> queryBuilder = builder.createQuery(UserEntity.class);
|
CriteriaQuery<UserEntity> queryBuilder = builder.createQuery(UserEntity.class);
|
||||||
Root<UserEntity> root = queryBuilder.from(UserEntity.class);
|
Root<UserEntity> root = queryBuilder.from(UserEntity.class);
|
||||||
|
@ -945,29 +925,18 @@ public class JpaUserProvider implements UserProvider, UserCredentialStore {
|
||||||
query.setMaxResults(maxResults);
|
query.setMaxResults(maxResults);
|
||||||
}
|
}
|
||||||
|
|
||||||
List<UserModel> results = new ArrayList<>();
|
|
||||||
UserProvider users = session.users();
|
UserProvider users = session.users();
|
||||||
|
return closing(query.getResultStream().map(userEntity -> users.getUserById(userEntity.getId(), realm)));
|
||||||
for (UserEntity entity : query.getResultList()) {
|
|
||||||
results.add(users.getUserById(entity.getId(), realm));
|
|
||||||
}
|
|
||||||
|
|
||||||
return results;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<UserModel> searchForUserByUserAttribute(String attrName, String attrValue, RealmModel realm) {
|
public Stream<UserModel> searchForUserByUserAttributeStream(String attrName, String attrValue, RealmModel realm) {
|
||||||
TypedQuery<UserEntity> query = em.createNamedQuery("getRealmUsersByAttributeNameAndValue", UserEntity.class);
|
TypedQuery<UserEntity> query = em.createNamedQuery("getRealmUsersByAttributeNameAndValue", UserEntity.class);
|
||||||
query.setParameter("name", attrName);
|
query.setParameter("name", attrName);
|
||||||
query.setParameter("value", attrValue);
|
query.setParameter("value", attrValue);
|
||||||
query.setParameter("realmId", realm.getId());
|
query.setParameter("realmId", realm.getId());
|
||||||
List<UserEntity> results = query.getResultList();
|
|
||||||
|
|
||||||
List<UserModel> users = new ArrayList<UserModel>();
|
return closing(query.getResultStream().map(userEntity -> new UserAdapter(session, realm, em, userEntity)));
|
||||||
for (UserEntity user : results) {
|
|
||||||
users.add(new UserAdapter(session, realm, em, user));
|
|
||||||
}
|
|
||||||
return users;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private FederatedIdentityEntity findFederatedIdentity(UserModel user, String identityProvider, LockModeType lockMode) {
|
private FederatedIdentityEntity findFederatedIdentity(UserModel user, String identityProvider, LockModeType lockMode) {
|
||||||
|
@ -982,16 +951,13 @@ public class JpaUserProvider implements UserProvider, UserCredentialStore {
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Set<FederatedIdentityModel> getFederatedIdentities(UserModel user, RealmModel realm) {
|
public Stream<FederatedIdentityModel> getFederatedIdentitiesStream(UserModel user, RealmModel realm) {
|
||||||
TypedQuery<FederatedIdentityEntity> query = em.createNamedQuery("findFederatedIdentityByUser", FederatedIdentityEntity.class);
|
TypedQuery<FederatedIdentityEntity> query = em.createNamedQuery("findFederatedIdentityByUser", FederatedIdentityEntity.class);
|
||||||
UserEntity userEntity = em.getReference(UserEntity.class, user.getId());
|
UserEntity userEntity = em.getReference(UserEntity.class, user.getId());
|
||||||
query.setParameter("user", userEntity);
|
query.setParameter("user", userEntity);
|
||||||
List<FederatedIdentityEntity> results = query.getResultList();
|
|
||||||
Set<FederatedIdentityModel> set = new HashSet<FederatedIdentityModel>();
|
return closing(query.getResultStream().map(entity -> new FederatedIdentityModel(entity.getIdentityProvider(),
|
||||||
for (FederatedIdentityEntity entity : results) {
|
entity.getUserId(), entity.getUserName(), entity.getToken())).distinct());
|
||||||
set.add(new FederatedIdentityModel(entity.getIdentityProvider(), entity.getUserId(), entity.getUserName(), entity.getToken()));
|
|
||||||
}
|
|
||||||
return set;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -24,7 +24,6 @@ import org.keycloak.models.KeycloakSession;
|
||||||
import org.keycloak.models.RealmModel;
|
import org.keycloak.models.RealmModel;
|
||||||
import org.keycloak.models.RoleModel;
|
import org.keycloak.models.RoleModel;
|
||||||
import org.keycloak.models.UserModel;
|
import org.keycloak.models.UserModel;
|
||||||
import org.keycloak.models.jpa.entities.GroupEntity;
|
|
||||||
import org.keycloak.models.jpa.entities.UserAttributeEntity;
|
import org.keycloak.models.jpa.entities.UserAttributeEntity;
|
||||||
import org.keycloak.models.jpa.entities.UserEntity;
|
import org.keycloak.models.jpa.entities.UserEntity;
|
||||||
import org.keycloak.models.jpa.entities.UserGroupMembershipEntity;
|
import org.keycloak.models.jpa.entities.UserGroupMembershipEntity;
|
||||||
|
@ -38,19 +37,13 @@ import javax.persistence.Query;
|
||||||
import javax.persistence.TypedQuery;
|
import javax.persistence.TypedQuery;
|
||||||
import javax.persistence.criteria.CriteriaBuilder;
|
import javax.persistence.criteria.CriteriaBuilder;
|
||||||
import javax.persistence.criteria.CriteriaQuery;
|
import javax.persistence.criteria.CriteriaQuery;
|
||||||
import javax.persistence.criteria.Join;
|
|
||||||
import javax.persistence.criteria.Predicate;
|
import javax.persistence.criteria.Predicate;
|
||||||
import javax.persistence.criteria.Root;
|
import javax.persistence.criteria.Root;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.Comparator;
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.stream.Collectors;
|
|
||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
import javax.persistence.LockModeType;
|
import javax.persistence.LockModeType;
|
||||||
|
|
||||||
|
@ -238,23 +231,18 @@ public class UserAdapter implements UserModel, JpaModel<UserEntity> {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<String> getAttribute(String name) {
|
public Stream<String> getAttributeStream(String name) {
|
||||||
if (UserModel.FIRST_NAME.equals(name)) {
|
if (UserModel.FIRST_NAME.equals(name)) {
|
||||||
return Collections.singletonList(user.getFirstName());
|
return Stream.of(user.getFirstName());
|
||||||
} else if (UserModel.LAST_NAME.equals(name)) {
|
} else if (UserModel.LAST_NAME.equals(name)) {
|
||||||
return Collections.singletonList(user.getLastName());
|
return Stream.of(user.getLastName());
|
||||||
} else if (UserModel.EMAIL.equals(name)) {
|
} else if (UserModel.EMAIL.equals(name)) {
|
||||||
return Collections.singletonList(user.getEmail());
|
return Stream.of(user.getEmail());
|
||||||
} else if (UserModel.USERNAME.equals(name)) {
|
} else if (UserModel.USERNAME.equals(name)) {
|
||||||
return Collections.singletonList(user.getUsername());
|
return Stream.of(user.getUsername());
|
||||||
}
|
}
|
||||||
List<String> result = new ArrayList<>();
|
return user.getAttributes().stream().filter(attribute -> Objects.equals(attribute.getName(), name)).
|
||||||
for (UserAttributeEntity attr : user.getAttributes()) {
|
map(attribute -> attribute.getValue());
|
||||||
if (attr.getName().equals(name)) {
|
|
||||||
result.add(attr.getValue());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -271,12 +259,8 @@ public class UserAdapter implements UserModel, JpaModel<UserEntity> {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Set<String> getRequiredActions() {
|
public Stream<String> getRequiredActionsStream() {
|
||||||
Set<String> result = new HashSet<>();
|
return user.getRequiredActions().stream().map(action -> action.getAction()).distinct();
|
||||||
for (UserRequiredActionEntity attr : user.getRequiredActions()) {
|
|
||||||
result.add(attr.getAction());
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -55,12 +55,11 @@ import org.keycloak.storage.jpa.entity.FederatedUserRoleMappingEntity;
|
||||||
|
|
||||||
import javax.persistence.EntityManager;
|
import javax.persistence.EntityManager;
|
||||||
import javax.persistence.TypedQuery;
|
import javax.persistence.TypedQuery;
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.LinkedList;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Objects;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
import javax.persistence.LockModeType;
|
import javax.persistence.LockModeType;
|
||||||
|
|
||||||
|
@ -164,12 +163,12 @@ public class JpaUserFederatedStorageProvider implements
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<String> getUsersByUserAttribute(RealmModel realm, String name, String value) {
|
public Stream<String> getUsersByUserAttributeStream(RealmModel realm, String name, String value) {
|
||||||
TypedQuery<String> query = em.createNamedQuery("getFederatedAttributesByNameAndValue", String.class)
|
TypedQuery<String> query = em.createNamedQuery("getFederatedAttributesByNameAndValue", String.class)
|
||||||
.setParameter("realmId", realm.getId())
|
.setParameter("realmId", realm.getId())
|
||||||
.setParameter("name", name)
|
.setParameter("name", name)
|
||||||
.setParameter("value", value);
|
.setParameter("value", value);
|
||||||
return query.getResultList();
|
return closing(query.getResultStream());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -242,16 +241,11 @@ public class JpaUserFederatedStorageProvider implements
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Set<FederatedIdentityModel> getFederatedIdentities(String userId, RealmModel realm) {
|
public Stream<FederatedIdentityModel> getFederatedIdentitiesStream(String userId, RealmModel realm) {
|
||||||
TypedQuery<BrokerLinkEntity> query = em.createNamedQuery("findBrokerLinkByUser", BrokerLinkEntity.class)
|
TypedQuery<BrokerLinkEntity> query = em.createNamedQuery("findBrokerLinkByUser", BrokerLinkEntity.class)
|
||||||
.setParameter("userId", userId);
|
.setParameter("userId", userId);
|
||||||
List<BrokerLinkEntity> results = query.getResultList();
|
return closing(query.getResultStream().map(entity -> new FederatedIdentityModel(entity.getIdentityProvider(),
|
||||||
Set<FederatedIdentityModel> set = new HashSet<>();
|
entity.getBrokerUserId(), entity.getBrokerUserName(), entity.getToken())).distinct());
|
||||||
for (BrokerLinkEntity entity : results) {
|
|
||||||
FederatedIdentityModel model = new FederatedIdentityModel(entity.getIdentityProvider(), entity.getBrokerUserId(), entity.getBrokerUserName(), entity.getToken());
|
|
||||||
set.add(model);
|
|
||||||
}
|
|
||||||
return set;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -300,17 +294,10 @@ public class JpaUserFederatedStorageProvider implements
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<UserConsentModel> getConsents(RealmModel realm, String userId) {
|
public Stream<UserConsentModel> getConsentsStream(RealmModel realm, String userId) {
|
||||||
TypedQuery<FederatedUserConsentEntity> query = em.createNamedQuery("userFederatedConsentsByUser", FederatedUserConsentEntity.class);
|
TypedQuery<FederatedUserConsentEntity> query = em.createNamedQuery("userFederatedConsentsByUser", FederatedUserConsentEntity.class);
|
||||||
query.setParameter("userId", userId);
|
query.setParameter("userId", userId);
|
||||||
List<FederatedUserConsentEntity> results = query.getResultList();
|
return closing(query.getResultStream().map(entity -> toConsentModel(realm, entity)));
|
||||||
|
|
||||||
List<UserConsentModel> consents = new ArrayList<UserConsentModel>();
|
|
||||||
for (FederatedUserConsentEntity entity : results) {
|
|
||||||
UserConsentModel model = toConsentModel(realm, entity);
|
|
||||||
consents.add(model);
|
|
||||||
}
|
|
||||||
return consents;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -478,7 +465,7 @@ public class JpaUserFederatedStorageProvider implements
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<String> getMembership(RealmModel realm, GroupModel group, int firstResult, int max) {
|
public Stream<String> getMembershipStream(RealmModel realm, GroupModel group, int firstResult, int max) {
|
||||||
TypedQuery<String> query = em.createNamedQuery("fedgroupMembership", String.class)
|
TypedQuery<String> query = em.createNamedQuery("fedgroupMembership", String.class)
|
||||||
.setParameter("realmId", realm.getId())
|
.setParameter("realmId", realm.getId())
|
||||||
.setParameter("groupId", group.getId());
|
.setParameter("groupId", group.getId());
|
||||||
|
@ -489,28 +476,21 @@ public class JpaUserFederatedStorageProvider implements
|
||||||
if (max != -1) {
|
if (max != -1) {
|
||||||
query.setMaxResults(max);
|
query.setMaxResults(max);
|
||||||
}
|
}
|
||||||
|
return closing(query.getResultStream());
|
||||||
return query.getResultList();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Set<String> getRequiredActions(RealmModel realm, String userId) {
|
public Stream<String> getRequiredActionsStream(RealmModel realm, String userId) {
|
||||||
Set<String> set = new HashSet<>();
|
return this.getRequiredActionEntitiesStream(realm, userId, LockModeType.NONE).
|
||||||
List<FederatedUserRequiredActionEntity> values = getRequiredActionEntities(realm, userId, LockModeType.NONE);
|
map(FederatedUserRequiredActionEntity::getAction).distinct();
|
||||||
for (FederatedUserRequiredActionEntity entity : values) {
|
|
||||||
set.add(entity.getAction());
|
|
||||||
}
|
|
||||||
|
|
||||||
return set;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<FederatedUserRequiredActionEntity> getRequiredActionEntities(RealmModel realm, String userId, LockModeType lockMode) {
|
private Stream<FederatedUserRequiredActionEntity> getRequiredActionEntitiesStream(RealmModel realm, String userId, LockModeType lockMode) {
|
||||||
TypedQuery<FederatedUserRequiredActionEntity> query = em.createNamedQuery("getFederatedUserRequiredActionsByUser", FederatedUserRequiredActionEntity.class)
|
TypedQuery<FederatedUserRequiredActionEntity> query = em.createNamedQuery("getFederatedUserRequiredActionsByUser", FederatedUserRequiredActionEntity.class)
|
||||||
.setParameter("userId", userId)
|
.setParameter("userId", userId)
|
||||||
.setParameter("realmId", realm.getId());
|
.setParameter("realmId", realm.getId());
|
||||||
query.setLockMode(lockMode);
|
query.setLockMode(lockMode);
|
||||||
return query.getResultList();
|
return closing(query.getResultStream());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -529,12 +509,9 @@ public class JpaUserFederatedStorageProvider implements
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void removeRequiredAction(RealmModel realm, String userId, String action) {
|
public void removeRequiredAction(RealmModel realm, String userId, String action) {
|
||||||
List<FederatedUserRequiredActionEntity> values = getRequiredActionEntities(realm, userId, LockModeType.PESSIMISTIC_WRITE);
|
this.getRequiredActionEntitiesStream(realm, userId, LockModeType.PESSIMISTIC_WRITE).
|
||||||
for (FederatedUserRequiredActionEntity entity : values) {
|
filter(entity -> Objects.equals(entity.getAction(), action)).collect(Collectors.toList()).forEach(em::remove);
|
||||||
if (action.equals(entity.getAction())) em.remove(entity);
|
|
||||||
}
|
|
||||||
em.flush();
|
em.flush();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -598,7 +575,7 @@ public class JpaUserFederatedStorageProvider implements
|
||||||
entity.setStorageProviderId(new StorageId(userId).getProviderId());
|
entity.setStorageProviderId(new StorageId(userId).getProviderId());
|
||||||
|
|
||||||
//add in linkedlist to last position
|
//add in linkedlist to last position
|
||||||
List<FederatedUserCredentialEntity> credentials = getStoredCredentialEntities(userId);
|
List<FederatedUserCredentialEntity> credentials = getStoredCredentialEntitiesStream(userId).collect(Collectors.toList());
|
||||||
int priority = credentials.isEmpty() ? JpaUserCredentialStore.PRIORITY_DIFFERENCE : credentials.get(credentials.size() - 1).getPriority() + JpaUserCredentialStore.PRIORITY_DIFFERENCE;
|
int priority = credentials.isEmpty() ? JpaUserCredentialStore.PRIORITY_DIFFERENCE : credentials.get(credentials.size() - 1).getPriority() + JpaUserCredentialStore.PRIORITY_DIFFERENCE;
|
||||||
entity.setPriority(priority);
|
entity.setPriority(priority);
|
||||||
|
|
||||||
|
@ -613,14 +590,8 @@ public class JpaUserFederatedStorageProvider implements
|
||||||
|
|
||||||
int currentPriority = entity.getPriority();
|
int currentPriority = entity.getPriority();
|
||||||
|
|
||||||
List<FederatedUserCredentialEntity> credentials = getStoredCredentialEntities(userId);
|
this.getStoredCredentialEntitiesStream(userId).filter(credentialEntity -> credentialEntity.getPriority() > currentPriority)
|
||||||
|
.forEach(credentialEntity -> credentialEntity.setPriority(credentialEntity.getPriority() - JpaUserCredentialStore.PRIORITY_DIFFERENCE));
|
||||||
// Decrease priority of all credentials after our
|
|
||||||
for (FederatedUserCredentialEntity cred : credentials) {
|
|
||||||
if (cred.getPriority() > currentPriority) {
|
|
||||||
cred.setPriority(cred.getPriority() - JpaUserCredentialStore.PRIORITY_DIFFERENCE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
em.remove(entity);
|
em.remove(entity);
|
||||||
return true;
|
return true;
|
||||||
|
@ -659,32 +630,22 @@ public class JpaUserFederatedStorageProvider implements
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<CredentialModel> getStoredCredentials(RealmModel realm, String userId) {
|
public Stream<CredentialModel> getStoredCredentialsStream(RealmModel realm, String userId) {
|
||||||
List<FederatedUserCredentialEntity> results = getStoredCredentialEntities(userId);
|
return this.getStoredCredentialEntitiesStream(userId).map(this::toModel);
|
||||||
List<CredentialModel> rtn = new LinkedList<>();
|
|
||||||
for (FederatedUserCredentialEntity entity : results) {
|
|
||||||
rtn.add(toModel(entity));
|
|
||||||
}
|
|
||||||
return rtn;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<FederatedUserCredentialEntity> getStoredCredentialEntities(String userId) {
|
private Stream<FederatedUserCredentialEntity> getStoredCredentialEntitiesStream(String userId) {
|
||||||
TypedQuery<FederatedUserCredentialEntity> query = em.createNamedQuery("federatedUserCredentialByUser", FederatedUserCredentialEntity.class)
|
TypedQuery<FederatedUserCredentialEntity> query = em.createNamedQuery("federatedUserCredentialByUser", FederatedUserCredentialEntity.class)
|
||||||
.setParameter("userId", userId);
|
.setParameter("userId", userId);
|
||||||
return query.getResultList();
|
return closing(query.getResultStream());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<CredentialModel> getStoredCredentialsByType(RealmModel realm, String userId, String type) {
|
public Stream<CredentialModel> getStoredCredentialsByTypeStream(RealmModel realm, String userId, String type) {
|
||||||
TypedQuery<FederatedUserCredentialEntity> query = em.createNamedQuery("federatedUserCredentialByUserAndType", FederatedUserCredentialEntity.class)
|
TypedQuery<FederatedUserCredentialEntity> query = em.createNamedQuery("federatedUserCredentialByUserAndType", FederatedUserCredentialEntity.class)
|
||||||
.setParameter("type", type)
|
.setParameter("type", type)
|
||||||
.setParameter("userId", userId);
|
.setParameter("userId", userId);
|
||||||
List<FederatedUserCredentialEntity> results = query.getResultList();
|
return closing(query.getResultStream().map(this::toModel));
|
||||||
List<CredentialModel> rtn = new LinkedList<>();
|
|
||||||
for (FederatedUserCredentialEntity entity : results) {
|
|
||||||
rtn.add(toModel(entity));
|
|
||||||
}
|
|
||||||
return rtn;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -699,12 +660,13 @@ public class JpaUserFederatedStorageProvider implements
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<String> getStoredUsers(RealmModel realm, int first, int max) {
|
public Stream<String> getStoredUsersStream(RealmModel realm, int first, int max) {
|
||||||
TypedQuery<String> query = em.createNamedQuery("getFederatedUserIds", String.class)
|
TypedQuery<String> query = em.createNamedQuery("getFederatedUserIds", String.class)
|
||||||
.setParameter("realmId", realm.getId())
|
.setParameter("realmId", realm.getId());
|
||||||
.setFirstResult(first);
|
if (first > 0)
|
||||||
|
query.setFirstResult(first);
|
||||||
if (max > 0) query.setMaxResults(max);
|
if (max > 0) query.setMaxResults(max);
|
||||||
return query.getResultList();
|
return closing(query.getResultStream());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -744,11 +706,8 @@ public class JpaUserFederatedStorageProvider implements
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean moveCredentialTo(RealmModel realm, UserModel user, String id, String newPreviousCredentialId) {
|
public boolean moveCredentialTo(RealmModel realm, UserModel user, String id, String newPreviousCredentialId) {
|
||||||
List<FederatedUserCredentialEntity> sortedCreds = getStoredCredentialEntities(user.getId());
|
|
||||||
|
|
||||||
// 1 - Create new list and move everything to it.
|
// 1 - Create new list and move everything to it.
|
||||||
List<FederatedUserCredentialEntity> newList = new ArrayList<>();
|
List<FederatedUserCredentialEntity> newList = this.getStoredCredentialEntitiesStream(user.getId()).collect(Collectors.toList());
|
||||||
newList.addAll(sortedCreds);
|
|
||||||
|
|
||||||
// 2 - Find indexes of our and newPrevious credential
|
// 2 - Find indexes of our and newPrevious credential
|
||||||
int ourCredentialIndex = -1;
|
int ourCredentialIndex = -1;
|
||||||
|
|
|
@ -152,12 +152,9 @@ public class InMemoryUserAdapter extends UserModelDefaultMethods {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<String> getAttribute(String name) {
|
public Stream<String> getAttributeStream(String name) {
|
||||||
List<String> value = attributes.get(name);
|
List<String> value = this.attributes.get(name);
|
||||||
if (value == null) {
|
return value != null ? value.stream() : Stream.empty();
|
||||||
return new LinkedList<>();
|
|
||||||
}
|
|
||||||
return value;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -166,8 +163,8 @@ public class InMemoryUserAdapter extends UserModelDefaultMethods {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Set<String> getRequiredActions() {
|
public Stream<String> getRequiredActionsStream() {
|
||||||
return requiredActions;
|
return this.requiredActions.stream();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -91,12 +91,37 @@ public interface UserModel extends RoleMapperModel {
|
||||||
/**
|
/**
|
||||||
* @param name
|
* @param name
|
||||||
* @return list of all attribute values or empty list if there are not any values. Never return null
|
* @return list of all attribute values or empty list if there are not any values. Never return null
|
||||||
|
* @deprecated Use {@link #getAttributeStream(String) getAttributeStream} instead.
|
||||||
*/
|
*/
|
||||||
List<String> getAttribute(String name);
|
@Deprecated
|
||||||
|
default List<String> getAttribute(String name) {
|
||||||
|
return this.getAttributeStream(name).collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Obtains all values associated with the specified attribute name.
|
||||||
|
*
|
||||||
|
* @param name the name of the attribute.
|
||||||
|
* @return a non-null {@code Stream} of attribute values.
|
||||||
|
*/
|
||||||
|
Stream<String> getAttributeStream(final String name);
|
||||||
|
|
||||||
Map<String, List<String>> getAttributes();
|
Map<String, List<String>> getAttributes();
|
||||||
|
|
||||||
Set<String> getRequiredActions();
|
/**
|
||||||
|
* @deprecated Use {@link #getRequiredActionsStream() getRequiredActionsStream} instead.
|
||||||
|
*/
|
||||||
|
@Deprecated
|
||||||
|
default Set<String> getRequiredActions() {
|
||||||
|
return this.getRequiredActionsStream().collect(Collectors.toSet());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Obtains the names of required actions associated with the user.
|
||||||
|
*
|
||||||
|
* @return a non-null {@code Stream} of required action names.
|
||||||
|
*/
|
||||||
|
Stream<String> getRequiredActionsStream();
|
||||||
|
|
||||||
void addRequiredAction(String action);
|
void addRequiredAction(String action);
|
||||||
|
|
||||||
|
@ -122,18 +147,32 @@ public interface UserModel extends RoleMapperModel {
|
||||||
|
|
||||||
void setEmailVerified(boolean verified);
|
void setEmailVerified(boolean verified);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @deprecated Use {@link #getGroupsStream() getGroupsStream} instead.
|
||||||
|
*/
|
||||||
@Deprecated
|
@Deprecated
|
||||||
default Set<GroupModel> getGroups() {
|
default Set<GroupModel> getGroups() {
|
||||||
return getGroupsStream().collect(Collectors.toSet());
|
return getGroupsStream().collect(Collectors.toSet());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Obtains the groups associated with the user.
|
||||||
|
*
|
||||||
|
* @return a non-null {@code Stream} of groups.
|
||||||
|
*/
|
||||||
Stream<GroupModel> getGroupsStream();
|
Stream<GroupModel> getGroupsStream();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @deprecated Use {@link #getGroupsStream(String, Integer, Integer) getGroupsStream} instead.
|
||||||
|
*/
|
||||||
@Deprecated
|
@Deprecated
|
||||||
default Set<GroupModel> getGroups(int first, int max) {
|
default Set<GroupModel> getGroups(int first, int max) {
|
||||||
return getGroupsStream(null, first, max).collect(Collectors.toSet());
|
return getGroupsStream(null, first, max).collect(Collectors.toSet());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @deprecated Use {@link #getGroupsStream(String, Integer, Integer) getGroupsStream} instead.
|
||||||
|
*/
|
||||||
@Deprecated
|
@Deprecated
|
||||||
default Set<GroupModel> getGroups(String search, int first, int max) {
|
default Set<GroupModel> getGroups(String search, int first, int max) {
|
||||||
return getGroupsStream(search, first, max)
|
return getGroupsStream(search, first, max)
|
||||||
|
@ -141,7 +180,7 @@ public interface UserModel extends RoleMapperModel {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a paginated stream of groups within this.realm with search in the name
|
* Returns a paginated stream of groups within this realm with search in the name
|
||||||
*
|
*
|
||||||
* @param search Case insensitive string which will be searched for. Ignored if null.
|
* @param search Case insensitive string which will be searched for. Ignored if null.
|
||||||
* @param first Index of first group to return. Ignored if negative or {@code null}.
|
* @param first Index of first group to return. Ignored if negative or {@code null}.
|
||||||
|
|
|
@ -26,6 +26,8 @@ import org.keycloak.storage.user.UserRegistrationProvider;
|
||||||
|
|
||||||
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>
|
||||||
|
@ -42,13 +44,47 @@ public interface UserProvider extends Provider,
|
||||||
boolean removeFederatedIdentity(RealmModel realm, UserModel user, String socialProvider);
|
boolean removeFederatedIdentity(RealmModel realm, UserModel user, String socialProvider);
|
||||||
void preRemove(RealmModel realm, IdentityProviderModel provider);
|
void preRemove(RealmModel realm, IdentityProviderModel provider);
|
||||||
void updateFederatedIdentity(RealmModel realm, UserModel federatedUser, FederatedIdentityModel federatedIdentityModel);
|
void updateFederatedIdentity(RealmModel realm, UserModel federatedUser, FederatedIdentityModel federatedIdentityModel);
|
||||||
Set<FederatedIdentityModel> getFederatedIdentities(UserModel user, RealmModel realm);
|
|
||||||
|
/**
|
||||||
|
* @deprecated Use {@link #getFederatedIdentitiesStream(UserModel, RealmModel) getFederatedIdentitiesStream} instead.
|
||||||
|
*/
|
||||||
|
@Deprecated
|
||||||
|
default Set<FederatedIdentityModel> getFederatedIdentities(UserModel user, RealmModel realm) {
|
||||||
|
return this.getFederatedIdentitiesStream(user, realm).collect(Collectors.toSet());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Obtains the federated identities of the specified user.
|
||||||
|
*
|
||||||
|
* @param user a reference to the user.
|
||||||
|
* @param realm a reference to the realm.
|
||||||
|
* @return a non-null {@code Stream} of federated identities associated with the user.
|
||||||
|
*/
|
||||||
|
Stream<FederatedIdentityModel> getFederatedIdentitiesStream(UserModel user, RealmModel realm);
|
||||||
|
|
||||||
FederatedIdentityModel getFederatedIdentity(UserModel user, String socialProvider, RealmModel realm);
|
FederatedIdentityModel getFederatedIdentity(UserModel user, String socialProvider, RealmModel realm);
|
||||||
UserModel getUserByFederatedIdentity(FederatedIdentityModel socialLink, RealmModel realm);
|
UserModel getUserByFederatedIdentity(FederatedIdentityModel socialLink, RealmModel realm);
|
||||||
|
|
||||||
void addConsent(RealmModel realm, String userId, UserConsentModel consent);
|
void addConsent(RealmModel realm, String userId, UserConsentModel consent);
|
||||||
UserConsentModel getConsentByClient(RealmModel realm, String userId, String clientInternalId);
|
UserConsentModel getConsentByClient(RealmModel realm, String userId, String clientInternalId);
|
||||||
List<UserConsentModel> getConsents(RealmModel realm, String userId);
|
|
||||||
|
/**
|
||||||
|
* @deprecated Use {@link #getConsentsStream(RealmModel, String) getConsentsStream} instead.
|
||||||
|
*/
|
||||||
|
@Deprecated
|
||||||
|
default List<UserConsentModel> getConsents(RealmModel realm, String userId) {
|
||||||
|
return getConsentsStream(realm, userId).collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Obtains the consents associated with the user identified by the specified {@code userId}.
|
||||||
|
*
|
||||||
|
* @param realm a reference to the realm.
|
||||||
|
* @param userId the user identifier.
|
||||||
|
* @return a non-null {@code Stream} of consents associated with the user.
|
||||||
|
*/
|
||||||
|
Stream<UserConsentModel> getConsentsStream(RealmModel realm, String userId);
|
||||||
|
|
||||||
void updateConsent(RealmModel realm, String userId, UserConsentModel consent);
|
void updateConsent(RealmModel realm, String userId, UserConsentModel consent);
|
||||||
boolean revokeConsentForClient(RealmModel realm, String userId, String clientInternalId);
|
boolean revokeConsentForClient(RealmModel realm, String userId, String clientInternalId);
|
||||||
|
|
||||||
|
@ -56,8 +92,42 @@ public interface UserProvider extends Provider,
|
||||||
int getNotBeforeOfUser(RealmModel realm, UserModel user);
|
int getNotBeforeOfUser(RealmModel realm, UserModel user);
|
||||||
|
|
||||||
UserModel getServiceAccount(ClientModel client);
|
UserModel getServiceAccount(ClientModel client);
|
||||||
List<UserModel> getUsers(RealmModel realm, boolean includeServiceAccounts);
|
|
||||||
List<UserModel> getUsers(RealmModel realm, int firstResult, int maxResults, boolean includeServiceAccounts);
|
/**
|
||||||
|
* @deprecated Use {@link #getUsersStream(RealmModel, boolean) getUsersStream} instead.
|
||||||
|
*/
|
||||||
|
@Deprecated
|
||||||
|
default List<UserModel> getUsers(RealmModel realm, boolean includeServiceAccounts) {
|
||||||
|
return this.getUsersStream(realm, includeServiceAccounts).collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Obtains the users associated with the specified realm.
|
||||||
|
*
|
||||||
|
* @param realm a reference to the realm being used for the search.
|
||||||
|
* @param includeServiceAccounts {@code true} if service accounts should be included in the result; {@code false} otherwise.
|
||||||
|
* @return a non-null {@code Stream} of users associated withe the realm.
|
||||||
|
*/
|
||||||
|
Stream<UserModel> getUsersStream(RealmModel realm, boolean includeServiceAccounts);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @deprecated Use {@link #getUsersStream(RealmModel, int, int, boolean) getUsersStream} instead.
|
||||||
|
*/
|
||||||
|
@Deprecated
|
||||||
|
default List<UserModel> getUsers(RealmModel realm, int firstResult, int maxResults, boolean includeServiceAccounts) {
|
||||||
|
return this.getUsersStream(realm, firstResult, maxResults, includeServiceAccounts).collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Obtains the users associated with the specified realm.
|
||||||
|
*
|
||||||
|
* @param realm a reference to the realm being used for the search.
|
||||||
|
* @param firstResult first result to return. Ignored if negative.
|
||||||
|
* @param maxResults maximum number of results to return. Ignored if negative.
|
||||||
|
* @param includeServiceAccounts {@code true} if service accounts should be included in the result; {@code false} otherwise.
|
||||||
|
* @return a non-null {@code Stream} of users associated withe the realm.
|
||||||
|
*/
|
||||||
|
Stream<UserModel> getUsersStream(RealmModel realm, int firstResult, int maxResults, boolean includeServiceAccounts);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* only used for local storage
|
* only used for local storage
|
||||||
|
|
|
@ -86,8 +86,8 @@ public class UserModelDelegate implements UserModel {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<String> getAttribute(String name) {
|
public Stream<String> getAttributeStream(String name) {
|
||||||
return delegate.getAttribute(name);
|
return delegate.getAttributeStream(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -96,8 +96,8 @@ public class UserModelDelegate implements UserModel {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Set<String> getRequiredActions() {
|
public Stream<String> getRequiredActionsStream() {
|
||||||
return delegate.getRequiredActions();
|
return delegate.getRequiredActionsStream();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -30,11 +30,8 @@ import org.keycloak.models.utils.RoleUtils;
|
||||||
import org.keycloak.storage.ReadOnlyException;
|
import org.keycloak.storage.ReadOnlyException;
|
||||||
import org.keycloak.storage.StorageId;
|
import org.keycloak.storage.StorageId;
|
||||||
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
|
||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -62,8 +59,8 @@ public abstract class AbstractUserAdapter extends UserModelDefaultMethods {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Set<String> getRequiredActions() {
|
public Stream<String> getRequiredActionsStream() {
|
||||||
return Collections.emptySet();
|
return Stream.empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -303,11 +300,11 @@ public abstract class AbstractUserAdapter extends UserModelDefaultMethods {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<String> getAttribute(String name) {
|
public Stream<String> getAttributeStream(String name) {
|
||||||
if (name.equals(UserModel.USERNAME)) {
|
if (name.equals(UserModel.USERNAME)) {
|
||||||
return Collections.singletonList(getUsername());
|
return Stream.of(getUsername());
|
||||||
}
|
}
|
||||||
return Collections.emptyList();
|
return Stream.empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -30,11 +30,8 @@ import org.keycloak.models.utils.RoleUtils;
|
||||||
import org.keycloak.storage.StorageId;
|
import org.keycloak.storage.StorageId;
|
||||||
import org.keycloak.storage.federated.UserFederatedStorageProvider;
|
import org.keycloak.storage.federated.UserFederatedStorageProvider;
|
||||||
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
|
||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -71,8 +68,8 @@ public abstract class AbstractUserAdapterFederatedStorage extends UserModelDefau
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Set<String> getRequiredActions() {
|
public Stream<String> getRequiredActionsStream() {
|
||||||
return getFederatedStorage().getRequiredActions(realm, this.getId());
|
return getFederatedStorage().getRequiredActionsStream(realm, this.getId());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -360,12 +357,12 @@ public abstract class AbstractUserAdapterFederatedStorage extends UserModelDefau
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<String> getAttribute(String name) {
|
public Stream<String> getAttributeStream(String name) {
|
||||||
if (UserModel.USERNAME.equals(name)) {
|
if (UserModel.USERNAME.equals(name)) {
|
||||||
return Collections.singletonList(getUsername());
|
return Stream.of(getUsername());
|
||||||
}
|
}
|
||||||
List<String> result = getFederatedStorage().getAttributes(realm, this.getId()).get(mapAttribute(name));
|
List<String> result = getFederatedStorage().getAttributes(realm, this.getId()).get(mapAttribute(name));
|
||||||
return (result == null) ? Collections.emptyList() : result;
|
return (result == null) ? Stream.empty() : result.stream();
|
||||||
}
|
}
|
||||||
|
|
||||||
private String mapAttribute(String attributeName) {
|
private String mapAttribute(String attributeName) {
|
||||||
|
|
|
@ -20,6 +20,8 @@ import org.keycloak.common.util.MultivaluedHashMap;
|
||||||
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;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||||
|
@ -30,5 +32,22 @@ public interface UserAttributeFederatedStorage {
|
||||||
void setAttribute(RealmModel realm, String userId, String name, List<String> values);
|
void setAttribute(RealmModel realm, String userId, String name, List<String> values);
|
||||||
void removeAttribute(RealmModel realm, String userId, String name);
|
void removeAttribute(RealmModel realm, String userId, String name);
|
||||||
MultivaluedHashMap<String, String> getAttributes(RealmModel realm, String userId);
|
MultivaluedHashMap<String, String> getAttributes(RealmModel realm, String userId);
|
||||||
List<String> getUsersByUserAttribute(RealmModel realm, String name, String value);
|
|
||||||
|
/**
|
||||||
|
* @deprecated Use {@link #getUsersByUserAttributeStream(RealmModel, String, String) getUsersByUserAttributeStream} instead.
|
||||||
|
*/
|
||||||
|
@Deprecated
|
||||||
|
default List<String> getUsersByUserAttribute(RealmModel realm, String name, String value) {
|
||||||
|
return this.getUsersByUserAttributeStream(realm, name, value).collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Searches for federated users that have an attribute with the specified {@code name} and {@code value}.
|
||||||
|
*
|
||||||
|
* @param realm a reference to the realm.
|
||||||
|
* @param name the attribute name.
|
||||||
|
* @param value the attribute value.
|
||||||
|
* @return a non-null {@code Stream} of users that match the search criteria.
|
||||||
|
*/
|
||||||
|
Stream<String> getUsersByUserAttributeStream(RealmModel realm, String name, String value);
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,6 +21,8 @@ import org.keycloak.models.IdentityProviderModel;
|
||||||
import org.keycloak.models.RealmModel;
|
import org.keycloak.models.RealmModel;
|
||||||
|
|
||||||
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>
|
||||||
|
@ -32,6 +34,23 @@ public interface UserBrokerLinkFederatedStorage {
|
||||||
boolean removeFederatedIdentity(RealmModel realm, String userId, String socialProvider);
|
boolean removeFederatedIdentity(RealmModel realm, String userId, String socialProvider);
|
||||||
void preRemove(RealmModel realm, IdentityProviderModel provider);
|
void preRemove(RealmModel realm, IdentityProviderModel provider);
|
||||||
void updateFederatedIdentity(RealmModel realm, String userId, FederatedIdentityModel federatedIdentityModel);
|
void updateFederatedIdentity(RealmModel realm, String userId, FederatedIdentityModel federatedIdentityModel);
|
||||||
Set<FederatedIdentityModel> getFederatedIdentities(String userId, RealmModel realm);
|
|
||||||
|
/**
|
||||||
|
* @deprecated Use {@link #getFederatedIdentitiesStream(String, RealmModel) getFederatedIdentitiesStream} instead.
|
||||||
|
*/
|
||||||
|
@Deprecated
|
||||||
|
default Set<FederatedIdentityModel> getFederatedIdentities(String userId, RealmModel realm) {
|
||||||
|
return this.getFederatedIdentitiesStream(userId, realm).collect(Collectors.toSet());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Obtains the identities of the federated user identified by {@code userId}.
|
||||||
|
*
|
||||||
|
* @param userId the user identifier.
|
||||||
|
* @param realm a reference to the realm.
|
||||||
|
* @return a non-null {@code Stream} of federated identities associated with the user.
|
||||||
|
*/
|
||||||
|
Stream<FederatedIdentityModel> getFederatedIdentitiesStream(String userId, RealmModel realm);
|
||||||
|
|
||||||
FederatedIdentityModel getFederatedIdentity(String userId, String socialProvider, RealmModel realm);
|
FederatedIdentityModel getFederatedIdentity(String userId, String socialProvider, RealmModel realm);
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,6 +20,8 @@ import org.keycloak.models.RealmModel;
|
||||||
import org.keycloak.models.UserConsentModel;
|
import org.keycloak.models.UserConsentModel;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
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>
|
||||||
|
@ -28,7 +30,24 @@ import java.util.List;
|
||||||
public interface UserConsentFederatedStorage {
|
public interface UserConsentFederatedStorage {
|
||||||
void addConsent(RealmModel realm, String userId, UserConsentModel consent);
|
void addConsent(RealmModel realm, String userId, UserConsentModel consent);
|
||||||
UserConsentModel getConsentByClient(RealmModel realm, String userId, String clientInternalId);
|
UserConsentModel getConsentByClient(RealmModel realm, String userId, String clientInternalId);
|
||||||
List<UserConsentModel> getConsents(RealmModel realm, String userId);
|
|
||||||
|
/**
|
||||||
|
* @deprecated Use {@link #getConsentsStream(RealmModel, String) getConsentsStream} instead.
|
||||||
|
*/
|
||||||
|
@Deprecated
|
||||||
|
default List<UserConsentModel> getConsents(RealmModel realm, String userId) {
|
||||||
|
return this.getConsentsStream(realm, userId).collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Obtains the consents associated with the federated user identified by {@code userId}.
|
||||||
|
*
|
||||||
|
* @param realm a reference to the realm.
|
||||||
|
* @param userId the user identifier.
|
||||||
|
* @return a non-null {@code Stream} of consents associated with the user.
|
||||||
|
*/
|
||||||
|
Stream<UserConsentModel> getConsentsStream(RealmModel realm, String userId);
|
||||||
|
|
||||||
void updateConsent(RealmModel realm, String userId, UserConsentModel consent);
|
void updateConsent(RealmModel realm, String userId, UserConsentModel consent);
|
||||||
boolean revokeConsentForClient(RealmModel realm, String userId, String clientInternalId);
|
boolean revokeConsentForClient(RealmModel realm, String userId, String clientInternalId);
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,6 +28,8 @@ import org.keycloak.models.UserModel;
|
||||||
import org.keycloak.provider.Provider;
|
import org.keycloak.provider.Provider;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
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>
|
||||||
|
@ -43,7 +45,24 @@ public interface UserFederatedStorageProvider extends Provider,
|
||||||
UserRoleMappingsFederatedStorage,
|
UserRoleMappingsFederatedStorage,
|
||||||
UserFederatedUserCredentialStore {
|
UserFederatedUserCredentialStore {
|
||||||
|
|
||||||
List<String> getStoredUsers(RealmModel realm, int first, int max);
|
/**
|
||||||
|
* @deprecated Use {@link #getStoredUsersStream(RealmModel, int, int) getStoredUsersStream} instead.
|
||||||
|
*/
|
||||||
|
@Deprecated
|
||||||
|
default List<String> getStoredUsers(RealmModel realm, int first, int max) {
|
||||||
|
return getStoredUsersStream(realm, first, max).collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Obtains the ids of all federated users in the realm.
|
||||||
|
*
|
||||||
|
* @param realm a reference to the realm.
|
||||||
|
* @param first first result to return. Ignored if negative.
|
||||||
|
* @param max maximum number of results to return. Ignored if negative.
|
||||||
|
* @return a non-null {@code Stream} of federated user ids.
|
||||||
|
*/
|
||||||
|
Stream<String> getStoredUsersStream(RealmModel realm, int first, int max);
|
||||||
|
|
||||||
int getStoredUsersCount(RealmModel realm);
|
int getStoredUsersCount(RealmModel realm);
|
||||||
|
|
||||||
void preRemove(RealmModel realm);
|
void preRemove(RealmModel realm);
|
||||||
|
|
|
@ -21,6 +21,8 @@ import org.keycloak.models.RealmModel;
|
||||||
import org.keycloak.provider.Provider;
|
import org.keycloak.provider.Provider;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
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>
|
||||||
|
@ -31,7 +33,41 @@ public interface UserFederatedUserCredentialStore extends Provider {
|
||||||
CredentialModel createCredential(RealmModel realm, String userId, CredentialModel cred);
|
CredentialModel createCredential(RealmModel realm, String userId, CredentialModel cred);
|
||||||
boolean removeStoredCredential(RealmModel realm, String userId, String id);
|
boolean removeStoredCredential(RealmModel realm, String userId, String id);
|
||||||
CredentialModel getStoredCredentialById(RealmModel realm, String userId, String id);
|
CredentialModel getStoredCredentialById(RealmModel realm, String userId, String id);
|
||||||
List<CredentialModel> getStoredCredentials(RealmModel realm, String userId);
|
|
||||||
List<CredentialModel> getStoredCredentialsByType(RealmModel realm, String userId, String type);
|
/**
|
||||||
|
* @deprecated Use {@link #getStoredCredentialsStream(RealmModel, String) getStoredCredentialsStream} instead.
|
||||||
|
*/
|
||||||
|
@Deprecated
|
||||||
|
default List<CredentialModel> getStoredCredentials(RealmModel realm, String userId) {
|
||||||
|
return this.getStoredCredentialsStream(realm, userId).collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Obtains the credentials associated with the federated user identified by {@code userId}.
|
||||||
|
*
|
||||||
|
* @param realm a reference to the realm.
|
||||||
|
* @param userId the user identifier.
|
||||||
|
* @return a non-null {@code Stream} of credentials.
|
||||||
|
*/
|
||||||
|
Stream<CredentialModel> getStoredCredentialsStream(RealmModel realm, String userId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @deprecated Use {@link #getStoredCredentialsByTypeStream(RealmModel, String, String) getStoredCredentialsByTypeStream} instead.
|
||||||
|
*/
|
||||||
|
@Deprecated
|
||||||
|
default List<CredentialModel> getStoredCredentialsByType(RealmModel realm, String userId, String type) {
|
||||||
|
return this.getStoredCredentialsByTypeStream(realm, userId, type).collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Obtains the credentials of type {@code type} that are associated with the federated user identified by {@code userId}.
|
||||||
|
*
|
||||||
|
* @param realm a reference to the realm.
|
||||||
|
* @param userId the user identifier.
|
||||||
|
* @param type the credential type.
|
||||||
|
* @return a non-null {@code Stream} of credentials.
|
||||||
|
*/
|
||||||
|
Stream<CredentialModel> getStoredCredentialsByTypeStream(RealmModel realm, String userId, String type);
|
||||||
|
|
||||||
CredentialModel getStoredCredentialByNameAndType(RealmModel realm, String userId, String name, String type);
|
CredentialModel getStoredCredentialByNameAndType(RealmModel realm, String userId, String name, String type);
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,6 +38,24 @@ public interface UserGroupMembershipFederatedStorage {
|
||||||
|
|
||||||
void joinGroup(RealmModel realm, String userId, GroupModel group);
|
void joinGroup(RealmModel realm, String userId, GroupModel group);
|
||||||
void leaveGroup(RealmModel realm, String userId, GroupModel group);
|
void leaveGroup(RealmModel realm, String userId, GroupModel group);
|
||||||
List<String> getMembership(RealmModel realm, GroupModel group, int firstResult, int max);
|
|
||||||
|
/**
|
||||||
|
* @deprecated Use {@link #getMembershipStream(RealmModel, GroupModel, int, int) getMembershipStream} instead.
|
||||||
|
*/
|
||||||
|
@Deprecated
|
||||||
|
default List<String> getMembership(RealmModel realm, GroupModel group, int firstResult, int max) {
|
||||||
|
return this.getMembershipStream(realm, group, firstResult, max).collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Obtains the federated users that are members of the given {@code group} in the specified {@code realm}.
|
||||||
|
*
|
||||||
|
* @param realm a reference to the realm.
|
||||||
|
* @param group a reference to the group whose federated members are being searched.
|
||||||
|
* @param firstResult first result to return. Ignored if negative.
|
||||||
|
* @param max maximum number of results to return. Ignored if negative.
|
||||||
|
* @return a non-null {@code Stream} of federated user ids that are members of the group in the realm.
|
||||||
|
*/
|
||||||
|
Stream<String> getMembershipStream(RealmModel realm, GroupModel group, int firstResult, int max);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,13 +19,31 @@ package org.keycloak.storage.federated;
|
||||||
import org.keycloak.models.RealmModel;
|
import org.keycloak.models.RealmModel;
|
||||||
|
|
||||||
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>
|
||||||
* @version $Revision: 1 $
|
* @version $Revision: 1 $
|
||||||
*/
|
*/
|
||||||
public interface UserRequiredActionsFederatedStorage {
|
public interface UserRequiredActionsFederatedStorage {
|
||||||
Set<String> getRequiredActions(RealmModel realm, String userId);
|
|
||||||
|
/**
|
||||||
|
* @deprecated Use {@link #getRequiredActionsStream(RealmModel, String) getRequiredActionsStream} instead.
|
||||||
|
*/
|
||||||
|
@Deprecated
|
||||||
|
default Set<String> getRequiredActions(RealmModel realm, String userId) {
|
||||||
|
return this.getRequiredActionsStream(realm, userId).collect(Collectors.toSet());
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Obtains the names of required actions associated with the federated user identified by {@code userId}.
|
||||||
|
*
|
||||||
|
* @param realm a reference to the realm.
|
||||||
|
* @param userId the user identifier.
|
||||||
|
* @return a non-null {@code Stream} of required action names.
|
||||||
|
*/
|
||||||
|
Stream<String> getRequiredActionsStream(RealmModel realm, String userId);
|
||||||
|
|
||||||
void addRequiredAction(RealmModel realm, String userId, String action);
|
void addRequiredAction(RealmModel realm, String userId, String action);
|
||||||
void removeRequiredAction(RealmModel realm, String userId, String action);
|
void removeRequiredAction(RealmModel realm, String userId, String action);
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,11 +31,21 @@ public interface UserRoleMappingsFederatedStorage {
|
||||||
|
|
||||||
void grantRole(RealmModel realm, String userId, RoleModel role);
|
void grantRole(RealmModel realm, String userId, RoleModel role);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @deprecated Use {@link #getRoleMappingsStream(RealmModel, String) getRoleMappingsStream} instead.
|
||||||
|
*/
|
||||||
@Deprecated
|
@Deprecated
|
||||||
default Set<RoleModel> getRoleMappings(RealmModel realm,String userId) {
|
default Set<RoleModel> getRoleMappings(RealmModel realm,String userId) {
|
||||||
return getRoleMappingsStream(realm, userId).collect(Collectors.toSet());
|
return getRoleMappingsStream(realm, userId).collect(Collectors.toSet());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Obtains the roles associated with the federated user identified by {@code userId}.
|
||||||
|
*
|
||||||
|
* @param realm a reference to the realm.
|
||||||
|
* @param userId the user identifier.
|
||||||
|
* @return a non-null {@code Stream} of roles.
|
||||||
|
*/
|
||||||
Stream<RoleModel> getRoleMappingsStream(RealmModel realm, String userId);
|
Stream<RoleModel> getRoleMappingsStream(RealmModel realm, String userId);
|
||||||
|
|
||||||
void deleteRoleMapping(RealmModel realm, String userId, RoleModel role);
|
void deleteRoleMapping(RealmModel realm, String userId, RoleModel role);
|
||||||
|
|
|
@ -21,10 +21,11 @@ import org.keycloak.models.RealmModel;
|
||||||
import org.keycloak.models.RoleModel;
|
import org.keycloak.models.RoleModel;
|
||||||
import org.keycloak.models.UserModel;
|
import org.keycloak.models.UserModel;
|
||||||
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Optional capability interface implemented by UserStorageProviders.
|
* Optional capability interface implemented by UserStorageProviders.
|
||||||
|
@ -56,8 +57,7 @@ public interface UserQueryProvider {
|
||||||
if (groupIds == null || groupIds.isEmpty()) {
|
if (groupIds == null || groupIds.isEmpty()) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
return countUsersInGroups(getUsersStream(realm), groupIds);
|
||||||
return countUsersInGroups(getUsers(realm), groupIds);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -68,7 +68,7 @@ public interface UserQueryProvider {
|
||||||
* @return number of users that match the search
|
* @return number of users that match the search
|
||||||
*/
|
*/
|
||||||
default int getUsersCount(String search, RealmModel realm) {
|
default int getUsersCount(String search, RealmModel realm) {
|
||||||
return searchForUser(search, realm).size();
|
return (int) searchForUserStream(search, realm).count();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -84,9 +84,7 @@ public interface UserQueryProvider {
|
||||||
if (groupIds == null || groupIds.isEmpty()) {
|
if (groupIds == null || groupIds.isEmpty()) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
return countUsersInGroups(searchForUserStream(search, realm), groupIds);
|
||||||
List<UserModel> users = searchForUser(search, realm);
|
|
||||||
return countUsersInGroups(users, groupIds);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -97,7 +95,7 @@ public interface UserQueryProvider {
|
||||||
* @return number of users that match the given filters
|
* @return number of users that match the given filters
|
||||||
*/
|
*/
|
||||||
default int getUsersCount(Map<String, String> params, RealmModel realm) {
|
default int getUsersCount(Map<String, String> params, RealmModel realm) {
|
||||||
return searchForUser(params, realm).size();
|
return (int) searchForUserStream(params, realm).count();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -113,9 +111,7 @@ public interface UserQueryProvider {
|
||||||
if (groupIds == null || groupIds.isEmpty()) {
|
if (groupIds == null || groupIds.isEmpty()) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
return countUsersInGroups(searchForUserStream(params, realm), groupIds);
|
||||||
List<UserModel> users = searchForUser(params, realm);
|
|
||||||
return countUsersInGroups(users, groupIds);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -126,10 +122,8 @@ public interface UserQueryProvider {
|
||||||
* @param groupIds id of groups that should be checked for
|
* @param groupIds id of groups that should be checked for
|
||||||
* @return number of users that are in at least one of the groups
|
* @return number of users that are in at least one of the groups
|
||||||
*/
|
*/
|
||||||
static int countUsersInGroups(List<UserModel> users, Set<String> groupIds) {
|
static int countUsersInGroups(Stream<UserModel> users, Set<String> groupIds) {
|
||||||
return (int) users.stream()
|
return (int) users.filter(u -> u.getGroupsStream().map(GroupModel::getId).anyMatch(groupIds::contains)).count();
|
||||||
.filter(u -> u.getGroupsStream().anyMatch(group -> groupIds.contains(group.getId())))
|
|
||||||
.count();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -143,8 +137,39 @@ public interface UserQueryProvider {
|
||||||
throw new RuntimeException("Not implemented");
|
throw new RuntimeException("Not implemented");
|
||||||
}
|
}
|
||||||
|
|
||||||
List<UserModel> getUsers(RealmModel realm);
|
/**
|
||||||
List<UserModel> getUsers(RealmModel realm, int firstResult, int maxResults);
|
* @deprecated Use {@link #getUsersStream(RealmModel) getUsersStream} instead.
|
||||||
|
*/
|
||||||
|
@Deprecated
|
||||||
|
default List<UserModel> getUsers(RealmModel realm) {
|
||||||
|
return this.getUsersStream(realm).collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Searches all users in the realm.
|
||||||
|
*
|
||||||
|
* @param realm a reference to the realm.
|
||||||
|
* @return a non-null {@code Stream} of users.
|
||||||
|
*/
|
||||||
|
Stream<UserModel> getUsersStream(RealmModel realm);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @deprecated Use {@link #getUsersStream(RealmModel, int, int) getUsersStream} instead.
|
||||||
|
*/
|
||||||
|
@Deprecated
|
||||||
|
default List<UserModel> getUsers(RealmModel realm, int firstResult, int maxResults) {
|
||||||
|
return this.getUsersStream(realm, firstResult, maxResults).collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Searches all users in the realm, starting from the {@code firstResult} and containing at most {@code maxResults}.
|
||||||
|
*
|
||||||
|
* @param realm a reference to the realm.
|
||||||
|
* @param firstResult first result to return. Ignored if negative.
|
||||||
|
* @param maxResults maximum number of results to return. Ignored if negative.
|
||||||
|
* @return a non-null {@code Stream} of users.
|
||||||
|
*/
|
||||||
|
Stream<UserModel> getUsersStream(RealmModel realm, int firstResult, int maxResults);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Search for users with username, email or first + last name that is like search string.
|
* Search for users with username, email or first + last name that is like search string.
|
||||||
|
@ -156,8 +181,24 @@ public interface UserQueryProvider {
|
||||||
* @param search
|
* @param search
|
||||||
* @param realm
|
* @param realm
|
||||||
* @return
|
* @return
|
||||||
|
* @deprecated Use {@link #searchForUserStream(String, RealmModel) searchForUserStream} instead.
|
||||||
*/
|
*/
|
||||||
List<UserModel> searchForUser(String search, RealmModel realm);
|
@Deprecated
|
||||||
|
default List<UserModel> searchForUser(String search, RealmModel realm) {
|
||||||
|
return this.searchForUserStream(search, realm).collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Searches for users with username, email or first + last name that is like search string. If possible, implementations
|
||||||
|
* should treat the parameter values as partial match patterns (i.e. in RDMBS terms use LIKE).
|
||||||
|
* <p/>
|
||||||
|
* This method is used by the admin console search box
|
||||||
|
*
|
||||||
|
* @param search case sensitive search string.
|
||||||
|
* @param realm a reference to the realm.
|
||||||
|
* @return a non-null {@code Stream} of users that match the search string.
|
||||||
|
*/
|
||||||
|
Stream<UserModel> searchForUserStream(String search, RealmModel realm);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Search for users with username, email or first + last name that is like search string.
|
* Search for users with username, email or first + last name that is like search string.
|
||||||
|
@ -171,8 +212,26 @@ public interface UserQueryProvider {
|
||||||
* @param firstResult
|
* @param firstResult
|
||||||
* @param maxResults
|
* @param maxResults
|
||||||
* @return
|
* @return
|
||||||
|
* @deprecated Use {@link #searchForUserStream(String, RealmModel, int, int) searchForUserStream} instead.
|
||||||
*/
|
*/
|
||||||
List<UserModel> searchForUser(String search, RealmModel realm, int firstResult, int maxResults);
|
@Deprecated
|
||||||
|
default List<UserModel> searchForUser(String search, RealmModel realm, int firstResult, int maxResults) {
|
||||||
|
return this.searchForUserStream(search, realm, firstResult, maxResults).collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Searches for users with username, email or first + last name that is like search string. If possible, implementations
|
||||||
|
* should treat the parameter values as partial match patterns (i.e. in RDMBS terms use LIKE).
|
||||||
|
* <p/>
|
||||||
|
* This method is used by the admin console search box
|
||||||
|
*
|
||||||
|
* @param search case sensitive search string.
|
||||||
|
* @param realm a reference to the realm.
|
||||||
|
* @param firstResult first result to return. Ignored if negative.
|
||||||
|
* @param maxResults maximum number of results to return. Ignored if negative.
|
||||||
|
* @return a non-null {@code Stream} of users that match the search criteria.
|
||||||
|
*/
|
||||||
|
Stream<UserModel> searchForUserStream(String search, RealmModel realm, int firstResult, int maxResults);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Search for user by parameter. Valid parameters are:
|
* Search for user by parameter. Valid parameters are:
|
||||||
|
@ -189,8 +248,30 @@ public interface UserQueryProvider {
|
||||||
* @param params
|
* @param params
|
||||||
* @param realm
|
* @param realm
|
||||||
* @return
|
* @return
|
||||||
|
* @deprecated Use {@link #searchForUserStream(Map, RealmModel) searchForUserStream} instead.
|
||||||
*/
|
*/
|
||||||
List<UserModel> searchForUser(Map<String, String> params, RealmModel realm);
|
@Deprecated
|
||||||
|
default List<UserModel> searchForUser(Map<String, String> params, RealmModel realm) {
|
||||||
|
return this.searchForUserStream(params, realm).collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Searches for user by parameter. If possible, implementations should treat the parameter values as partial match patterns
|
||||||
|
* (i.e. in RDMBS terms use LIKE). Valid parameters are:
|
||||||
|
* <ul>
|
||||||
|
* <li><b>first</b> - first name</li>
|
||||||
|
* <li><b>last</b> - last name</li>
|
||||||
|
* <li><b>email</b> - email</li>
|
||||||
|
* <li><b>username</b> - username</li>
|
||||||
|
* <li><b>enabled</b> - if user is enabled (true/false)</li>
|
||||||
|
* </ul>
|
||||||
|
* This method is used by the REST API when querying users.
|
||||||
|
*
|
||||||
|
* @param params a map containing the search parameters.
|
||||||
|
* @param realm a reference to the realm.
|
||||||
|
* @return a non-null {@code Stream} of users that match the search parameters.
|
||||||
|
*/
|
||||||
|
Stream<UserModel> searchForUserStream(Map<String, String> params, RealmModel realm);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Search for user by parameter. Valid parameters are:
|
* Search for user by parameter. Valid parameters are:
|
||||||
|
@ -209,8 +290,60 @@ public interface UserQueryProvider {
|
||||||
* @param firstResult
|
* @param firstResult
|
||||||
* @param maxResults
|
* @param maxResults
|
||||||
* @return
|
* @return
|
||||||
|
* @deprecated Use {@link #searchForUserStream(Map, RealmModel, int, int) searchForUserStream} instead.
|
||||||
*/
|
*/
|
||||||
List<UserModel> searchForUser(Map<String, String> params, RealmModel realm, int firstResult, int maxResults);
|
@Deprecated
|
||||||
|
default List<UserModel> searchForUser(Map<String, String> params, RealmModel realm, int firstResult, int maxResults) {
|
||||||
|
return this.searchForUserStream(params, realm, firstResult, maxResults).collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Searches for user by parameter. If possible, implementations should treat the parameter values as partial match patterns
|
||||||
|
* (i.e. in RDMBS terms use LIKE). Valid parameters are:
|
||||||
|
* <ul>
|
||||||
|
* <li><b>first</b> - first name</li>
|
||||||
|
* <li><b>last</b> - last name</li>
|
||||||
|
* <li><b>email</b> - email</li>
|
||||||
|
* <li><b>username</b> - username</li>
|
||||||
|
* <li><b>enabled</b> - if user is enabled (true/false)</li>
|
||||||
|
* </ul>
|
||||||
|
* This method is used by the REST API when querying users.
|
||||||
|
*
|
||||||
|
* @param params a map containing the search parameters.
|
||||||
|
* @param realm a reference to the realm.
|
||||||
|
* @param firstResult first result to return. Ignored if negative.
|
||||||
|
* @param maxResults maximum number of results to return. Ignored if negative.
|
||||||
|
* @return a non-null {@code Stream} of users that match the search criteria.
|
||||||
|
*/
|
||||||
|
Stream<UserModel> searchForUserStream(Map<String, String> params, RealmModel realm, int firstResult, int maxResults);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get users that belong to a specific group. Implementations do not have to search in UserFederatedStorageProvider
|
||||||
|
* as this is done automatically.
|
||||||
|
*
|
||||||
|
* @see org.keycloak.storage.federated.UserFederatedStorageProvider
|
||||||
|
*
|
||||||
|
* @param realm
|
||||||
|
* @param group
|
||||||
|
* @return
|
||||||
|
* @deprecated Use {@link #getGroupMembersStream(RealmModel, GroupModel) getGroupMembersStream} instead.
|
||||||
|
*/
|
||||||
|
@Deprecated
|
||||||
|
default List<UserModel> getGroupMembers(RealmModel realm, GroupModel group) {
|
||||||
|
return this.getGroupMembersStream(realm, group).collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Obtains users that belong to a specific group. Implementations do not have to search in {@code UserFederatedStorageProvider}
|
||||||
|
* as this is done automatically.
|
||||||
|
*
|
||||||
|
* @see org.keycloak.storage.federated.UserFederatedStorageProvider
|
||||||
|
*
|
||||||
|
* @param realm a reference to the realm.
|
||||||
|
* @param group a reference to the group.
|
||||||
|
* @return a non-null {@code Stream} of users that belong to the group.
|
||||||
|
*/
|
||||||
|
Stream<UserModel> getGroupMembersStream(RealmModel realm, GroupModel group);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get users that belong to a specific group. Implementations do not have to search in UserFederatedStorageProvider
|
* Get users that belong to a specific group. Implementations do not have to search in UserFederatedStorageProvider
|
||||||
|
@ -223,51 +356,77 @@ public interface UserQueryProvider {
|
||||||
* @param firstResult
|
* @param firstResult
|
||||||
* @param maxResults
|
* @param maxResults
|
||||||
* @return
|
* @return
|
||||||
|
* @deprecated Use {@link #getGroupMembersStream(RealmModel, GroupModel, int, int) getGroupMembersStream} instead.
|
||||||
*/
|
*/
|
||||||
List<UserModel> getGroupMembers(RealmModel realm, GroupModel group, int firstResult, int maxResults);
|
@Deprecated
|
||||||
|
default List<UserModel> getGroupMembers(RealmModel realm, GroupModel group, int firstResult, int maxResults) {
|
||||||
|
return this.getGroupMembersStream(realm, group, firstResult, maxResults).collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Obtains users that belong to a specific group. Implementations do not have to search in {@code UserFederatedStorageProvider}
|
||||||
|
* as this is done automatically.
|
||||||
|
*
|
||||||
|
* @see org.keycloak.storage.federated.UserFederatedStorageProvider
|
||||||
|
*
|
||||||
|
* @param realm a reference to the realm.
|
||||||
|
* @param group a reference to the group.
|
||||||
|
* @param firstResult first result to return. Ignored if negative.
|
||||||
|
* @param maxResults maximum number of results to return. Ignored if negative.
|
||||||
|
* @return a non-null {@code Stream} of users that belong to the group.
|
||||||
|
*/
|
||||||
|
Stream<UserModel> getGroupMembersStream(RealmModel realm, GroupModel group, int firstResult, int maxResults);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get users that belong to a specific role.
|
* Get users that belong to a specific role.
|
||||||
*
|
*
|
||||||
*
|
|
||||||
*
|
|
||||||
* @param realm
|
* @param realm
|
||||||
* @param role
|
* @param role
|
||||||
* @return
|
* @return
|
||||||
|
* @deprecated Use {@link #getRoleMembersStream(RealmModel, RoleModel) getRoleMembersStream} instead.
|
||||||
*/
|
*/
|
||||||
default List<UserModel> getRoleMembers(RealmModel realm, RoleModel role)
|
@Deprecated
|
||||||
{
|
default List<UserModel> getRoleMembers(RealmModel realm, RoleModel role) {
|
||||||
return Collections.EMPTY_LIST;
|
return this.getRoleMembersStream(realm, role).collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Obtains users that have the specified role.
|
||||||
|
*
|
||||||
|
* @param realm a reference to the realm.
|
||||||
|
* @param role a reference to the role.
|
||||||
|
* @return a non-null {@code Stream} of users that have the specified role.
|
||||||
|
*/
|
||||||
|
default Stream<UserModel> getRoleMembersStream(RealmModel realm, RoleModel role) {
|
||||||
|
return Stream.empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Search for users that have a specific role with a specific roleId.
|
* Search for users that have a specific role with a specific roleId.
|
||||||
*
|
*
|
||||||
*
|
|
||||||
*
|
|
||||||
* @param firstResult
|
* @param firstResult
|
||||||
* @param maxResults
|
* @param maxResults
|
||||||
* @param role
|
* @param role
|
||||||
* @return
|
* @return
|
||||||
|
* @deprecated Use {@link #getRoleMembersStream(RealmModel, RoleModel, int, int) getRoleMembersStream} instead.
|
||||||
*/
|
*/
|
||||||
default List<UserModel> getRoleMembers(RealmModel realm, RoleModel role, int firstResult, int maxResults)
|
@Deprecated
|
||||||
{
|
default List<UserModel> getRoleMembers(RealmModel realm, RoleModel role, int firstResult, int maxResults) {
|
||||||
return Collections.EMPTY_LIST;
|
return this.getRoleMembersStream(realm, role, firstResult, maxResults).collect(Collectors.toList());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get users that belong to a specific group. Implementations do not have to search in UserFederatedStorageProvider
|
* Searches for users that have the specified role.
|
||||||
* as this is done automatically.
|
|
||||||
*
|
*
|
||||||
* @see org.keycloak.storage.federated.UserFederatedStorageProvider
|
* @param realm a reference to the realm.
|
||||||
*
|
* @param role a reference to the role.
|
||||||
*
|
* @param firstResult first result to return. Ignored if negative.
|
||||||
*
|
* @param maxResults maximum number of results to return. Ignored if negative.
|
||||||
* @param realm
|
* @return a non-null {@code Stream} of users that have the specified role.
|
||||||
* @param group
|
|
||||||
* @return
|
|
||||||
*/
|
*/
|
||||||
List<UserModel> getGroupMembers(RealmModel realm, GroupModel group);
|
default Stream<UserModel> getRoleMembersStream(RealmModel realm, RoleModel role, int firstResult, int maxResults) {
|
||||||
|
return Stream.empty();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Search for users that have a specific attribute with a specific value.
|
* Search for users that have a specific attribute with a specific value.
|
||||||
|
@ -275,13 +434,29 @@ public interface UserQueryProvider {
|
||||||
* as this is done automatically.
|
* as this is done automatically.
|
||||||
*
|
*
|
||||||
* @see org.keycloak.storage.federated.UserFederatedStorageProvider
|
* @see org.keycloak.storage.federated.UserFederatedStorageProvider
|
||||||
*
|
|
||||||
|
|
||||||
*
|
*
|
||||||
* @param attrName
|
* @param attrName
|
||||||
* @param attrValue
|
* @param attrValue
|
||||||
* @param realm
|
* @param realm
|
||||||
* @return
|
* @return
|
||||||
|
* @deprecated Use {@link #searchForUserByUserAttributeStream(String, String, RealmModel) searchForUserByUserAttributeStream}
|
||||||
|
* instead.
|
||||||
*/
|
*/
|
||||||
List<UserModel> searchForUserByUserAttribute(String attrName, String attrValue, RealmModel realm);
|
@Deprecated
|
||||||
|
default List<UserModel> searchForUserByUserAttribute(String attrName, String attrValue, RealmModel realm) {
|
||||||
|
return this.searchForUserByUserAttributeStream(attrName, attrValue, realm).collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Searches for users that have a specific attribute with a specific value. Implementations do not have to search in
|
||||||
|
* {@code UserFederatedStorageProvider} as this is done automatically.
|
||||||
|
*
|
||||||
|
* @see org.keycloak.storage.federated.UserFederatedStorageProvider
|
||||||
|
*
|
||||||
|
* @param attrName the attribute name.
|
||||||
|
* @param attrValue the attribute value.
|
||||||
|
* @param realm a reference to the realm.
|
||||||
|
* @return a non-null {@code Stream} of users that match the search criteria.
|
||||||
|
*/
|
||||||
|
Stream<UserModel> searchForUserByUserAttributeStream(String attrName, String attrValue, RealmModel realm);
|
||||||
}
|
}
|
||||||
|
|
|
@ -46,6 +46,7 @@ import javax.ws.rs.core.MultivaluedMap;
|
||||||
import javax.ws.rs.core.Response;
|
import javax.ws.rs.core.Response;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
||||||
|
@ -130,8 +131,8 @@ public class IdpReviewProfileAuthenticator extends AbstractIdpAuthenticator {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<String> getAttribute(String name) {
|
public Stream<String> getAttributeStream(String name) {
|
||||||
return userCtx.getAttribute(name);
|
return userCtx.getAttribute(name).stream();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
|
|
||||||
package org.keycloak.storage;
|
package org.keycloak.storage;
|
||||||
|
|
||||||
|
import com.google.common.collect.Streams;
|
||||||
import org.jboss.logging.Logger;
|
import org.jboss.logging.Logger;
|
||||||
import org.keycloak.component.ComponentFactory;
|
import org.keycloak.component.ComponentFactory;
|
||||||
import org.keycloak.component.ComponentModel;
|
import org.keycloak.component.ComponentModel;
|
||||||
|
@ -50,14 +51,12 @@ import org.keycloak.storage.user.UserQueryProvider;
|
||||||
import org.keycloak.storage.user.UserRegistrationProvider;
|
import org.keycloak.storage.user.UserRegistrationProvider;
|
||||||
|
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
import java.util.function.Predicate;
|
import java.util.function.Predicate;
|
||||||
import java.util.stream.Collectors;
|
|
||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
import static org.keycloak.models.utils.KeycloakModelUtils.runJobInTransaction;
|
import static org.keycloak.models.utils.KeycloakModelUtils.runJobInTransaction;
|
||||||
|
@ -130,19 +129,14 @@ public class UserStorageManager extends AbstractStorageManager<UserStorageProvid
|
||||||
if (userCache != null) {
|
if (userCache != null) {
|
||||||
userCache.evict(realm, user);
|
userCache.evict(realm, user);
|
||||||
}
|
}
|
||||||
runJobInTransaction(session.getKeycloakSessionFactory(), new KeycloakSessionTask() {
|
runJobInTransaction(session.getKeycloakSessionFactory(), session -> {
|
||||||
|
RealmModel realmModel = session.realms().getRealm(realm.getId());
|
||||||
@Override
|
if (realmModel == null) return;
|
||||||
public void run(KeycloakSession session) {
|
UserModel deletedUser = session.userLocalStorage().getUserById(userId, realmModel);
|
||||||
RealmModel realmModel = session.realms().getRealm(realm.getId());
|
if (deletedUser != null) {
|
||||||
if (realmModel == null) return;
|
new UserManager(session).removeUser(realmModel, deletedUser, session.userLocalStorage());
|
||||||
UserModel deletedUser = session.userLocalStorage().getUserById(userId, realmModel);
|
logger.debugf("Removed invalid user '%s'", userName);
|
||||||
if (deletedUser != null) {
|
|
||||||
new UserManager(session).removeUser(realmModel, deletedUser, session.userLocalStorage());
|
|
||||||
logger.debugf("Removed invalid user '%s'", userName);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -270,70 +264,70 @@ public class UserStorageManager extends AbstractStorageManager<UserStorageProvid
|
||||||
{@link UserQueryProvider} methods implementation start here */
|
{@link UserQueryProvider} methods implementation start here */
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<UserModel> getGroupMembers(RealmModel realm, GroupModel group) {
|
public Stream<UserModel> getGroupMembersStream(RealmModel realm, GroupModel group) {
|
||||||
return getGroupMembers(realm, group, -1, -1);
|
return getGroupMembersStream(realm, group, -1, -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<UserModel> getGroupMembers(final RealmModel realm, final GroupModel group, int firstResult, int maxResults) {
|
public Stream<UserModel> getGroupMembersStream(final RealmModel realm, final GroupModel group, int firstResult, int maxResults) {
|
||||||
Stream<UserModel> results = query((provider) -> {
|
Stream<UserModel> results = query((provider) -> {
|
||||||
if (provider instanceof UserQueryProvider) {
|
if (provider instanceof UserQueryProvider) {
|
||||||
return ((UserQueryProvider)provider).getGroupMembers(realm, group).stream();
|
return ((UserQueryProvider)provider).getGroupMembersStream(realm, group);
|
||||||
|
|
||||||
} else if (provider instanceof UserFederatedStorageProvider) {
|
} else if (provider instanceof UserFederatedStorageProvider) {
|
||||||
Stream<String> ids = ((UserFederatedStorageProvider)provider).getMembership(realm, group, -1, -1).stream();
|
return ((UserFederatedStorageProvider)provider).getMembershipStream(realm, group, -1, -1).
|
||||||
return ids.map(id -> getUserById(id, realm));
|
map(id -> getUserById(id, realm));
|
||||||
}
|
}
|
||||||
return Stream.empty();
|
return Stream.empty();
|
||||||
}, realm, firstResult, maxResults);
|
}, realm, firstResult, maxResults);
|
||||||
|
|
||||||
return importValidation(realm, results).collect(Collectors.toList());
|
return importValidation(realm, results);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<UserModel> getRoleMembers(RealmModel realm, RoleModel role) {
|
public Stream<UserModel> getRoleMembersStream(RealmModel realm, RoleModel role) {
|
||||||
return getRoleMembers(realm, role, -1, -1);
|
return getRoleMembersStream(realm, role, -1, -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<UserModel> getRoleMembers(final RealmModel realm, final RoleModel role, int firstResult, int maxResults) {
|
public Stream<UserModel> getRoleMembersStream(final RealmModel realm, final RoleModel role, int firstResult, int maxResults) {
|
||||||
Stream<UserModel> results = query((provider) -> {
|
Stream<UserModel> results = query((provider) -> {
|
||||||
if (provider instanceof UserQueryProvider) {
|
if (provider instanceof UserQueryProvider) {
|
||||||
return ((UserQueryProvider)provider).getRoleMembers(realm, role).stream();
|
return ((UserQueryProvider)provider).getRoleMembersStream(realm, role);
|
||||||
}
|
}
|
||||||
return Stream.empty();
|
return Stream.empty();
|
||||||
}, realm, firstResult, maxResults);
|
}, realm, firstResult, maxResults);
|
||||||
return importValidation(realm, results).collect(Collectors.toList());
|
return importValidation(realm, results);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<UserModel> getUsers(RealmModel realm) {
|
public Stream<UserModel> getUsersStream(RealmModel realm) {
|
||||||
return getUsers(realm, false);
|
return getUsersStream(realm, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<UserModel> getUsers(RealmModel realm, int firstResult, int maxResults) {
|
public Stream<UserModel> getUsersStream(RealmModel realm, int firstResult, int maxResults) {
|
||||||
return getUsers(realm, firstResult, maxResults, false);
|
return getUsersStream(realm, firstResult, maxResults, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<UserModel> getUsers(RealmModel realm, boolean includeServiceAccounts) {
|
public Stream<UserModel> getUsersStream(RealmModel realm, boolean includeServiceAccounts) {
|
||||||
return getUsers(realm, 0, Integer.MAX_VALUE - 1, includeServiceAccounts);
|
return getUsersStream(realm, 0, Integer.MAX_VALUE - 1, includeServiceAccounts);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<UserModel> getUsers(final RealmModel realm, int firstResult, int maxResults, final boolean includeServiceAccounts) {
|
public Stream<UserModel> getUsersStream(final RealmModel realm, int firstResult, int maxResults, final boolean includeServiceAccounts) {
|
||||||
Stream<UserModel> results = query((provider) -> {
|
Stream<UserModel> results = query((provider) -> {
|
||||||
if (provider instanceof UserProvider) { // it is local storage
|
if (provider instanceof UserProvider) { // it is local storage
|
||||||
return ((UserProvider) provider).getUsers(realm, includeServiceAccounts).stream();
|
return ((UserProvider) provider).getUsersStream(realm, includeServiceAccounts);
|
||||||
} else if (provider instanceof UserQueryProvider) {
|
} else if (provider instanceof UserQueryProvider) {
|
||||||
return ((UserQueryProvider)provider).getUsers(realm).stream();
|
return ((UserQueryProvider)provider).getUsersStream(realm);
|
||||||
}
|
}
|
||||||
return Stream.empty();
|
return Stream.empty();
|
||||||
}
|
}
|
||||||
, realm, firstResult, maxResults);
|
, realm, firstResult, maxResults);
|
||||||
return importValidation(realm, results).collect(Collectors.toList());
|
return importValidation(realm, results);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -377,51 +371,49 @@ public class UserStorageManager extends AbstractStorageManager<UserStorageProvid
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<UserModel> searchForUser(String search, RealmModel realm) {
|
public Stream<UserModel> searchForUserStream(String search, RealmModel realm) {
|
||||||
return searchForUser(search, realm, 0, Integer.MAX_VALUE - 1);
|
return searchForUserStream(search, realm, 0, Integer.MAX_VALUE - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<UserModel> searchForUser(String search, RealmModel realm, int firstResult, int maxResults) {
|
public Stream<UserModel> searchForUserStream(String search, RealmModel realm, int firstResult, int maxResults) {
|
||||||
Stream<UserModel> results = query((provider) -> {
|
Stream<UserModel> results = query((provider) -> {
|
||||||
if (provider instanceof UserQueryProvider) {
|
if (provider instanceof UserQueryProvider) {
|
||||||
return ((UserQueryProvider)provider).searchForUser(search, realm).stream();
|
return ((UserQueryProvider)provider).searchForUserStream(search, realm);
|
||||||
|
|
||||||
}
|
}
|
||||||
return Stream.empty();
|
return Stream.empty();
|
||||||
}, realm, firstResult, maxResults);
|
}, realm, firstResult, maxResults);
|
||||||
return importValidation(realm, results).collect(Collectors.toList());
|
return importValidation(realm, results);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<UserModel> searchForUser(Map<String, String> attributes, RealmModel realm) {
|
public Stream<UserModel> searchForUserStream(Map<String, String> attributes, RealmModel realm) {
|
||||||
return searchForUser(attributes, realm, 0, Integer.MAX_VALUE - 1);
|
return searchForUserStream(attributes, realm, 0, Integer.MAX_VALUE - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<UserModel> searchForUser(Map<String, String> attributes, RealmModel realm, int firstResult, int maxResults) {
|
public Stream<UserModel> searchForUserStream(Map<String, String> attributes, RealmModel realm, int firstResult, int maxResults) {
|
||||||
Stream<UserModel> results = query((provider) -> {
|
|
||||||
if (provider instanceof UserQueryProvider) {
|
|
||||||
if (attributes.containsKey(UserModel.SEARCH)) {
|
|
||||||
return ((UserQueryProvider)provider).searchForUser(attributes.get(UserModel.SEARCH), realm).stream();
|
|
||||||
} else {
|
|
||||||
return ((UserQueryProvider)provider).searchForUser(attributes, realm).stream();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return Stream.empty();
|
|
||||||
}
|
|
||||||
, realm, firstResult, maxResults);
|
|
||||||
return importValidation(realm, results).collect(Collectors.toList());
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public List<UserModel> searchForUserByUserAttribute(String attrName, String attrValue, RealmModel realm) {
|
|
||||||
Stream<UserModel> results = query((provider) -> {
|
Stream<UserModel> results = query((provider) -> {
|
||||||
if (provider instanceof UserQueryProvider) {
|
if (provider instanceof UserQueryProvider) {
|
||||||
return ((UserQueryProvider)provider).searchForUserByUserAttribute(attrName, attrValue, realm).stream();
|
if (attributes.containsKey(UserModel.SEARCH)) {
|
||||||
|
return ((UserQueryProvider)provider).searchForUserStream(attributes.get(UserModel.SEARCH), realm);
|
||||||
|
} else {
|
||||||
|
return ((UserQueryProvider)provider).searchForUserStream(attributes, realm);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Stream.empty();
|
||||||
|
}
|
||||||
|
, realm, firstResult, maxResults);
|
||||||
|
return importValidation(realm, results);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Stream<UserModel> searchForUserByUserAttributeStream(String attrName, String attrValue, RealmModel realm) {
|
||||||
|
Stream<UserModel> results = query((provider) -> {
|
||||||
|
if (provider instanceof UserQueryProvider) {
|
||||||
|
return ((UserQueryProvider)provider).searchForUserByUserAttributeStream(attrName, attrValue, realm);
|
||||||
} else if (provider instanceof UserFederatedStorageProvider) {
|
} else if (provider instanceof UserFederatedStorageProvider) {
|
||||||
return ((UserFederatedStorageProvider)provider).getUsersByUserAttribute(realm, attrName, attrValue).stream()
|
return ((UserFederatedStorageProvider)provider).getUsersByUserAttributeStream(realm, attrName, attrValue)
|
||||||
.map(id -> getUserById(id, realm))
|
.map(id -> getUserById(id, realm))
|
||||||
.filter(Objects::nonNull);
|
.filter(Objects::nonNull);
|
||||||
|
|
||||||
|
@ -432,7 +424,7 @@ public class UserStorageManager extends AbstractStorageManager<UserStorageProvid
|
||||||
// removeDuplicates method may cause concurrent issues, it should not be used on parallel streams
|
// removeDuplicates method may cause concurrent issues, it should not be used on parallel streams
|
||||||
results = removeDuplicates(results);
|
results = removeDuplicates(results);
|
||||||
|
|
||||||
return importValidation(realm, results).collect(Collectors.toList());
|
return importValidation(realm, results);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** {@link UserQueryProvider} methods implementation end here
|
/** {@link UserQueryProvider} methods implementation end here
|
||||||
|
@ -545,11 +537,11 @@ public class UserStorageManager extends AbstractStorageManager<UserStorageProvid
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<UserConsentModel> getConsents(RealmModel realm, String userId) {
|
public Stream<UserConsentModel> getConsentsStream(RealmModel realm, String userId) {
|
||||||
if (StorageId.isLocalStorage(userId)) {
|
if (StorageId.isLocalStorage(userId)) {
|
||||||
return localStorage().getConsents(realm, userId);
|
return localStorage().getConsentsStream(realm, userId);
|
||||||
} else {
|
} else {
|
||||||
return getFederatedStorage().getConsents(realm, userId);
|
return getFederatedStorage().getConsentsStream(realm, userId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -608,14 +600,13 @@ public class UserStorageManager extends AbstractStorageManager<UserStorageProvid
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Set<FederatedIdentityModel> getFederatedIdentities(UserModel user, RealmModel realm) {
|
public Stream<FederatedIdentityModel> getFederatedIdentitiesStream(UserModel user, RealmModel realm) {
|
||||||
if (user == null) throw new IllegalStateException("Federated user no longer valid");
|
if (user == null) throw new IllegalStateException("Federated user no longer valid");
|
||||||
Set<FederatedIdentityModel> set = new HashSet<>();
|
Stream<FederatedIdentityModel> stream = StorageId.isLocalStorage(user) ?
|
||||||
if (StorageId.isLocalStorage(user)) {
|
localStorage().getFederatedIdentitiesStream(user, realm) : Stream.empty();
|
||||||
set.addAll(localStorage().getFederatedIdentities(user, realm));
|
if (getFederatedStorage() != null)
|
||||||
}
|
stream = Streams.concat(stream, getFederatedStorage().getFederatedIdentitiesStream(user.getId(), realm));
|
||||||
if (getFederatedStorage() != null) set.addAll(getFederatedStorage().getFederatedIdentities(user.getId(), realm));
|
return stream.distinct();
|
||||||
return set;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -18,13 +18,10 @@
|
||||||
|
|
||||||
package org.keycloak.testsuite.federation;
|
package org.keycloak.testsuite.federation;
|
||||||
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
import org.jboss.logging.Logger;
|
import org.jboss.logging.Logger;
|
||||||
import org.keycloak.common.util.Time;
|
import org.keycloak.common.util.Time;
|
||||||
|
@ -319,58 +316,57 @@ public class BackwardsCompatibilityUserStorage implements UserLookupProvider, Us
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<UserModel> getUsers(RealmModel realm) {
|
public Stream<UserModel> getUsersStream(RealmModel realm) {
|
||||||
return getUsers(realm, -1, -1);
|
return getUsersStream(realm, -1, -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<UserModel> getUsers(RealmModel realm, int firstResult, int maxResults) {
|
public Stream<UserModel> getUsersStream(RealmModel realm, int firstResult, int maxResults) {
|
||||||
return users.values()
|
return users.values()
|
||||||
.stream()
|
.stream()
|
||||||
.skip(firstResult).limit(maxResults)
|
.skip(firstResult).limit(maxResults)
|
||||||
.map(myUser -> createUser(realm, myUser.username))
|
.map(myUser -> createUser(realm, myUser.username));
|
||||||
.collect(Collectors.toList());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<UserModel> searchForUser(String search, RealmModel realm) {
|
public Stream<UserModel> searchForUserStream(String search, RealmModel realm) {
|
||||||
return searchForUser(search, realm, -1, -1);
|
return searchForUserStream(search, realm, -1, -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<UserModel> searchForUser(String search, RealmModel realm, int firstResult, int maxResults) {
|
public Stream<UserModel> searchForUserStream(String search, RealmModel realm, int firstResult, int maxResults) {
|
||||||
UserModel user = getUserByUsername(search, realm);
|
UserModel user = getUserByUsername(search, realm);
|
||||||
return user == null ? Collections.emptyList() : Arrays.asList(user);
|
return user == null ? Stream.empty() : Stream.of(user);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<UserModel> searchForUser(Map<String, String> params, RealmModel realm) {
|
public Stream<UserModel> searchForUserStream(Map<String, String> params, RealmModel realm) {
|
||||||
// Assume that this is not supported
|
// Assume that this is not supported
|
||||||
return Collections.emptyList();
|
return Stream.empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<UserModel> searchForUser(Map<String, String> params, RealmModel realm, int firstResult, int maxResults) {
|
public Stream<UserModel> searchForUserStream(Map<String, String> params, RealmModel realm, int firstResult, int maxResults) {
|
||||||
// Assume that this is not supported
|
// Assume that this is not supported
|
||||||
return Collections.emptyList();
|
return Stream.empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<UserModel> getGroupMembers(RealmModel realm, GroupModel group, int firstResult, int maxResults) {
|
public Stream<UserModel> getGroupMembersStream(RealmModel realm, GroupModel group, int firstResult, int maxResults) {
|
||||||
// Assume that this is not supported
|
// Assume that this is not supported
|
||||||
return Collections.emptyList();
|
return Stream.empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<UserModel> getGroupMembers(RealmModel realm, GroupModel group) {
|
public Stream<UserModel> getGroupMembersStream(RealmModel realm, GroupModel group) {
|
||||||
// Assume that this is not supported
|
// Assume that this is not supported
|
||||||
return Collections.emptyList();
|
return Stream.empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<UserModel> searchForUserByUserAttribute(String attrName, String attrValue, RealmModel realm) {
|
public Stream<UserModel> searchForUserByUserAttributeStream(String attrName, String attrValue, RealmModel realm) {
|
||||||
// Assume that this is not supported
|
// Assume that this is not supported
|
||||||
return Collections.emptyList();
|
return Stream.empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -21,7 +21,6 @@ import org.keycloak.component.ComponentModel;
|
||||||
import org.keycloak.credential.CredentialInput;
|
import org.keycloak.credential.CredentialInput;
|
||||||
import org.keycloak.credential.CredentialInputUpdater;
|
import org.keycloak.credential.CredentialInputUpdater;
|
||||||
import org.keycloak.credential.CredentialInputValidator;
|
import org.keycloak.credential.CredentialInputValidator;
|
||||||
import org.keycloak.credential.CredentialModel;
|
|
||||||
import org.keycloak.models.GroupModel;
|
import org.keycloak.models.GroupModel;
|
||||||
import org.keycloak.models.KeycloakSession;
|
import org.keycloak.models.KeycloakSession;
|
||||||
import org.keycloak.models.RealmModel;
|
import org.keycloak.models.RealmModel;
|
||||||
|
@ -35,11 +34,10 @@ import org.keycloak.storage.user.UserLookupProvider;
|
||||||
import org.keycloak.storage.user.UserQueryProvider;
|
import org.keycloak.storage.user.UserQueryProvider;
|
||||||
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.LinkedList;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
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>
|
||||||
|
@ -224,79 +222,67 @@ public class FailableHardcodedStorageProvider implements UserStorageProvider, Us
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<UserModel> getUsers(RealmModel realm) {
|
public Stream<UserModel> getUsersStream(RealmModel realm) {
|
||||||
checkForceFail();
|
checkForceFail();
|
||||||
UserModel hardcoded = getUserByUsername(username, realm);
|
UserModel model = getUserByUsername(username, realm);
|
||||||
List<UserModel> list = new LinkedList<>();
|
return model != null ? Stream.of(model) : Stream.empty();
|
||||||
list.add(hardcoded);
|
|
||||||
return list;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<UserModel> getUsers(RealmModel realm, int firstResult, int maxResults) {
|
public Stream<UserModel> getUsersStream(RealmModel realm, int firstResult, int maxResults) {
|
||||||
checkForceFail();
|
checkForceFail();
|
||||||
UserModel hardcoded = getUserByUsername(username, realm);
|
UserModel model = getUserByUsername(username, realm);
|
||||||
List<UserModel> list = new LinkedList<>();
|
return model != null ? Stream.of(model) : Stream.empty();
|
||||||
list.add(hardcoded);
|
|
||||||
return list;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<UserModel> searchForUser(String search, RealmModel realm) {
|
public Stream<UserModel> searchForUserStream(String search, RealmModel realm) {
|
||||||
checkForceFail();
|
checkForceFail();
|
||||||
if (!search.equals(username)) return Collections.EMPTY_LIST;
|
if (!search.equals(username)) return Stream.empty();
|
||||||
UserModel hardcoded = getUserByUsername(username, realm);
|
UserModel model = getUserByUsername(username, realm);
|
||||||
List<UserModel> list = new LinkedList<>();
|
return model != null ? Stream.of(model) : Stream.empty();
|
||||||
list.add(hardcoded);
|
|
||||||
return list;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<UserModel> searchForUser(String search, RealmModel realm, int firstResult, int maxResults) {
|
public Stream<UserModel> searchForUserStream(String search, RealmModel realm, int firstResult, int maxResults) {
|
||||||
checkForceFail();
|
checkForceFail();
|
||||||
if (!search.equals(username)) return Collections.EMPTY_LIST;
|
if (!search.equals(username)) return Stream.empty();
|
||||||
UserModel hardcoded = getUserByUsername(username, realm);
|
UserModel model = getUserByUsername(username, realm);
|
||||||
List<UserModel> list = new LinkedList<>();
|
return model != null ? Stream.of(model) : Stream.empty();
|
||||||
list.add(hardcoded);
|
|
||||||
return list;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<UserModel> searchForUser(Map<String, String> params, RealmModel realm) {
|
public Stream<UserModel> searchForUserStream(Map<String, String> params, RealmModel realm) {
|
||||||
checkForceFail();
|
checkForceFail();
|
||||||
if (!username.equals(params.get("username")))return Collections.EMPTY_LIST;
|
if (!username.equals(params.get("username")))return Stream.empty();
|
||||||
UserModel hardcoded = getUserByUsername(username, realm);
|
UserModel model = getUserByUsername(username, realm);
|
||||||
List<UserModel> list = new LinkedList<>();
|
return model != null ? Stream.of(model) : Stream.empty();
|
||||||
list.add(hardcoded);
|
|
||||||
return list;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<UserModel> searchForUser(Map<String, String> params, RealmModel realm, int firstResult, int maxResults) {
|
public Stream<UserModel> searchForUserStream(Map<String, String> params, RealmModel realm, int firstResult, int maxResults) {
|
||||||
checkForceFail();
|
checkForceFail();
|
||||||
if (!username.equals(params.get("username")))return Collections.EMPTY_LIST;
|
if (!username.equals(params.get("username")))return Stream.empty();
|
||||||
UserModel hardcoded = getUserByUsername(username, realm);
|
UserModel model = getUserByUsername(username, realm);
|
||||||
List<UserModel> list = new LinkedList<>();
|
return model != null ? Stream.of(model) : Stream.empty();
|
||||||
list.add(hardcoded);
|
|
||||||
return list;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<UserModel> getGroupMembers(RealmModel realm, GroupModel group, int firstResult, int maxResults) {
|
public Stream<UserModel> getGroupMembersStream(RealmModel realm, GroupModel group, int firstResult, int maxResults) {
|
||||||
checkForceFail();
|
checkForceFail();
|
||||||
return Collections.EMPTY_LIST;
|
return Stream.empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<UserModel> getGroupMembers(RealmModel realm, GroupModel group) {
|
public Stream<UserModel> getGroupMembersStream(RealmModel realm, GroupModel group) {
|
||||||
checkForceFail();
|
checkForceFail();
|
||||||
return Collections.EMPTY_LIST;
|
return Stream.empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<UserModel> searchForUserByUserAttribute(String attrName, String attrValue, RealmModel realm) {
|
public Stream<UserModel> searchForUserByUserAttributeStream(String attrName, String attrValue, RealmModel realm) {
|
||||||
checkForceFail();
|
checkForceFail();
|
||||||
return Collections.EMPTY_LIST;
|
return Stream.empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -40,14 +40,12 @@ import org.keycloak.storage.user.UserQueryProvider;
|
||||||
import org.keycloak.storage.user.UserRegistrationProvider;
|
import org.keycloak.storage.user.UserRegistrationProvider;
|
||||||
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.concurrent.ConcurrentMap;
|
import java.util.concurrent.ConcurrentMap;
|
||||||
import java.util.concurrent.ConcurrentSkipListSet;
|
import java.util.concurrent.ConcurrentSkipListSet;
|
||||||
import java.util.concurrent.atomic.AtomicInteger;
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
import java.util.stream.Collectors;
|
|
||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
import org.jboss.logging.Logger;
|
import org.jboss.logging.Logger;
|
||||||
import static org.keycloak.storage.UserStorageProviderModel.IMPORT_ENABLED;
|
import static org.keycloak.storage.UserStorageProviderModel.IMPORT_ENABLED;
|
||||||
|
@ -293,49 +291,48 @@ public class UserMapStorage implements UserLookupProvider, UserStorageProvider,
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<UserModel> getUsers(RealmModel realm) {
|
public Stream<UserModel> getUsersStream(RealmModel realm) {
|
||||||
return userPasswords.keySet().stream()
|
return userPasswords.keySet().stream()
|
||||||
.map(userName -> createUser(realm, userName))
|
.map(userName -> createUser(realm, userName));
|
||||||
.collect(Collectors.toList());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<UserModel> getUsers(RealmModel realm, int firstResult, int maxResults) {
|
public Stream<UserModel> getUsersStream(RealmModel realm, int firstResult, int maxResults) {
|
||||||
return userPasswords.keySet().stream()
|
Stream<String> userStream = userPasswords.keySet().stream().sorted();
|
||||||
.sorted()
|
if (firstResult > 0)
|
||||||
.skip(firstResult)
|
userStream = userStream.skip(firstResult);
|
||||||
.limit(maxResults)
|
if (maxResults >= 0)
|
||||||
.map(userName -> createUser(realm, userName))
|
userStream = userStream.limit(maxResults);
|
||||||
.collect(Collectors.toList());
|
return userStream.map(userName -> createUser(realm, userName));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<UserModel> searchForUser(String search, RealmModel realm) {
|
public Stream<UserModel> searchForUserStream(String search, RealmModel realm) {
|
||||||
return userPasswords.keySet().stream()
|
return userPasswords.keySet().stream()
|
||||||
.sorted()
|
.sorted()
|
||||||
.filter(userName -> userName.contains(search))
|
.filter(userName -> userName.contains(search))
|
||||||
.map(userName -> createUser(realm, userName))
|
.map(userName -> createUser(realm, userName));
|
||||||
.collect(Collectors.toList());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<UserModel> searchForUser(String search, RealmModel realm, int firstResult, int maxResults) {
|
public Stream<UserModel> searchForUserStream(String search, RealmModel realm, int firstResult, int maxResults) {
|
||||||
return userPasswords.keySet().stream()
|
Stream<String> userStream = userPasswords.keySet().stream()
|
||||||
.sorted()
|
.sorted()
|
||||||
.filter(userName -> userName.contains(search))
|
.filter(userName -> userName.contains(search));
|
||||||
.skip(firstResult)
|
if (firstResult > 0)
|
||||||
.limit(maxResults)
|
userStream = userStream.skip(firstResult);
|
||||||
.map(userName -> createUser(realm, userName))
|
if (maxResults >= 0)
|
||||||
.collect(Collectors.toList());
|
userStream = userStream.limit(maxResults);
|
||||||
|
return userStream.map(userName -> createUser(realm, userName));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<UserModel> searchForUser(Map<String, String> params, RealmModel realm) {
|
public Stream<UserModel> searchForUserStream(Map<String, String> params, RealmModel realm) {
|
||||||
return searchForUser(params, realm, 0, Integer.MAX_VALUE - 1);
|
return searchForUserStream(params, realm, 0, Integer.MAX_VALUE - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<UserModel> searchForUser(Map<String, String> params, RealmModel realm, int firstResult, int maxResults) {
|
public Stream<UserModel> searchForUserStream(Map<String, String> params, RealmModel realm, int firstResult, int maxResults) {
|
||||||
Stream<String> userStream = userPasswords.keySet().stream()
|
Stream<String> userStream = userPasswords.keySet().stream()
|
||||||
.sorted();
|
.sorted();
|
||||||
|
|
||||||
|
@ -358,33 +355,31 @@ public class UserMapStorage implements UserLookupProvider, UserStorageProvider,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return userStream
|
if (firstResult > 0)
|
||||||
.skip(firstResult)
|
userStream = userStream.skip(firstResult);
|
||||||
.limit(maxResults)
|
if (maxResults >= 0)
|
||||||
.map(userName -> createUser(realm, userName))
|
userStream = userStream.limit(maxResults);
|
||||||
.collect(Collectors.toList());
|
return userStream.map(userName -> createUser(realm, userName));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<UserModel> getGroupMembers(RealmModel realm, GroupModel group, int firstResult, int maxResults) {
|
public Stream<UserModel> getGroupMembersStream(RealmModel realm, GroupModel group, int firstResult, int maxResults) {
|
||||||
return getMembership(realm, group, firstResult, maxResults).stream()
|
return getMembershipStream(realm, group, firstResult, maxResults)
|
||||||
.map(userName -> createUser(realm, userName))
|
.map(userName -> createUser(realm, userName));
|
||||||
.collect(Collectors.toList());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<UserModel> getGroupMembers(RealmModel realm, GroupModel group) {
|
public Stream<UserModel> getGroupMembersStream(RealmModel realm, GroupModel group) {
|
||||||
return getGroupMembers(realm, group, 0, Integer.MAX_VALUE - 1);
|
return getGroupMembersStream(realm, group, 0, Integer.MAX_VALUE - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<UserModel> searchForUserByUserAttribute(String attrName, String attrValue, RealmModel realm) {
|
public Stream<UserModel> searchForUserByUserAttributeStream(String attrName, String attrValue, RealmModel realm) {
|
||||||
if (isImportEnabled()) {
|
if (isImportEnabled()) {
|
||||||
return session.userLocalStorage().searchForUserByUserAttribute(attrName, attrValue, realm);
|
return session.userLocalStorage().searchForUserByUserAttributeStream(attrName, attrValue, realm);
|
||||||
} else {
|
} else {
|
||||||
return session.userFederatedStorage().getUsersByUserAttribute(realm, attrName, attrValue).stream()
|
return session.userFederatedStorage().getUsersByUserAttributeStream(realm, attrName, attrValue)
|
||||||
.map(userName -> createUser(realm, userName))
|
.map(userName -> createUser(realm, userName));
|
||||||
.collect(Collectors.toList());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -412,15 +407,17 @@ public class UserMapStorage implements UserLookupProvider, UserStorageProvider,
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<String> getMembership(RealmModel realm, GroupModel group, int firstResult, int max) {
|
public Stream<String> getMembershipStream(RealmModel realm, GroupModel group, int firstResult, int max) {
|
||||||
return userGroups.entrySet().stream()
|
Stream<String> userStream = userGroups.entrySet().stream()
|
||||||
.filter(me -> me.getValue().contains(group.getId()))
|
.filter(me -> me.getValue().contains(group.getId()))
|
||||||
.map(Map.Entry::getKey)
|
.map(Map.Entry::getKey)
|
||||||
.filter(realmUser -> realmUser.startsWith(realm.getId()))
|
.filter(realmUser -> realmUser.startsWith(realm.getId()))
|
||||||
.map(realmUser -> realmUser.substring(realmUser.indexOf("/") + 1))
|
.map(realmUser -> realmUser.substring(realmUser.indexOf("/") + 1));
|
||||||
.skip(firstResult)
|
if (firstResult > 0)
|
||||||
.limit(max)
|
userStream = userStream.skip(firstResult);
|
||||||
.collect(Collectors.toList());
|
if (max >= 0)
|
||||||
|
userStream = userStream.limit(max);
|
||||||
|
return userStream;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -33,13 +33,11 @@ import org.keycloak.storage.adapter.AbstractUserAdapterFederatedStorage;
|
||||||
import org.keycloak.storage.user.UserLookupProvider;
|
import org.keycloak.storage.user.UserLookupProvider;
|
||||||
import org.keycloak.storage.user.UserQueryProvider;
|
import org.keycloak.storage.user.UserQueryProvider;
|
||||||
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.LinkedList;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
import java.util.function.Predicate;
|
import java.util.function.Predicate;
|
||||||
|
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>
|
||||||
|
@ -146,67 +144,59 @@ public class UserPropertyFileStorage implements UserLookupProvider, UserStorageP
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<UserModel> getUsers(RealmModel realm) {
|
public Stream<UserModel> getUsersStream(RealmModel realm) {
|
||||||
List<UserModel> users = new LinkedList<>();
|
return userPasswords.keySet().stream().map(obj -> createUser(realm, (String) obj));
|
||||||
for (Object username : userPasswords.keySet()) {
|
|
||||||
users.add(createUser(realm, (String)username));
|
|
||||||
}
|
|
||||||
return users;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<UserModel> searchForUser(Map<String, String> attributes, RealmModel realm) {
|
public Stream<UserModel> searchForUserStream(Map<String, String> attributes, RealmModel realm) {
|
||||||
return searchForUser(attributes, realm, 0, Integer.MAX_VALUE - 1);
|
return searchForUserStream(attributes, realm, 0, Integer.MAX_VALUE - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<UserModel> getUsers(RealmModel realm, int firstResult, int maxResults) {
|
public Stream<UserModel> getUsersStream(RealmModel realm, int firstResult, int maxResults) {
|
||||||
if (maxResults == 0) return Collections.EMPTY_LIST;
|
Stream<Object> stream = userPasswords.keySet().stream();
|
||||||
List<UserModel> users = new LinkedList<>();
|
if (firstResult > 0)
|
||||||
int count = 0;
|
stream = stream.skip(firstResult);
|
||||||
for (Object un : userPasswords.keySet()) {
|
if (maxResults >= 0)
|
||||||
if (count++ < firstResult) continue;
|
stream = stream.limit(maxResults);
|
||||||
String username = (String)un;
|
return stream.map(obj -> createUser(realm, (String) obj));
|
||||||
users.add(createUser(realm, username));
|
|
||||||
if (users.size() + 1 > maxResults) break;
|
|
||||||
}
|
|
||||||
return users;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<UserModel> searchForUser(String search, RealmModel realm, int firstResult, int maxResults) {
|
public Stream<UserModel> searchForUserStream(String search, RealmModel realm, int firstResult, int maxResults) {
|
||||||
return searchForUser(search, realm, firstResult, maxResults, username -> username.contains(search));
|
return searchForUserStream(search, realm, firstResult, maxResults, username -> username.contains(search));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<UserModel> searchForUser(Map<String, String> attributes, RealmModel realm, int firstResult, int maxResults) {
|
public Stream<UserModel> searchForUserStream(Map<String, String> attributes, RealmModel realm, int firstResult, int maxResults) {
|
||||||
String search = Optional.ofNullable(attributes.get(UserModel.USERNAME))
|
String search = Optional.ofNullable(attributes.get(UserModel.USERNAME))
|
||||||
.orElseGet(()-> attributes.get(UserModel.SEARCH));
|
.orElseGet(()-> attributes.get(UserModel.SEARCH));
|
||||||
if (search == null) return Collections.EMPTY_LIST;
|
if (search == null) return Stream.empty();
|
||||||
Predicate<String> p = Boolean.valueOf(attributes.getOrDefault(UserModel.EXACT, Boolean.FALSE.toString()))
|
Predicate<String> p = Boolean.valueOf(attributes.getOrDefault(UserModel.EXACT, Boolean.FALSE.toString()))
|
||||||
? username -> username.equals(search)
|
? username -> username.equals(search)
|
||||||
: username -> username.contains(search);
|
: username -> username.contains(search);
|
||||||
return searchForUser(search, realm, firstResult, maxResults, p);
|
return searchForUserStream(search, realm, firstResult, maxResults, p);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<UserModel> getGroupMembers(RealmModel realm, GroupModel group, int firstResult, int maxResults) {
|
public Stream<UserModel> getGroupMembersStream(RealmModel realm, GroupModel group, int firstResult, int maxResults) {
|
||||||
return Collections.EMPTY_LIST;
|
return Stream.empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<UserModel> getGroupMembers(RealmModel realm, GroupModel group) {
|
public Stream<UserModel> getGroupMembersStream(RealmModel realm, GroupModel group) {
|
||||||
return Collections.EMPTY_LIST;
|
return Stream.empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<UserModel> searchForUser(String search, RealmModel realm) {
|
public Stream<UserModel> searchForUserStream(String search, RealmModel realm) {
|
||||||
return searchForUser(search, realm, 0, Integer.MAX_VALUE - 1);
|
return searchForUserStream(search, realm, 0, Integer.MAX_VALUE - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<UserModel> searchForUserByUserAttribute(String attrName, String attrValue, RealmModel realm) {
|
public Stream<UserModel> searchForUserByUserAttributeStream(String attrName, String attrValue, RealmModel realm) {
|
||||||
return Collections.EMPTY_LIST;
|
return Stream.empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -214,20 +204,8 @@ public class UserPropertyFileStorage implements UserLookupProvider, UserStorageP
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<UserModel> searchForUser(String search, RealmModel realm, int firstResult, int maxResults, Predicate<String> matcher) {
|
private Stream<UserModel> searchForUserStream(String search, RealmModel realm, int firstResult, int maxResults, Predicate<String> matcher) {
|
||||||
if (maxResults == 0) return Collections.EMPTY_LIST;
|
return userPasswords.keySet().stream().filter(obj -> matcher.test((String) obj)).skip(firstResult < 0 ? 0 : firstResult)
|
||||||
List<UserModel> users = new LinkedList<>();
|
.limit(maxResults < 0 ? 0 : maxResults).map(obj -> createUser(realm, (String) obj));
|
||||||
int count = 0;
|
|
||||||
for (Object un : userPasswords.keySet()) {
|
|
||||||
String username = (String)un;
|
|
||||||
if (matcher.test(username)) {
|
|
||||||
if (count++ < firstResult) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
users.add(createUser(realm, username));
|
|
||||||
if (users.size() + 1 > maxResults) break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return users;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -44,7 +44,13 @@ import org.keycloak.storage.ldap.mappers.membership.role.RoleLDAPStorageMapper;
|
||||||
import org.keycloak.storage.ldap.mappers.membership.role.RoleLDAPStorageMapperFactory;
|
import org.keycloak.storage.ldap.mappers.membership.role.RoleLDAPStorageMapperFactory;
|
||||||
import org.keycloak.storage.ldap.mappers.membership.role.RoleMapperConfig;
|
import org.keycloak.storage.ldap.mappers.membership.role.RoleMapperConfig;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.Collections;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
||||||
|
@ -101,21 +107,21 @@ public class LDAPTestUtils {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<String> getAttribute(String name) {
|
public Stream<String> getAttributeStream(String name) {
|
||||||
if (UserModel.LAST_NAME.equals(name)) {
|
if (UserModel.LAST_NAME.equals(name)) {
|
||||||
return Collections.singletonList(lastName);
|
return Stream.of(lastName);
|
||||||
} else if (UserModel.FIRST_NAME.equals(name)) {
|
} else if (UserModel.FIRST_NAME.equals(name)) {
|
||||||
return Collections.singletonList(firstName);
|
return Stream.of(firstName);
|
||||||
} else if (UserModel.EMAIL.equals(name)) {
|
} else if (UserModel.EMAIL.equals(name)) {
|
||||||
return Collections.singletonList(email);
|
return Stream.of(email);
|
||||||
} else if (UserModel.USERNAME.equals(name)) {
|
} else if (UserModel.USERNAME.equals(name)) {
|
||||||
return Collections.singletonList(username);
|
return Stream.of(username);
|
||||||
} else if ("postal_code".equals(name) && postalCode != null && postalCode.length > 0) {
|
} else if ("postal_code".equals(name) && postalCode != null && postalCode.length > 0) {
|
||||||
return Arrays.asList(postalCode);
|
return Stream.of(postalCode);
|
||||||
} else if ("street".equals(name) && street != null) {
|
} else if ("street".equals(name) && street != null) {
|
||||||
return Collections.singletonList(street);
|
return Stream.of(street);
|
||||||
} else {
|
} else {
|
||||||
return Collections.emptyList();
|
return Stream.empty();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -45,6 +45,7 @@ import javax.ws.rs.core.Response;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
||||||
|
@ -227,19 +228,19 @@ public class LDAPBinaryAttributesTest extends AbstractLDAPTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<String> getAttribute(String name) {
|
public Stream<String> getAttributeStream(String name) {
|
||||||
if (UserModel.LAST_NAME.equals(name)) {
|
if (UserModel.LAST_NAME.equals(name)) {
|
||||||
return Collections.singletonList(lastName);
|
return Stream.of(lastName);
|
||||||
} else if (UserModel.FIRST_NAME.equals(name)) {
|
} else if (UserModel.FIRST_NAME.equals(name)) {
|
||||||
return Collections.singletonList(firstName);
|
return Stream.of(firstName);
|
||||||
} else if (UserModel.EMAIL.equals(name)) {
|
} else if (UserModel.EMAIL.equals(name)) {
|
||||||
return Collections.singletonList(email);
|
return Stream.of(email);
|
||||||
} else if (UserModel.USERNAME.equals(name)) {
|
} else if (UserModel.USERNAME.equals(name)) {
|
||||||
return Collections.singletonList(username);
|
return Stream.of(username);
|
||||||
} else if (LDAPConstants.JPEG_PHOTO.equals(name)) {
|
} else if (LDAPConstants.JPEG_PHOTO.equals(name)) {
|
||||||
return Arrays.asList(jpegPhoto);
|
return Stream.of(jpegPhoto);
|
||||||
} else {
|
} else {
|
||||||
return Collections.emptyList();
|
return Stream.empty();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -17,8 +17,15 @@
|
||||||
|
|
||||||
package org.keycloak.testsuite.util.cli;
|
package org.keycloak.testsuite.util.cli;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.HashMap;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.Set;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
import org.keycloak.component.ComponentModel;
|
import org.keycloak.component.ComponentModel;
|
||||||
import org.keycloak.models.KeycloakSession;
|
import org.keycloak.models.KeycloakSession;
|
||||||
|
@ -166,28 +173,26 @@ public class LdapManyObjectsInitializerCommand extends AbstractCommand {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<String> getAttribute(String name) {
|
public Stream<String> getAttributeStream(String name) {
|
||||||
if (UserModel.FIRST_NAME.equals(name)) {
|
if (UserModel.FIRST_NAME.equals(name)) {
|
||||||
return Collections.singletonList(firstName);
|
return Stream.of(firstName);
|
||||||
} else if (UserModel.LAST_NAME.equals(name)) {
|
} else if (UserModel.LAST_NAME.equals(name)) {
|
||||||
return Collections.singletonList(lastName);
|
return Stream.of(lastName);
|
||||||
} else if (UserModel.EMAIL.equals(name)) {
|
} else if (UserModel.EMAIL.equals(name)) {
|
||||||
return Collections.singletonList(email);
|
return Stream.of(email);
|
||||||
} else if (UserModel.USERNAME.equals(name)) {
|
} else if (UserModel.USERNAME.equals(name)) {
|
||||||
return Collections.singletonList(username);
|
return Stream.of(username);
|
||||||
} else if ("street".equals(name)) {
|
} else if ("street".equals(name)) {
|
||||||
|
Stream.Builder<String> builder = Stream.builder();
|
||||||
List<String> groupNamesList = new ArrayList<>();
|
for (int i = startOffsetGroups; i < startOffsetGroups + countGroups; i++) {
|
||||||
for (int i=startOffsetGroups ; i<startOffsetGroups + countGroups ; i++) {
|
|
||||||
String groupName = "group" + i;
|
String groupName = "group" + i;
|
||||||
LDAPDn groupDn = LDAPDn.fromString(groupsDN);
|
LDAPDn groupDn = LDAPDn.fromString(groupsDN);
|
||||||
groupDn.addFirst("cn", groupName);
|
groupDn.addFirst("cn", groupName);
|
||||||
groupNamesList.add(groupDn.toString());
|
builder.add(groupDn.toString());
|
||||||
}
|
}
|
||||||
return groupNamesList;
|
return builder.build();
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
return Collections.emptyList();
|
return Stream.empty();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in a new issue