keycloak-uncached

Details

diff --git a/forms/common-themes/src/main/resources/theme/admin/base/resources/js/controllers/realm.js b/forms/common-themes/src/main/resources/theme/admin/base/resources/js/controllers/realm.js
index 392e726..251a62f 100755
--- a/forms/common-themes/src/main/resources/theme/admin/base/resources/js/controllers/realm.js
+++ b/forms/common-themes/src/main/resources/theme/admin/base/resources/js/controllers/realm.js
@@ -925,7 +925,13 @@ module.controller('RealmLDAPSettingsCtrl', function($scope, $location, Notificat
             console.log("LDAP vendor changed");
             $scope.lastVendor = $scope.realm.ldapServer.vendor;
 
-            $scope.realm.ldapServer.usernameLDAPAttribute = ($scope.lastVendor === "ad") ? "cn" : "uid";
+            if ($scope.lastVendor === "ad") {
+                $scope.realm.ldapServer.usernameLDAPAttribute = "cn";
+                $scope.realm.ldapServer.userObjectClasses = "person, organizationalPerson";
+            } else {
+                $scope.realm.ldapServer.usernameLDAPAttribute = "uid";
+                $scope.realm.ldapServer.userObjectClasses = "inetOrgPerson, organizationalPerson";
+            }
         }
     }, true);
 
diff --git a/forms/common-themes/src/main/resources/theme/admin/base/resources/partials/realm-ldap.html b/forms/common-themes/src/main/resources/theme/admin/base/resources/partials/realm-ldap.html
index 6cbf269..edf8ece 100644
--- a/forms/common-themes/src/main/resources/theme/admin/base/resources/partials/realm-ldap.html
+++ b/forms/common-themes/src/main/resources/theme/admin/base/resources/partials/realm-ldap.html
@@ -36,6 +36,12 @@
                     </div>
                 </div>
                 <div class="form-group clearfix">
+                    <label class="col-sm-2 control-label" for="userObjectClasses">User Object Classes <span class="required">*</span></label>
+                    <div class="col-sm-4">
+                        <input class="form-control" id="userObjectClasses" type="text" ng-model="realm.ldapServer.userObjectClasses" placeholder="LDAP User Object Classes (div. by comma)" required>
+                    </div>
+                </div>
+                <div class="form-group clearfix">
                     <label class="col-sm-2 control-label" for="ldapConnectionUrl">Connection URL <span class="required">*</span></label>
                     <div class="col-sm-4">
                         <input class="form-control" id="ldapConnectionUrl" type="text" ng-model="realm.ldapServer.connectionUrl" placeholder="LDAP connection URL" required>
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 49f61ab..3b6ac1c 100644
--- a/model/api/src/main/java/org/keycloak/models/LDAPConstants.java
+++ b/model/api/src/main/java/org/keycloak/models/LDAPConstants.java
@@ -11,6 +11,7 @@ public class LDAPConstants {
     public static final String VENDOR_OTHER = "other";
 
     public static final String USERNAME_LDAP_ATTRIBUTE = "usernameLDAPAttribute";
+    public static final String USER_OBJECT_CLASSES = "userObjectClasses";
 
     public static final String CONNECTION_URL = "connectionUrl";
     public static final String BASE_DN = "baseDn";
diff --git a/picketlink/keycloak-picketlink-realm/src/main/java/org/keycloak/picketlink/realm/PartitionManagerRegistry.java b/picketlink/keycloak-picketlink-realm/src/main/java/org/keycloak/picketlink/realm/PartitionManagerRegistry.java
index 84a62c2..a084eb4 100644
--- a/picketlink/keycloak-picketlink-realm/src/main/java/org/keycloak/picketlink/realm/PartitionManagerRegistry.java
+++ b/picketlink/keycloak-picketlink-realm/src/main/java/org/keycloak/picketlink/realm/PartitionManagerRegistry.java
@@ -91,6 +91,8 @@ public class PartitionManagerRegistry {
         String ldapLastNameMapping = getNameOfLDAPAttribute("keycloak.ldap.idm.lastName", SN, SN, activeDirectory);
         String ldapEmailMapping =  getNameOfLDAPAttribute("keycloak.ldap.idm.email", EMAIL, EMAIL, activeDirectory);
 
+        String[] userObjectClasses = getUserObjectClasses(ldapConfig);
+
         logger.infof("LDAP Attributes mapping: loginName: %s, firstName: %s, lastName: %s, email: %s", ldapLoginNameMapping, ldapFirstNameMapping, ldapLastNameMapping, ldapEmailMapping);
 
         // Use same mapping for User and Agent for now
@@ -108,7 +110,7 @@ public class PartitionManagerRegistry {
                         .supportAllFeatures()
                         .mapping(User.class)
                             .baseDN(ldapConfig.get(LDAPConstants.USER_DN_SUFFIX))
-                            .objectClasses("inetOrgPerson", "organizationalPerson")
+                            .objectClasses(userObjectClasses)
                             .attribute("loginName", ldapLoginNameMapping, true)
                             .attribute("firstName", ldapFirstNameMapping)
                             .attribute("lastName", ldapLastNameMapping)
@@ -138,6 +140,21 @@ public class PartitionManagerRegistry {
         return activeDirectory ? defaultAttrNameInActiveDirectory : defaultAttrName;
     }
 
+    // Parse array of strings like [ "inetOrgPerson", "organizationalPerson" ] from the string like: "inetOrgPerson, organizationalPerson"
+    private String[] getUserObjectClasses(Map<String,String> ldapConfig) {
+        String objClassesCfg = ldapConfig.get(LDAPConstants.USER_OBJECT_CLASSES);
+        String objClassesStr = (objClassesCfg != null && objClassesCfg.length() > 0) ? objClassesCfg.trim() : "inetOrgPerson, organizationalPerson";
+
+        String[] objectClasses = objClassesStr.split(",");
+
+        // Trim them
+        String[] userObjectClasses = new String[objectClasses.length];
+        for (int i=0 ; i<objectClasses.length ; i++) {
+            userObjectClasses[i] = objectClasses[i].trim();
+        }
+        return userObjectClasses;
+    }
+
     private class PartitionManagerContext {
 
         private PartitionManagerContext(Map<String,String> config, PartitionManager manager) {