package models; import java.nio.charset.Charset; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.util.Arrays; import java.util.Collections; import java.util.List; import java.util.Map; import java.util.UUID; import javax.jcr.SimpleCredentials; import javax.jcr.nodetype.NodeType; import org.apache.commons.codec.binary.Hex; import org.apache.commons.lang.builder.EqualsBuilder; import org.apache.commons.lang.builder.HashCodeBuilder; import org.jcrom.annotations.JcrChildNode; import org.jcrom.annotations.JcrIdentifier; import org.jcrom.annotations.JcrName; import org.jcrom.annotations.JcrNode; import org.jcrom.annotations.JcrPath; import org.jcrom.annotations.JcrProperty; import play.data.validation.Constraints.Email; import play.data.validation.Constraints.MinLength; import play.data.validation.Constraints.Required; import play.data.validation.ValidationError; import com.feth.play.module.pa.providers.password.UsernamePasswordAuthProvider.UsernamePassword; import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableMap.Builder; @JcrNode( nodeType = NodeType.NT_UNSTRUCTURED, mixinTypes = { NodeType.MIX_CREATED, NodeType.MIX_LAST_MODIFIED, NodeType.MIX_REFERENCEABLE }, classNameProperty = "className") public class User implements IdentifiableUser { @JcrIdentifier private String id; @JcrName private String nodeName; @JcrPath private String nodePath; @JcrProperty private String email; @JcrProperty private String name; @JcrProperty private String verificationToken; @JcrProperty private boolean verified; @JcrChildNode private List<Notification> notifications = Collections.emptyList(); public static class ChangePassword { @Required @MinLength(8) public String password; @Required public String repeatPassword; public Map<String,List<ValidationError>> validate() { Builder<String, List<ValidationError>> b = ImmutableMap.<String, List<ValidationError>>builder(); if (!password.equals(repeatPassword)) { b.put("repeatPassword", Arrays.asList( new ValidationError("password.match", "Passwords don't match"))); } return b.build(); } } public static class Login implements UsernamePassword { @Required @Email public String email; @Required public String password; @Override public String getEmail() { return email; } @Override public String getPassword() { return password; } } public static class Invite implements UsernamePassword { @Required @Email public String email; @Required @MinLength(2) public String name; public Invite() {} public Invite(String e, String n) { this.email = e; this.name = n; } @Override public String getEmail() { return email; } @Override public String getPassword() { return null; } } public static class ResetPassword { @Required @Email public String email; public ResetPassword() {} public ResetPassword(String e) { this.email = e; } public String getEmail() { return email; } } public User() {} @Override public String getId() { return id; } public String getJackrabbitUserId() { return getId(); } public SimpleCredentials getCredentials() { return new SimpleCredentials(email, "".toCharArray()); } @Override public String getEmail() { return email; } public void setEmail(String email) { this.email = email; this.nodeName = generateNodeName(email); } @Override public String getName() { return name; } public void setName(String name) { this.name = name; } String getNodePath() { return nodePath; } public boolean isVerified() { return verified; } public void clearVerificationToken() { this.verificationToken = null; } public String createVerificationToken() { this.verificationToken = generateVerificationToken(); return this.verificationToken; } public boolean checkVerificationToken(String token) { if (this.verificationToken == null) return false; return this.verificationToken.equals(token); } protected String generateVerificationToken() { return UUID.randomUUID().toString(); } public void setVerified(boolean state) { this.verified = state; } static String generateNodeName(String email) { final MessageDigest md; try { md = MessageDigest.getInstance("SHA-1"); } catch (NoSuchAlgorithmException e) { // Algorithm is fixed, so this should never happen throw new RuntimeException(e); } return Hex.encodeHexString( md.digest(email.getBytes(Charset.forName("UTF-8")))); } public List<Notification> getNotifications() { return notifications; } public void setNotifications(List<Notification> notifications) { this.notifications = notifications; } @Override public boolean equals(Object obj) { if (obj == this) { return true; } if (obj == null || obj.getClass() != getClass()) { return false; } final User other = (User) obj; return new EqualsBuilder() .append(this.getId(), other.getId()) .append(this.getEmail(), other.getEmail()) .isEquals(); } @Override public int hashCode() { return new HashCodeBuilder() .append(this.getId()) .append(this.getEmail()) .toHashCode(); } @Override public String toString() { if (verified) { return String.format("%s <%s> [id: %s]", getName(), getEmail(), getId()); } else { return String.format("%s <%s> [VT: %s][id: %s]", getName(), getEmail(), verificationToken, getId()); } } }