KEYCLOAK-2379 Fix possible error during sycnchronization changed users with Active Directory

This commit is contained in:
mposolda 2016-01-26 10:43:04 +01:00
parent a21f70fcd2
commit 506194fb7f
7 changed files with 60 additions and 24 deletions

View file

@ -1,7 +1,7 @@
package org.keycloak.federation.ldap.idm.query; package org.keycloak.federation.ldap.idm.query;
/** /**
* <p>A {@link Condition} is used to specify how a specific {@link QueryParameter} * <p>A {@link Condition} is used to specify how a specific query parameter
* is defined in order to filter query results.</p> * is defined in order to filter query results.</p>
* *
* @author Pedro Igor * @author Pedro Igor
@ -11,6 +11,15 @@ public interface Condition {
String getParameterName(); String getParameterName();
void setParameterName(String parameterName); void setParameterName(String parameterName);
/**
* Will change the parameter name if it is "modelParamName" to "ldapParamName" . Implementation can apply this to subconditions as well.
*
* It is used to update LDAP queries, which were created with model parameter name ( for example "firstName" ) and rewrite them to use real
* LDAP mapped attribute (for example "givenName" )
*/
void updateParameterName(String modelParamName, String ldapParamName);
void applyCondition(StringBuilder filter); void applyCondition(StringBuilder filter);
} }

View file

@ -22,6 +22,11 @@ class CustomLDAPFilter implements Condition {
public void setParameterName(String parameterName) { public void setParameterName(String parameterName) {
} }
@Override
public void updateParameterName(String modelParamName, String ldapParamName) {
}
@Override @Override
public void applyCondition(StringBuilder filter) { public void applyCondition(StringBuilder filter) {
filter.append(customFilter); filter.append(customFilter);

View file

@ -22,4 +22,12 @@ public abstract class NamedParameterCondition implements Condition {
public void setParameterName(String parameterName) { public void setParameterName(String parameterName) {
this.parameterName = parameterName; this.parameterName = parameterName;
} }
@Override
public void updateParameterName(String modelParamName, String ldapParamName) {
if (parameterName.equalsIgnoreCase(modelParamName)) {
this.parameterName = ldapParamName;
}
}
} }

View file

@ -22,6 +22,13 @@ class OrCondition implements Condition {
public void setParameterName(String parameterName) { public void setParameterName(String parameterName) {
} }
@Override
public void updateParameterName(String modelParamName, String ldapParamName) {
for (Condition innerCondition : innerConditions) {
innerCondition.updateParameterName(modelParamName, ldapParamName);
}
}
@Override @Override
public void applyCondition(StringBuilder filter) { public void applyCondition(StringBuilder filter) {
filter.append("(|"); filter.append("(|");

View file

@ -324,10 +324,7 @@ public class UserAttributeLDAPFederationMapper extends AbstractLDAPFederationMap
// Change conditions and use ldapAttribute instead of userModel // Change conditions and use ldapAttribute instead of userModel
for (Condition condition : query.getConditions()) { for (Condition condition : query.getConditions()) {
String paramName = condition.getParameterName(); condition.updateParameterName(userModelAttrName, ldapAttrName);
if (paramName != null && paramName.equalsIgnoreCase(userModelAttrName)) {
condition.setParameterName(ldapAttrName);
}
} }
} }

View file

@ -752,6 +752,25 @@ module.controller('GenericUserFederationCtrl', function($scope, $location, Notif
module.controller('LDAPCtrl', function($scope, $location, $route, Notifications, Dialog, realm, instance, UserFederationInstances, UserFederationSync, RealmLDAPConnectionTester) { module.controller('LDAPCtrl', function($scope, $location, $route, Notifications, Dialog, realm, instance, UserFederationInstances, UserFederationSync, RealmLDAPConnectionTester) {
console.log('LDAPCtrl'); console.log('LDAPCtrl');
$scope.ldapVendors = [
{ "id": "ad", "name": "Active Directory" },
{ "id": "rhds", "name": "Red Hat Directory Server" },
{ "id": "tivoli", "name": "Tivoli" },
{ "id": "edirectory", "name": "Novell eDirectory" },
{ "id": "other", "name": "Other" }
];
$scope.authTypes = [
{ "id": "none", "name": "none" },
{ "id": "simple", "name": "simple" }
];
$scope.searchScopes = [
{ "id": "1", "name": "One Level" },
{ "id": "2", "name": "Subtree" }
];
var DEFAULT_BATCH_SIZE = "1000"; var DEFAULT_BATCH_SIZE = "1000";
$scope.create = !instance.providerName; $scope.create = !instance.providerName;
@ -799,6 +818,12 @@ module.controller('LDAPCtrl', function($scope, $location, $route, Notifications,
$scope.fullSyncEnabled = (instance.fullSyncPeriod && instance.fullSyncPeriod > 0); $scope.fullSyncEnabled = (instance.fullSyncPeriod && instance.fullSyncPeriod > 0);
$scope.changedSyncEnabled = (instance.changedSyncPeriod && instance.changedSyncPeriod > 0); $scope.changedSyncEnabled = (instance.changedSyncPeriod && instance.changedSyncPeriod > 0);
for (var i=0 ; i<$scope.ldapVendors.length ; i++) {
if ($scope.ldapVendors[i].id === instance.config.vendor) {
$scope.vendorName = $scope.ldapVendors[i].name;
}
};
} }
$scope.changed = false; $scope.changed = false;
@ -808,24 +833,6 @@ module.controller('LDAPCtrl', function($scope, $location, $route, Notifications,
initFederationSettings(); initFederationSettings();
$scope.instance = angular.copy(instance); $scope.instance = angular.copy(instance);
$scope.ldapVendors = [
{ "id": "ad", "name": "Active Directory" },
{ "id": "rhds", "name": "Red Hat Directory Server" },
{ "id": "tivoli", "name": "Tivoli" },
{ "id": "edirectory", "name": "Novell eDirectory" },
{ "id": "other", "name": "Other" }
];
$scope.authTypes = [
{ "id": "none", "name": "none" },
{ "id": "simple", "name": "simple" }
];
$scope.searchScopes = [
{ "id": "1", "name": "One Level" },
{ "id": "2", "name": "Subtree" }
];
$scope.realm = realm; $scope.realm = realm;
$scope.$watch('fullSyncEnabled', function(newVal, oldVal) { $scope.$watch('fullSyncEnabled', function(newVal, oldVal) {

View file

@ -55,13 +55,16 @@
<div class="form-group clearfix"> <div class="form-group clearfix">
<label class="col-md-2 control-label" for="vendor"><span class="required">*</span> Vendor</label> <label class="col-md-2 control-label" for="vendor"><span class="required">*</span> Vendor</label>
<div class="col-md-6"> <div class="col-md-6">
<div> <div data-ng-show="create">
<select class="form-control" id="vendor" <select class="form-control" id="vendor"
ng-model="instance.config.vendor" ng-model="instance.config.vendor"
ng-options="vendor.id as vendor.name for vendor in ldapVendors" ng-options="vendor.id as vendor.name for vendor in ldapVendors"
required> required>
</select> </select>
</div> </div>
<div data-ng-show="!create">
<input class="form-control" id="vendor-ro" type="text" ng-model="vendorName" readonly>
</div>
</div> </div>
<kc-tooltip>LDAP vendor (provider)</kc-tooltip> <kc-tooltip>LDAP vendor (provider)</kc-tooltip>
</div> </div>