Skip to content

Commit

Permalink
KEYCLOAK-1906 Customized LDAP filter. LDAP conditions improvements
Browse files Browse the repository at this point in the history
  • Loading branch information
mposolda committed Dec 14, 2015
1 parent 82a573a commit 06a5541
Show file tree
Hide file tree
Showing 27 changed files with 312 additions and 323 deletions.
Expand Up @@ -14,7 +14,6 @@
/** /**
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a> * @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
* *
* TODO: init properties at constructor instead of always compute them
*/ */
public class LDAPConfig { public class LDAPConfig {


Expand Down Expand Up @@ -147,6 +146,18 @@ public String getRdnLdapAttribute() {
return rdn; 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() { public UserFederationProvider.EditMode getEditMode() {
String editModeString = config.get(LDAPConstants.EDIT_MODE); String editModeString = config.get(LDAPConstants.EDIT_MODE);
if (editModeString == null) { if (editModeString == null) {
Expand Down
Expand Up @@ -5,7 +5,6 @@
import org.keycloak.federation.kerberos.impl.SPNEGOAuthenticator; import org.keycloak.federation.kerberos.impl.SPNEGOAuthenticator;
import org.keycloak.federation.ldap.idm.model.LDAPObject; import org.keycloak.federation.ldap.idm.model.LDAPObject;
import org.keycloak.federation.ldap.idm.query.Condition; 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.LDAPQuery;
import org.keycloak.federation.ldap.idm.query.internal.LDAPQueryConditionsBuilder; import org.keycloak.federation.ldap.idm.query.internal.LDAPQueryConditionsBuilder;
import org.keycloak.federation.ldap.idm.store.ldap.LDAPIdentityStore; import org.keycloak.federation.ldap.idm.store.ldap.LDAPIdentityStore;
Expand Down Expand Up @@ -209,10 +208,10 @@ protected List<LDAPObject> searchLDAP(RealmModel realm, Map<String, String> attr


// Mapper should replace parameter with correct LDAP mapped attributes // Mapper should replace parameter with correct LDAP mapped attributes
if (attributes.containsKey(FIRST_NAME)) { 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)) { 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<LDAPObject> ldapObjects = ldapQuery.getResultList(); List<LDAPObject> ldapObjects = ldapQuery.getResultList();
Expand Down Expand Up @@ -287,8 +286,8 @@ protected LDAPObject queryByEmail(RealmModel realm, String email) {
LDAPQueryConditionsBuilder conditionsBuilder = new LDAPQueryConditionsBuilder(); LDAPQueryConditionsBuilder conditionsBuilder = new LDAPQueryConditionsBuilder();


// Mapper should replace "email" in parameter name with correct LDAP mapped attribute // Mapper should replace "email" in parameter name with correct LDAP mapped attribute
Condition emailCondition = conditionsBuilder.equal(new QueryParameter(UserModel.EMAIL), email); Condition emailCondition = conditionsBuilder.equal(UserModel.EMAIL, email);
ldapQuery.where(emailCondition); ldapQuery.addWhereCondition(emailCondition);


return ldapQuery.getFirstResult(); return ldapQuery.getFirstResult();
} }
Expand Down Expand Up @@ -434,8 +433,8 @@ public LDAPObject loadLDAPUserByUsername(RealmModel realm, String username) {
LDAPQueryConditionsBuilder conditionsBuilder = new LDAPQueryConditionsBuilder(); LDAPQueryConditionsBuilder conditionsBuilder = new LDAPQueryConditionsBuilder();


String usernameMappedAttribute = this.ldapIdentityStore.getConfig().getUsernameLdapAttribute(); String usernameMappedAttribute = this.ldapIdentityStore.getConfig().getUsernameLdapAttribute();
Condition usernameCondition = conditionsBuilder.equal(new QueryParameter(usernameMappedAttribute), username); Condition usernameCondition = conditionsBuilder.equal(usernameMappedAttribute, username);
ldapQuery.where(usernameCondition); ldapQuery.addWhereCondition(usernameCondition);


LDAPObject ldapUser = ldapQuery.getFirstResult(); LDAPObject ldapUser = ldapQuery.getFirstResult();
if (ldapUser == null) { if (ldapUser == null) {
Expand Down
Expand Up @@ -8,7 +8,6 @@
import org.keycloak.federation.kerberos.impl.SPNEGOAuthenticator; import org.keycloak.federation.kerberos.impl.SPNEGOAuthenticator;
import org.keycloak.federation.ldap.idm.model.LDAPObject; import org.keycloak.federation.ldap.idm.model.LDAPObject;
import org.keycloak.federation.ldap.idm.query.Condition; 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.LDAPQuery;
import org.keycloak.federation.ldap.idm.query.internal.LDAPQueryConditionsBuilder; import org.keycloak.federation.ldap.idm.query.internal.LDAPQueryConditionsBuilder;
import org.keycloak.federation.ldap.idm.store.ldap.LDAPIdentityStore; import org.keycloak.federation.ldap.idm.store.ldap.LDAPIdentityStore;
Expand All @@ -21,7 +20,6 @@
import org.keycloak.models.KeycloakSessionFactory; import org.keycloak.models.KeycloakSessionFactory;
import org.keycloak.models.KeycloakSessionTask; import org.keycloak.models.KeycloakSessionTask;
import org.keycloak.models.LDAPConstants; import org.keycloak.models.LDAPConstants;
import org.keycloak.models.ModelDuplicateException;
import org.keycloak.models.ModelException; import org.keycloak.models.ModelException;
import org.keycloak.models.RealmModel; import org.keycloak.models.RealmModel;
import org.keycloak.models.UserFederationEventAwareProviderFactory; import org.keycloak.models.UserFederationEventAwareProviderFactory;
Expand Down Expand Up @@ -211,12 +209,12 @@ public UserFederationSyncResult syncChangedUsers(KeycloakSessionFactory sessionF


// Sync newly created and updated users // Sync newly created and updated users
LDAPQueryConditionsBuilder conditionsBuilder = new LDAPQueryConditionsBuilder(); LDAPQueryConditionsBuilder conditionsBuilder = new LDAPQueryConditionsBuilder();
Condition createCondition = conditionsBuilder.greaterThanOrEqualTo(new QueryParameter(LDAPConstants.CREATE_TIMESTAMP), lastSync); Condition createCondition = conditionsBuilder.greaterThanOrEqualTo(LDAPConstants.CREATE_TIMESTAMP, lastSync);
Condition modifyCondition = conditionsBuilder.greaterThanOrEqualTo(new QueryParameter(LDAPConstants.MODIFY_TIMESTAMP), lastSync); Condition modifyCondition = conditionsBuilder.greaterThanOrEqualTo(LDAPConstants.MODIFY_TIMESTAMP, lastSync);
Condition orCondition = conditionsBuilder.orCondition(createCondition, modifyCondition); Condition orCondition = conditionsBuilder.orCondition(createCondition, modifyCondition);


LDAPQuery userQuery = createQuery(sessionFactory, realmId, model); LDAPQuery userQuery = createQuery(sessionFactory, realmId, model);
userQuery.where(orCondition); userQuery.addWhereCondition(orCondition);
UserFederationSyncResult result = syncImpl(sessionFactory, userQuery, realmId, model); UserFederationSyncResult result = syncImpl(sessionFactory, userQuery, realmId, model);


logger.infof("Sync changed users finished: %s", result.getStatus()); logger.infof("Sync changed users finished: %s", result.getStatus());
Expand Down
Expand Up @@ -4,7 +4,9 @@


import org.keycloak.federation.ldap.idm.model.LDAPDn; import org.keycloak.federation.ldap.idm.model.LDAPDn;
import org.keycloak.federation.ldap.idm.model.LDAPObject; 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.LDAPQuery;
import org.keycloak.federation.ldap.idm.query.internal.LDAPQueryConditionsBuilder;
import org.keycloak.federation.ldap.idm.store.ldap.LDAPIdentityStore; import org.keycloak.federation.ldap.idm.store.ldap.LDAPIdentityStore;
import org.keycloak.federation.ldap.mappers.LDAPFederationMapper; import org.keycloak.federation.ldap.mappers.LDAPFederationMapper;
import org.keycloak.models.ModelException; import org.keycloak.models.ModelException;
Expand Down Expand Up @@ -51,6 +53,12 @@ public static LDAPQuery createQueryForUserSearch(LDAPFederationProvider ldapProv
ldapQuery.setSearchDn(config.getUsersDn()); ldapQuery.setSearchDn(config.getUsersDn());
ldapQuery.addObjectClasses(config.getUserObjectClasses()); ldapQuery.addObjectClasses(config.getUserObjectClasses());


String customFilter = config.getCustomUserSearchFilter();
if (customFilter != null) {
Condition customFilterCondition = new LDAPQueryConditionsBuilder().addCustomLDAPFilter(customFilter);
ldapQuery.addWhereCondition(customFilterCondition);
}

Set<UserFederationMapperModel> mapperModels = realm.getUserFederationMappersByFederationProvider(ldapProvider.getModel().getId()); Set<UserFederationMapperModel> mapperModels = realm.getUserFederationMappersByFederationProvider(ldapProvider.getModel().getId());
ldapQuery.addMappers(mapperModels); ldapQuery.addMappers(mapperModels);


Expand Down
Expand Up @@ -8,11 +8,9 @@
*/ */
public interface Condition { public interface Condition {


/** String getParameterName();
* <p>The {@link QueryParameter} restricted by this condition.</p> void setParameterName(String parameterName);
*
* @return void applyCondition(StringBuilder filter);
*/
QueryParameter getParameter();


} }

This file was deleted.

Expand Up @@ -5,16 +5,16 @@
*/ */
public class Sort { public class Sort {


private final QueryParameter parameter; private final String paramName;
private final boolean asc; private final boolean asc;


public Sort(QueryParameter parameter, boolean asc) { public Sort(String paramName, boolean asc) {
this.parameter = parameter; this.paramName = paramName;
this.asc = asc; this.asc = asc;
} }


public QueryParameter getParameter() { public String getParameter() {
return this.parameter; return this.paramName;
} }


public boolean isAscending() { public boolean isAscending() {
Expand Down
@@ -1,33 +1,36 @@
package org.keycloak.federation.ldap.idm.query.internal; package org.keycloak.federation.ldap.idm.query.internal;


import org.keycloak.federation.ldap.idm.query.Condition; import java.util.Date;
import org.keycloak.federation.ldap.idm.query.QueryParameter;
import org.keycloak.federation.ldap.idm.store.ldap.LDAPUtil;


/** /**
* @author Pedro Igor * @author Pedro Igor
*/ */
public class BetweenCondition implements Condition { class BetweenCondition extends NamedParameterCondition {


private final Comparable x; private final Comparable x;
private final Comparable y; private final Comparable y;
private final QueryParameter parameter;


public BetweenCondition(QueryParameter parameter, Comparable x, Comparable y) { public BetweenCondition(String name, Comparable x, Comparable y) {
this.parameter = parameter; super(name);
this.x = x; this.x = x;
this.y = y; this.y = y;
} }


@Override @Override
public QueryParameter getParameter() { public void applyCondition(StringBuilder filter) {
return this.parameter; Comparable x = this.x;
} Comparable y = this.y;


public Comparable getX() { if (Date.class.isInstance(x)) {
return this.x; x = LDAPUtil.formatDate((Date) x);
} }

if (Date.class.isInstance(y)) {
y = LDAPUtil.formatDate((Date) y);
}


public Comparable getY() { filter.append("(").append(x).append("<=").append(getParameterName()).append("<=").append(y).append(")");
return this.y;
} }
} }
@@ -0,0 +1,29 @@
package org.keycloak.federation.ldap.idm.query.internal;

import org.keycloak.federation.ldap.idm.query.Condition;

/**
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*/
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);
}
}
@@ -1,34 +1,40 @@
package org.keycloak.federation.ldap.idm.query.internal; package org.keycloak.federation.ldap.idm.query.internal;


import org.keycloak.federation.ldap.idm.query.Condition; import java.util.Date;
import org.keycloak.federation.ldap.idm.query.QueryParameter;
import org.keycloak.federation.ldap.idm.store.ldap.LDAPUtil;
import org.keycloak.models.LDAPConstants;


/** /**
* @author Pedro Igor * @author Pedro Igor
*/ */
public class EqualCondition implements Condition { public class EqualCondition extends NamedParameterCondition {


private final QueryParameter parameter;
private final Object value; private final Object value;


public EqualCondition(QueryParameter parameter, Object value) { public EqualCondition(String name, Object value) {
this.parameter = parameter; super(name);
this.value = value; this.value = value;
} }


@Override
public QueryParameter getParameter() {
return this.parameter;
}

public Object getValue() { public Object getValue() {
return this.value; 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 @Override
public String toString() { public String toString() {
return "EqualCondition{" + return "EqualCondition{" +
"parameter=" + parameter.getName() + "paramName=" + getParameterName() +
", value=" + value + ", value=" + value +
'}'; '}';
} }
Expand Down
@@ -1,34 +1,37 @@
package org.keycloak.federation.ldap.idm.query.internal; 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.Condition;
import org.keycloak.federation.ldap.idm.query.QueryParameter; import org.keycloak.federation.ldap.idm.store.ldap.LDAPUtil;


/** /**
* @author Pedro Igor * @author Pedro Igor
*/ */
public class GreaterThanCondition implements Condition { class GreaterThanCondition extends NamedParameterCondition {


private final boolean orEqual; private final boolean orEqual;


private final QueryParameter parameter;
private final Comparable value; private final Comparable value;


public GreaterThanCondition(QueryParameter parameter, Comparable value, boolean orEqual) { public GreaterThanCondition(String name, Comparable value, boolean orEqual) {
this.parameter = parameter; super(name);
this.value = value; this.value = value;
this.orEqual = orEqual; this.orEqual = orEqual;
} }


@Override @Override
public QueryParameter getParameter() { public void applyCondition(StringBuilder filter) {
return this.parameter; Comparable parameterValue = value;
}

if (Date.class.isInstance(parameterValue)) {
public Comparable getValue() { parameterValue = LDAPUtil.formatDate((Date) parameterValue);
return this.value; }
}

if (orEqual) {
public boolean isOrEqual() { filter.append("(").append(getParameterName()).append(">=").append(parameterValue).append(")");
return this.orEqual; } else {
filter.append("(").append(getParameterName()).append(">").append(parameterValue).append(")");
}
} }
} }

0 comments on commit 06a5541

Please sign in to comment.