package controllers;
import models.Token;
import models.User;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.mail.EmailException;
import play.Logger;
import play.data.DynamicForm;
import play.data.Form;
import play.data.validation.Constraints;
import play.i18n.Messages;
import play.mvc.Controller;
import play.mvc.Result;
import uk.bl.exception.ActException;
import uk.bl.scope.EmailHelper;
import views.html.users.reset.emailForm;
import views.html.users.reset.resetPassword;
import views.html.users.reset.emailRequestLink;
import views.html.users.reset.resetConfirmation;
import java.net.MalformedURLException;
import static play.data.Form.form;
/**
* Token password :
* - ask for an email address.
* - send a link pointing them to a reset page.
* - show the reset page and set them reset it.
* <p/>
* <p/>
* User: yesnault
* Date: 20/01/12
*/
public class ResetController extends Controller {
public static class AskForm {
@Constraints.Required
public String email;
}
public static class ResetForm {
@Constraints.Required
public String inputPassword;
}
/**
* Display the reset password form.
*
* @return reset password form
*/
public static Result showEmailForm() {
Form<AskForm> askForm = form(AskForm.class);
return ok(emailForm.render(askForm));
}
/**
* Run ask password.
*
* @return reset password form if error, runAsk render otherwise
*/
public static Result confirmEmail() {
Form<AskForm> askForm = form(AskForm.class).bindFromRequest();
DynamicForm requestData = form().bindFromRequest();
String hostname = requestData.get("hostname");
String email = requestData.get("email");
if (StringUtils.isBlank(email)) {
flash("message", "Email is required");
return badRequest(emailForm.render(askForm));
}
// final String email = askForm.get().email;
Logger.debug("runAsk: email = " + email);
User user = User.findByEmail(email);
Logger.debug("runAsk: user = " + user);
// If we do not have this email address in the list, we should not expose this to the user.
// This exposes that the user has an account, allowing a user enumeration attack.
// See http://www.troyhunt.com/2012/05/everything-you-ever-wanted-to-know.html for details.
// Instead, email the person saying that the reset failed.
if (user == null) {
Logger.debug("No user found with email " + email);
flash("message", "No user with that email");
// sendFailedPasswordResetAttempt(email);
return badRequest(emailForm.render(askForm));
}
Logger.debug("Sending password reset link to user " + user);
Logger.debug("hostname: " + hostname);
try {
Token.sendMailResetPassword(user, hostname);
return ok(emailRequestLink.render(email));
} catch (MalformedURLException e) {
Logger.error("Cannot validate URL", e);
flash("message", Messages.get("error.technical"));
}
return badRequest(emailForm.render(askForm));
}
public static Result resetPassword(String token) {
if (token == null) {
flash("error", Messages.get("error.technical"));
Form<AskForm> askForm = form(AskForm.class);
return badRequest(emailForm.render(askForm));
}
Token resetToken = Token.findByTokenAndType(token, Token.TypeToken.password);
if (resetToken == null) {
flash("error", Messages.get("error.technical"));
Form<AskForm> askForm = form(AskForm.class);
return badRequest(emailForm.render(askForm));
}
if (resetToken.isExpired()) {
resetToken.delete();
flash("error", Messages.get("error.expiredresetlink"));
Form<AskForm> askForm = form(AskForm.class);
return badRequest(emailForm.render(askForm));
}
Form<ResetForm> resetForm = form(ResetForm.class);
return ok(resetPassword.render(resetForm, token));
}
/**
* @return reset password form
*/
public static Result confirmPassword(String token) {
Form<ResetForm> resetForm = form(ResetForm.class).bindFromRequest();
Logger.debug("runReset: " + token);
Logger.debug("errors: " + resetForm.errors());
DynamicForm requestData = form().bindFromRequest();
// if (resetForm.hasErrors()) {
// flash("message", Messages.get("signup.valid.password"));
// return badRequest(reset.render(resetForm, token));
// }
try {
String password = requestData.get("inputPassword");
String confirmPassword = requestData.get("confirmPassword");
if (StringUtils.isBlank(password) && StringUtils.isBlank(confirmPassword)) {
flash("message", "Both Password and Confirm is required");
return badRequest(resetPassword.render(resetForm, token));
}
if (!password.equals(confirmPassword)) {
flash("message", "Passwords do not match");
return badRequest(resetPassword.render(resetForm, token));
}
Token resetToken = Token.findByTokenAndType(token, Token.TypeToken.password);
if (resetToken == null) {
flash("message", Messages.get("error.technical"));
return badRequest(resetPassword.render(resetForm, token));
}
if (resetToken.isExpired()) {
resetToken.delete();
flash("message", Messages.get("error.expiredresetlink"));
return badRequest(resetPassword.render(resetForm, token));
}
// check email
User user = User.findById(resetToken.userId);
if (user == null) {
// display no detail (email unknown for example) to
// avoir check email by foreigner
flash("message", Messages.get("error.technical"));
return badRequest(resetPassword.render(resetForm, token));
}
user.changePassword(password);
// Send email saying that the password has just been changed.
sendPasswordChanged(user);
flash("message", Messages.get("resetpassword.success"));
return ok(resetConfirmation.render(user.email));
} catch (ActException e) {
flash("message", Messages.get("error.technical"));
return badRequest(resetPassword.render(resetForm, token));
} catch (EmailException e) {
flash("message", Messages.get("error.technical"));
return badRequest(resetPassword.render(resetForm, token));
}
}
/**
* Send mail with the new password.
*
* @param user user created
* @throws EmailException Exception when sending mail
*/
private static void sendPasswordChanged(User user) throws EmailException {
String subject = Messages.get("mail.reset.confirm.subject");
String message = Messages.get("mail.reset.confirm.message");
EmailHelper.sendMessage(user.email, subject, message);
}
}