package org.fluxtream.mvc.controllers; import com.postmark.PostmarkMailSender; import org.apache.commons.httpclient.HttpException; import org.apache.velocity.app.VelocityEngine; import org.fluxtream.core.Configuration; import org.fluxtream.core.aspects.FlxLogger; import org.fluxtream.core.domain.Guest; import org.fluxtream.core.domain.ResetPasswordToken; import org.fluxtream.core.services.GuestService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.mail.SimpleMailMessage; import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.core.Authentication; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.servlet.ModelAndView; import javax.servlet.http.HttpServletRequest; import java.io.IOException; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; @Controller @RequestMapping("/support") public class SupportController { static FlxLogger logger = FlxLogger.getLogger(SupportController.class); @Qualifier("authenticationManager") @Autowired AuthenticationManager authenticationManager; @Autowired Configuration env; @Autowired GuestService guestService; @Autowired VelocityEngine velocityEngine; @RequestMapping(value = "/lostPassword") public ModelAndView lostPassword(HttpServletRequest request) { ModelAndView mav = new ModelAndView("support/lostPassword"); mav.addObject("release", env.get("release")); return mav; } @RequestMapping(value = "/sendResetRequest") public ModelAndView sendResetRequest(HttpServletRequest request) throws HttpException,IOException { // create a hash for this request String email = request.getParameter("recover[email]"); Guest guest = guestService.getGuestByEmail(email); if (guest == null) { ModelAndView mav = new ModelAndView("support/lostPassword"); mav.addObject("error", "Sorry, we could not find a user with your email address. Please try again."); mav.addObject("release", env.get("release")); return mav; } SimpleMailMessage message = new SimpleMailMessage(); message.setTo(email); // Retrieve postmark properties. Keys postmarkApiKey and postmarkSendAddress should be set // in common.properties String postmarkSendAddress = env.get("postmarkSendAddress"); String postmarkApiKey = env.get("postmarkApiKey"); // Process postmarkSendAddress if(postmarkSendAddress==null) { postmarkSendAddress = "support@fluxtream.com"; logger.warn("component=support_controller action=sendResetRequest" + " guestId=" + guest.getId() + " message=\"**** PLEASE SET postmarkSendAddress IN common.properties; defaulting to support@fluxtream.com\""); } message.setFrom(postmarkSendAddress); // Process postmarkApiKey if(postmarkApiKey==null) { logger.error("component=support_controller action=sendResetRequest" + " guestId=" + guest.getId() + " message=\"**** PLEASE SET postmarkApiKey IN common.properties. Cannot send reset email without it.\""); ModelAndView mav = new ModelAndView("support/serverConfigError"); mav.addObject("release", env.get("release")); mav.addObject("userMessage", "We are not able to send email for resetting your password"); mav.addObject("adminMessage", "Please set up the following keys in common.properties to enable email sending: postmarkApiKey and postmarkSendAddress"); return mav; } PostmarkMailSender sender = new PostmarkMailSender( env.get("postmarkApiKey")); message.setSubject("Fluxtream Reset password request"); Map<String, String> vars = new HashMap<String, String>(); ResetPasswordToken pToken = guestService.createToken(guest.getId()); vars.put("token", pToken.token); vars.put("homeBaseUrl", env.get("homeBaseUrl")); if (guest.firstname != null && !guest.firstname.equals("")) vars.put("username", guest.firstname); else vars.put("username", guest.username); String mailMessage ="Hi " + vars.get("username") + ",\n" + "\n" + "Someone requested that your Fluxtream password be reset.\n" + "\n" + "If this wasn't you, there's nothing to worry about - simply ignore this email and nothing will change.\n" + "\n" + "If you DID ask to reset the password on your Fluxtream account, just click here to make it happen:\n" + "\n" + vars.get("homeBaseUrl") + "support/resetPassword?token=" + vars.get("token") + "\n" + "\n" + "Thanks,\n" + "\n" + "The Fluxtream Team"; message.setText(mailMessage); sender.send(message); ModelAndView mav = new ModelAndView("support/resetRequestSent"); mav.addObject("release", env.get("release")); return mav; } @RequestMapping(value = "/resetPassword") public ModelAndView resetPassword(HttpServletRequest request, @RequestParam("token") String token) throws Exception { List<String> errors = new ArrayList<String>(); ResetPasswordToken pToken = guestService.getToken(token); Guest guest = null; if (pToken == null) errors.add("invalidToken"); else { guest = guestService.getGuestById(pToken.guestId); } ModelAndView mav = new ModelAndView("support/resetPassword"); if (pToken != null && guest != null) { if (guest.firstname != null && !guest.firstname.equals("")) request.setAttribute("username", guest.firstname); else request.setAttribute("username", guest.username); request.setAttribute("token", pToken.token); } else request.setAttribute("errors", errors); mav.addObject("release", env.get("release")); return mav; } @RequestMapping(value = "/doResetPassword") public ModelAndView doResetPassword(HttpServletRequest request, @RequestParam("token") String token, @RequestParam("password") String password, @RequestParam("password2") String password2) throws Exception { // create a hash for this request List<String> required = new ArrayList<String>(); List<String> errors = new ArrayList<String>(); if (password == "") required.add("password"); if (password2 == "") required.add("password2"); if (password.length() < 8) errors.add("passwordTooShort"); if (!password.equals(password2)) errors.add("passwordsDontMatch"); ResetPasswordToken pToken = guestService.getToken(token); long now = System.currentTimeMillis(); int resetPasswordTokensExpireDelay = Integer.valueOf(env .get("resetPasswordTokensExpireDelay")); Guest guest = null; if (pToken == null) errors.add("invalidToken"); else if ((now - pToken.ts) > resetPasswordTokensExpireDelay) { errors.add("tokenExpired"); guestService.deleteToken(token); } else { guest = guestService.getGuestById(pToken.guestId); } if (errors.size() > 0 || required.size() > 0) { ModelAndView mav = new ModelAndView("support/resetPassword"); if (guest != null) { if (guest.firstname != null && !guest.firstname.equals("")) request.setAttribute("username", guest.firstname); else request.setAttribute("username", guest.username); } else request.setAttribute("username", "Stranger"); mav.addObject("errors", errors); mav.addObject("required", required); mav.addObject("token", pToken == null ? "null" : pToken.token); mav.addObject("release", env.get("release")); return mav; } else { guestService.setPassword(guest.getId(), password); guestService.deleteToken(pToken.token); UsernamePasswordAuthenticationToken authToken = new UsernamePasswordAuthenticationToken( guest.username, password); Authentication authentication = authenticationManager .authenticate(authToken); SecurityContextHolder.getContext().setAuthentication(authentication); ModelAndView mav = new ModelAndView("support/passwordReset"); mav.addObject("token", pToken.token); mav.addObject("release", env.get("release")); return mav; } } }