/** * <a href="http://www.openolat.org"> * OpenOLAT - Online Learning and Training</a><br> * <p> * Licensed under the Apache License, Version 2.0 (the "License"); <br> * you may not use this file except in compliance with the License.<br> * You may obtain a copy of the License at the * <a href="http://www.apache.org/licenses/LICENSE-2.0">Apache homepage</a> * <p> * Unless required by applicable law or agreed to in writing,<br> * software distributed under the License is distributed on an "AS IS" BASIS, <br> * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br> * See the License for the specific language governing permissions and <br> * limitations under the License. * <p> * Initial code contributed and copyrighted by<br> * frentix GmbH, http://www.frentix.com * <p> */ package org.olat.ldap; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.Set; import javax.naming.directory.Attributes; import org.olat.core.logging.OLog; import org.olat.core.logging.Tracing; import org.olat.core.util.StringHelper; import org.olat.user.UserManager; import org.olat.user.propertyhandlers.UserPropertyHandler; /** * * Hold all configurations to use a LDAP server to sync * users with OpenOLAT.<br /> * * Initial date: 24.11.2014<br> * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com * */ public class LDAPSyncConfiguration { private static final OLog log = Tracing.createLoggerFor(LDAPSyncConfiguration.class); private String ldapUserFilter; private String ldapGroupFilter; private List<String> ldapBases; private List<String> ldapGroupBases; private String ldapUserCreatedTimestampAttribute; private String ldapUserLastModifiedTimestampAttribute; private String ldapUserPasswordAttribute; private String ldapUserLoginAttribute; private String[] userAttributes; private String coachRoleAttribute; private String coachRoleValue; private String groupAttribute; private String groupAttributeSeparator; private String coachedGroupAttribute; private String coachedGroupAttributeSeparator; private Map<String, String> requestAttributes; private Map<String, String> userAttributeMap; private Set<String> syncOnlyOnCreateProperties; private List<String> authorsGroupBase; private String authorRoleAttribute; private String authorRoleValue; private List<String> userManagersGroupBase; private String userManagerRoleAttribute; private String userManagerRoleValue; private List<String> groupManagersGroupBase; private String groupManagerRoleAttribute; private String groupManagerRoleValue; private List<String> qpoolManagersGroupBase; private String qpoolManagerRoleAttribute; private String qpoolManagerRoleValue; private List<String> learningResourceManagersGroupBase; private String learningResourceManagerRoleAttribute; private String learningResourceManagerRoleValue; /** * Static user properties that should be added to user when syncing */ private Map<String, String> staticUserProperties; private UserManager userManager; /** * [used by Spring] * @param userManager */ public void setUserManager(UserManager userManager) { this.userManager = userManager; } public String getLdapUserCreatedTimestampAttribute() { return ldapUserCreatedTimestampAttribute; } public List<String> getLdapBases() { return ldapBases; } public void setLdapBases(List<String> bases) { ldapBases = toList(bases); } public List<String> getLdapGroupBases() { return ldapGroupBases; } public void setLdapGroupBases(List<String> bases) { ldapGroupBases = toList(bases); } private List<String> toList(List<String> list) { List<String> listToUse = new ArrayList<String>(); if (list != null) { for (String entry : list) { if (StringHelper.containsNonWhitespace(entry) && entry.contains("!#")) { String[] oneLineList = entry.split("!#"); for (String oneLineEntry : oneLineList) { if (StringHelper.containsNonWhitespace(oneLineEntry)) { listToUse.add(oneLineEntry.trim()); } } } else if (StringHelper.containsNonWhitespace(entry)) { listToUse.add(entry.trim()); } } } return listToUse; } /** * @return A filter expression enclosed in () brackets to filter for valid users or NULL for no filtering */ public String getLdapUserFilter() { return ldapUserFilter; } public void setLdapUserFilter(String filter) { if (StringHelper.containsNonWhitespace(filter)) { ldapUserFilter = filter.trim(); } else { // set explicitly to null for no filter ldapUserFilter = null; } } public String getLdapGroupFilter() { return ldapGroupFilter; } public void setLdapGroupFilter(String filter) { if (StringHelper.containsNonWhitespace(filter)) { ldapGroupFilter = filter.trim(); } else { ldapGroupFilter = null; } } public boolean syncGroupWithLDAPGroup() { return ldapGroupBases != null && ldapGroupBases.size() > 0; } public boolean syncGroupWithAttribute() { return StringHelper.containsNonWhitespace(groupAttribute) || StringHelper.containsNonWhitespace(coachedGroupAttribute); } public String getCoachRoleAttribute() { return coachRoleAttribute; } public void setCoachRoleAttribute(String attribute) { this.coachRoleAttribute = attribute; } public String getCoachRoleValue() { return coachRoleValue; } public void setCoachRoleValue(String coachRoleValue) { this.coachRoleValue = coachRoleValue; } public String getGroupAttribute() { return groupAttribute; } public void setGroupAttribute(String attribute) { this.groupAttribute = attribute; } public String getGroupAttributeSeparator() { return groupAttributeSeparator; } public void setGroupAttributeSeparator(String groupAttributeSeparator) { this.groupAttributeSeparator = groupAttributeSeparator; } public String getCoachedGroupAttribute() { return coachedGroupAttribute; } public void setCoachedGroupAttribute(String coachedGroupAttribute) { this.coachedGroupAttribute = coachedGroupAttribute; } public String getCoachedGroupAttributeSeparator() { return coachedGroupAttributeSeparator; } public void setCoachedGroupAttributeSeparator(String coachedGroupAttributeSeparator) { this.coachedGroupAttributeSeparator = coachedGroupAttributeSeparator; } public List<String> getAuthorsGroupBase() { return authorsGroupBase; } public void setAuthorsGroupBase(List<String> bases) { authorsGroupBase = toList(bases); } public String getAuthorRoleAttribute() { return authorRoleAttribute; } public void setAuthorRoleAttribute(String attribute) { this.authorRoleAttribute = attribute; } public String getAuthorRoleValue() { return authorRoleValue; } public void setAuthorRoleValue(String value) { this.authorRoleValue = value; } public List<String> getUserManagersGroupBase() { return userManagersGroupBase; } public void setUserManagersGroupBase(List<String> bases) { userManagersGroupBase = toList(bases); } public String getUserManagerRoleAttribute() { return userManagerRoleAttribute; } public void setUserManagerRoleAttribute(String attribute) { userManagerRoleAttribute = attribute; } public String getUserManagerRoleValue() { return userManagerRoleValue; } public void setUserManagerRoleValue(String value) { userManagerRoleValue = value; } public List<String> getGroupManagersGroupBase() { return groupManagersGroupBase; } public void setGroupManagersGroupBase(List<String> bases) { this.groupManagersGroupBase = toList(bases); } public String getGroupManagerRoleAttribute() { return groupManagerRoleAttribute; } public void setGroupManagerRoleAttribute(String attribute) { this.groupManagerRoleAttribute = attribute; } public String getGroupManagerRoleValue() { return groupManagerRoleValue; } public void setGroupManagerRoleValue(String value) { this.groupManagerRoleValue = value; } public List<String> getQpoolManagersGroupBase() { return qpoolManagersGroupBase; } public void setQpoolManagersGroupBase(List<String> bases) { this.qpoolManagersGroupBase = toList(bases); } public String getQpoolManagerRoleAttribute() { return qpoolManagerRoleAttribute; } public void setQpoolManagerRoleAttribute(String attribute) { this.qpoolManagerRoleAttribute = attribute; } public String getQpoolManagerRoleValue() { return qpoolManagerRoleValue; } public void setQpoolManagerRoleValue(String value) { this.qpoolManagerRoleValue = value; } public List<String> getLearningResourceManagersGroupBase() { return learningResourceManagersGroupBase; } public void setLearningResourceManagersGroupBase(List<String> bases) { this.learningResourceManagersGroupBase = toList(bases); } public String getLearningResourceManagerRoleAttribute() { return learningResourceManagerRoleAttribute; } public void setLearningResourceManagerRoleAttribute(String attribute) { this.learningResourceManagerRoleAttribute = attribute; } public String getLearningResourceManagerRoleValue() { return learningResourceManagerRoleValue; } public void setLearningResourceManagerRoleValue(String attribute) { this.learningResourceManagerRoleValue = attribute; } public void setLdapUserCreatedTimestampAttribute(String attribute) { this.ldapUserCreatedTimestampAttribute = attribute; } public String getLdapUserLastModifiedTimestampAttribute() { return ldapUserLastModifiedTimestampAttribute; } public void setLdapUserLastModifiedTimestampAttribute(String attribute) { this.ldapUserLastModifiedTimestampAttribute = attribute; } public String getLdapUserPasswordAttribute() { return ldapUserPasswordAttribute; } public void setLdapUserPasswordAttribute(String attribute) { this.ldapUserPasswordAttribute = attribute; } public String getLdapUserLoginAttribute() { return ldapUserLoginAttribute; } public void setLdapUserLoginAttribute(String ldapUserLoginAttribute) { this.ldapUserLoginAttribute = ldapUserLoginAttribute; } public Map<String, String> getRequestAttributes() { return requestAttributes; } public void setRequestAttributes(Map<String, String> mapping) { requestAttributes = new HashMap<String, String>(); for (Map.Entry<String, String> entry : mapping.entrySet()) { requestAttributes.put(entry.getKey().trim(), entry.getValue().trim()); } } public String[] getUserAttributes() { return userAttributes; } public Map<String, String> getUserAttributeMap() { return userAttributeMap; } public void setUserAttributeMap(Map<String, String> mapping) { userAttributeMap = new HashMap<String, String>(); for (Entry<String, String> entry : mapping.entrySet()) { String ldapAttrib = entry.getKey(); String olatProp = entry.getValue(); if (StringHelper.containsNonWhitespace(ldapAttrib) && StringHelper.containsNonWhitespace(olatProp)){ userAttributeMap.put(ldapAttrib.trim(), olatProp.trim()); } } // optimizes for later usage userAttributes = userAttributeMap.keySet().toArray(new String[userAttributeMap.size()]); } public Map<String, String> getStaticUserProperties() { return staticUserProperties; } public void setStaticUserProperties(Map<String, String> mapping) { staticUserProperties = new HashMap<String, String>(); for (Map.Entry<String, String> entry : mapping.entrySet()) { String olatPropKey = entry.getKey(); String staticValue = entry.getValue(); if (StringHelper.containsNonWhitespace(olatPropKey) && StringHelper.containsNonWhitespace(staticValue)){ staticUserProperties.put(olatPropKey.trim(), staticValue.trim()); } } } public Set<String> getSyncOnlyOnCreateProperties() { return syncOnlyOnCreateProperties; } public void setSyncOnlyOnCreateProperties(Set<String> properties) { syncOnlyOnCreateProperties = new HashSet<String>(); for (String property : properties) { if (StringHelper.containsNonWhitespace(property)){ syncOnlyOnCreateProperties.add(property.trim()); } } } /** * Checks if defined OLAT Properties in olatextconfig.xml exist in OLAT. * * Configuration: LDAP Attributes Map = olatextconfig.xml (property=reqAttrs, property=userAttributeMapper) * * @param attrs Map of OLAT Properties from of the LDAP configuration * @return true All exist OK, false Error * */ protected boolean checkIfOlatPropertiesExists(Map<String, String> attrs) { List<UserPropertyHandler> upHandler = userManager.getAllUserPropertyHandlers(); for (String ldapAttribute : attrs.keySet()) { boolean propertyExists = false; String olatProperty = attrs.get(ldapAttribute); if (olatProperty.equals(LDAPConstants.LDAP_USER_IDENTIFYER)) { // LDAP user identifyer is not a user propery, it's the username continue; } for (UserPropertyHandler userPropItr : upHandler) { if (olatProperty.equals(userPropItr.getName())) { // ok, this property exist, continue with next one propertyExists = true; break; } } if ( ! propertyExists ) { log.error("Error in checkIfOlatPropertiesExists(): configured LDAP attribute::" + ldapAttribute + " configured to map to OLAT user property::" + olatProperty + " but no such user property configured in olat_userconfig.xml"); return false; } } return true; } /** * Checks if defined Static OLAT Property in olatextconfig.xml exist in OLAT. * * Configuration: olatextconfig.xml (property=staticUserProperties) * * @param olatProperties Set of OLAT Properties from of the LDAP configuration * @return true All exist OK, false Error * */ protected boolean checkIfStaticOlatPropertiesExists(Set<String> olatProperties) { List<UserPropertyHandler> upHandler = userManager.getAllUserPropertyHandlers(); for (String olatProperty : olatProperties) { boolean propertyExists = false; for (UserPropertyHandler userPropItr : upHandler) { if (olatProperty.equals(userPropItr.getName())) { // ok, this property exist, continue with next one propertyExists = true; break; } } if ( ! propertyExists ) { log.error("Error in checkIfStaticOlatPropertiesExists(): configured static OLAT user property::" + olatProperty + " is not configured in olat_userconfig.xml"); return false; } } return true; } /** * Checks if Collection of naming Attributes contain defined required properties for OLAT * * * Configuration: LDAP Required Map = olatextconfig.xml (property=reqAttrs) * * @param attributes Collection of LDAP Naming Attribute * @return null If all required Attributes are found, otherwise String[] of missing Attributes * */ public String[] checkRequestAttributes(Attributes attrs) { Map<String, String> reqAttrMap = getRequestAttributes(); String[] missingAttr = new String[reqAttrMap.size()]; int y = 0; for (String attKey : reqAttrMap.keySet()) { attKey = attKey.trim(); if (attrs.get(attKey) == null) { missingAttr[y++] = attKey; } } return (y == 0) ? null : missingAttr; } /** * Maps OLAT Property to the LDAP Attributes * * Configuration: LDAP Attributes Map = ldapContext.xml (property=userAttrs) * * @param olatProperty OLAT Property attribute ID * @return LDAP Attribute */ public String getOlatPropertyToLdapAttribute(String olatProperty) { Map<String, String> userAttrMapper = getRequestAttributes(); if (userAttrMapper.containsValue(olatProperty)) { Iterator<String> itr = userAttrMapper.keySet().iterator(); while (itr.hasNext()) { String key = itr.next(); if (userAttrMapper.get(key).compareTo(olatProperty) == 0) return key; } } return null; } }