package models; import models.utils.Mail; import play.Configuration; import play.Logger; import play.data.format.Formats; import play.data.validation.Constraints; import com.avaje.ebean.Model; import play.i18n.Messages; import play.libs.mailer.Email; import play.libs.mailer.MailerClient; import javax.annotation.Nullable; import javax.persistence.Entity; import javax.persistence.EnumType; import javax.persistence.Enumerated; import javax.persistence.Id; import java.net.MalformedURLException; import java.net.URL; import java.util.Calendar; import java.util.Date; import java.util.UUID; /** * @author wsargent * @since 5/15/12 */ @Entity public class Token extends Model { // Reset tokens will expire after a day. private static final int EXPIRATION_DAYS = 1; public enum TypeToken { password("reset"), email("email"); private String urlPath; TypeToken(String urlPath) { this.urlPath = urlPath; } } @Id public String token; @Constraints.Required @Formats.NonEmpty public Long userId; @Constraints.Required @Enumerated(EnumType.STRING) public TypeToken type; @Formats.DateTime(pattern = "yyyy-MM-dd HH:mm:ss") public Date dateCreation; @Constraints.Required @Formats.NonEmpty public String email; // -- Queries @SuppressWarnings("unchecked") public static Model.Finder<String, Token> find = new Finder(String.class, Token.class); /** * Retrieve a token by id and type. * * @param token token Id * @param type type of token * @return a resetToken */ public static Token findByTokenAndType(String token, TypeToken type) { return find.where().eq("token", token).eq("type", type).findUnique(); } /** * @return true if the reset token is too old to use, false otherwise. */ public boolean isExpired() { return dateCreation != null && dateCreation.before(expirationTime()); } /** * @return a date before which the password link has expired. */ private Date expirationTime() { Calendar cal = Calendar.getInstance(); cal.set(Calendar.DATE, -EXPIRATION_DAYS); return cal.getTime(); } /** * Return a new Token. * * @param user user * @param type type of token * @param email email for a token change email * @return a reset token */ private Token getNewToken(User user, TypeToken type, String email) { Token token = new Token(); token.token = UUID.randomUUID().toString(); token.userId = user.id; token.type = type; token.email = email; token.save(); return token; } /** * Send the Email to confirm ask new password. * * @param user the current user * @throws java.net.MalformedURLException if token is wrong. */ public void sendMailResetPassword(User user, MailerClient mc) throws MalformedURLException { sendMail(user, TypeToken.password, null, mc); } /** * Send the Email to confirm ask new password. * * @param user the current user * @param email email for a change email token * @throws java.net.MalformedURLException if token is wrong. */ public void sendMailChangeMail(User user, @Nullable String email,MailerClient mc) throws MalformedURLException { sendMail(user, TypeToken.email, email,mc ); } /** * Send the Email to confirm ask new password. * * @param user the current user * @param type token type * @param email email for a change email token * @throws java.net.MalformedURLException if token is wrong. */ private void sendMail(User user, TypeToken type, String email, MailerClient mc) throws MalformedURLException { Token token = getNewToken(user, type, email); String externalServer = Configuration.root().getString("server.hostname"); String subject = null; String message = null; String toMail = null; // Should use reverse routing here. String urlString = urlString = "http://" + externalServer + "/" + type.urlPath + "/" + token.token; URL url = new URL(urlString); // validate the URL switch (type) { case password: subject = Messages.get("mail.reset.ask.subject"); message = Messages.get("mail.reset.ask.message", url.toString()); toMail = user.email; break; case email: subject = Messages.get("mail.change.ask.subject"); message = Messages.get("mail.change.ask.message", url.toString()); toMail = token.email; // == email parameter break; } Logger.debug("sendMailResetLink: url = " + url); Mail.Envelop envelop = new Mail.Envelop(subject, message, toMail); Mail mailer = new Mail(mc); mailer.sendMail(envelop); } }