package models; import play.Configuration; import play.Logger; import play.data.format.Formats; import play.data.validation.Constraints; import play.db.ebean.Model; import play.i18n.Messages; import uk.bl.scope.EmailHelper; import javax.annotation.Nullable; import javax.persistence.Entity; import javax.persistence.EnumType; import javax.persistence.Enumerated; import javax.persistence.Id; import org.apache.commons.lang3.StringUtils; import java.net.MalformedURLException; import java.net.URL; import java.util.Calendar; import java.util.Date; import java.util.UUID; /** * @author * @since */ @Entity public class Token extends Model { /** * */ private static final long serialVersionUID = 2922262473092105525L; // 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 public static Model.Finder<String, Token> find = new Finder<String, Token>(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 static 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 static void sendMailResetPassword(User user, String hostname) throws MalformedURLException { sendMail(user, TypeToken.password, null, hostname); } /** * 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 static void sendMailChangeMail(User user, @Nullable String email, String hostname) throws MalformedURLException { sendMail(user, TypeToken.email, email, hostname); } /** * 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 static void sendMail(User user, TypeToken type, String email, String hostname) throws MalformedURLException { Token token = getNewToken(user, type, email); String context = Configuration.root().getString("application.context"); String externalServer = hostname + context; String subject = null; String message = null; String toMail = null; // Should use reverse routing here. String urlString = externalServer + "/" + type.urlPath + "/" + token.token; Logger.debug("urlString: " + urlString); 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; Logger.debug("subject: " + subject); Logger.debug("message: " + message); Logger.debug("toMail: " + toMail); 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); EmailHelper.sendMessage(toMail, subject, message); // Mail.Envelop envelop = new Mail.Envelop(subject, message, toMail); // Mail.sendMail(envelop); } }