Index: lams_admin/conf/language/lams/ApplicationResources.properties =================================================================== RCS file: /usr/local/cvsroot/lams_admin/conf/language/lams/ApplicationResources.properties,v diff -u -r1.10.2.2 -r1.10.2.3 --- lams_admin/conf/language/lams/ApplicationResources.properties 20 Sep 2007 02:54:16 -0000 1.10.2.2 +++ lams_admin/conf/language/lams/ApplicationResources.properties 28 Sep 2007 01:35:21 -0000 1.10.2.3 @@ -258,6 +258,12 @@ msg.done =Synchronise done! msg.tool.management =Tool Management sysadmin.tool.management =Tool Management +msg.ldap.synchronise.wait = Please wait while synchronisation completes... +msg.ldap.synchronise.errors = The following errors were encountered: +msg.num.search.results.users = LDAP server returned {0} users. +msg.num.created.users = {0} users were created in LAMS. +msg.num.updated.users = {0} users already existed in LAMS and were updated. +msg.num.disabled.users = {0} users were disabled in LAMS. #======= End labels: Exported 254 labels for en AU ===== Index: lams_admin/conf/language/lams/ApplicationResources_en_AU.properties =================================================================== RCS file: /usr/local/cvsroot/lams_admin/conf/language/lams/ApplicationResources_en_AU.properties,v diff -u -r1.10.2.2 -r1.10.2.3 --- lams_admin/conf/language/lams/ApplicationResources_en_AU.properties 20 Sep 2007 02:54:16 -0000 1.10.2.2 +++ lams_admin/conf/language/lams/ApplicationResources_en_AU.properties 28 Sep 2007 01:35:21 -0000 1.10.2.3 @@ -258,6 +258,12 @@ msg.done =Synchronise done! msg.tool.management =Tool Management sysadmin.tool.management =Tool Management +msg.ldap.synchronise.wait = Please wait while synchronisation completes... +msg.ldap.synchronise.errors = The following errors were encountered: +msg.num.search.results.users = LDAP server returned {0} users. +msg.num.created.users = {0} users were created in LAMS. +msg.num.updated.users = {0} users already existed in LAMS and were updated. +msg.num.disabled.users = {0} users were disabled in LAMS. #======= End labels: Exported 254 labels for en AU ===== Index: lams_admin/src/java/org/lamsfoundation/lams/admin/web/action/LdapConfigAction.java =================================================================== RCS file: /usr/local/cvsroot/lams_admin/src/java/org/lamsfoundation/lams/admin/web/action/LdapConfigAction.java,v diff -u -r1.1.2.1 -r1.1.2.2 --- lams_admin/src/java/org/lamsfoundation/lams/admin/web/action/LdapConfigAction.java 18 Sep 2007 07:20:48 -0000 1.1.2.1 +++ lams_admin/src/java/org/lamsfoundation/lams/admin/web/action/LdapConfigAction.java 28 Sep 2007 01:35:21 -0000 1.1.2.2 @@ -37,6 +37,7 @@ import org.lamsfoundation.lams.admin.service.AdminServiceProxy; import org.lamsfoundation.lams.usermanagement.AuthenticationMethod; import org.lamsfoundation.lams.usermanagement.User; +import org.lamsfoundation.lams.usermanagement.dto.BulkUpdateResultDTO; import org.lamsfoundation.lams.usermanagement.service.IUserManagementService; import org.lamsfoundation.lams.usermanagement.service.LdapService; import org.lamsfoundation.lams.util.MessageService; @@ -85,28 +86,13 @@ HttpServletRequest request, HttpServletResponse response) throws Exception { - // check if url contains request for refresh folder sizes only String action = WebUtil.readStrParam(request, "action", true); if (action != null && StringUtils.equals(action, "sync")) { return sync(mapping, form, request, response); } - // get number of ldap users - List ldapUsers = getService().findByProperty( - User.class, - "authenticationMethod.authenticationMethodId", - AuthenticationMethod.LDAP - ); - if (ldapUsers != null) { - int numLdapUsers = ldapUsers.size(); - request.setAttribute( - "numLdapUsersMsg", - getMessageService().getMessage( - "msg.num.ldap.users", - getNumLdapUsersMessage(numLdapUsers) - ) - ); - } + int numLdapUsers = getNumLdapUsers(); + request.setAttribute("numLdapUsersMsg", getNumLdapUsersMsg(numLdapUsers)); return mapping.findForward("ldap"); } @@ -117,23 +103,65 @@ HttpServletResponse response) throws Exception { log.info("=== Beginning LDAP user sync ==="); - int numLdapUsers = getLdapService().updateLAMSFromLdap(); + long start = System.currentTimeMillis(); + BulkUpdateResultDTO dto = getLdapService().bulkUpdate(); + long end = System.currentTimeMillis(); log.info("=== Finished LDAP user sync ==="); - request.setAttribute( - "numLdapUsersMsg", - getMessageService().getMessage( - "msg.num.ldap.users", - getNumLdapUsersMessage(numLdapUsers) - ) - ); + log.info("Bulk update took " + (end-start)/1000 + " seconds."); + + int numLdapUsers = getNumLdapUsers(); + request.setAttribute("numLdapUsersMsg", getNumLdapUsersMsg(numLdapUsers)); + + request.setAttribute("numSearchResults", getNumSearchResultsUsersMsg(dto.getNumSearchResults())); + request.setAttribute("numLdapUsersCreated", getNumCreatedUsersMsg(dto.getNumUsersCreated())); + request.setAttribute("numLdapUsersUpdated", getNumUpdatedUsersMsg(dto.getNumUsersUpdated())); + request.setAttribute("numLdapUsersDisabled", getNumDisabledUsersMsg(dto.getNumUsersDisabled())); + request.setAttribute("messages", dto.getMessages()); request.setAttribute("done", getMessageService().getMessage("msg.done")); return mapping.findForward("ldap"); } - private String[] getNumLdapUsersMessage(int numLdapUsers) { + private int getNumLdapUsers() { + // get number of ldap users + List ldapUsers = getService().findByProperty( + User.class, + "authenticationMethod.authenticationMethodId", + AuthenticationMethod.LDAP + ); + if (ldapUsers != null) { + return ldapUsers.size(); + } + return -1; + } + + private String getNumLdapUsersMsg(int numLdapUsers) { String[] args = new String[1]; args[0] = String.valueOf(numLdapUsers); - return args; + return getMessageService().getMessage("msg.num.ldap.users", args); } + + private String getNumSearchResultsUsersMsg(int searchResults) { + String[] args = new String[1]; + args[0] = String.valueOf(searchResults); + return getMessageService().getMessage("msg.num.search.results.users", args); + } + + private String getNumCreatedUsersMsg(int created) { + String[] args = new String[1]; + args[0] = String.valueOf(created); + return getMessageService().getMessage("msg.num.created.users", args); + } + + private String getNumUpdatedUsersMsg(int updated) { + String[] args = new String[1]; + args[0] = String.valueOf(updated); + return getMessageService().getMessage("msg.num.updated.users", args); + } + + private String getNumDisabledUsersMsg(int disabled) { + String[] args = new String[1]; + args[0] = String.valueOf(disabled); + return getMessageService().getMessage("msg.num.disabled.users", args); + } } Index: lams_admin/web/ldap.jsp =================================================================== RCS file: /usr/local/cvsroot/lams_admin/web/ldap.jsp,v diff -u -r1.2.2.1 -r1.2.2.2 --- lams_admin/web/ldap.jsp 18 Sep 2007 07:20:49 -0000 1.2.2.1 +++ lams_admin/web/ldap.jsp 28 Sep 2007 01:35:21 -0000 1.2.2.2 @@ -1,5 +1,12 @@ <%@ include file="/taglibs.jsp"%> + +

:

@@ -19,15 +26,37 @@

- -

-
-

+ + + + +

 

+

+ +
+ Index: lams_central/src/java/org/lamsfoundation/lams/security/LDAPAuthenticator.java =================================================================== RCS file: /usr/local/cvsroot/lams_central/src/java/org/lamsfoundation/lams/security/LDAPAuthenticator.java,v diff -u -r1.6.2.2 -r1.6.2.3 --- lams_central/src/java/org/lamsfoundation/lams/security/LDAPAuthenticator.java 25 Sep 2007 01:38:36 -0000 1.6.2.2 +++ lams_central/src/java/org/lamsfoundation/lams/security/LDAPAuthenticator.java 28 Sep 2007 01:35:21 -0000 1.6.2.3 @@ -92,9 +92,7 @@ env.setProperty(Context.SECURITY_AUTHENTICATION, Configuration.get(ConfigurationKeys.LDAP_SECURITY_AUTHENTICATION)); String principalDNPrefix = Configuration.get(ConfigurationKeys.LDAP_PRINCIPAL_DN_PREFIX); - String principalDNSuffix = Configuration.get(ConfigurationKeys.LDAP_PRINCIPAL_DN_SUFFIX); - String userDN = principalDNPrefix + username + principalDNSuffix; - env.setProperty(Context.SECURITY_PRINCIPAL, userDN); + String[] principalDNSuffixes = Configuration.get(ConfigurationKeys.LDAP_PRINCIPAL_DN_SUFFIX).split(";"); env.setProperty(Context.PROVIDER_URL, Configuration.get(ConfigurationKeys.LDAP_PROVIDER_URL)); env.put(Context.SECURITY_CREDENTIALS, credential); @@ -114,61 +112,69 @@ log.debug("===> LDAP authenticator: " + env); InitialLdapContext ctx = null; - try { - ctx = new InitialLdapContext(env, null); - log.debug("===> LDAP context created: "+ctx); - Attributes attrs = ctx.getAttributes(userDN); - setAttrs(attrs); - - if (log.isDebugEnabled()) { - NamingEnumeration enumAttrs = attrs.getAll(); - while (enumAttrs.hasMoreElements()) { - log.debug(enumAttrs.next()); - } + + for (String principalDNSuffix : principalDNSuffixes) { + if (!principalDNSuffix.startsWith(",")) { + principalDNSuffix = "," + principalDNSuffix; } + String userDN = principalDNPrefix + username + principalDNSuffix; + env.setProperty(Context.SECURITY_PRINCIPAL, userDN); + try { + ctx = new InitialLdapContext(env, null); + log.debug("===> LDAP context created using DN: "+userDN); + Attributes attrs = ctx.getAttributes(userDN); + setAttrs(attrs); + + if (log.isDebugEnabled()) { + NamingEnumeration enumAttrs = attrs.getAll(); + while (enumAttrs.hasMoreElements()) { + log.debug(enumAttrs.next()); + } + } - // check user is disabled in ldap - if (getLdapService().getDisabledBoolean(attrs)) { - log.debug("===> User is disabled in LDAP."); - User user = getService().getUserByLogin(username); - if (user != null) { - getService().disableUser(user.getUserId()); + // check user is disabled in ldap + if (getLdapService().getDisabledBoolean(attrs)) { + log.debug("===> User is disabled in LDAP."); + User user = getService().getUserByLogin(username); + if (user != null) { + getService().disableUser(user.getUserId()); + } + return false; } - return false; - } - if (Configuration.getAsBoolean(ConfigurationKeys.LDAP_UPDATE_ON_LOGIN)) { - User user = getService().getUserByLogin(username); - if (user != null) { - // update user's attributes and org membership - getLdapService().updateLDAPUser(user, attrs); - getLdapService().addLDAPUser(attrs, user.getUserId()); + if (Configuration.getAsBoolean(ConfigurationKeys.LDAP_UPDATE_ON_LOGIN)) { + User user = getService().getUserByLogin(username); + if (user != null) { + // update user's attributes and org membership + getLdapService().updateLDAPUser(user, attrs); + getLdapService().addLDAPUser(attrs, user.getUserId()); + } } - } - return true; - } catch (AuthenticationNotSupportedException e) { - log.error("===> Authentication mechanism not supported. Check your " - +ConfigurationKeys.LDAP_SECURITY_AUTHENTICATION+" parameter: " - +Configuration.get(ConfigurationKeys.LDAP_SECURITY_AUTHENTICATION)); - } catch (AuthenticationException e) { - log.info("===> Incorrect username ("+userDN+") or password ("+credential+"): "+e.getMessage()); - } catch (Exception e) { - log.error("===> LDAP exception: " + e, e); - } finally { + return true; + } catch (AuthenticationNotSupportedException e) { + log.error("===> Authentication mechanism not supported. Check your " + +ConfigurationKeys.LDAP_SECURITY_AUTHENTICATION+" parameter: " + +Configuration.get(ConfigurationKeys.LDAP_SECURITY_AUTHENTICATION)); + } catch (AuthenticationException e) { + log.info("===> Incorrect username ("+userDN+") or password ("+credential+"): "+e.getMessage()); + } catch (Exception e) { + log.error("===> LDAP exception: " + e, e); + } finally { - try { - //FIXME: synchronization issue -- dynamically load certificate - // instead of overwritting system properties - //System.setProperty("javax.net.ssl.trustStore",(String)originalTrustStore - // ); - //System.setProperty("javax.net.ssl.trustStorePassword",(String)originalTrustPass - // ); + try { + // FIXME: synchronization issue -- dynamically load certificate + // instead of overwritting system properties + //System.setProperty("javax.net.ssl.trustStore",(String)originalTrustStore + // ); + //System.setProperty("javax.net.ssl.trustStorePassword",(String)originalTrustPass + // ); - if (ctx != null) - ctx.close(); - } catch (Exception e) { - log.error("===> gettting problem when closing context. Excetion: "+e); + if (ctx != null) + ctx.close(); + } catch (Exception e) { + log.error("===> gettting problem when closing context. Excetion: "+e); + } } } Index: lams_common/db/sql/insert_lams_unix_config_data.sql =================================================================== RCS file: /usr/local/cvsroot/lams_common/db/sql/insert_lams_unix_config_data.sql,v diff -u -r1.6.4.1.2.4 -r1.6.4.1.2.5 --- lams_common/db/sql/insert_lams_unix_config_data.sql 25 Sep 2007 01:38:37 -0000 1.6.4.1.2.4 +++ lams_common/db/sql/insert_lams_unix_config_data.sql 28 Sep 2007 01:35:22 -0000 1.6.4.1.2.5 @@ -67,4 +67,5 @@ insert into lams_configuration (config_key, config_value) values ('LDAPUpdateOnLogin', 'true'); insert into lams_configuration (config_key, config_value) values ('LDAPOrgField', 'code'); insert into lams_configuration (config_key, config_value) values ('LDAPOnlyOneOrg', 'true'); -insert into lams_configuration (config_key, config_value) values ('LDAPEncryptPasswordFromBrowser', 'false'); \ No newline at end of file +insert into lams_configuration (config_key, config_value) values ('LDAPEncryptPasswordFromBrowser', 'false'); +insert into lams_configuration (config_key, config_value) values ('LDAPSearchResultsPageSize', '100'); \ No newline at end of file Index: lams_common/db/sql/insert_lams_windows_config_data.sql =================================================================== RCS file: /usr/local/cvsroot/lams_common/db/sql/insert_lams_windows_config_data.sql,v diff -u -r1.3.4.1.2.4 -r1.3.4.1.2.5 --- lams_common/db/sql/insert_lams_windows_config_data.sql 25 Sep 2007 01:38:37 -0000 1.3.4.1.2.4 +++ lams_common/db/sql/insert_lams_windows_config_data.sql 28 Sep 2007 01:35:22 -0000 1.3.4.1.2.5 @@ -67,4 +67,5 @@ insert into lams_configuration (config_key, config_value) values ('LDAPUpdateOnLogin', 'true'); insert into lams_configuration (config_key, config_value) values ('LDAPOrgField', 'code'); insert into lams_configuration (config_key, config_value) values ('LDAPOnlyOneOrg', 'true'); -insert into lams_configuration (config_key, config_value) values ('LDAPEncryptPasswordFromBrowser', 'false'); \ No newline at end of file +insert into lams_configuration (config_key, config_value) values ('LDAPEncryptPasswordFromBrowser', 'false'); +insert into lams_configuration (config_key, config_value) values ('LDAPSearchResultsPageSize', '100'); \ No newline at end of file Index: lams_common/db/sql/updatescripts/alter_205_ldap.sql =================================================================== RCS file: /usr/local/cvsroot/lams_common/db/sql/updatescripts/Attic/alter_205_ldap.sql,v diff -u -r1.1.2.3 -r1.1.2.4 --- lams_common/db/sql/updatescripts/alter_205_ldap.sql 25 Sep 2007 01:38:36 -0000 1.1.2.3 +++ lams_common/db/sql/updatescripts/alter_205_ldap.sql 28 Sep 2007 01:35:22 -0000 1.1.2.4 @@ -35,4 +35,5 @@ insert into lams_configuration (config_key, config_value) values ('LDAPUpdateOnLogin', 'true'); insert into lams_configuration (config_key, config_value) values ('LDAPOrgField', 'code'); insert into lams_configuration (config_key, config_value) values ('LDAPOnlyOneOrg', 'true'); -insert into lams_configuration (config_key, config_value) values ('LDAPEncryptPasswordFromBrowser', 'false'); \ No newline at end of file +insert into lams_configuration (config_key, config_value) values ('LDAPEncryptPasswordFromBrowser', 'false'); +insert into lams_configuration (config_key, config_value) values ('LDAPSearchResultsPageSize', '100'); \ No newline at end of file Index: lams_common/src/java/org/lamsfoundation/lams/usermanagement/ldapContext.xml =================================================================== RCS file: /usr/local/cvsroot/lams_common/src/java/org/lamsfoundation/lams/usermanagement/ldapContext.xml,v diff -u -r1.1.2.1 -r1.1.2.2 --- lams_common/src/java/org/lamsfoundation/lams/usermanagement/ldapContext.xml 18 Sep 2007 07:20:51 -0000 1.1.2.1 +++ lams_common/src/java/org/lamsfoundation/lams/usermanagement/ldapContext.xml 28 Sep 2007 01:35:23 -0000 1.1.2.2 @@ -15,9 +15,9 @@ true - PROPAGATION_REQUIRED - PROPAGATION_REQUIRED - PROPAGATION_REQUIRED + PROPAGATION_REQUIRED + PROPAGATION_REQUIRED + PROPAGATION_REQUIRED Fisheye: Tag 1.1 refers to a dead (removed) revision in file `lams_common/src/java/org/lamsfoundation/lams/usermanagement/dto/BulkUpdateResultDTO.java'. Fisheye: No comparison available. Pass `N' to diff? Index: lams_common/src/java/org/lamsfoundation/lams/usermanagement/service/ILdapService.java =================================================================== RCS file: /usr/local/cvsroot/lams_common/src/java/org/lamsfoundation/lams/usermanagement/service/ILdapService.java,v diff -u -r1.2.2.2 -r1.2.2.3 --- lams_common/src/java/org/lamsfoundation/lams/usermanagement/service/ILdapService.java 25 Sep 2007 01:38:37 -0000 1.2.2.2 +++ lams_common/src/java/org/lamsfoundation/lams/usermanagement/service/ILdapService.java 28 Sep 2007 01:35:23 -0000 1.2.2.3 @@ -23,10 +23,10 @@ /* $Id$ */ package org.lamsfoundation.lams.usermanagement.service; -import javax.naming.directory.Attribute; import javax.naming.directory.Attributes; import org.lamsfoundation.lams.usermanagement.User; +import org.lamsfoundation.lams.usermanagement.dto.BulkUpdateResultDTO; /** * @author jliew @@ -75,7 +75,7 @@ /** * Bulk updates LAMS with LDAP users. - * @return number of LDAP users received. + * @return stats on result of bulk update. */ - public int updateLAMSFromLdap(); + public BulkUpdateResultDTO bulkUpdate(); } Index: lams_common/src/java/org/lamsfoundation/lams/usermanagement/service/LdapService.java =================================================================== RCS file: /usr/local/cvsroot/lams_common/src/java/org/lamsfoundation/lams/usermanagement/service/LdapService.java,v diff -u -r1.3.2.7 -r1.3.2.8 --- lams_common/src/java/org/lamsfoundation/lams/usermanagement/service/LdapService.java 26 Sep 2007 00:16:41 -0000 1.3.2.7 +++ lams_common/src/java/org/lamsfoundation/lams/usermanagement/service/LdapService.java 28 Sep 2007 01:35:23 -0000 1.3.2.8 @@ -37,10 +37,13 @@ import javax.naming.NamingException; import javax.naming.directory.Attribute; import javax.naming.directory.Attributes; -import javax.naming.directory.DirContext; -import javax.naming.directory.InitialDirContext; import javax.naming.directory.SearchControls; import javax.naming.directory.SearchResult; +import javax.naming.ldap.Control; +import javax.naming.ldap.InitialLdapContext; +import javax.naming.ldap.LdapContext; +import javax.naming.ldap.PagedResultsControl; +import javax.naming.ldap.PagedResultsResponseControl; import org.apache.commons.lang.StringUtils; import org.apache.log4j.Logger; @@ -52,6 +55,7 @@ import org.lamsfoundation.lams.usermanagement.SupportedLocale; import org.lamsfoundation.lams.usermanagement.User; import org.lamsfoundation.lams.usermanagement.UserOrganisation; +import org.lamsfoundation.lams.usermanagement.dto.BulkUpdateResultDTO; import org.lamsfoundation.lams.util.Configuration; import org.lamsfoundation.lams.util.ConfigurationKeys; import org.lamsfoundation.lams.util.LanguageUtil; @@ -64,6 +68,9 @@ private Logger log = Logger.getLogger(LdapService.class); private IUserManagementService service; + private static final int BULK_UPDATE_CREATED = 0; + private static final int BULK_UPDATE_UPDATED = 1; + private static final int BULK_UPDATE_DISABLED = 2; public IUserManagementService getService() { return service; @@ -117,9 +124,23 @@ if (map.get("login")!=null && map.get("login").trim().length()>0) { if (log.isDebugEnabled()) { log.debug("===> using LDAP attributes: " - +map.get("login")+","+map.get("fname")+","+map.get("lname")+"," - +map.get("email")+","+map.get("phone")+","+map.get("fax")+"," - +map.get("mobile")); + +map.get("login")+"," + +map.get("fname")+"," + +map.get("lname")+"," + +map.get("email")+"," + +map.get("address1")+"," + +map.get("address2")+"," + +map.get("address3")+"," + +map.get("city")+"," + +map.get("state")+"," + +map.get("postcode")+"," + +map.get("country")+"," + +map.get("dayphone")+"," + +map.get("eveningphone")+"," + +map.get("fax")+"," + +map.get("mobile")+"," + +map.get("locale") + ); } user.setLogin(map.get("login")); user.setPassword("dummy"); // password column is not-null @@ -181,6 +202,54 @@ } catch (Exception e) { log.error("===> Exception occurred while getting LDAP user attributes: ", e); } + + // field validation; trim values before they get to database + if (map.get("login") != null && map.get("login").trim().length() > 255) { + map.put("login", map.get("login").substring(0, 255)); + } + if (map.get("fname") != null && map.get("fname").trim().length() > 128) { + map.put("fname", map.get("fname").substring(0, 128)); + } + if (map.get("lname") != null && map.get("lname").trim().length() > 128) { + map.put("lname", map.get("lname").substring(0, 128)); + } + if (map.get("email") != null && map.get("email").trim().length() > 128) { + map.put("email", map.get("email").substring(0, 128)); + } + if (map.get("address1") != null && map.get("address1").trim().length() > 64) { + map.put("address1", map.get("address1").substring(0, 64)); + } + if (map.get("address2") != null && map.get("address2").trim().length() > 64) { + map.put("address2", map.get("address2").substring(0, 64)); + } + if (map.get("address3") != null && map.get("address3").trim().length() > 64) { + map.put("address3", map.get("address3").substring(0, 64)); + } + if (map.get("city") != null && map.get("city").trim().length() > 64) { + map.put("city", map.get("city").substring(0, 64)); + } + if (map.get("state") != null && map.get("state").trim().length() > 64) { + map.put("state", map.get("state").substring(0, 64)); + } + if (map.get("postcode") != null && map.get("postcode").trim().length() > 10) { + map.put("postcode", map.get("postcode").substring(0, 10)); + } + if (map.get("country") != null && map.get("country").trim().length() > 64) { + map.put("country", map.get("country").substring(0, 64)); + } + if (map.get("dayphone") != null && map.get("dayphone").trim().length() > 64) { + map.put("dayphone", map.get("dayphone").substring(0, 64)); + } + if (map.get("eveningphone") != null && map.get("eveningphone").trim().length() > 64) { + map.put("eveningphone", map.get("eveningphone").substring(0, 64)); + } + if (map.get("fax") != null && map.get("fax").trim().length() > 64) { + map.put("fax", map.get("fax").substring(0, 64)); + } + if (map.get("mobile") != null && map.get("mobile").trim().length() > 64) { + map.put("mobile", map.get("mobile").substring(0, 64)); + } + return map; } @@ -357,11 +426,13 @@ return null; } - public int updateLAMSFromLdap() { + public BulkUpdateResultDTO bulkUpdate() { // setup ldap context Properties env = new Properties(); env.setProperty(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory"); env.setProperty(Context.SECURITY_AUTHENTICATION, Configuration.get(ConfigurationKeys.LDAP_SECURITY_AUTHENTICATION)); + // make java ldap provider return 10 results at a time instead of default 1 + env.setProperty(Context.BATCHSIZE, "10"); env.setProperty(Context.PROVIDER_URL, Configuration.get(ConfigurationKeys.LDAP_PROVIDER_URL)); String securityProtocol = Configuration.get(ConfigurationKeys.LDAP_SECURITY_PROTOCOL); if (StringUtils.equals("ssl", securityProtocol)) { @@ -372,71 +443,145 @@ System.setProperty("javax.net.ssl.trustStorePassword", Configuration.get(ConfigurationKeys.LDAP_TRUSTSTORE_PASSWORD)); } - // get base dn - String baseDN = Configuration.get(ConfigurationKeys.LDAP_PRINCIPAL_DN_SUFFIX); - if (baseDN.startsWith(",")) { - baseDN = baseDN.substring(1); - } + // get base DN/s to search on + String[] baseDNs = Configuration.get(ConfigurationKeys.LDAP_PRINCIPAL_DN_SUFFIX).split(";"); // get search filter String filter = Configuration.get(ConfigurationKeys.LDAP_PRINCIPAL_DN_PREFIX); filter = "(" + filter + (filter.endsWith("=") ? "" : "=") + "*)"; - int numResults = 0; + // get page size + int pageSize = 100; try { - DirContext ctx = new InitialDirContext(env); - - // set search to subtree of base dn - SearchControls ctrl = new SearchControls(); - ctrl.setSearchScope(SearchControls.SUBTREE_SCOPE); + pageSize = new Integer(Configuration.get(ConfigurationKeys.LDAP_SEARCH_RESULTS_PAGE_SIZE)).intValue(); + } catch (Exception e) { + log.error("Couldn't read " + ConfigurationKeys.LDAP_SEARCH_RESULTS_PAGE_SIZE + ", using default page size of 100."); + } + + int totalResults = 0; + int createdUsers = 0; + int updatedUsers = 0; + int disabledUsers = 0; + List messages = new ArrayList(); + + for (String baseDN : baseDNs) { + int contextResults = 0; + if (baseDN.startsWith(",")) { + baseDN = baseDN.substring(1); + } + try { + // open LDAP connection + LdapContext ctx = null; + try { + ctx = new InitialLdapContext(env, null); + // ask ldap server to return results in pages of PAGE_SIZE, if supported + ctx.setRequestControls(new Control[] { + new PagedResultsControl(pageSize, Control.NONCRITICAL) }); + } catch (Exception e) { + messages.add("Error creating control."); + log.error(e, e); + } + + // perform ldap search, in batches + byte[] cookie = null; + do { + // set search to subtree of base dn + SearchControls ctrl = new SearchControls(); + ctrl.setSearchScope(SearchControls.SUBTREE_SCOPE); - // do the search for all ldap users - NamingEnumeration results = ctx.search(baseDN, filter, ctrl); - while (results.hasMore()) { - SearchResult result = results.next(); - Attributes attrs = result.getAttributes(); + // do the search for all ldap users + NamingEnumeration results = ctx.search(baseDN, filter, ctrl); + while (results.hasMore()) { + SearchResult result = results.next(); + Attributes attrs = result.getAttributes(); - // add or update this user to LAMS - boolean disabled = getDisabledBoolean(attrs); - String login = getSingleAttributeString(attrs.get(Configuration.get(ConfigurationKeys.LDAP_LOGIN_ATTR))); - if (login != null && login.trim().length() > 0) { - User user = getService().getUserByLogin(login); - if (!disabled) { - if (user == null) { - log.info("Creating new user for LDAP username: " + login); - if (createLDAPUser(attrs)) { - user = getService().getUserByLogin(login); - } else { - log.error("Couldn't create new user for LDAP username: "+login); - } - } else { - updateLDAPUser(user, attrs); - } - if (!addLDAPUser(attrs, user.getUserId())) { - log.error("Couldn't add LDAP user: "+login+" to organisation."); - } - } else { - // remove user from groups and set disabled flag - if (user != null) { - getService().disableUser(user.getUserId()); - } - } - } else { - log.error("Couldn't find login attribute for user using attribute name: " - + Configuration.get(ConfigurationKeys.LDAP_LOGIN_ATTR) + ". Dumping attributes..."); - NamingEnumeration enumAttrs = attrs.getAll(); - while (enumAttrs.hasMoreElements()) { - log.error(enumAttrs.next()); - } - } + // add or update this user to LAMS + boolean disabled = getDisabledBoolean(attrs); + String login = getSingleAttributeString(attrs.get(Configuration.get(ConfigurationKeys.LDAP_LOGIN_ATTR))); + if (login != null && login.trim().length() > 0) { + int code = bulkUpdateLDAPUser(login, attrs, disabled); + switch (code) { + case BULK_UPDATE_CREATED: createdUsers++; break; + case BULK_UPDATE_UPDATED: updatedUsers++; break; + case BULK_UPDATE_DISABLED: disabledUsers++; break; + } + } else { + log.error("Couldn't find login attribute for user using attribute name: " + + Configuration.get(ConfigurationKeys.LDAP_LOGIN_ATTR) + ". Dumping attributes..."); + NamingEnumeration enumAttrs = attrs.getAll(); + while (enumAttrs.hasMoreElements()) { + log.error(enumAttrs.next()); + } + } - numResults++; - } - log.info("Ldap returned " + numResults + " users."); - } catch (Exception e) { - log.error(e, e); + contextResults++; + } + + cookie = getPagedResponseCookie(ctx.getResponseControls()); + + // set response cookie to continue paged result + ctx.setRequestControls(new Control[] { + new PagedResultsControl(pageSize, cookie, Control.NONCRITICAL) } + ); + } while (cookie != null); + log.info("Ldap context " + baseDN + " returned " + contextResults + " users."); + ctx.close(); + } catch (Exception e) { + messages.add("Error while processing " + baseDN + ": " + e.getMessage()); + log.error(e, e); + } + totalResults += contextResults; } - return numResults; + BulkUpdateResultDTO dto = new BulkUpdateResultDTO(totalResults, createdUsers, updatedUsers, disabledUsers, messages); + + log.info("Ldap returned " + totalResults + " users."); + log.info(createdUsers + " were created, " + updatedUsers + " were updated/existed, and " + disabledUsers + " were disabled."); + + return dto; } + + // create, update, or disable this user + private int bulkUpdateLDAPUser(String login, Attributes attrs, boolean disabled) { + int returnCode = -1; + User user = getService().getUserByLogin(login); + if (!disabled) { + if (user == null) { + log.info("Creating new user for LDAP username: " + login); + if (createLDAPUser(attrs)) { + user = getService().getUserByLogin(login); + returnCode = BULK_UPDATE_CREATED; + } else { + log.error("Couldn't create new user for LDAP username: "+login); + } + } else { + updateLDAPUser(user, attrs); + returnCode = BULK_UPDATE_UPDATED; + } + if (!addLDAPUser(attrs, user.getUserId())) { + log.error("Couldn't add LDAP user: "+login+" to organisation."); + } + } else { + // remove user from groups and set disabled flag + if (user != null) { + getService().disableUser(user.getUserId()); + returnCode = BULK_UPDATE_DISABLED; + } + } + return returnCode; + } + + // get paged result response cookie + private byte[] getPagedResponseCookie(Control[] controls) { + if (controls != null) { + for (Control control : controls) { + if (control instanceof PagedResultsResponseControl) { + PagedResultsResponseControl prrc = (PagedResultsResponseControl)control; + return prrc.getCookie(); + } + } + } + return null; + } + } Index: lams_common/src/java/org/lamsfoundation/lams/util/ConfigurationKeys.java =================================================================== RCS file: /usr/local/cvsroot/lams_common/src/java/org/lamsfoundation/lams/util/ConfigurationKeys.java,v diff -u -r1.24.4.4 -r1.24.4.5 --- lams_common/src/java/org/lamsfoundation/lams/util/ConfigurationKeys.java 25 Sep 2007 01:38:36 -0000 1.24.4.4 +++ lams_common/src/java/org/lamsfoundation/lams/util/ConfigurationKeys.java 28 Sep 2007 01:35:22 -0000 1.24.4.5 @@ -206,4 +206,6 @@ public static String LDAP_ONLY_ONE_ORG = "LDAPOnlyOneOrg"; public static String LDAP_ENCRYPT_PASSWORD_FROM_BROWSER = "LDAPEncryptPasswordFromBrowser"; + + public static String LDAP_SEARCH_RESULTS_PAGE_SIZE = "LDAPSearchResultsPageSize"; } \ No newline at end of file