Index: lams_build/lib/lams/lams.jar =================================================================== diff -u -r04f70c56cf4d63d83a332402a572c9062f318bbf -r5cf9e6a0f2d86fd8371a466a07b8c0cbf3f81cb8 Binary files differ Index: lams_central/conf/language/lams/ApplicationResources.properties =================================================================== diff -u -r696744f584a475fe75ff35be7e09c55d5dcb21eb -r5cf9e6a0f2d86fd8371a466a07b8c0cbf3f81cb8 --- lams_central/conf/language/lams/ApplicationResources.properties (.../ApplicationResources.properties) (revision 696744f584a475fe75ff35be7e09c55d5dcb21eb) +++ lams_central/conf/language/lams/ApplicationResources.properties (.../ApplicationResources.properties) (revision 5cf9e6a0f2d86fd8371a466a07b8c0cbf3f81cb8) @@ -265,6 +265,9 @@ signup.confirm.email =Confirm email signup.course.key =Course key signup.submit =Submit +signup.email.verify.sent =A confirmation email has been sent to {0}
Check your email and follow the instructions. +signup.email.verify.success =You email has been verified +signup.email.verify.fail =Your email could not be verified title.lams.signup =LAMS Signup error.username.blank =Username cannot be blank error.username.exists =Username is taken Index: lams_central/src/java/org/lamsfoundation/lams/web/action/SignupAction.java =================================================================== diff -u -rd5b05f6e239a87908856f9f4251a487158ed9ca8 -r5cf9e6a0f2d86fd8371a466a07b8c0cbf3f81cb8 --- lams_central/src/java/org/lamsfoundation/lams/web/action/SignupAction.java (.../SignupAction.java) (revision d5b05f6e239a87908856f9f4251a487158ed9ca8) +++ lams_central/src/java/org/lamsfoundation/lams/web/action/SignupAction.java (.../SignupAction.java) (revision 5cf9e6a0f2d86fd8371a466a07b8c0cbf3f81cb8) @@ -1,5 +1,10 @@ package org.lamsfoundation.lams.web.action; +import java.io.UnsupportedEncodingException; +import java.net.URLEncoder; + +import javax.mail.MessagingException; +import javax.mail.internet.AddressException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; @@ -36,18 +41,22 @@ @Override public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) { + String method = WebUtil.readStrParam(request, "method", true); + if (StringUtils.equals(method, "emailVerify")) { + return emailVerify(mapping, form, request, response); + } if (signupService == null || timezoneService == null) { WebApplicationContext wac = WebApplicationContextUtils .getRequiredWebApplicationContext(getServlet().getServletContext()); signupService = (ISignupService) wac.getBean("signupService"); timezoneService = (ITimezoneService) wac.getBean("timezoneService"); } - + request.setAttribute("countryCodes", LanguageUtil.getCountryCodes(true)); DynaActionForm signupForm = (DynaActionForm) form; - String method = WebUtil.readStrParam(request, "method", true); + String context = WebUtil.readStrParam(request, "context", true); SignupOrganisation signupOrganisation = null; if (StringUtils.isNotBlank(context)) { @@ -81,6 +90,12 @@ saveErrors(request, errors); return mapping.findForward("signup"); } else { + boolean emailVerify = false; + String context = WebUtil.readStrParam(request, "context", true); + if (StringUtils.isNotBlank(context)) { + SignupOrganisation signupOrganisation = signupService.getSignupOrganisation(context); + emailVerify = signupOrganisation.getEmailVerify(); + } // proceed with signup User user = new User(); user.setLogin(signupForm.getString("username")); @@ -92,28 +107,29 @@ String salt = HashUtil.salt(); user.setSalt(salt); user.setPassword(HashUtil.sha256(signupForm.getString("password"), salt)); - signupService.signupUser(user, signupForm.getString("context")); - - // send email - try { - String subject = "Your LAMS account details"; - String body = "Hi there,\n\n"; - body += "You've successfully registered an account with username " + user.getLogin(); - body += " on the LAMS server at " + Configuration.get(ConfigurationKeys.SERVER_URL); - body += ". If you ever forget your password, you can reset it via this URL " - + Configuration.get(ConfigurationKeys.SERVER_URL) + "/forgotPassword.jsp."; - body += "\n\n"; - body += "Regards,\n"; - body += "LAMS Signup System"; - boolean isHtmlFormat = false; - - Emailer.sendFromSupportEmail(subject, user.getEmail(), body, isHtmlFormat); - } catch (Exception e) { - log.error(e.getMessage(), e); - request.setAttribute("error", e.getMessage()); + if (emailVerify) { + user.setEmailVerified(false); + user.setDisabledFlag(true); + signupService.signupUser(user, signupForm.getString("context")); + try { + sendVerificationEmail(user); + } catch (Exception e) { + log.error(e.getMessage(), e); + request.setAttribute("error", e.getMessage()); + } + request.setAttribute("email", user.getEmail()); + return mapping.findForward("emailVerify"); + } else { + user.setDisabledFlag(false); + signupService.signupUser(user, signupForm.getString("context")); + try { + sendWelcomeEmail(user); + } catch (Exception e) { + log.error(e.getMessage(), e); + request.setAttribute("error", e.getMessage()); + } + return mapping.findForward("success"); } - - return mapping.findForward("success"); } } catch (Exception e) { log.error(e.getMessage(), e); @@ -123,6 +139,37 @@ return mapping.findForward("index"); } + private void sendWelcomeEmail(User user) throws AddressException, MessagingException, UnsupportedEncodingException { + String subject = "LAMS: account details"; + String body = "Hi there,\n\n"; + body += "You've successfully registered an account with username " + user.getLogin(); + body += " on the LAMS server at " + Configuration.get(ConfigurationKeys.SERVER_URL); + body += ". If you ever forget your password, you can reset it via this URL " + + Configuration.get(ConfigurationKeys.SERVER_URL) + "/forgotPassword.jsp."; + body += "\n\n"; + body += "Regards,\n"; + body += "LAMS Signup System"; + boolean isHtmlFormat = false; + + Emailer.sendFromSupportEmail(subject, user.getEmail(), body, isHtmlFormat); + } + + private void sendVerificationEmail(User user) + throws AddressException, MessagingException, UnsupportedEncodingException { + String hash = HashUtil.sha256(user.getEmail(), user.getSalt()); + String link = Configuration.get(ConfigurationKeys.SERVER_URL) + "signup/signup.do?method=emailVerify&login=" + + URLEncoder.encode(user.getLogin(), "UTF-8") + "&hash=" + hash; + String subject = "LAMS: confirm email address"; + String body = "Hi there,

"; + body += "Please confirm your email address by clicking on the link below
"; + body += "" + link + "

"; + body += "Regards,
"; + body += "LAMS Signup System"; + boolean isHtmlFormat = true; + + Emailer.sendFromSupportEmail(subject, user.getEmail(), body, isHtmlFormat); + } + private ActionForward signIn(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) { try { @@ -204,16 +251,15 @@ } else if (!StringUtils.equals(userEmail, signupForm.getString("confirmEmail"))) { errors.add("email", new ActionMessage("error.emails.unequal")); } - + //country validation String country = (signupForm.get("country") == null) ? null : (String) signupForm.get("country"); if (StringUtils.isBlank(country) || "0".equals(country)) { errors.add("email", new ActionMessage("error.country.required")); } // courseKey validation - if (!signupService.courseKeyIsValid(signupForm.getString("context"), - signupForm.getString("courseKey"))) { + if (!signupService.courseKeyIsValid(signupForm.getString("context"), signupForm.getString("courseKey"))) { errors.add("courseKey", new ActionMessage("error.course.key.invalid")); } return errors; @@ -227,8 +273,7 @@ if (StringUtils.isBlank(signupForm.getString("passwordTab2"))) { errors.add("passwordTab2", new ActionMessage("error.password.blank")); } - if (!signupService.courseKeyIsValid(signupForm.getString("context"), - signupForm.getString("courseKeyTab2"))) { + if (!signupService.courseKeyIsValid(signupForm.getString("context"), signupForm.getString("courseKeyTab2"))) { errors.add("courseKeyTab2", new ActionMessage("error.course.key.invalid")); } @@ -251,4 +296,26 @@ return errors; } + + /** + * Checks whether incoming hash is the same as the expected hash for email verification + */ + public ActionForward emailVerify(ActionMapping mapping, ActionForm form, HttpServletRequest request, + HttpServletResponse response) { + String login = WebUtil.readStrParam(request, "login", false); + String hash = WebUtil.readStrParam(request, "hash", false); + + boolean verified = signupService.emailVerify(login, hash); + if (verified) { + request.setAttribute("emailVerified", verified); + User user = signupService.getUserByLogin(login); + try { + sendWelcomeEmail(user); + } catch (Exception e) { + log.error(e.getMessage(), e); + request.setAttribute("error", e.getMessage()); + } + } + return mapping.findForward("emailVerifyResult"); + } } Index: lams_central/web/WEB-INF/struts-config.xml =================================================================== diff -u -rb959a5f41013249a0537fb19bb7129dd727bb55a -r5cf9e6a0f2d86fd8371a466a07b8c0cbf3f81cb8 --- lams_central/web/WEB-INF/struts-config.xml (.../struts-config.xml) (revision b959a5f41013249a0537fb19bb7129dd727bb55a) +++ lams_central/web/WEB-INF/struts-config.xml (.../struts-config.xml) (revision 5cf9e6a0f2d86fd8371a466a07b8c0cbf3f81cb8) @@ -278,6 +278,16 @@ redirect="false" /> + + +<%@ taglib uri="tags-fmt" prefix="fmt"%> +<%@ taglib uri="tags-core" prefix="c"%> +<%@ taglib uri="tags-html" prefix="html"%> +<%@ page language="java" pageEncoding="UTF-8" contentType="text/html;charset=utf-8"%> + + + + + + + + +
+ +
+
+ + + + + + + + + + + , + + + + + +
+ + + Index: lams_central/web/signup/emailVerifyResult.jsp =================================================================== diff -u --- lams_central/web/signup/emailVerifyResult.jsp (revision 0) +++ lams_central/web/signup/emailVerifyResult.jsp (revision 5cf9e6a0f2d86fd8371a466a07b8c0cbf3f81cb8) @@ -0,0 +1,45 @@ +<%@ taglib uri="tags-lams" prefix="lams"%> +<%@ taglib uri="tags-fmt" prefix="fmt"%> +<%@ taglib uri="tags-core" prefix="c"%> +<%@ taglib uri="tags-html" prefix="html"%> +<%@ page language="java" pageEncoding="UTF-8" contentType="text/html;charset=utf-8"%> + + + + + + + + +
+ +
+
+ + + , + + + + + + + + +
+ +

+ +

+
+
+ + + + + +
+
+ + + Index: lams_common/conf/hibernate/mappings/org/lamsfoundation/lams/usermanagement/User.hbm.xml =================================================================== diff -u -r60e44b19b8de02a00faa437fba8117928baa3d73 -r5cf9e6a0f2d86fd8371a466a07b8c0cbf3f81cb8 --- lams_common/conf/hibernate/mappings/org/lamsfoundation/lams/usermanagement/User.hbm.xml (.../User.hbm.xml) (revision 60e44b19b8de02a00faa437fba8117928baa3d73) +++ lams_common/conf/hibernate/mappings/org/lamsfoundation/lams/usermanagement/User.hbm.xml (.../User.hbm.xml) (revision 5cf9e6a0f2d86fd8371a466a07b8c0cbf3f81cb8) @@ -194,6 +194,9 @@ length="128" + + Index: lams_common/src/java/org/lamsfoundation/lams/signup/service/ISignupService.java =================================================================== diff -u -r51fb2a37254f24bb2a805d4ffd54482c779f43fa -r5cf9e6a0f2d86fd8371a466a07b8c0cbf3f81cb8 --- lams_common/src/java/org/lamsfoundation/lams/signup/service/ISignupService.java (.../ISignupService.java) (revision 51fb2a37254f24bb2a805d4ffd54482c779f43fa) +++ lams_common/src/java/org/lamsfoundation/lams/signup/service/ISignupService.java (.../ISignupService.java) (revision 5cf9e6a0f2d86fd8371a466a07b8c0cbf3f81cb8) @@ -20,7 +20,6 @@ * **************************************************************** */ - package org.lamsfoundation.lams.signup.service; import java.util.List; @@ -47,4 +46,6 @@ void signinUser(String login, String context); User getUserByLogin(String login); + + boolean emailVerify(String login, String hash); } Index: lams_common/src/java/org/lamsfoundation/lams/signup/service/SignupService.java =================================================================== diff -u -r098532cd2b5687da032408b04a1120dab668083b -r5cf9e6a0f2d86fd8371a466a07b8c0cbf3f81cb8 --- lams_common/src/java/org/lamsfoundation/lams/signup/service/SignupService.java (.../SignupService.java) (revision 098532cd2b5687da032408b04a1120dab668083b) +++ lams_common/src/java/org/lamsfoundation/lams/signup/service/SignupService.java (.../SignupService.java) (revision 5cf9e6a0f2d86fd8371a466a07b8c0cbf3f81cb8) @@ -21,6 +21,7 @@ import org.lamsfoundation.lams.usermanagement.service.IUserManagementService; import org.lamsfoundation.lams.util.Configuration; import org.lamsfoundation.lams.util.ConfigurationKeys; +import org.lamsfoundation.lams.util.HashUtil; import org.lamsfoundation.lams.util.LanguageUtil; public class SignupService implements ISignupService { @@ -33,7 +34,6 @@ public void signupUser(User user, String context) { // save User user.setTheme(userManagementService.getDefaultTheme()); - user.setDisabledFlag(false); user.setAuthenticationMethod(getAuthenticationMethod(AuthenticationMethod.DB)); user.setLocale(getDefaultLocale()); user.setCreateDate(new Date()); @@ -142,6 +142,20 @@ return signupDAO.contextExists(soid, context); } + @Override + public boolean emailVerify(String login, String hash) { + User user = getUserByLogin(login); + if (user == null || !hash.equals(HashUtil.sha256(user.getEmail(), user.getSalt()))) { + return false; + } + if (!Boolean.TRUE.equals(user.getEmailVerified())) { + user.setEmailVerified(true); + user.setDisabledFlag(false); + userManagementService.save(user); + } + return true; + } + public void setSignupDAO(ISignupDAO signupDAO) { this.signupDAO = signupDAO; } Index: lams_common/src/java/org/lamsfoundation/lams/usermanagement/User.java =================================================================== diff -u -r455c0190de52ccfe3116ecf5d805e344a6506b69 -r5cf9e6a0f2d86fd8371a466a07b8c0cbf3f81cb8 --- lams_common/src/java/org/lamsfoundation/lams/usermanagement/User.java (.../User.java) (revision 455c0190de52ccfe3116ecf5d805e344a6506b69) +++ lams_common/src/java/org/lamsfoundation/lams/usermanagement/User.java (.../User.java) (revision 5cf9e6a0f2d86fd8371a466a07b8c0cbf3f81cb8) @@ -41,7 +41,6 @@ import org.lamsfoundation.lams.util.LanguageUtil; public class User implements Serializable, Comparable { - /** identifier field */ private Integer userId; @@ -112,6 +111,9 @@ private String email; /** persistent field */ + private Boolean emailVerified = true; + + /** persistent field */ private Boolean disabledFlag; /** persistent field */ @@ -355,6 +357,14 @@ this.email = email; } + public Boolean getEmailVerified() { + return emailVerified; + } + + public void setEmailVerified(Boolean emailVerified) { + this.emailVerified = emailVerified; + } + public Boolean getDisabledFlag() { return disabledFlag; } @@ -502,14 +512,10 @@ : pagesWithDisabledTutorials; return new UserDTO(userId, firstName, lastName, login, languageIsoCode, countryIsoCode, direction, email, - theme != null ? new ThemeDTO(theme) : null, - timeZone, authenticationMethod.getAuthenticationMethodId(), fckLanguageMapping, - (tutorialsDisabled == null ? false : true), // assume tutorials enabled if not set - tutorialPages, - (firstLogin == null ? true : false), // assume no firstLogin value means they haven't logged in - lastVisitedOrganisationId, - portraitUuid - ); + theme != null ? new ThemeDTO(theme) : null, timeZone, authenticationMethod.getAuthenticationMethodId(), + fckLanguageMapping, (tutorialsDisabled == null ? false : true), // assume tutorials enabled if not set + tutorialPages, (firstLogin == null ? true : false), // assume no firstLogin value means they haven't logged in + lastVisitedOrganisationId, portraitUuid); } public UserBasicDTO getUserBasicDTO() {