Index: lams_admin/src/java/org/lamsfoundation/lams/admin/web/action/LdapConfigAction.java
===================================================================
diff -u -r18df5a739d3e9dff1734cf64ee63595acff7a71e -r053b3694d8631a983eb8e95e3f0374a22540b43a
--- lams_admin/src/java/org/lamsfoundation/lams/admin/web/action/LdapConfigAction.java (.../LdapConfigAction.java) (revision 18df5a739d3e9dff1734cf64ee63595acff7a71e)
+++ lams_admin/src/java/org/lamsfoundation/lams/admin/web/action/LdapConfigAction.java (.../LdapConfigAction.java) (revision 053b3694d8631a983eb8e95e3f0374a22540b43a)
@@ -23,10 +23,9 @@
/* $Id$ */
package org.lamsfoundation.lams.admin.web.action;
-import java.util.List;
-
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
+import javax.servlet.http.HttpSession;
import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
@@ -36,11 +35,13 @@
import org.apache.struts.action.ActionMapping;
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.ILdapService;
import org.lamsfoundation.lams.usermanagement.service.IUserManagementService;
import org.lamsfoundation.lams.usermanagement.service.LdapService;
import org.lamsfoundation.lams.util.MessageService;
import org.lamsfoundation.lams.util.WebUtil;
+import org.lamsfoundation.lams.web.session.SessionManager;
/**
* @author jliew
@@ -85,28 +86,15 @@
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);
+ if (action != null) {
+ if (StringUtils.equals(action, "sync")) return sync(mapping, form, request, response);
+ if (StringUtils.equals(action, "waiting")) return waiting(mapping, form, request, response);
+ if (StringUtils.equals(action, "results")) return results(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");
}
@@ -116,24 +104,99 @@
HttpServletRequest request,
HttpServletResponse response) throws Exception {
- log.info("=== Beginning LDAP user sync ===");
- int numLdapUsers = getLdapService().updateLAMSFromLdap();
- log.info("=== Finished LDAP user sync ===");
- request.setAttribute(
- "numLdapUsersMsg",
- getMessageService().getMessage(
- "msg.num.ldap.users",
- getNumLdapUsersMessage(numLdapUsers)
- )
- );
+ String sessionId = (String)SessionManager.getSession().getId();
+ Thread t = new Thread(new LdapSyncThread(sessionId));
+ t.start();
+
+ request.setAttribute("wait", getMessageService().getMessage("msg.ldap.synchronise.wait"));
+
+ return mapping.findForward("ldap");
+ }
+
+ public ActionForward waiting(ActionMapping mapping,
+ ActionForm form,
+ HttpServletRequest request,
+ HttpServletResponse response) throws Exception {
+
+ request.setAttribute("wait", getMessageService().getMessage("msg.ldap.synchronise.wait"));
+
+ return mapping.findForward("ldap");
+ }
+
+ public ActionForward results(ActionMapping mapping,
+ ActionForm form,
+ HttpServletRequest request,
+ HttpServletResponse response) throws Exception {
+
+ HttpSession ss = SessionManager.getSession();
+ BulkUpdateResultDTO dto = (BulkUpdateResultDTO)ss.getAttribute(ILdapService.SYNC_RESULTS);
+
+ 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"));
+ // remove session variable that flags bulk update as done
+ ss.removeAttribute(ILdapService.SYNC_RESULTS);
+
return mapping.findForward("ldap");
}
- private String[] getNumLdapUsersMessage(int numLdapUsers) {
+ private int getNumLdapUsers() {
+ Integer count = getService().getCountUsers(AuthenticationMethod.LDAP);
+ return (count != null ? count.intValue() : -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);
+ }
+
+ private class LdapSyncThread implements Runnable {
+ private String sessionId;
+
+ public LdapSyncThread(String sessionId) {
+ this.sessionId = sessionId;
+ }
+
+ public void run() {
+ log.info("=== Beginning LDAP user sync ===");
+ long start = System.currentTimeMillis();
+ BulkUpdateResultDTO dto = getLdapService().bulkUpdate();
+ long end = System.currentTimeMillis();
+ log.info("=== Finished LDAP user sync ===");
+ log.info("Bulk update took " + (end-start)/1000 + " seconds.");
+ SessionManager.getSession(sessionId).setAttribute(ILdapService.SYNC_RESULTS, dto);
+ }
+ }
}
Index: lams_admin/web/ldap.jsp
===================================================================
diff -u -rfec1d7a65d1a4d66c7ddccef5d0b79ff20c0da61 -r053b3694d8631a983eb8e95e3f0374a22540b43a
--- lams_admin/web/ldap.jsp (.../ldap.jsp) (revision fec1d7a65d1a4d66c7ddccef5d0b79ff20c0da61)
+++ lams_admin/web/ldap.jsp (.../ldap.jsp) (revision 053b3694d8631a983eb8e95e3f0374a22540b43a)
@@ -1,5 +1,16 @@
<%@ include file="/taglibs.jsp"%>
+<%@ page import="org.lamsfoundation.lams.web.session.SessionManager" %>
+<%@ page import="org.lamsfoundation.lams.usermanagement.service.ILdapService" %>
+
+
:
@@ -19,15 +30,44 @@
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
Index: lams_central/src/java/org/lamsfoundation/lams/security/LDAPAuthenticator.java
===================================================================
diff -u -r109725d30c92dd25ac9cec693a233d6592cfe0e6 -r053b3694d8631a983eb8e95e3f0374a22540b43a
--- lams_central/src/java/org/lamsfoundation/lams/security/LDAPAuthenticator.java (.../LDAPAuthenticator.java) (revision 109725d30c92dd25ac9cec693a233d6592cfe0e6)
+++ lams_central/src/java/org/lamsfoundation/lams/security/LDAPAuthenticator.java (.../LDAPAuthenticator.java) (revision 053b3694d8631a983eb8e95e3f0374a22540b43a)
@@ -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_central/src/java/org/lamsfoundation/lams/security/UniversalLoginModule.java
===================================================================
diff -u -r2cdc9593bafb191bcc07439fe37d41d3cd718651 -r053b3694d8631a983eb8e95e3f0374a22540b43a
--- lams_central/src/java/org/lamsfoundation/lams/security/UniversalLoginModule.java (.../UniversalLoginModule.java) (revision 2cdc9593bafb191bcc07439fe37d41d3cd718651)
+++ lams_central/src/java/org/lamsfoundation/lams/security/UniversalLoginModule.java (.../UniversalLoginModule.java) (revision 053b3694d8631a983eb8e95e3f0374a22540b43a)
@@ -150,9 +150,16 @@
// if the password is not encrypted when sent from the jsp (e.g. when it is passed
// unencrypted to say, ldap) then encrypt it here when authenticating against local db
if (!Configuration.getAsBoolean(ConfigurationKeys.LDAP_ENCRYPT_PASSWORD_FROM_BROWSER)) {
- inputPassword = HashUtil.sha1(inputPassword);
+ // try the passed in password first, LoginRequestServlet always passes in encrypted
+ // passwords
+ isValid = authenticator.authenticate(username,inputPassword);
+ if (!isValid) {
+ inputPassword = HashUtil.sha1(inputPassword);
+ }
+ isValid = authenticator.authenticate(username,inputPassword);
+ } else {
+ isValid = authenticator.authenticate(username,inputPassword);
}
- isValid = authenticator.authenticate(username,inputPassword);
} else if (AuthenticationMethodType.WEB_AUTH.equals(type)) {
WebAuthAuthenticator authenticator = new WebAuthAuthenticator();
isValid = authenticator.authenticate(username,inputPassword);
Index: lams_common/db/sql/insert_lams_unix_config_data.sql
===================================================================
diff -u -r109725d30c92dd25ac9cec693a233d6592cfe0e6 -r053b3694d8631a983eb8e95e3f0374a22540b43a
--- lams_common/db/sql/insert_lams_unix_config_data.sql (.../insert_lams_unix_config_data.sql) (revision 109725d30c92dd25ac9cec693a233d6592cfe0e6)
+++ lams_common/db/sql/insert_lams_unix_config_data.sql (.../insert_lams_unix_config_data.sql) (revision 053b3694d8631a983eb8e95e3f0374a22540b43a)
@@ -32,7 +32,7 @@
insert into lams_configuration (config_key, config_value) values ('AllowDirectLessonLaunch','false');
insert into lams_configuration (config_key, config_value) values ('LAMS_Community_enable','false');
insert into lams_configuration (config_key, config_value) values ('AllowLiveEdit','true');
-insert into lams_configuration (config_key, config_value) values ('LDAPProvisioningEnabled','true');
+insert into lams_configuration (config_key, config_value) values ('LDAPProvisioningEnabled','false');
insert into lams_configuration (config_key, config_value) values ('LDAPProviderURL','ldap://192.168.111.15');
insert into lams_configuration (config_key, config_value) values ('LDAPSecurityAuthentication','simple');
insert into lams_configuration (config_key, config_value) values ('LDAPPrincipalDNPrefix','cn=');
@@ -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', 'true');
+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
===================================================================
diff -u -r109725d30c92dd25ac9cec693a233d6592cfe0e6 -r053b3694d8631a983eb8e95e3f0374a22540b43a
--- lams_common/db/sql/insert_lams_windows_config_data.sql (.../insert_lams_windows_config_data.sql) (revision 109725d30c92dd25ac9cec693a233d6592cfe0e6)
+++ lams_common/db/sql/insert_lams_windows_config_data.sql (.../insert_lams_windows_config_data.sql) (revision 053b3694d8631a983eb8e95e3f0374a22540b43a)
@@ -1,6 +1,6 @@
insert into lams_configuration (config_key, config_value) values ('ServerURL','http://localhost:8080/lams/');
insert into lams_configuration (config_key, config_value) values ('ServerURLContextPath','lams/');
-insert into lams_configuration (config_key, config_value) values ('Version','2.0.3');
+insert into lams_configuration (config_key, config_value) values ('Version','2.0.4');
insert into lams_configuration (config_key, config_value) values ('TempDir','C:/lams/temp');
insert into lams_configuration (config_key, config_value) values ('DumpDir','C:/lams/dump');
insert into lams_configuration (config_key, config_value) values ('EARDir','C:/jboss-4.0.2/server/default/deploy/lams.ear');
@@ -15,10 +15,10 @@
insert into lams_configuration (config_key, config_value) values ('UseCacheDebugListener','false');
insert into lams_configuration (config_key, config_value) values ('CleanupPreviewOlderThanDays','7');
insert into lams_configuration (config_key, config_value) values ('AuthoringActivitiesColour', 'true');
-insert into lams_configuration (config_key, config_value) values ('AuthoringClientVersion','2.0.3.@datetimestamp@');
-insert into lams_configuration (config_key, config_value) values ('MonitorClientVersion','2.0.3.@datetimestamp@');
-insert into lams_configuration (config_key, config_value) values ('LearnerClientVersion','2.0.3.@datetimestamp@');
-insert into lams_configuration (config_key, config_value) values ('ServerVersionNumber','2.0.3.@datetimestamp@');
+insert into lams_configuration (config_key, config_value) values ('AuthoringClientVersion','2.0.4.@datetimestamp@');
+insert into lams_configuration (config_key, config_value) values ('MonitorClientVersion','2.0.4.@datetimestamp@');
+insert into lams_configuration (config_key, config_value) values ('LearnerClientVersion','2.0.4.@datetimestamp@');
+insert into lams_configuration (config_key, config_value) values ('ServerVersionNumber','2.0.4.@datetimestamp@');
insert into lams_configuration (config_key, config_value) values ('ServerLanguage','en_AU');
insert into lams_configuration (config_key, config_value) values ('ServerPageDirection','LTR');
insert into lams_configuration (config_key, config_value) values ('DictionaryDateCreated','2007-05-24');
@@ -32,7 +32,7 @@
insert into lams_configuration (config_key, config_value) values ('AllowDirectLessonLaunch','false');
insert into lams_configuration (config_key, config_value) values ('LAMS_Community_enable','false');
insert into lams_configuration (config_key, config_value) values ('AllowLiveEdit','true');
-insert into lams_configuration (config_key, config_value) values ('LDAPProvisioningEnabled','true');
+insert into lams_configuration (config_key, config_value) values ('LDAPProvisioningEnabled','false');
insert into lams_configuration (config_key, config_value) values ('LDAPProviderURL','ldap://192.168.111.15');
insert into lams_configuration (config_key, config_value) values ('LDAPSecurityAuthentication','simple');
insert into lams_configuration (config_key, config_value) values ('LDAPPrincipalDNPrefix','cn=');
@@ -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
===================================================================
diff -u -r109725d30c92dd25ac9cec693a233d6592cfe0e6 -r053b3694d8631a983eb8e95e3f0374a22540b43a
--- lams_common/db/sql/updatescripts/alter_205_ldap.sql (.../alter_205_ldap.sql) (revision 109725d30c92dd25ac9cec693a233d6592cfe0e6)
+++ lams_common/db/sql/updatescripts/alter_205_ldap.sql (.../alter_205_ldap.sql) (revision 053b3694d8631a983eb8e95e3f0374a22540b43a)
@@ -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/dto/BulkUpdateResultDTO.java
===================================================================
diff -u
--- lams_common/src/java/org/lamsfoundation/lams/usermanagement/dto/BulkUpdateResultDTO.java (revision 0)
+++ lams_common/src/java/org/lamsfoundation/lams/usermanagement/dto/BulkUpdateResultDTO.java (revision 053b3694d8631a983eb8e95e3f0374a22540b43a)
@@ -0,0 +1,69 @@
+/****************************************************************
+ * Copyright (C) 2005 LAMS Foundation (http://lamsfoundation.org)
+ * =============================================================
+ * License Information: http://lamsfoundation.org/licensing/lams/2.0/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2.0
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 * USA
+ *
+ * http://www.gnu.org/licenses/gpl.txt
+ * ****************************************************************
+ */
+
+/* $Id$ */
+package org.lamsfoundation.lams.usermanagement.dto;
+
+import java.util.List;
+
+/**
+ * @author jliew
+ *
+ */
+public class BulkUpdateResultDTO {
+
+ private int numSearchResults;
+ private int numUsersCreated;
+ private int numUsersUpdated;
+ private int numUsersDisabled;
+ private List messages;
+
+ public BulkUpdateResultDTO(int results, int created,
+ int updated, int disabled, List messages) {
+ this.numSearchResults = results;
+ this.numUsersCreated = created;
+ this.numUsersUpdated = updated;
+ this.numUsersDisabled = disabled;
+ this.messages = messages;
+ }
+
+ public int getNumSearchResults() {
+ return numSearchResults;
+ }
+
+ public int getNumUsersCreated() {
+ return numUsersCreated;
+ }
+
+ public int getNumUsersUpdated() {
+ return numUsersUpdated;
+ }
+
+ public int getNumUsersDisabled() {
+ return numUsersDisabled;
+ }
+
+ public List getMessages() {
+ return messages;
+ }
+}
+
\ No newline at end of file
Index: lams_common/src/java/org/lamsfoundation/lams/usermanagement/ldapContext.xml
===================================================================
diff -u -r43dfd9f833c87c58f4dc4a61f386b6c2cf961720 -r053b3694d8631a983eb8e95e3f0374a22540b43a
--- lams_common/src/java/org/lamsfoundation/lams/usermanagement/ldapContext.xml (.../ldapContext.xml) (revision 43dfd9f833c87c58f4dc4a61f386b6c2cf961720)
+++ lams_common/src/java/org/lamsfoundation/lams/usermanagement/ldapContext.xml (.../ldapContext.xml) (revision 053b3694d8631a983eb8e95e3f0374a22540b43a)
@@ -15,9 +15,9 @@
true
- PROPAGATION_REQUIRED
- PROPAGATION_REQUIRED
- PROPAGATION_REQUIRED
+ PROPAGATION_REQUIRED
+ PROPAGATION_REQUIRED
+ PROPAGATION_REQUIRED
Index: lams_common/src/java/org/lamsfoundation/lams/usermanagement/service/ILdapService.java
===================================================================
diff -u -r109725d30c92dd25ac9cec693a233d6592cfe0e6 -r053b3694d8631a983eb8e95e3f0374a22540b43a
--- lams_common/src/java/org/lamsfoundation/lams/usermanagement/service/ILdapService.java (.../ILdapService.java) (revision 109725d30c92dd25ac9cec693a233d6592cfe0e6)
+++ lams_common/src/java/org/lamsfoundation/lams/usermanagement/service/ILdapService.java (.../ILdapService.java) (revision 053b3694d8631a983eb8e95e3f0374a22540b43a)
@@ -23,17 +23,19 @@
/* $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
*
*/
public interface ILdapService {
+ public static final String SYNC_RESULTS = "syncResults";
+
/**
* Updates a LAMS user's profile with LDAP attributes.
* @param user
@@ -75,7 +77,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/IUserManagementService.java
===================================================================
diff -u -r9b9a8c320a611027445fe94db5cd458c2968700d -r053b3694d8631a983eb8e95e3f0374a22540b43a
--- lams_common/src/java/org/lamsfoundation/lams/usermanagement/service/IUserManagementService.java (.../IUserManagementService.java) (revision 9b9a8c320a611027445fe94db5cd458c2968700d)
+++ lams_common/src/java/org/lamsfoundation/lams/usermanagement/service/IUserManagementService.java (.../IUserManagementService.java) (revision 053b3694d8631a983eb8e95e3f0374a22540b43a)
@@ -385,4 +385,8 @@
public void auditPasswordChanged(User user, String moduleName);
public void auditUserCreated(User user, String moduleName);
+
+ public Integer getCountUsers();
+
+ public Integer getCountUsers(Integer authenticationMethodId);
}
\ No newline at end of file
Index: lams_common/src/java/org/lamsfoundation/lams/usermanagement/service/LdapService.java
===================================================================
diff -u -r4d72f55fbac086d72edbf3b2975fc0bb2b464213 -r053b3694d8631a983eb8e95e3f0374a22540b43a
--- lams_common/src/java/org/lamsfoundation/lams/usermanagement/service/LdapService.java (.../LdapService.java) (revision 4d72f55fbac086d72edbf3b2975fc0bb2b464213)
+++ lams_common/src/java/org/lamsfoundation/lams/usermanagement/service/LdapService.java (.../LdapService.java) (revision 053b3694d8631a983eb8e95e3f0374a22540b43a)
@@ -37,13 +37,17 @@
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;
+import org.lamsfoundation.lams.integration.security.RandomPasswordGenerator;
import org.lamsfoundation.lams.usermanagement.AuthenticationMethod;
import org.lamsfoundation.lams.usermanagement.Organisation;
import org.lamsfoundation.lams.usermanagement.OrganisationState;
@@ -52,8 +56,10 @@
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.HashUtil;
import org.lamsfoundation.lams.util.LanguageUtil;
/**
@@ -64,6 +70,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,12 +126,26 @@
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
+ user.setPassword(HashUtil.sha1(RandomPasswordGenerator.nextPassword(10)));
user.setFirstName(map.get("fname"));
user.setLastName(map.get("lname"));
user.setEmail(map.get("email"));
@@ -181,6 +204,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 +428,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 +445,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/usermanagement/service/UserManagementService.java
===================================================================
diff -u -r9b9a8c320a611027445fe94db5cd458c2968700d -r053b3694d8631a983eb8e95e3f0374a22540b43a
--- lams_common/src/java/org/lamsfoundation/lams/usermanagement/service/UserManagementService.java (.../UserManagementService.java) (revision 9b9a8c320a611027445fe94db5cd458c2968700d)
+++ lams_common/src/java/org/lamsfoundation/lams/usermanagement/service/UserManagementService.java (.../UserManagementService.java) (revision 053b3694d8631a983eb8e95e3f0374a22540b43a)
@@ -39,6 +39,7 @@
import org.lamsfoundation.lams.dao.IBaseDAO;
import org.lamsfoundation.lams.learningdesign.dao.IGroupDAO;
import org.lamsfoundation.lams.themes.CSSThemeVisualElement;
+import org.lamsfoundation.lams.usermanagement.AuthenticationMethod;
import org.lamsfoundation.lams.usermanagement.Organisation;
import org.lamsfoundation.lams.usermanagement.OrganisationType;
import org.lamsfoundation.lams.usermanagement.Role;
@@ -529,7 +530,7 @@
}
return organisation;
- }
+ }
@SuppressWarnings("unchecked")
public List getUserManageBeans(Integer orgId) {
@@ -909,5 +910,25 @@
String message = messageService.getMessage("audit.user.create", args);
getAuditService().log(moduleName, message);
}
+
+ public Integer getCountUsers() {
+ String query = "select count(u) from User u";
+ return getFindIntegerResult(query);
+ }
+
+ public Integer getCountUsers(Integer authenticationMethodId) {
+ String query = "select count(u) from User u "
+ + "where u.authenticationMethod.authenticationMethodId="
+ + authenticationMethodId;
+ return getFindIntegerResult(query);
+ }
+
+ private Integer getFindIntegerResult(String query) {
+ List list = baseDAO.find(query);
+ if (list != null && list.size() > 0) {
+ return (Integer)list.get(0);
+ }
+ return null;
+ }
}
\ No newline at end of file
Index: lams_common/src/java/org/lamsfoundation/lams/util/ConfigurationKeys.java
===================================================================
diff -u -r109725d30c92dd25ac9cec693a233d6592cfe0e6 -r053b3694d8631a983eb8e95e3f0374a22540b43a
--- lams_common/src/java/org/lamsfoundation/lams/util/ConfigurationKeys.java (.../ConfigurationKeys.java) (revision 109725d30c92dd25ac9cec693a233d6592cfe0e6)
+++ lams_common/src/java/org/lamsfoundation/lams/util/ConfigurationKeys.java (.../ConfigurationKeys.java) (revision 053b3694d8631a983eb8e95e3f0374a22540b43a)
@@ -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