Index: src/main/java/com/xpn/xwiki/plugin/ldap/XWikiLDAPUtils.java =================================================================== --- src/main/java/com/xpn/xwiki/plugin/ldap/XWikiLDAPUtils.java (revision 34210) +++ src/main/java/com/xpn/xwiki/plugin/ldap/XWikiLDAPUtils.java (working copy) @@ -27,6 +27,7 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Set; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -39,6 +40,10 @@ import com.novell.ldap.LDAPConnection; import com.xpn.xwiki.XWikiContext; import com.xpn.xwiki.XWikiException; +import com.xpn.xwiki.doc.XWikiDocument; +import com.xpn.xwiki.objects.BaseObject; +import com.xpn.xwiki.objects.classes.BaseClass; +import com.xpn.xwiki.user.impl.LDAP.LDAPProfileXClass; import com.xpn.xwiki.web.Utils; /** @@ -65,6 +70,11 @@ private static final String CACHE_NAME_GROUPS = "groups"; /** + * The name of the XWiki group member field. + */ + private static final String XWIKI_GROUP_MEMBERFIELD = "member"; + + /** * The configuration of the LDAP group cache. */ private static CacheConfiguration cacheConfigurationGroups; @@ -600,4 +610,305 @@ return userDN; } + + /** + * Update or create XWiki user base on LDAP. + * + * @param userProfile the name of the user. + * @param ldapDn the LDAP user DN. + * @param ldapUid the UID field. + * @param searchAttributeListIn the attributes of the LDAP user. + * @param context the XWiki context. + * @throws XWikiException error when updating or creating XWiki user. + */ + // TODO this method does a variable re-assignment on userProfile. + // This need to be investigated and refactored to avoid this need. + public void syncUser(XWikiDocument userProfile, List searchAttributeListIn, + String ldapDn, String ldapUid, XWikiContext context) throws XWikiException + { + // check if we have to create the user + XWikiLDAPConfig config = XWikiLDAPConfig.getInstance(); + + if (userProfile.isNew() || config.getLDAPParam("ldap_update_user", "0", context).equals("1")) { + + LOG.debug("LDAP attributes will be used to update XWiki attributes."); + + List searchAttributeList = searchAttributeListIn; + + // get attributes from LDAP if we don't already have them + if (searchAttributeList == null) { + // didn't get attributes before, so do it now + searchAttributeList = + this.getConnection().searchLDAP(ldapDn, null, getAttributeNameTable(context), + LDAPConnection.SCOPE_BASE); + } + + if (searchAttributeList == null) { + if (LOG.isDebugEnabled()) { + LOG.error("Can't find any attributes for user [" + ldapDn + "]"); + } + } + + if (userProfile.isNew()) { + LOG.debug("Creating new XWiki user based on LDAP attribues located at [" + ldapDn + "]"); + + userProfile = createUserFromLDAP(userProfile, searchAttributeList, ldapDn, ldapUid, context); + + LOG.debug("New XWiki user created: [" + userProfile.getDocumentReference() + "]"); + + } else { + + LOG.debug("Updating existing user with LDAP attribues located at " + ldapDn); + + try { + updateUserFromLDAP(userProfile, searchAttributeList, ldapDn, ldapUid, context); + } catch (XWikiException e) { + LOG.error("Failed to synchronise user's informations", e); + } + } + } + } + + /** + * Synchronize user XWiki membership with it's LDAP membership. + * + * @param xwikiUserName the name of the user. + * @param userDN the LDAP DN of the user. + * @param groupMappings the mapping between XWiki groups names and LDAP groups names. + * @param context the XWiki context. + * @throws XWikiException error when synchronizing user membership. + */ + public void syncGroupsMembership(String xwikiUserName, String userDN, Map> groupMappings, + XWikiContext context) throws XWikiException + { + if (LOG.isDebugEnabled()) { + LOG.debug("Updating group membership for the user: " + xwikiUserName); + } + + Collection xwikiUserGroupList = + context.getWiki().getGroupService(context).getAllGroupsNamesForMember(xwikiUserName, 0, 0, context); + + if (LOG.isDebugEnabled()) { + LOG.debug("The user belongs to following XWiki groups: "); + for (String userGroupName : xwikiUserGroupList) { + LOG.debug(userGroupName); + } + } + + // go through mapped groups to locate the user + for (Map.Entry> entry : groupMappings.entrySet()) { + String xwikiGrouNamep = entry.getKey(); + Set groupDNSet = entry.getValue(); + + if (xwikiUserGroupList.contains(xwikiGrouNamep)) { + if (!this.isMemberOfGroups(userDN, groupDNSet, context)) { + removeUserFromXWikiGroup(xwikiUserName, xwikiGrouNamep, context); + } + } else { + if (this.isMemberOfGroups(userDN, groupDNSet, context)) { + addUserToXWikiGroup(xwikiUserName, xwikiGrouNamep, context); + } + } + } + } + + /** + * @param context the XWiki context. + * @return the LDAP user attributes names. + */ + public String[] getAttributeNameTable(XWikiContext context) + { + String[] attributeNameTable = null; + + XWikiLDAPConfig config = XWikiLDAPConfig.getInstance(); + + List attributeNameList = new ArrayList(); + config.getUserMappings(attributeNameList, context); + + int lsize = attributeNameList.size(); + if (lsize > 0) { + attributeNameTable = attributeNameList.toArray(new String[lsize]); + } + + return attributeNameTable; + } + + /** + * Create an XWiki user and set all mapped attributes from LDAP to XWiki attributes. + * + * @param userProfile the XWiki user profile. + * @param searchAttributes the attributes. + * @param ldapDN the LDAP DN of the user. + * @param ldapUid the LDAP unique id of the user. + * @param context the XWiki context. + * @return the created user. + * @throws XWikiException error when creating XWiki user. + */ + protected XWikiDocument createUserFromLDAP(XWikiDocument userProfile, + List searchAttributes, String ldapDN, String ldapUid, XWikiContext context) + throws XWikiException + { + XWikiLDAPConfig config = XWikiLDAPConfig.getInstance(); + + Map userMappings = config.getUserMappings(null, context); + + if (LOG.isDebugEnabled()) { + LOG.debug("Start first synchronization of LDAP profile [" + searchAttributes + + "] with new user profile based on mapping " + userMappings); + } + + Map map = new HashMap(); + if (searchAttributes != null) { + for (XWikiLDAPSearchAttribute lattr : searchAttributes) { + String lval = lattr.value; + String xattr = userMappings.get(lattr.name.toLowerCase()); + + if (xattr == null) { + continue; + } + + map.put(xattr, lval); + } + } + + // Mark user active + map.put("active", "1"); + + context.getWiki().createUser(userProfile.getName(), map, context); + + // Update ldap profile object + XWikiDocument createdUserProfile = context.getWiki().getDocument(userProfile.getDocumentReference(), context); + LDAPProfileXClass ldapXClass = new LDAPProfileXClass(context); + + if (ldapXClass.updateLDAPObject(createdUserProfile, ldapDN, ldapUid)) { + context.getWiki().saveDocument(createdUserProfile, context); + } + + return createdUserProfile; + } + + /** + * Sets attributes on the user object based on attribute values provided by the LDAP. + * + * @param userProfile the XWiki user profile document. + * @param searchAttributes the attributes of the LDAP user to update. + * @param ldapDN the DN of the LDAP user to update + * @param ldapUid value of the unique identifier for the user to update. + * @param context the XWiki context. + * @throws XWikiException error when updating XWiki user. + */ + protected void updateUserFromLDAP(XWikiDocument userProfile, List searchAttributes, + String ldapDN, String ldapUid, XWikiContext context) throws XWikiException + { + XWikiLDAPConfig config = XWikiLDAPConfig.getInstance(); + + Map userMappings = config.getUserMappings(null, context); + + BaseClass userClass = context.getWiki().getUserClass(context); + + BaseObject userObj = userProfile.getXObject(userClass.getDocumentReference()); + + if (LOG.isDebugEnabled()) { + LOG.debug("Start synchronization of LDAP profile [" + searchAttributes + + "] with existing user profile based on mapping " + userMappings); + } + + Map map = new HashMap(); + if (searchAttributes != null) { + for (XWikiLDAPSearchAttribute lattr : searchAttributes) { + String key = userMappings.get(lattr.name.toLowerCase()); + if (key == null || userClass.get(key) == null) { + continue; + } + String value = lattr.value; + + String objValue = userObj.getStringValue(key); + if (objValue == null || !objValue.equals(value)) { + map.put(key, value); + } + } + } + + boolean needsUpdate = false; + if (!map.isEmpty()) { + userClass.fromMap(map, userObj); + needsUpdate = true; + } + + // Update ldap profile object + LDAPProfileXClass ldaXClass = new LDAPProfileXClass(context); + needsUpdate |= ldaXClass.updateLDAPObject(userProfile, ldapDN, ldapUid); + + if (needsUpdate) { + context.getWiki().saveDocument(userProfile, "Synchronized user profile with LDAP server", true, context); + } + } + + /** + * Add user name to provided XWiki group. + * + * @param xwikiUserName the full name of the user. + * @param groupName the name of the group. + * @param context the XWiki context. + */ + // TODO move this methods in a toolkit for all platform. + protected void addUserToXWikiGroup(String xwikiUserName, String groupName, XWikiContext context) + { + try { + if (LOG.isDebugEnabled()) { + LOG.debug(MessageFormat.format("Adding user {0} to xwiki group {1}", xwikiUserName, groupName)); + } + + BaseClass groupClass = context.getWiki().getGroupClass(context); + + // Get document representing group + XWikiDocument groupDoc = context.getWiki().getDocument(groupName, context); + + // Add a member object to document + BaseObject memberObj = groupDoc.newXObject(groupClass.getDocumentReference(), context); + Map map = new HashMap(); + map.put(XWIKI_GROUP_MEMBERFIELD, xwikiUserName); + groupClass.fromMap(map, memberObj); + + // Save modifications + context.getWiki().saveDocument(groupDoc, context); + + if (LOG.isDebugEnabled()) { + LOG.debug(MessageFormat.format("Finished adding user {0} to xwiki group {1}", + xwikiUserName, groupName)); + } + + } catch (Exception e) { + LOG.error(MessageFormat.format("Failed to add a user [{0}] to a group [{1}]", xwikiUserName, groupName), e); + } + } + + /** + * Remove user name from provided XWiki group. + * + * @param xwikiUserName the full name of the user. + * @param groupName the name of the group. + * @param context the XWiki context. + */ + // TODO move this methods in a toolkit for all platform. + protected void removeUserFromXWikiGroup(String xwikiUserName, String groupName, XWikiContext context) + { + try { + BaseClass groupClass = context.getWiki().getGroupClass(context); + + // Get the XWiki document holding the objects comprising the group membership list + XWikiDocument groupDoc = context.getWiki().getDocument(groupName, context); + + // Get and remove the specific group membership object for the user + BaseObject groupObj = + groupDoc.getXObject(groupClass.getDocumentReference(), XWIKI_GROUP_MEMBERFIELD, xwikiUserName); + groupDoc.removeXObject(groupObj); + + // Save modifications + context.getWiki().saveDocument(groupDoc, context); + } catch (Exception e) { + LOG.error("Failed to remove a user from a group " + xwikiUserName + " group: " + groupName, e); + } + } + } Index: src/main/java/com/xpn/xwiki/user/impl/LDAP/XWikiLDAPAuthServiceImpl.java =================================================================== --- src/main/java/com/xpn/xwiki/user/impl/LDAP/XWikiLDAPAuthServiceImpl.java (revision 34210) +++ src/main/java/com/xpn/xwiki/user/impl/LDAP/XWikiLDAPAuthServiceImpl.java (working copy) @@ -459,7 +459,9 @@ /** * @param context the XWiki context. * @return the LDAP user attributes names. + * @deprecated since 2.7.1 and 3.0-M1. Use {@link XWikiLDAPUtils#getAttributeNameTable(XWikiContext)} instead. */ + @Deprecated public String[] getAttributeNameTable(XWikiContext context) { String[] attributeNameTable = null; @@ -490,52 +492,7 @@ protected void syncUser(XWikiDocument userProfile, List searchAttributeListIn, String ldapDn, String ldapUid, XWikiLDAPUtils ldapUtils, XWikiContext context) throws XWikiException { - // check if we have to create the user - XWikiLDAPConfig config = XWikiLDAPConfig.getInstance(); - - if (userProfile.isNew() || config.getLDAPParam("ldap_update_user", "0", context).equals("1")) { - if (LOG.isDebugEnabled()) { - LOG.debug("LDAP attributes will be used to update XWiki attributes."); - } - - List searchAttributeList = searchAttributeListIn; - - // get attributes from LDAP if we don't already have them - if (searchAttributeList == null) { - // didn't get attributes before, so do it now - searchAttributeList = - ldapUtils.getConnection().searchLDAP(ldapDn, null, getAttributeNameTable(context), - LDAPConnection.SCOPE_BASE); - - if (searchAttributeList == null) { - if (LOG.isDebugEnabled()) { - LOG.error("Can't find any attributes for user [" + ldapDn + "]"); - } - } - } - - if (userProfile.isNew()) { - if (LOG.isDebugEnabled()) { - LOG.debug("Creating new XWiki user based on LDAP attribues located at [" + ldapDn + "]"); - } - - userProfile = createUserFromLDAP(userProfile, searchAttributeList, ldapDn, ldapUid, context); - - if (LOG.isDebugEnabled()) { - LOG.debug("New XWiki user created: [" + userProfile.getDocumentReference() + "]"); - } - } else { - if (LOG.isDebugEnabled()) { - LOG.debug("Updating existing user with LDAP attribues located at " + ldapDn); - } - - try { - updateUserFromLDAP(userProfile, searchAttributeList, ldapDn, ldapUid, context); - } catch (XWikiException e) { - LOG.error("Failed to synchronise user's informations", e); - } - } - } + ldapUtils.syncUser(userProfile, searchAttributeListIn, ldapDn, ldapUid, context); } /** @@ -581,212 +538,9 @@ protected void syncGroupsMembership(String xwikiUserName, String userDN, Map> groupMappings, XWikiLDAPUtils ldapUtils, XWikiContext context) throws XWikiException { - if (LOG.isDebugEnabled()) { - LOG.debug("Updating group membership for the user: " + xwikiUserName); - } - - Collection xwikiUserGroupList = - context.getWiki().getGroupService(context).getAllGroupsNamesForMember(xwikiUserName, 0, 0, context); - - if (LOG.isDebugEnabled()) { - LOG.debug("The user belongs to following XWiki groups: "); - for (String userGroupName : xwikiUserGroupList) { - LOG.debug(userGroupName); - } - } - - // go through mapped groups to locate the user - for (Map.Entry> entry : groupMappings.entrySet()) { - String xwikiGrouNamep = entry.getKey(); - Set groupDNSet = entry.getValue(); - - if (xwikiUserGroupList.contains(xwikiGrouNamep)) { - if (!ldapUtils.isMemberOfGroups(userDN, groupDNSet, context)) { - removeUserFromXWikiGroup(xwikiUserName, xwikiGrouNamep, context); - } - } else { - if (ldapUtils.isMemberOfGroups(userDN, groupDNSet, context)) { - addUserToXWikiGroup(xwikiUserName, xwikiGrouNamep, context); - } - } - } + ldapUtils.syncGroupsMembership(xwikiUserName, userDN, groupMappings, context); } - /** - * Add user name to provided XWiki group. - * - * @param xwikiUserName the full name of the user. - * @param groupName the name of the group. - * @param context the XWiki context. - */ - // TODO move this methods in a toolkit for all platform. - protected void addUserToXWikiGroup(String xwikiUserName, String groupName, XWikiContext context) - { - try { - if (LOG.isDebugEnabled()) { - LOG.debug(MessageFormat.format("Adding user {0} to xwiki group {1}", xwikiUserName, groupName)); - } - - BaseClass groupClass = context.getWiki().getGroupClass(context); - - // Get document representing group - XWikiDocument groupDoc = context.getWiki().getDocument(groupName, context); - - // Add a member object to document - BaseObject memberObj = groupDoc.newXObject(groupClass.getDocumentReference(), context); - Map map = new HashMap(); - map.put(XWIKI_GROUP_MEMBERFIELD, xwikiUserName); - groupClass.fromMap(map, memberObj); - - // Save modifications - context.getWiki().saveDocument(groupDoc, context); - - if (LOG.isDebugEnabled()) { - LOG.debug(MessageFormat.format("Finished adding user {0} to xwiki group {1}", xwikiUserName, groupName)); - } - - } catch (Exception e) { - LOG.error(MessageFormat.format("Failed to add a user [{0}] to a group [{1}]", xwikiUserName, groupName), e); - } - } - - /** - * Remove user name from provided XWiki group. - * - * @param xwikiUserName the full name of the user. - * @param groupName the name of the group. - * @param context the XWiki context. - */ - // TODO move this methods in a toolkit for all platform. - protected void removeUserFromXWikiGroup(String xwikiUserName, String groupName, XWikiContext context) - { - try { - BaseClass groupClass = context.getWiki().getGroupClass(context); - - // Get the XWiki document holding the objects comprising the group membership list - XWikiDocument groupDoc = context.getWiki().getDocument(groupName, context); - - // Get and remove the specific group membership object for the user - BaseObject groupObj = - groupDoc.getXObject(groupClass.getDocumentReference(), XWIKI_GROUP_MEMBERFIELD, xwikiUserName); - groupDoc.removeXObject(groupObj); - - // Save modifications - context.getWiki().saveDocument(groupDoc, context); - } catch (Exception e) { - LOG.error("Failed to remove a user from a group " + xwikiUserName + " group: " + groupName, e); - } - } - - /** - * Sets attributes on the user object based on attribute values provided by the LDAP. - * - * @param xwikiUserName the XWiki user name. - * @param searchAttributes the attributes. - * @param context the XWiki context. - * @throws XWikiException error when updating XWiki user. - */ - protected void updateUserFromLDAP(XWikiDocument userProfile, List searchAttributes, - String ldapDN, String ldapUid, XWikiContext context) throws XWikiException - { - XWikiLDAPConfig config = XWikiLDAPConfig.getInstance(); - - Map userMappings = config.getUserMappings(null, context); - - BaseClass userClass = context.getWiki().getUserClass(context); - - BaseObject userObj = userProfile.getXObject(userClass.getDocumentReference()); - - if (LOG.isDebugEnabled()) { - LOG.debug("Start synchronising LDAP profile [" + searchAttributes + "] with user profile based on mapping " - + userMappings); - } - - Map map = new HashMap(); - if (searchAttributes != null) { - for (XWikiLDAPSearchAttribute lattr : searchAttributes) { - String key = userMappings.get(lattr.name.toLowerCase()); - if (key == null || userClass.get(key) == null) { - continue; - } - String value = lattr.value; - - String objValue = userObj.getStringValue(key); - if (objValue == null || !objValue.equals(value)) { - map.put(key, value); - } - } - } - - boolean needsUpdate = false; - if (!map.isEmpty()) { - userClass.fromMap(map, userObj); - needsUpdate = true; - } - - // Update ldap profile object - LDAPProfileXClass ldaXClass = new LDAPProfileXClass(context); - needsUpdate |= ldaXClass.updateLDAPObject(userProfile, ldapDN, ldapUid); - - if (needsUpdate) { - context.getWiki().saveDocument(userProfile, "Synchronized user profile with LDAP server", true, context); - } - } - - /** - * Create an XWiki user and set all mapped attributes from LDAP to XWiki attributes. - * - * @param userProfile the XWiki user profile. - * @param searchAttributes the attributes. - * @param ldapDN the LDAP DN of the user. - * @param ldapUid the LDAP unique id of the user. - * @param context the XWiki context. - * @return the created user. - * @throws XWikiException error when creating XWiki user. - */ - protected XWikiDocument createUserFromLDAP(XWikiDocument userProfile, - List searchAttributes, String ldapDN, String ldapUid, XWikiContext context) - throws XWikiException - { - XWikiLDAPConfig config = XWikiLDAPConfig.getInstance(); - - Map userMappings = config.getUserMappings(null, context); - - if (LOG.isDebugEnabled()) { - LOG.debug("Start synchronising LDAP profile [" + searchAttributes + "] with user profile based on mapping " - + userMappings); - } - - Map map = new HashMap(); - if (searchAttributes != null) { - for (XWikiLDAPSearchAttribute lattr : searchAttributes) { - String lval = lattr.value; - String xattr = userMappings.get(lattr.name.toLowerCase()); - - if (xattr == null) { - continue; - } - - map.put(xattr, lval); - } - } - - // Mark user active - map.put("active", "1"); - - context.getWiki().createUser(userProfile.getName(), map, context); - - // Update ldap profile object - XWikiDocument createdUserProfile = context.getWiki().getDocument(userProfile.getDocumentReference(), context); - LDAPProfileXClass ldapXClass = new LDAPProfileXClass(context); - - if (ldapXClass.updateLDAPObject(createdUserProfile, ldapDN, ldapUid)) { - context.getWiki().saveDocument(createdUserProfile, context); - } - - return createdUserProfile; - } - protected XWikiDocument getUserProfileByUid(String validXWikiUserName, String ldapUid, XWikiContext context) throws XWikiException { Index: pom.xml =================================================================== --- pom.xml (revision 34210) +++ pom.xml (working copy) @@ -1152,6 +1152,9 @@ **/plugin/graphviz/GraphVizPlugin.java, **/plugin/ldap/LDAPPluginApi.java, **/plugin/ldap/LDAPPlugin.java, + **/plugin/mail/MailPluginApi.java, **/plugin/mail/MailPlugin.java, **/plugin/packaging/DocumentFilter.java,