Index: lams_central/conf/language/lams/ApplicationResources.properties =================================================================== diff -u -rf5aa1f4851530d5b79d1624bab1989b92b28a227 -re9d226f1680751f53da50848214c85df0e1f06fb --- lams_central/conf/language/lams/ApplicationResources.properties (.../ApplicationResources.properties) (revision f5aa1f4851530d5b79d1624bab1989b92b28a227) +++ lams_central/conf/language/lams/ApplicationResources.properties (.../ApplicationResources.properties) (revision e9d226f1680751f53da50848214c85df0e1f06fb) @@ -2,7 +2,7 @@ #language code: en #locale code: AU - # CVS ID: $Id$ Exported from the LAMS Community by Ernie Ghiglione on Thu Apr 10 02:42:36 BST 2008 + # CVS ID: $Id$ Exported from the LAMS Community by Ernie Ghiglione on Fri Mar 07 07:26:28 GMT 2008 #=================== labels for LAMS Central =================# @@ -193,7 +193,22 @@ label.show.groups =Show Groups error.newpassword.mismatch =Your new passwords do not match each other. label.forgot.password =Forgot your password? +title.forgot.password =LAMS :: Forgot Password +label.forgot.password.confirm =Password Request +label.forgot.password.instructions =Please enter your user name and email below. An email will be sent to you shortly with a link that will allow you to change your password. If you do not know your email address in LAMS, please contact your System Administrator. +forgot.password.email.subject =LAMS server - Forgot password response. +forgot.password.email.body =Click the link below to and it will take you to a page where you can change your password. +forgot.password.email.sent =An email has been sent to your email address. +error.user.not.found =Unable to find the username in LAMS. Please check your username and try again. +error.email.does.not.match =The email address does not match your saved email address. Please try again. +error.support.email.not.set =Email could not be sent. The LAMS server has not been configured to handle emails. Please contact your System Administrator. +error.password.request.expired =This request for a new password has expired. Please click the "Forgot your Password" link again to make a new request. +label.enable.flash =Enable Flash for Learner Window +label.yes =Yes +label.no =No +label.ok =OK error.general.1 =Sorry, there has been an error. + #======= End labels: Exported 188 labels for en AU ===== Index: lams_central/src/java/org/lamsfoundation/lams/util/Emailer.java =================================================================== diff -u --- lams_central/src/java/org/lamsfoundation/lams/util/Emailer.java (revision 0) +++ lams_central/src/java/org/lamsfoundation/lams/util/Emailer.java (revision e9d226f1680751f53da50848214c85df0e1f06fb) @@ -0,0 +1,67 @@ +package org.lamsfoundation.lams.util; + +import java.io.IOException; +import java.io.InputStream; +import java.util.Properties; + +import org.lamsfoundation.lams.integration.service.IntegrationService; +import org.lamsfoundation.lams.util.Configuration; + +import javax.mail.MessagingException; +import javax.mail.Session; +import javax.mail.Transport; +import javax.mail.Message.RecipientType; +import javax.mail.internet.AddressException; +import javax.mail.internet.InternetAddress; +import javax.mail.internet.MimeMessage; +import org.apache.log4j.Logger; + +/** + * A class that handles emails, used for forgot password task + * @author lfoxton + */ +public class Emailer { + + private static Logger log = Logger.getLogger(Emailer.class); + + public Emailer() {} + + + /** + * Sends an email sourced from admin + * @param subject the subject of the email + * @param to the email of the recipient + * @param body the body of the email + */ + public static void sendFromSupportEmail(String subject, String to, String body) + throws AddressException, MessagingException + { + String supportEmail = Configuration.get("LamsSupportEmail"); + String smtpServer = Configuration.get("SMTPServer"); + Properties properties = new Properties(); + properties.put("mail.smtp.host", smtpServer); + send(subject, to, supportEmail, body, properties); + } + + + /** + * Send email to recipients + * @param subject the subject of the email + * @param to the email of the recipient + * @param from the email to source the email from + * @param body the body of the email + */ + public static void send(String subject, String to, String from, String body, Properties mailServerConfig) + throws AddressException, MessagingException + { + Session session = Session.getDefaultInstance(mailServerConfig, null); + MimeMessage message = new MimeMessage(session); + message.setFrom(new InternetAddress(from)); + message.addRecipient(RecipientType.TO, new InternetAddress(to)); + message.setSubject(subject); + message.setText(body); + Transport.send(message); + } + + +} Index: lams_central/src/java/org/lamsfoundation/lams/web/ForgotPasswordServlet.java =================================================================== diff -u --- lams_central/src/java/org/lamsfoundation/lams/web/ForgotPasswordServlet.java (revision 0) +++ lams_central/src/java/org/lamsfoundation/lams/web/ForgotPasswordServlet.java (revision e9d226f1680751f53da50848214c85df0e1f06fb) @@ -0,0 +1,240 @@ +package org.lamsfoundation.lams.web; + +import java.io.IOException; +import java.util.Date; +import java.util.Calendar; +import java.util.Properties; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.mail.internet.AddressException; +import javax.mail.MessagingException; +import org.springframework.web.context.WebApplicationContext; +import org.springframework.web.context.support.WebApplicationContextUtils; +import org.apache.log4j.Logger; +import org.hibernate.id.IdentifierGenerator; +import org.hibernate.id.UUIDHexGenerator; +import org.hibernate.Hibernate; +import org.hibernate.id.Configurable; + + +import org.lamsfoundation.lams.usermanagement.User; +import org.lamsfoundation.lams.usermanagement.ForgotPasswordRequest; +import org.lamsfoundation.lams.usermanagement.service.IUserManagementService; +import org.lamsfoundation.lams.util.Configuration; +import org.lamsfoundation.lams.util.FileUtilException; +import org.lamsfoundation.lams.util.MessageService; +import org.lamsfoundation.lams.util.Emailer; + + +/** + * Servlet to handle forgot password requests + * + * This servlet handles two type of requests, one to save the request and send an email to the user, + * and one to save the new password + * @author lfoxton + * + * @web:servlet name="forgotPasswordServlet" + * @web:servlet-mapping url-pattern="/ForgotPasswordRequest" + */ +public class ForgotPasswordServlet extends HttpServlet +{ + private static Logger log = Logger.getLogger(ForgotPasswordServlet.class); + + // states + public static int SMTP_SERVER_NOT_SET = 100; + public static int EMAIL_DOES_NOT_MATCH = 101; + public static int USER_NOT_FOUND = 102; + public static int PASSWORD_REQUEST_EXPIRED = 103; + public static int SUCCESS_REQUEST_EMAIL = 104; + public static int SUCCESS_CHANGE_PASS = 105; + + public static int MILLISECONDS_IN_A_DAY = 86400000; + + private static String STATE = "?state="; + + public void doGet(HttpServletRequest request, HttpServletResponse response) + throws ServletException, IOException + { + String method = request.getParameter("method"); + + if (method.equals("requestEmail")) + { + String login = request.getParameter("login"); + String email = request.getParameter("email"); + handleEmailRequest(login, email, response); + } + else if (method.equals("requestPasswordChange")) + { + String newPassword = request.getParameter("newPassword"); + String key = request.getParameter("key"); + handlePasswordChange(newPassword, key, response); + } + else + { + response.sendError(HttpServletResponse.SC_BAD_REQUEST); + } + + } + + public void handleEmailRequest(String login, String email, HttpServletResponse response) + throws ServletException, IOException + { + + String state = STATE; + boolean err = false; + + if (login==null||login.equals("")||email==null||email.equals("")) + { + response.sendError(HttpServletResponse.SC_BAD_REQUEST); + return; + } + + String SMPTServer = Configuration.get("SMTPServer"); + String supportEmail = Configuration.get("LamsSupportEmail"); + + + + if (SMPTServer==null||SMPTServer.equals("")||supportEmail==null||supportEmail.equals("")) + { + // Validate + state += this.SMTP_SERVER_NOT_SET; + } + else + { + WebApplicationContext ctx = WebApplicationContextUtils.getRequiredWebApplicationContext(this.getServletContext()); + IUserManagementService userService = (IUserManagementService) ctx.getBean("userManagementService"); + MessageService messageService = (MessageService)ctx.getBean("centralMessageService"); + + if (userService.getUserByLogin(login)!=null) + { + User user = userService.getUserByLogin(login); + + if (user.getEmail().equals(email)) + { + // generate a key for the request + String key = generateUniqueKey(); + + // all good, save the request in the db + ForgotPasswordRequest fp = new ForgotPasswordRequest(); + fp.setRequestDate(new Date()); + fp.setUserId(user.getUserId()); + fp.setRequestKey(key); + userService.save(fp); + + // Constructing the body of the email + String body = messageService.getMessage("forgot.password.email.body") + + "\n\n" + + Configuration.get("ServerURL") + + "forgotPasswordChange.jsp?key=" + + key; + + // send the email + try{ + Emailer.sendFromSupportEmail( + messageService.getMessage("forgot.password.email.subject"), + email, + body + ); + state += this.SUCCESS_REQUEST_EMAIL; + } + catch (AddressException e) + { + // failure handling + log.debug(e); + response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); + } + catch (MessagingException e) + { + // failure handling + log.debug(e); + response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); + } + catch (Exception e) + { + // failure handling + log.debug(e); + response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); + } + + } + else + { + // validate email does not match user + state += this.EMAIL_DOES_NOT_MATCH; + } + + } + else + { + // validate user is not found + state += this.USER_NOT_FOUND; + } + } + + response.sendRedirect(Configuration.get("ServerURL") + "forgotPasswordProc.jsp" + state); + + } + + /** + * Updates the user's password + * @param key the key of the forgot password request + */ + public void handlePasswordChange(String newPassword, String key, HttpServletResponse response) + throws ServletException, IOException + { + String state = STATE; + + if (key==null||key.equals("")||newPassword==null||newPassword.equals("")) + { + response.sendError(HttpServletResponse.SC_BAD_REQUEST); + return; + } + + WebApplicationContext ctx = WebApplicationContextUtils.getRequiredWebApplicationContext(this.getServletContext()); + IUserManagementService userService = (IUserManagementService) ctx.getBean("userManagementService"); + + ForgotPasswordRequest fp = userService.getForgotPasswordRequest(key); + long cutoffTime = fp.getRequestDate().getTime() + MILLISECONDS_IN_A_DAY; + Date now = new Date(); + long nowLong = now.getTime(); + + if (nowLong < cutoffTime) + { + User user = (User)userService.findById(User.class, fp.getUserId()); + userService.updatePassword(user.getLogin(), newPassword); + state += this.SUCCESS_CHANGE_PASS; + } + else + { + // validate password request expired + state += this.PASSWORD_REQUEST_EXPIRED; + } + + response.sendRedirect(Configuration.get("ServerURL") + "forgotPasswordProc.jsp" + state); + } + + /** + * Generates the unique key used for the forgot password request + * @return a unique key + * @throws FileUtilException + * @throws IOException + */ + public static String generateUniqueKey() + { + String newUniqueContentFolderID = null; + Properties props = new Properties(); + + IdentifierGenerator uuidGen = new UUIDHexGenerator(); + ( (Configurable) uuidGen).configure(Hibernate.STRING, props, null); + + return ((String) uuidGen.generate(null, null)).toLowerCase(); + } + + + + + +} Index: lams_central/web/forgotPassword.jsp =================================================================== diff -u --- lams_central/web/forgotPassword.jsp (revision 0) +++ lams_central/web/forgotPassword.jsp (revision e9d226f1680751f53da50848214c85df0e1f06fb) @@ -0,0 +1,80 @@ +<%@page import="org.apache.struts.action.ActionMessages" %> + + +<%@ taglib uri="tags-html" prefix="html" %> +<%@ taglib uri="tags-logic" prefix="logic" %> +<%@ taglib uri="tags-fmt" prefix="fmt" %> +<%@ taglib uri="tags-lams" prefix="lams" %> + + + + + + + + <fmt:message key="title.forgot.password"/> + + + + + + + +
+ + +

+
+
+ +
+

+
+ +
+ + + + + + + + + + + + + + + + +
+ : + + +
+ : + + + +
  + + + +
+
+
+ + + + \ No newline at end of file Index: lams_central/web/forgotPasswordChange.jsp =================================================================== diff -u --- lams_central/web/forgotPasswordChange.jsp (revision 0) +++ lams_central/web/forgotPasswordChange.jsp (revision e9d226f1680751f53da50848214c85df0e1f06fb) @@ -0,0 +1,77 @@ +<%@page import="org.apache.struts.action.ActionMessages" %> + + +<%@ taglib uri="tags-html" prefix="html" %> +<%@ taglib uri="tags-logic" prefix="logic" %> +<%@ taglib uri="tags-fmt" prefix="fmt" %> +<%@ taglib uri="tags-lams" prefix="lams" %> + +<% +String key = request.getParameter("key"); +%> + + + + + + + <fmt:message key="title.forgot.password"/> + + + + + + + + + + +

+
+
+ +
+

+
+ + + + + + + + + + + + + + + +
+ : + + +
+ : + + +
  + +
+
+
+ + + + \ No newline at end of file Index: lams_central/web/forgotPasswordProc.jsp =================================================================== diff -u --- lams_central/web/forgotPasswordProc.jsp (revision 0) +++ lams_central/web/forgotPasswordProc.jsp (revision e9d226f1680751f53da50848214c85df0e1f06fb) @@ -0,0 +1,63 @@ +<%@page import="org.apache.struts.action.ActionMessages" %> +<%@page import="org.lamsfoundation.lams.web.ForgotPasswordServlet" %> +<%@page import="org.lamsfoundation.lams.util.MessageService" %> +<%@page import="org.springframework.web.context.WebApplicationContext" %> +<%@page import="org.springframework.web.context.support.WebApplicationContextUtils" %> + +<%@ taglib uri="tags-html" prefix="html" %> +<%@ taglib uri="tags-logic" prefix="logic" %> +<%@ taglib uri="tags-fmt" prefix="fmt" %> +<%@ taglib uri="tags-lams" prefix="lams" %> + +<% + +String message=""; + +String stateStr = request.getParameter("state"); +int state = Integer.parseInt(stateStr); + +WebApplicationContext ctx = WebApplicationContextUtils.getRequiredWebApplicationContext(this.getServletContext()); +MessageService messageService = (MessageService)ctx.getBean("centralMessageService"); + +switch (state) +{ +case 100: message = "" + messageService.getMessage("error.support.email.not.set") + ""; break; +case 101: message = "" + messageService.getMessage("error.email.does.not.match") + ""; break; +case 102: message = "" + messageService.getMessage("error.user.not.found") + ""; break; +case 103: message = "" + messageService.getMessage("error.password.request.expired") + ""; break; +case 104: message = messageService.getMessage("forgot.password.email.sent"); break; +case 105: message = messageService.getMessage("heading.password.changed.screen"); break; +} + +%> + + + + + + + <fmt:message key="title.forgot.password"/> + + + + + + + +
+
+
+
+

+
+
+ <%=message %> +

+ +
+
+ + +
\ No newline at end of file Index: lams_central/web/login.jsp =================================================================== diff -u -r7c4ea36bc5fd95011e835f4db412aa9627e744bb -re9d226f1680751f53da50848214c85df0e1f06fb --- lams_central/web/login.jsp (.../login.jsp) (revision 7c4ea36bc5fd95011e835f4db412aa9627e744bb) +++ lams_central/web/login.jsp (.../login.jsp) (revision e9d226f1680751f53da50848214c85df0e1f06fb) @@ -137,16 +137,17 @@ +   + + +

- - - - + - Index: lams_common/conf/hibernate/mappings/org/lamsfoundation/lams/usermanagement/ForgotPasswordRequest.hbm.xml =================================================================== diff -u --- lams_common/conf/hibernate/mappings/org/lamsfoundation/lams/usermanagement/ForgotPasswordRequest.hbm.xml (revision 0) +++ lams_common/conf/hibernate/mappings/org/lamsfoundation/lams/usermanagement/ForgotPasswordRequest.hbm.xml (revision e9d226f1680751f53da50848214c85df0e1f06fb) @@ -0,0 +1,93 @@ + + + + + + + + + + @hibernate.class + table="lams_password_request" + + true + + + + + + @hibernate.id + generator-class="native" + type="java.lang.Integer" + column="request_id" + + + + + + + + + @hibernate.property + column="user_id" + not-null="true" + + + + + true + + @hibernate.property + column="request_key" + length="32" + not-null="true" + unique="true" + + + + + + + @hibernate.property + column="request_date" + length="19" + not-null="true" + + + + + + + \ No newline at end of file Index: lams_common/src/java/org/lamsfoundation/lams/commonContext.xml =================================================================== diff -u -r07578aaa7f526c0c1b537c127cf5f88e0410d472 -re9d226f1680751f53da50848214c85df0e1f06fb --- lams_common/src/java/org/lamsfoundation/lams/commonContext.xml (.../commonContext.xml) (revision 07578aaa7f526c0c1b537c127cf5f88e0410d472) +++ lams_common/src/java/org/lamsfoundation/lams/commonContext.xml (.../commonContext.xml) (revision e9d226f1680751f53da50848214c85df0e1f06fb) @@ -36,6 +36,7 @@ org/lamsfoundation/lams/usermanagement/Privilege.hbm.xml org/lamsfoundation/lams/usermanagement/RolePrivilege.hbm.xml org/lamsfoundation/lams/usermanagement/User.hbm.xml + org/lamsfoundation/lams/usermanagement/ForgotPasswordRequest.hbm.xml org/lamsfoundation/lams/usermanagement/UserOrganisation.hbm.xml org/lamsfoundation/lams/usermanagement/UserOrganisationCollapsed.hbm.xml org/lamsfoundation/lams/usermanagement/UserOrganisationRole.hbm.xml Index: lams_common/src/java/org/lamsfoundation/lams/usermanagement/ForgotPasswordRequest.java =================================================================== diff -u --- lams_common/src/java/org/lamsfoundation/lams/usermanagement/ForgotPasswordRequest.java (revision 0) +++ lams_common/src/java/org/lamsfoundation/lams/usermanagement/ForgotPasswordRequest.java (revision e9d226f1680751f53da50848214c85df0e1f06fb) @@ -0,0 +1,72 @@ +package org.lamsfoundation.lams.usermanagement; + +import java.io.Serializable; +import java.util.Date; + +/** + * @hibernate.class + * table="lams_password_request" + * + * + * @author lfoxton + * + */ +public class ForgotPasswordRequest implements Serializable +{ + /** identifier field */ + private Integer requestId; + + /** identifier field */ + private Integer userId; + + /** persistent field */ + private String requestKey; + + /** persistent field */ + private Date requestDate; + + /** Full Constructor */ + public ForgotPasswordRequest(Integer requestId, Integer userId, + String requestKey, Date requestDate) { + super(); + this.requestId = requestId; + this.userId = userId; + this.requestKey = requestKey; + this.requestDate = requestDate; + } + + /** default constructor */ + public ForgotPasswordRequest() {} + + public Integer getRequestId() { + return requestId; + } + + public void setRequestId(Integer requestId) { + this.requestId = requestId; + } + + public Integer getUserId() { + return userId; + } + + public void setUserId(Integer userId) { + this.userId = userId; + } + + public String getRequestKey() { + return requestKey; + } + + public void setRequestKey(String requestKey) { + this.requestKey = requestKey; + } + + public Date getRequestDate() { + return requestDate; + } + + public void setRequestDate(Date requestDate) { + this.requestDate = requestDate; + } +} Index: lams_common/src/java/org/lamsfoundation/lams/usermanagement/service/IUserManagementService.java =================================================================== diff -u -r7ab9e2377fd1ff4c3c5554bd1f6dffe3384f6f9a -re9d226f1680751f53da50848214c85df0e1f06fb --- lams_common/src/java/org/lamsfoundation/lams/usermanagement/service/IUserManagementService.java (.../IUserManagementService.java) (revision 7ab9e2377fd1ff4c3c5554bd1f6dffe3384f6f9a) +++ lams_common/src/java/org/lamsfoundation/lams/usermanagement/service/IUserManagementService.java (.../IUserManagementService.java) (revision e9d226f1680751f53da50848214c85df0e1f06fb) @@ -30,6 +30,7 @@ import java.util.Vector; import org.lamsfoundation.lams.themes.CSSThemeVisualElement; +import org.lamsfoundation.lams.usermanagement.ForgotPasswordRequest; import org.lamsfoundation.lams.usermanagement.Organisation; import org.lamsfoundation.lams.usermanagement.OrganisationType; import org.lamsfoundation.lams.usermanagement.Role; @@ -269,6 +270,7 @@ */ public User getUserByLogin(String login); + /** * @param login user's login * @param password new password @@ -464,4 +466,11 @@ * @return boolean */ public boolean canEditGroup(Integer userId, Integer orgId); + + /** + * Gets a forgot password request from the db with the given key + * @param key + * @return + */ + public ForgotPasswordRequest getForgotPasswordRequest(String key); } \ No newline at end of file Index: lams_common/src/java/org/lamsfoundation/lams/usermanagement/service/UserManagementService.java =================================================================== diff -u -ra260d2b0a1690b192d6c83163e42b4212c587980 -re9d226f1680751f53da50848214c85df0e1f06fb --- lams_common/src/java/org/lamsfoundation/lams/usermanagement/service/UserManagementService.java (.../UserManagementService.java) (revision a260d2b0a1690b192d6c83163e42b4212c587980) +++ lams_common/src/java/org/lamsfoundation/lams/usermanagement/service/UserManagementService.java (.../UserManagementService.java) (revision e9d226f1680751f53da50848214c85df0e1f06fb) @@ -43,6 +43,7 @@ import org.lamsfoundation.lams.usermanagement.OrganisationType; import org.lamsfoundation.lams.usermanagement.Role; import org.lamsfoundation.lams.usermanagement.User; +import org.lamsfoundation.lams.usermanagement.ForgotPasswordRequest; import org.lamsfoundation.lams.usermanagement.UserOrganisation; import org.lamsfoundation.lams.usermanagement.UserOrganisationRole; import org.lamsfoundation.lams.usermanagement.Workspace; @@ -421,7 +422,7 @@ List results = baseDAO.findByProperty(User.class,"login",login); return results.isEmpty() ? null : (User)results.get(0); } - + public void updatePassword(String login, String password) { try{ User user = getUserByLogin(login); @@ -1082,4 +1083,9 @@ } return false; } + + public ForgotPasswordRequest getForgotPasswordRequest(String key) { + List results = baseDAO.findByProperty(ForgotPasswordRequest.class,"requestKey",key); + return results.isEmpty() ? null : (ForgotPasswordRequest)results.get(0); + } } \ No newline at end of file