diff --git a/federation/ldap/src/main/java/org/keycloak/federation/ldap/LDAPConfig.java b/federation/ldap/src/main/java/org/keycloak/federation/ldap/LDAPConfig.java index 3317b9d1d012..18c2d8fc3d3f 100644 --- a/federation/ldap/src/main/java/org/keycloak/federation/ldap/LDAPConfig.java +++ b/federation/ldap/src/main/java/org/keycloak/federation/ldap/LDAPConfig.java @@ -14,7 +14,6 @@ /** * @author Marek Posolda * - * TODO: init properties at constructor instead of always compute them */ public class LDAPConfig { @@ -147,6 +146,18 @@ public String getRdnLdapAttribute() { return rdn; } + + public String getCustomUserSearchFilter() { + String customFilter = config.get(LDAPConstants.CUSTOM_USER_SEARCH_FILTER); + if (customFilter != null) { + customFilter = customFilter.trim(); + if (customFilter.length() > 0) { + return customFilter; + } + } + return null; + } + public UserFederationProvider.EditMode getEditMode() { String editModeString = config.get(LDAPConstants.EDIT_MODE); if (editModeString == null) { diff --git a/federation/ldap/src/main/java/org/keycloak/federation/ldap/LDAPFederationProvider.java b/federation/ldap/src/main/java/org/keycloak/federation/ldap/LDAPFederationProvider.java index 3704f7626fa8..f9f6600390eb 100755 --- a/federation/ldap/src/main/java/org/keycloak/federation/ldap/LDAPFederationProvider.java +++ b/federation/ldap/src/main/java/org/keycloak/federation/ldap/LDAPFederationProvider.java @@ -5,7 +5,6 @@ import org.keycloak.federation.kerberos.impl.SPNEGOAuthenticator; import org.keycloak.federation.ldap.idm.model.LDAPObject; import org.keycloak.federation.ldap.idm.query.Condition; -import org.keycloak.federation.ldap.idm.query.QueryParameter; import org.keycloak.federation.ldap.idm.query.internal.LDAPQuery; import org.keycloak.federation.ldap.idm.query.internal.LDAPQueryConditionsBuilder; import org.keycloak.federation.ldap.idm.store.ldap.LDAPIdentityStore; @@ -209,10 +208,10 @@ protected List searchLDAP(RealmModel realm, Map attr // Mapper should replace parameter with correct LDAP mapped attributes if (attributes.containsKey(FIRST_NAME)) { - ldapQuery.where(conditionsBuilder.equal(new QueryParameter(FIRST_NAME), attributes.get(FIRST_NAME))); + ldapQuery.addWhereCondition(conditionsBuilder.equal(FIRST_NAME, attributes.get(FIRST_NAME))); } if (attributes.containsKey(LAST_NAME)) { - ldapQuery.where(conditionsBuilder.equal(new QueryParameter(LAST_NAME), attributes.get(LAST_NAME))); + ldapQuery.addWhereCondition(conditionsBuilder.equal(LAST_NAME, attributes.get(LAST_NAME))); } List ldapObjects = ldapQuery.getResultList(); @@ -287,8 +286,8 @@ protected LDAPObject queryByEmail(RealmModel realm, String email) { LDAPQueryConditionsBuilder conditionsBuilder = new LDAPQueryConditionsBuilder(); // Mapper should replace "email" in parameter name with correct LDAP mapped attribute - Condition emailCondition = conditionsBuilder.equal(new QueryParameter(UserModel.EMAIL), email); - ldapQuery.where(emailCondition); + Condition emailCondition = conditionsBuilder.equal(UserModel.EMAIL, email); + ldapQuery.addWhereCondition(emailCondition); return ldapQuery.getFirstResult(); } @@ -434,8 +433,8 @@ public LDAPObject loadLDAPUserByUsername(RealmModel realm, String username) { LDAPQueryConditionsBuilder conditionsBuilder = new LDAPQueryConditionsBuilder(); String usernameMappedAttribute = this.ldapIdentityStore.getConfig().getUsernameLdapAttribute(); - Condition usernameCondition = conditionsBuilder.equal(new QueryParameter(usernameMappedAttribute), username); - ldapQuery.where(usernameCondition); + Condition usernameCondition = conditionsBuilder.equal(usernameMappedAttribute, username); + ldapQuery.addWhereCondition(usernameCondition); LDAPObject ldapUser = ldapQuery.getFirstResult(); if (ldapUser == null) { diff --git a/federation/ldap/src/main/java/org/keycloak/federation/ldap/LDAPFederationProviderFactory.java b/federation/ldap/src/main/java/org/keycloak/federation/ldap/LDAPFederationProviderFactory.java index 915e5bbf7388..31ff560475f1 100755 --- a/federation/ldap/src/main/java/org/keycloak/federation/ldap/LDAPFederationProviderFactory.java +++ b/federation/ldap/src/main/java/org/keycloak/federation/ldap/LDAPFederationProviderFactory.java @@ -8,7 +8,6 @@ import org.keycloak.federation.kerberos.impl.SPNEGOAuthenticator; import org.keycloak.federation.ldap.idm.model.LDAPObject; import org.keycloak.federation.ldap.idm.query.Condition; -import org.keycloak.federation.ldap.idm.query.QueryParameter; import org.keycloak.federation.ldap.idm.query.internal.LDAPQuery; import org.keycloak.federation.ldap.idm.query.internal.LDAPQueryConditionsBuilder; import org.keycloak.federation.ldap.idm.store.ldap.LDAPIdentityStore; @@ -21,7 +20,6 @@ import org.keycloak.models.KeycloakSessionFactory; import org.keycloak.models.KeycloakSessionTask; import org.keycloak.models.LDAPConstants; -import org.keycloak.models.ModelDuplicateException; import org.keycloak.models.ModelException; import org.keycloak.models.RealmModel; import org.keycloak.models.UserFederationEventAwareProviderFactory; @@ -211,12 +209,12 @@ public UserFederationSyncResult syncChangedUsers(KeycloakSessionFactory sessionF // Sync newly created and updated users LDAPQueryConditionsBuilder conditionsBuilder = new LDAPQueryConditionsBuilder(); - Condition createCondition = conditionsBuilder.greaterThanOrEqualTo(new QueryParameter(LDAPConstants.CREATE_TIMESTAMP), lastSync); - Condition modifyCondition = conditionsBuilder.greaterThanOrEqualTo(new QueryParameter(LDAPConstants.MODIFY_TIMESTAMP), lastSync); + Condition createCondition = conditionsBuilder.greaterThanOrEqualTo(LDAPConstants.CREATE_TIMESTAMP, lastSync); + Condition modifyCondition = conditionsBuilder.greaterThanOrEqualTo(LDAPConstants.MODIFY_TIMESTAMP, lastSync); Condition orCondition = conditionsBuilder.orCondition(createCondition, modifyCondition); LDAPQuery userQuery = createQuery(sessionFactory, realmId, model); - userQuery.where(orCondition); + userQuery.addWhereCondition(orCondition); UserFederationSyncResult result = syncImpl(sessionFactory, userQuery, realmId, model); logger.infof("Sync changed users finished: %s", result.getStatus()); diff --git a/federation/ldap/src/main/java/org/keycloak/federation/ldap/LDAPUtils.java b/federation/ldap/src/main/java/org/keycloak/federation/ldap/LDAPUtils.java index 91f0000c6aab..7594ed45bb98 100755 --- a/federation/ldap/src/main/java/org/keycloak/federation/ldap/LDAPUtils.java +++ b/federation/ldap/src/main/java/org/keycloak/federation/ldap/LDAPUtils.java @@ -4,7 +4,9 @@ import org.keycloak.federation.ldap.idm.model.LDAPDn; import org.keycloak.federation.ldap.idm.model.LDAPObject; +import org.keycloak.federation.ldap.idm.query.Condition; import org.keycloak.federation.ldap.idm.query.internal.LDAPQuery; +import org.keycloak.federation.ldap.idm.query.internal.LDAPQueryConditionsBuilder; import org.keycloak.federation.ldap.idm.store.ldap.LDAPIdentityStore; import org.keycloak.federation.ldap.mappers.LDAPFederationMapper; import org.keycloak.models.ModelException; @@ -51,6 +53,12 @@ public static LDAPQuery createQueryForUserSearch(LDAPFederationProvider ldapProv ldapQuery.setSearchDn(config.getUsersDn()); ldapQuery.addObjectClasses(config.getUserObjectClasses()); + String customFilter = config.getCustomUserSearchFilter(); + if (customFilter != null) { + Condition customFilterCondition = new LDAPQueryConditionsBuilder().addCustomLDAPFilter(customFilter); + ldapQuery.addWhereCondition(customFilterCondition); + } + Set mapperModels = realm.getUserFederationMappersByFederationProvider(ldapProvider.getModel().getId()); ldapQuery.addMappers(mapperModels); diff --git a/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/query/Condition.java b/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/query/Condition.java index 85d81d8915c6..6e5789021b3d 100644 --- a/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/query/Condition.java +++ b/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/query/Condition.java @@ -8,11 +8,9 @@ */ public interface Condition { - /** - *

The {@link QueryParameter} restricted by this condition.

- * - * @return - */ - QueryParameter getParameter(); + String getParameterName(); + void setParameterName(String parameterName); + + void applyCondition(StringBuilder filter); } \ No newline at end of file diff --git a/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/query/QueryParameter.java b/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/query/QueryParameter.java deleted file mode 100644 index bfc58f744ca4..000000000000 --- a/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/query/QueryParameter.java +++ /dev/null @@ -1,25 +0,0 @@ -package org.keycloak.federation.ldap.idm.query; - -/** - * A marker interface indicating that the implementing class can be used as a - * parameter within an IdentityQuery or RelationshipQuery - * - * @author Shane Bryzak - * - */ -public class QueryParameter { - - private String name; - - public QueryParameter(String name) { - this.name = name; - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } -} diff --git a/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/query/Sort.java b/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/query/Sort.java index dfd331ed59aa..2716cbae801d 100644 --- a/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/query/Sort.java +++ b/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/query/Sort.java @@ -5,16 +5,16 @@ */ public class Sort { - private final QueryParameter parameter; + private final String paramName; private final boolean asc; - public Sort(QueryParameter parameter, boolean asc) { - this.parameter = parameter; + public Sort(String paramName, boolean asc) { + this.paramName = paramName; this.asc = asc; } - public QueryParameter getParameter() { - return this.parameter; + public String getParameter() { + return this.paramName; } public boolean isAscending() { diff --git a/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/query/internal/BetweenCondition.java b/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/query/internal/BetweenCondition.java index 672fdaa72bed..f8f9084d157f 100644 --- a/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/query/internal/BetweenCondition.java +++ b/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/query/internal/BetweenCondition.java @@ -1,33 +1,36 @@ package org.keycloak.federation.ldap.idm.query.internal; -import org.keycloak.federation.ldap.idm.query.Condition; -import org.keycloak.federation.ldap.idm.query.QueryParameter; +import java.util.Date; + +import org.keycloak.federation.ldap.idm.store.ldap.LDAPUtil; /** * @author Pedro Igor */ -public class BetweenCondition implements Condition { +class BetweenCondition extends NamedParameterCondition { private final Comparable x; private final Comparable y; - private final QueryParameter parameter; - public BetweenCondition(QueryParameter parameter, Comparable x, Comparable y) { - this.parameter = parameter; + public BetweenCondition(String name, Comparable x, Comparable y) { + super(name); this.x = x; this.y = y; } @Override - public QueryParameter getParameter() { - return this.parameter; - } + public void applyCondition(StringBuilder filter) { + Comparable x = this.x; + Comparable y = this.y; - public Comparable getX() { - return this.x; - } + if (Date.class.isInstance(x)) { + x = LDAPUtil.formatDate((Date) x); + } + + if (Date.class.isInstance(y)) { + y = LDAPUtil.formatDate((Date) y); + } - public Comparable getY() { - return this.y; + filter.append("(").append(x).append("<=").append(getParameterName()).append("<=").append(y).append(")"); } } diff --git a/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/query/internal/CustomLDAPFilter.java b/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/query/internal/CustomLDAPFilter.java new file mode 100644 index 000000000000..17caa3c04453 --- /dev/null +++ b/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/query/internal/CustomLDAPFilter.java @@ -0,0 +1,29 @@ +package org.keycloak.federation.ldap.idm.query.internal; + +import org.keycloak.federation.ldap.idm.query.Condition; + +/** + * @author Marek Posolda + */ +class CustomLDAPFilter implements Condition { + + private final String customFilter; + + public CustomLDAPFilter(String customFilter) { + this.customFilter = customFilter; + } + + @Override + public String getParameterName() { + return null; + } + + @Override + public void setParameterName(String parameterName) { + } + + @Override + public void applyCondition(StringBuilder filter) { + filter.append(customFilter); + } +} diff --git a/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/query/internal/EqualCondition.java b/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/query/internal/EqualCondition.java index 9f6e6e754177..5387476caa5a 100644 --- a/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/query/internal/EqualCondition.java +++ b/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/query/internal/EqualCondition.java @@ -1,34 +1,40 @@ package org.keycloak.federation.ldap.idm.query.internal; -import org.keycloak.federation.ldap.idm.query.Condition; -import org.keycloak.federation.ldap.idm.query.QueryParameter; +import java.util.Date; + +import org.keycloak.federation.ldap.idm.store.ldap.LDAPUtil; +import org.keycloak.models.LDAPConstants; /** * @author Pedro Igor */ -public class EqualCondition implements Condition { +public class EqualCondition extends NamedParameterCondition { - private final QueryParameter parameter; private final Object value; - public EqualCondition(QueryParameter parameter, Object value) { - this.parameter = parameter; + public EqualCondition(String name, Object value) { + super(name); this.value = value; } - @Override - public QueryParameter getParameter() { - return this.parameter; - } - public Object getValue() { return this.value; } + @Override + public void applyCondition(StringBuilder filter) { + Object parameterValue = value; + if (Date.class.isInstance(value)) { + parameterValue = LDAPUtil.formatDate((Date) parameterValue); + } + + filter.append("(").append(getParameterName()).append(LDAPConstants.EQUAL).append(parameterValue).append(")"); + } + @Override public String toString() { return "EqualCondition{" + - "parameter=" + parameter.getName() + + "paramName=" + getParameterName() + ", value=" + value + '}'; } diff --git a/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/query/internal/GreaterThanCondition.java b/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/query/internal/GreaterThanCondition.java index cbdf5407b687..4be2f83a8549 100644 --- a/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/query/internal/GreaterThanCondition.java +++ b/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/query/internal/GreaterThanCondition.java @@ -1,34 +1,37 @@ package org.keycloak.federation.ldap.idm.query.internal; +import java.util.Date; + import org.keycloak.federation.ldap.idm.query.Condition; -import org.keycloak.federation.ldap.idm.query.QueryParameter; +import org.keycloak.federation.ldap.idm.store.ldap.LDAPUtil; /** * @author Pedro Igor */ -public class GreaterThanCondition implements Condition { +class GreaterThanCondition extends NamedParameterCondition { private final boolean orEqual; - private final QueryParameter parameter; private final Comparable value; - public GreaterThanCondition(QueryParameter parameter, Comparable value, boolean orEqual) { - this.parameter = parameter; + public GreaterThanCondition(String name, Comparable value, boolean orEqual) { + super(name); this.value = value; this.orEqual = orEqual; } @Override - public QueryParameter getParameter() { - return this.parameter; - } - - public Comparable getValue() { - return this.value; - } - - public boolean isOrEqual() { - return this.orEqual; + public void applyCondition(StringBuilder filter) { + Comparable parameterValue = value; + + if (Date.class.isInstance(parameterValue)) { + parameterValue = LDAPUtil.formatDate((Date) parameterValue); + } + + if (orEqual) { + filter.append("(").append(getParameterName()).append(">=").append(parameterValue).append(")"); + } else { + filter.append("(").append(getParameterName()).append(">").append(parameterValue).append(")"); + } } } \ No newline at end of file diff --git a/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/query/internal/InCondition.java b/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/query/internal/InCondition.java index 54d22342a987..5bf21d86f115 100644 --- a/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/query/internal/InCondition.java +++ b/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/query/internal/InCondition.java @@ -1,28 +1,31 @@ package org.keycloak.federation.ldap.idm.query.internal; -import org.keycloak.federation.ldap.idm.query.Condition; -import org.keycloak.federation.ldap.idm.query.QueryParameter; +import org.keycloak.models.LDAPConstants; /** * @author Pedro Igor */ -public class InCondition implements Condition { +class InCondition extends NamedParameterCondition { - private final QueryParameter parameter; - private final Object[] value; + private final Object[] valuesToCompare; - public InCondition(QueryParameter parameter, Object[] value) { - this.parameter = parameter; - this.value = value; + public InCondition(String name, Object[] valuesToCompare) { + super(name); + this.valuesToCompare = valuesToCompare; } @Override - public QueryParameter getParameter() { - return this.parameter; - } + public void applyCondition(StringBuilder filter) { + + filter.append("(&("); + + for (int i = 0; i< valuesToCompare.length; i++) { + Object value = valuesToCompare[i]; + + filter.append("(").append(getParameterName()).append(LDAPConstants.EQUAL).append(value).append(")"); + } - public Object[] getValue() { - return this.value; + filter.append("))"); } } diff --git a/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/query/internal/LDAPQuery.java b/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/query/internal/LDAPQuery.java index be4ddcd59ce5..6939697db282 100644 --- a/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/query/internal/LDAPQuery.java +++ b/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/query/internal/LDAPQuery.java @@ -47,14 +47,12 @@ public class LDAPQuery { private final List mappers = new ArrayList(); private int searchScope = SearchControls.SUBTREE_SCOPE; - - private String ldapFilter = null; public LDAPQuery(LDAPFederationProvider ldapProvider) { this.ldapFedProvider = ldapProvider; } - public LDAPQuery where(Condition... condition) { + public LDAPQuery addWhereCondition(Condition... condition) { this.conditions.addAll(Arrays.asList(condition)); return this; } @@ -191,12 +189,4 @@ public Set getConditions() { return this.conditions; } - public String getLdapFilter() { - return ldapFilter; - } - - public void setLdapFilter(String ldapFilter) { - this.ldapFilter = ldapFilter; - } - } diff --git a/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/query/internal/LDAPQueryConditionsBuilder.java b/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/query/internal/LDAPQueryConditionsBuilder.java index 9ebfd075221a..66c8e149e016 100644 --- a/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/query/internal/LDAPQueryConditionsBuilder.java +++ b/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/query/internal/LDAPQueryConditionsBuilder.java @@ -1,7 +1,6 @@ package org.keycloak.federation.ldap.idm.query.internal; import org.keycloak.federation.ldap.idm.query.Condition; -import org.keycloak.federation.ldap.idm.query.QueryParameter; import org.keycloak.federation.ldap.idm.query.Sort; import org.keycloak.models.ModelException; @@ -10,38 +9,30 @@ */ public class LDAPQueryConditionsBuilder { - public Condition like(QueryParameter parameter, String pattern) { - return new LikeCondition(parameter, pattern); - } - - public Condition equal(QueryParameter parameter, Object value) { + public Condition equal(String parameter, Object value) { return new EqualCondition(parameter, value); } - public Condition greaterThan(QueryParameter parameter, Object x) { + public Condition greaterThan(String paramName, Object x) { throwExceptionIfNotComparable(x); - return new GreaterThanCondition(parameter, (Comparable) x, false); + return new GreaterThanCondition(paramName, (Comparable) x, false); } - public Condition greaterThanOrEqualTo(QueryParameter parameter, Object x) { + public Condition greaterThanOrEqualTo(String paramName, Object x) { throwExceptionIfNotComparable(x); - return new GreaterThanCondition(parameter, (Comparable) x, true); + return new GreaterThanCondition(paramName, (Comparable) x, true); } - public Condition lessThan(QueryParameter parameter, Object x) { - throwExceptionIfNotComparable(x); - return new LessThanCondition(parameter, (Comparable) x, false); + public Condition lessThan(String paramName, Comparable x) { + return new LessThanCondition(paramName, x, false); } - public Condition lessThanOrEqualTo(QueryParameter parameter, Object x) { - throwExceptionIfNotComparable(x); - return new LessThanCondition(parameter, (Comparable) x, true); + public Condition lessThanOrEqualTo(String paramName, Comparable x) { + return new LessThanCondition(paramName, x, true); } - public Condition between(QueryParameter parameter, Object x, Object y) { - throwExceptionIfNotComparable(x); - throwExceptionIfNotComparable(y); - return new BetweenCondition(parameter, (Comparable) x, (Comparable) y); + public Condition between(String paramName, Comparable x, Comparable y) { + return new BetweenCondition(paramName, x, y); } public Condition orCondition(Condition... conditions) { @@ -51,16 +42,24 @@ public Condition orCondition(Condition... conditions) { return new OrCondition(conditions); } - public Condition in(QueryParameter parameter, Object... x) { - return new InCondition(parameter, x); + public Condition addCustomLDAPFilter(String filter) { + filter = filter.trim(); + if (!filter.startsWith("(") || !filter.endsWith(")")) { + throw new ModelException("Custom filter doesn't start with ( or doesn't end with ). "); + } + return new CustomLDAPFilter(filter); + } + + public Condition in(String paramName, Object... x) { + return new InCondition(paramName, x); } - public Sort asc(QueryParameter parameter) { - return new Sort(parameter, true); + public Sort asc(String paramName) { + return new Sort(paramName, true); } - public Sort desc(QueryParameter parameter) { - return new Sort(parameter, false); + public Sort desc(String paramName) { + return new Sort(paramName, false); } private void throwExceptionIfNotComparable(Object x) { diff --git a/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/query/internal/LessThanCondition.java b/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/query/internal/LessThanCondition.java index 5906a5ced0be..45ff5a62e457 100644 --- a/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/query/internal/LessThanCondition.java +++ b/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/query/internal/LessThanCondition.java @@ -1,34 +1,37 @@ package org.keycloak.federation.ldap.idm.query.internal; +import java.util.Date; + import org.keycloak.federation.ldap.idm.query.Condition; -import org.keycloak.federation.ldap.idm.query.QueryParameter; +import org.keycloak.federation.ldap.idm.store.ldap.LDAPUtil; /** * @author Pedro Igor */ -public class LessThanCondition implements Condition { +class LessThanCondition extends NamedParameterCondition { private final boolean orEqual; - private final QueryParameter parameter; private final Comparable value; - public LessThanCondition(QueryParameter parameter, Comparable value, boolean orEqual) { - this.parameter = parameter; + public LessThanCondition(String name, Comparable value, boolean orEqual) { + super(name); this.value = value; this.orEqual = orEqual; } @Override - public QueryParameter getParameter() { - return this.parameter; - } - - public Comparable getValue() { - return this.value; - } - - public boolean isOrEqual() { - return this.orEqual; + public void applyCondition(StringBuilder filter) { + Comparable parameterValue = value; + + if (Date.class.isInstance(parameterValue)) { + parameterValue = LDAPUtil.formatDate((Date) parameterValue); + } + + if (orEqual) { + filter.append("(").append(getParameterName()).append("<=").append(parameterValue).append(")"); + } else { + filter.append("(").append(getParameterName()).append("<").append(parameterValue).append(")"); + } } } diff --git a/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/query/internal/LikeCondition.java b/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/query/internal/LikeCondition.java deleted file mode 100644 index 6c6810362be1..000000000000 --- a/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/query/internal/LikeCondition.java +++ /dev/null @@ -1,28 +0,0 @@ -package org.keycloak.federation.ldap.idm.query.internal; - -import org.keycloak.federation.ldap.idm.query.Condition; -import org.keycloak.federation.ldap.idm.query.QueryParameter; - -/** - * @author Pedro Igor - */ -public class LikeCondition implements Condition { - - private final QueryParameter parameter; - private final Object value; - - public LikeCondition(QueryParameter parameter, Object value) { - this.parameter = parameter; - this.value = value; - } - - @Override - public QueryParameter getParameter() { - return this.parameter; - } - - public Object getValue() { - return this.value; - } - -} diff --git a/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/query/internal/NamedParameterCondition.java b/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/query/internal/NamedParameterCondition.java new file mode 100644 index 000000000000..427fa0837fb1 --- /dev/null +++ b/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/query/internal/NamedParameterCondition.java @@ -0,0 +1,25 @@ +package org.keycloak.federation.ldap.idm.query.internal; + +import org.keycloak.federation.ldap.idm.query.Condition; + +/** + * @author Marek Posolda + */ +public abstract class NamedParameterCondition implements Condition { + + private String parameterName; + + public NamedParameterCondition(String parameterName) { + this.parameterName = parameterName; + } + + @Override + public String getParameterName() { + return parameterName; + } + + @Override + public void setParameterName(String parameterName) { + this.parameterName = parameterName; + } +} diff --git a/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/query/internal/OrCondition.java b/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/query/internal/OrCondition.java index d898ffd23a8e..121b3c574984 100644 --- a/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/query/internal/OrCondition.java +++ b/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/query/internal/OrCondition.java @@ -1,12 +1,11 @@ package org.keycloak.federation.ldap.idm.query.internal; import org.keycloak.federation.ldap.idm.query.Condition; -import org.keycloak.federation.ldap.idm.query.QueryParameter; /** * @author Marek Posolda */ -public class OrCondition implements Condition { +class OrCondition implements Condition { private final Condition[] innerConditions; @@ -14,12 +13,23 @@ public OrCondition(Condition... innerConditions) { this.innerConditions = innerConditions; } - public Condition[] getInnerConditions() { - return innerConditions; + @Override + public String getParameterName() { + return null; } @Override - public QueryParameter getParameter() { - return null; + public void setParameterName(String parameterName) { + } + + @Override + public void applyCondition(StringBuilder filter) { + filter.append("(|"); + + for (Condition innerCondition : innerConditions) { + innerCondition.applyCondition(filter); + } + + filter.append(")"); } } diff --git a/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/store/ldap/LDAPIdentityStore.java b/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/store/ldap/LDAPIdentityStore.java index 9bc51f36c5c9..8193679be4ac 100644 --- a/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/store/ldap/LDAPIdentityStore.java +++ b/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/store/ldap/LDAPIdentityStore.java @@ -4,7 +4,6 @@ import java.util.Arrays; import java.util.Collection; import java.util.Collections; -import java.util.Date; import java.util.LinkedHashSet; import java.util.List; import java.util.Map; @@ -28,14 +27,8 @@ import org.keycloak.federation.ldap.idm.model.LDAPDn; import org.keycloak.federation.ldap.idm.model.LDAPObject; import org.keycloak.federation.ldap.idm.query.Condition; -import org.keycloak.federation.ldap.idm.query.QueryParameter; -import org.keycloak.federation.ldap.idm.query.internal.BetweenCondition; import org.keycloak.federation.ldap.idm.query.internal.LDAPQuery; import org.keycloak.federation.ldap.idm.query.internal.EqualCondition; -import org.keycloak.federation.ldap.idm.query.internal.GreaterThanCondition; -import org.keycloak.federation.ldap.idm.query.internal.InCondition; -import org.keycloak.federation.ldap.idm.query.internal.LessThanCondition; -import org.keycloak.federation.ldap.idm.query.internal.OrCondition; import org.keycloak.federation.ldap.idm.store.IdentityStore; import org.keycloak.models.LDAPConstants; import org.keycloak.models.ModelException; @@ -124,18 +117,18 @@ public List fetchQueryResults(LDAPQuery identityQuery) { // Check if we are searching by ID String uuidAttrName = getConfig().getUuidLDAPAttributeName(); - if (condition.getParameter() != null && condition.getParameter().getName().equalsIgnoreCase(uuidAttrName)) { - if (EqualCondition.class.isInstance(condition)) { - EqualCondition equalCondition = (EqualCondition) condition; + if (condition instanceof EqualCondition) { + EqualCondition equalCondition = (EqualCondition) condition; + if (equalCondition.getParameterName().equalsIgnoreCase(uuidAttrName)) { SearchResult search = this.operationManager .lookupById(baseDN, equalCondition.getValue().toString(), identityQuery.getReturningLdapAttributes()); if (search != null) { results.add(populateAttributedType(search, identityQuery)); } - } - return results; + return results; + } } } @@ -253,10 +246,7 @@ protected StringBuilder createIdentityTypeSearchFilter(final LDAPQuery identityQ StringBuilder filter = new StringBuilder(); for (Condition condition : identityQuery.getConditions()) { - applyCondition(filter, condition); - } - if (!(identityQuery.getLdapFilter() == null || identityQuery.getLdapFilter().isEmpty())) { - filter.append(identityQuery.getLdapFilter()); + condition.applyCondition(filter); } filter.insert(0, "(&"); @@ -270,95 +260,6 @@ protected StringBuilder createIdentityTypeSearchFilter(final LDAPQuery identityQ } - protected void applyCondition(StringBuilder filter, Condition condition) { - if (OrCondition.class.isInstance(condition)) { - OrCondition orCondition = (OrCondition) condition; - filter.append("(|"); - - for (Condition innerCondition : orCondition.getInnerConditions()) { - applyCondition(filter, innerCondition); - } - - filter.append(")"); - return; - } - - QueryParameter queryParameter = condition.getParameter(); - - if (!getConfig().getUuidLDAPAttributeName().equalsIgnoreCase(queryParameter.getName())) { - String attributeName = queryParameter.getName(); - - if (attributeName != null) { - if (EqualCondition.class.isInstance(condition)) { - EqualCondition equalCondition = (EqualCondition) condition; - Object parameterValue = equalCondition.getValue(); - - if (Date.class.isInstance(parameterValue)) { - parameterValue = LDAPUtil.formatDate((Date) parameterValue); - } - - filter.append("(").append(attributeName).append(LDAPConstants.EQUAL).append(parameterValue).append(")"); - } else if (GreaterThanCondition.class.isInstance(condition)) { - GreaterThanCondition greaterThanCondition = (GreaterThanCondition) condition; - Comparable parameterValue = greaterThanCondition.getValue(); - - if (Date.class.isInstance(parameterValue)) { - parameterValue = LDAPUtil.formatDate((Date) parameterValue); - } - - if (greaterThanCondition.isOrEqual()) { - filter.append("(").append(attributeName).append(">=").append(parameterValue).append(")"); - } else { - filter.append("(").append(attributeName).append(">").append(parameterValue).append(")"); - } - } else if (LessThanCondition.class.isInstance(condition)) { - LessThanCondition lessThanCondition = (LessThanCondition) condition; - Comparable parameterValue = lessThanCondition.getValue(); - - if (Date.class.isInstance(parameterValue)) { - parameterValue = LDAPUtil.formatDate((Date) parameterValue); - } - - if (lessThanCondition.isOrEqual()) { - filter.append("(").append(attributeName).append("<=").append(parameterValue).append(")"); - } else { - filter.append("(").append(attributeName).append("<").append(parameterValue).append(")"); - } - } else if (BetweenCondition.class.isInstance(condition)) { - BetweenCondition betweenCondition = (BetweenCondition) condition; - Comparable x = betweenCondition.getX(); - Comparable y = betweenCondition.getY(); - - if (Date.class.isInstance(x)) { - x = LDAPUtil.formatDate((Date) x); - } - - if (Date.class.isInstance(y)) { - y = LDAPUtil.formatDate((Date) y); - } - - filter.append("(").append(x).append("<=").append(attributeName).append("<=").append(y).append(")"); - } else if (InCondition.class.isInstance(condition)) { - InCondition inCondition = (InCondition) condition; - Object[] valuesToCompare = inCondition.getValue(); - - filter.append("(&("); - - for (int i = 0; i< valuesToCompare.length; i++) { - Object value = valuesToCompare[i]; - - filter.append("(").append(attributeName).append(LDAPConstants.EQUAL).append(value).append(")"); - } - - filter.append("))"); - } else { - throw new ModelException("Unsupported query condition [" + condition + "]."); - } - } - } - } - - private StringBuilder getObjectClassesFilter(Collection objectClasses) { StringBuilder builder = new StringBuilder(); diff --git a/federation/ldap/src/main/java/org/keycloak/federation/ldap/mappers/FullNameLDAPFederationMapper.java b/federation/ldap/src/main/java/org/keycloak/federation/ldap/mappers/FullNameLDAPFederationMapper.java index a29581d68e25..03235f6b98f4 100644 --- a/federation/ldap/src/main/java/org/keycloak/federation/ldap/mappers/FullNameLDAPFederationMapper.java +++ b/federation/ldap/src/main/java/org/keycloak/federation/ldap/mappers/FullNameLDAPFederationMapper.java @@ -6,7 +6,6 @@ import org.keycloak.federation.ldap.LDAPFederationProvider; import org.keycloak.federation.ldap.idm.model.LDAPObject; import org.keycloak.federation.ldap.idm.query.Condition; -import org.keycloak.federation.ldap.idm.query.QueryParameter; import org.keycloak.federation.ldap.idm.query.internal.EqualCondition; import org.keycloak.federation.ldap.idm.query.internal.LDAPQuery; import org.keycloak.models.LDAPConstants; @@ -105,18 +104,18 @@ public void beforeLDAPQuery(UserFederationMapperModel mapperModel, LDAPQuery que EqualCondition lastNameCondition = null; Set conditionsCopy = new HashSet(query.getConditions()); for (Condition condition : conditionsCopy) { - QueryParameter param = condition.getParameter(); - if (param != null) { - if (param.getName().equals(UserModel.FIRST_NAME)) { + String paramName = condition.getParameterName(); + if (paramName != null) { + if (paramName.equals(UserModel.FIRST_NAME)) { firstNameCondition = (EqualCondition) condition; query.getConditions().remove(condition); - } else if (param.getName().equals(UserModel.LAST_NAME)) { + } else if (paramName.equals(UserModel.LAST_NAME)) { lastNameCondition = (EqualCondition) condition; query.getConditions().remove(condition); - } else if (param.getName().equals(LDAPConstants.GIVENNAME)) { + } else if (paramName.equals(LDAPConstants.GIVENNAME)) { // Some previous mapper already converted it to LDAP name firstNameCondition = (EqualCondition) condition; - } else if (param.getName().equals(LDAPConstants.SN)) { + } else if (paramName.equals(LDAPConstants.SN)) { // Some previous mapper already converted it to LDAP name lastNameCondition = (EqualCondition) condition; } @@ -134,8 +133,8 @@ public void beforeLDAPQuery(UserFederationMapperModel mapperModel, LDAPQuery que } else { return; } - EqualCondition fullNameCondition = new EqualCondition(new QueryParameter(ldapFullNameAttrName), fullName); - query.getConditions().add(fullNameCondition); + EqualCondition fullNameCondition = new EqualCondition(ldapFullNameAttrName, fullName); + query.addWhereCondition(fullNameCondition); } protected String getLdapFullNameAttrName(UserFederationMapperModel mapperModel) { diff --git a/federation/ldap/src/main/java/org/keycloak/federation/ldap/mappers/RoleLDAPFederationMapper.java b/federation/ldap/src/main/java/org/keycloak/federation/ldap/mappers/RoleLDAPFederationMapper.java index 76d2df955252..6c45481a99a0 100644 --- a/federation/ldap/src/main/java/org/keycloak/federation/ldap/mappers/RoleLDAPFederationMapper.java +++ b/federation/ldap/src/main/java/org/keycloak/federation/ldap/mappers/RoleLDAPFederationMapper.java @@ -11,7 +11,6 @@ import org.keycloak.federation.ldap.idm.model.LDAPDn; import org.keycloak.federation.ldap.idm.model.LDAPObject; import org.keycloak.federation.ldap.idm.query.Condition; -import org.keycloak.federation.ldap.idm.query.QueryParameter; import org.keycloak.federation.ldap.idm.query.internal.LDAPQuery; import org.keycloak.federation.ldap.idm.query.internal.LDAPQueryConditionsBuilder; import org.keycloak.models.ClientModel; @@ -26,7 +25,7 @@ import org.keycloak.models.utils.UserModelDelegate; /** - * Map realm roles or roles of particular client to LDAP roles + * Map realm roles or roles of particular client to LDAP groups * * @author Marek Posolda */ @@ -131,7 +130,13 @@ public LDAPQuery createRoleQuery(UserFederationMapperModel mapperModel, LDAPFede ldapQuery.addObjectClasses(roleObjectClasses); String rolesRdnAttr = getRoleNameLdapAttribute(mapperModel); - ldapQuery.setLdapFilter(mapperModel.getConfig().get(RoleLDAPFederationMapper.ROLES_LDAP_FILTER)); + + String customFilter = mapperModel.getConfig().get(RoleLDAPFederationMapper.ROLES_LDAP_FILTER); + if (customFilter != null && customFilter.trim().length() > 0) { + Condition customFilterCondition = new LDAPQueryConditionsBuilder().addCustomLDAPFilter(customFilter); + ldapQuery.addWhereCondition(customFilterCondition); + } + String membershipAttr = getMembershipLdapAttribute(mapperModel); ldapQuery.addReturningLdapAttribute(rolesRdnAttr); ldapQuery.addReturningLdapAttribute(membershipAttr); @@ -227,7 +232,7 @@ public void addRoleMappingInLDAP(UserFederationMapperModel mapperModel, String r // Remove membership placeholder if present for (String membership : memberships) { - if (membership.trim().length() == 0) { + if (LDAPConstants.EMPTY_MEMBER_ATTRIBUTE_VALUE.equals(membership)) { memberships.remove(membership); break; } @@ -243,7 +248,7 @@ public void deleteRoleMappingInLDAP(UserFederationMapperModel mapperModel, LDAPF Set memberships = getExistingMemberships(mapperModel, ldapRole); memberships.remove(ldapUser.getDn().toString()); - // Some membership placeholder needs to be always here as "member" is mandatory attribute on some LDAP servers. But not on active directory! (Empty membership is not allowed here) + // Some membership placeholder needs to be always here as "member" is mandatory attribute on some LDAP servers. But not on active directory! (Placeholder, which not matches any real object is not allowed here) if (memberships.size() == 0 && !ldapProvider.getLdapIdentityStore().getConfig().isActiveDirectory()) { memberships.add(LDAPConstants.EMPTY_MEMBER_ATTRIBUTE_VALUE); } @@ -254,8 +259,8 @@ public void deleteRoleMappingInLDAP(UserFederationMapperModel mapperModel, LDAPF public LDAPObject loadLDAPRoleByName(UserFederationMapperModel mapperModel, LDAPFederationProvider ldapProvider, String roleName) { LDAPQuery ldapQuery = createRoleQuery(mapperModel, ldapProvider); - Condition roleNameCondition = new LDAPQueryConditionsBuilder().equal(new QueryParameter(getRoleNameLdapAttribute(mapperModel)), roleName); - ldapQuery.where(roleNameCondition); + Condition roleNameCondition = new LDAPQueryConditionsBuilder().equal(getRoleNameLdapAttribute(mapperModel), roleName); + ldapQuery.addWhereCondition(roleNameCondition); return ldapQuery.getFirstResult(); } @@ -271,8 +276,8 @@ protected Set getExistingMemberships(UserFederationMapperModel mapperMod protected List getLDAPRoleMappings(UserFederationMapperModel mapperModel, LDAPFederationProvider ldapProvider, LDAPObject ldapUser) { LDAPQuery ldapQuery = createRoleQuery(mapperModel, ldapProvider); String membershipAttr = getMembershipLdapAttribute(mapperModel); - Condition membershipCondition = new LDAPQueryConditionsBuilder().equal(new QueryParameter(membershipAttr), ldapUser.getDn().toString()); - ldapQuery.where(membershipCondition); + Condition membershipCondition = new LDAPQueryConditionsBuilder().equal(membershipAttr, ldapUser.getDn().toString()); + ldapQuery.addWhereCondition(membershipCondition); return ldapQuery.getResultList(); } @@ -431,9 +436,9 @@ public void deleteRoleMapping(RoleModel role) { LDAPQuery ldapQuery = createRoleQuery(mapperModel, ldapProvider); LDAPQueryConditionsBuilder conditionsBuilder = new LDAPQueryConditionsBuilder(); - Condition roleNameCondition = conditionsBuilder.equal(new QueryParameter(getRoleNameLdapAttribute(mapperModel)), role.getName()); - Condition membershipCondition = conditionsBuilder.equal(new QueryParameter(getMembershipLdapAttribute(mapperModel)), ldapUser.getDn().toString()); - ldapQuery.where(roleNameCondition).where(membershipCondition); + Condition roleNameCondition = conditionsBuilder.equal(getRoleNameLdapAttribute(mapperModel), role.getName()); + Condition membershipCondition = conditionsBuilder.equal(getMembershipLdapAttribute(mapperModel), ldapUser.getDn().toString()); + ldapQuery.addWhereCondition(roleNameCondition).addWhereCondition(membershipCondition); LDAPObject ldapRole = ldapQuery.getFirstResult(); if (ldapRole == null) { diff --git a/federation/ldap/src/main/java/org/keycloak/federation/ldap/mappers/RoleLDAPFederationMapperFactory.java b/federation/ldap/src/main/java/org/keycloak/federation/ldap/mappers/RoleLDAPFederationMapperFactory.java index 07b4635568c5..bdd0e51e6337 100644 --- a/federation/ldap/src/main/java/org/keycloak/federation/ldap/mappers/RoleLDAPFederationMapperFactory.java +++ b/federation/ldap/src/main/java/org/keycloak/federation/ldap/mappers/RoleLDAPFederationMapperFactory.java @@ -54,7 +54,7 @@ public class RoleLDAPFederationMapperFactory extends AbstractLDAPFederationMappe ProviderConfigProperty ldapFilter = createConfigProperty(RoleLDAPFederationMapper.ROLES_LDAP_FILTER, "LDAP Filter", - "LDAP Filter adds additional custom filter to the whole query.", + "LDAP Filter adds additional custom filter to the whole query. Make sure that it starts with '(' and ends with ')'", ProviderConfigProperty.STRING_TYPE, null); configProperties.add(ldapFilter); @@ -153,6 +153,11 @@ public void validateConfig(UserFederationMapperModel mapperModel) throws MapperC throw new MapperConfigValidationException("Client ID needs to be provided in config when Realm Roles Mapping is not used"); } } + + String customLdapFilter = mapperModel.getConfig().get(RoleLDAPFederationMapper.ROLES_LDAP_FILTER); + if ((customLdapFilter != null && customLdapFilter.trim().length() > 0) && (!customLdapFilter.startsWith("(") || !customLdapFilter.endsWith(")"))) { + throw new MapperConfigValidationException("Custom Roles LDAP filter must starts with '(' and ends with ')'"); + } } @Override diff --git a/federation/ldap/src/main/java/org/keycloak/federation/ldap/mappers/UserAttributeLDAPFederationMapper.java b/federation/ldap/src/main/java/org/keycloak/federation/ldap/mappers/UserAttributeLDAPFederationMapper.java index 536753fb6058..aac34f54dc5d 100644 --- a/federation/ldap/src/main/java/org/keycloak/federation/ldap/mappers/UserAttributeLDAPFederationMapper.java +++ b/federation/ldap/src/main/java/org/keycloak/federation/ldap/mappers/UserAttributeLDAPFederationMapper.java @@ -14,7 +14,6 @@ import org.keycloak.federation.ldap.LDAPFederationProvider; import org.keycloak.federation.ldap.idm.model.LDAPObject; import org.keycloak.federation.ldap.idm.query.Condition; -import org.keycloak.federation.ldap.idm.query.QueryParameter; import org.keycloak.federation.ldap.idm.query.internal.LDAPQuery; import org.keycloak.models.KeycloakSession; import org.keycloak.models.LDAPConstants; @@ -322,9 +321,9 @@ public void beforeLDAPQuery(UserFederationMapperModel mapperModel, LDAPQuery que // Change conditions and use ldapAttribute instead of userModel for (Condition condition : query.getConditions()) { - QueryParameter param = condition.getParameter(); - if (param != null && param.getName().equalsIgnoreCase(userModelAttrName)) { - param.setName(ldapAttrName); + String paramName = condition.getParameterName(); + if (paramName != null && paramName.equalsIgnoreCase(userModelAttrName)) { + condition.setParameterName(ldapAttrName); } } } diff --git a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/federated-ldap.html b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/federated-ldap.html index e405f7218b98..6263f3d9f650 100755 --- a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/federated-ldap.html +++ b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/federated-ldap.html @@ -149,6 +149,13 @@ Test authentication +
+ +
+ +
+ Additional LDAP Filter for filtering searched users. Leave this empty if you don't need additional filter. Make sure that it starts with '(' and ends with ')' +
diff --git a/model/api/src/main/java/org/keycloak/models/LDAPConstants.java b/model/api/src/main/java/org/keycloak/models/LDAPConstants.java index e9350631103e..79bd7b51d852 100644 --- a/model/api/src/main/java/org/keycloak/models/LDAPConstants.java +++ b/model/api/src/main/java/org/keycloak/models/LDAPConstants.java @@ -46,6 +46,9 @@ public class LDAPConstants { // Applicable just for active directory public static final String USER_ACCOUNT_CONTROLS_AFTER_PASSWORD_UPDATE = "userAccountControlsAfterPasswordUpdate"; + // Custom user search filter + public static final String CUSTOM_USER_SEARCH_FILTER = "customUserSearchFilter"; + // Custom attributes on UserModel, which is mapped to LDAP public static final String LDAP_ID = "LDAP_ID"; public static final String LDAP_ENTRY_DN = "LDAP_ENTRY_DN"; diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/federation/FederationProvidersIntegrationTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/federation/FederationProvidersIntegrationTest.java index ae2e4bebd2d5..ef1a721d2d73 100755 --- a/testsuite/integration/src/test/java/org/keycloak/testsuite/federation/FederationProvidersIntegrationTest.java +++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/federation/FederationProvidersIntegrationTest.java @@ -659,6 +659,45 @@ public void testSearch() { } } + @Test + public void testSearchWithCustomLDAPFilter() { + // Add custom filter for searching users + KeycloakSession session = keycloakRule.startSession(); + try { + RealmModel appRealm = session.realms().getRealmByName("test"); + ldapModel.getConfig().put(LDAPConstants.CUSTOM_USER_SEARCH_FILTER, "(|(mail=user5@email.org)(mail=user6@email.org))"); + appRealm.updateUserFederationProvider(ldapModel); + } finally { + keycloakRule.stopSession(session, true); + } + + session = keycloakRule.startSession(); + try { + LDAPFederationProvider ldapProvider = FederationTestUtils.getLdapProvider(session, ldapModel); + RealmModel appRealm = session.realms().getRealmByName("test"); + + FederationTestUtils.addLDAPUser(ldapProvider, appRealm, "username5", "John5", "Doel5", "user5@email.org", null, "125"); + FederationTestUtils.addLDAPUser(ldapProvider, appRealm, "username6", "John6", "Doel6", "user6@email.org", null, "126"); + FederationTestUtils.addLDAPUser(ldapProvider, appRealm, "username7", "John7", "Doel7", "user7@email.org", null, "127"); + + // search by email + session.users().searchForUser("user5@email.org", appRealm); + FederationTestUtils.assertUserImported(session.userStorage(), appRealm, "username5", "John5", "Doel5", "user5@email.org", "125"); + + session.users().searchForUser("user6@email.org", appRealm); + FederationTestUtils.assertUserImported(session.userStorage(), appRealm, "username6", "John6", "Doel6", "user6@email.org", "126"); + + session.users().searchForUser("user7@email.org", appRealm); + Assert.assertNull(session.userStorage().getUserByUsername("username7", appRealm)); + + // Remove custom filter + ldapModel.getConfig().remove(LDAPConstants.CUSTOM_USER_SEARCH_FILTER); + appRealm.updateUserFederationProvider(ldapModel); + } finally { + keycloakRule.stopSession(session, true); + } + } + @Test public void testUnsynced() { KeycloakSession session = keycloakRule.startSession(); diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/federation/LDAPRoleMappingsTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/federation/LDAPRoleMappingsTest.java index c0a8cd652dbf..5bb229154782 100644 --- a/testsuite/integration/src/test/java/org/keycloak/testsuite/federation/LDAPRoleMappingsTest.java +++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/federation/LDAPRoleMappingsTest.java @@ -15,7 +15,6 @@ import org.keycloak.federation.ldap.LDAPFederationProviderFactory; import org.keycloak.federation.ldap.idm.model.LDAPObject; import org.keycloak.federation.ldap.idm.query.Condition; -import org.keycloak.federation.ldap.idm.query.QueryParameter; import org.keycloak.federation.ldap.idm.query.internal.LDAPQuery; import org.keycloak.federation.ldap.idm.query.internal.LDAPQueryConditionsBuilder; import org.keycloak.federation.ldap.mappers.RoleLDAPFederationMapper; @@ -331,8 +330,8 @@ public void test03_importRoleMappings() { private void deleteRoleMappingsInLDAP(UserFederationMapperModel roleMapperModel, RoleLDAPFederationMapper roleMapper, LDAPFederationProvider ldapProvider, LDAPObject ldapUser, String roleName) { LDAPQuery ldapQuery = roleMapper.createRoleQuery(roleMapperModel, ldapProvider); LDAPQueryConditionsBuilder conditionsBuilder = new LDAPQueryConditionsBuilder(); - Condition roleNameCondition = conditionsBuilder.equal(new QueryParameter(LDAPConstants.CN), roleName); - ldapQuery.where(roleNameCondition); + Condition roleNameCondition = conditionsBuilder.equal(LDAPConstants.CN, roleName); + ldapQuery.addWhereCondition(roleNameCondition); LDAPObject ldapRole1 = ldapQuery.getFirstResult(); roleMapper.deleteRoleMappingInLDAP(roleMapperModel, ldapProvider, ldapUser, ldapRole1); }