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);
}
}