/** * Model for storing users * * @author Edward Y. Chen * @since 12/13/2012 */ package edu.mssm.pharm.maayanlab.Enrichr; import static javax.persistence.GenerationType.IDENTITY; import java.io.Serializable; import java.math.BigInteger; import java.security.SecureRandom; import java.util.Date; import java.util.HashSet; import java.util.Random; import java.util.Set; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.FetchType; import javax.persistence.GeneratedValue; import javax.persistence.Id; import javax.persistence.OneToMany; import javax.persistence.Table; import javax.persistence.Temporal; import javax.persistence.TemporalType; import javax.persistence.UniqueConstraint; import org.hibernate.annotations.Cascade; import org.hibernate.annotations.CascadeType; import org.hibernate.annotations.DynamicInsert; import org.hibernate.annotations.DynamicUpdate; import edu.mssm.pharm.maayanlab.common.math.HashFunctions; @Entity @DynamicInsert @DynamicUpdate @Table(name = "users", catalog = "enrichr", uniqueConstraints = @UniqueConstraint(columnNames = "email")) public class User implements Serializable { private static final long serialVersionUID = 1893085998342363733L; private Integer userid; private String email; private String salt; private String password; private String first; private String last; private String institute; private Date accessed; private Set<List> lists; public User() { } public User(String email, String password) { this(email, password, null, null, null, new HashSet<List>(0)); } public User(String email, String password, String first, String last, String institute) { this(email, password, first, last, institute, new HashSet<List>(0)); } public User(String email, String password, String first, String last, String institute, Set<List> lists) { updateUser(email, password, first, last, institute); this.lists = lists; } public boolean updateUser(String email, String password, String first, String last, String institute) { boolean changed = false; if (!email.equals(this.email) && !email.trim().isEmpty()) { // Do not update user if field is same or empty this.email = email; changed |= true; } if (!password.trim().isEmpty()) { updatePassword(password); changed |= true; } if (!first.equals(this.first) && !first.trim().isEmpty()) { this.first = first; changed |= true; } if (!last.equals(this.last) && !last.trim().isEmpty()) { this.last = last; changed |= true; } if (!institute.equals(this.institute) && !institute.trim().isEmpty()) { this.institute = institute; changed |= true; } return changed; } @Id @GeneratedValue(strategy = IDENTITY) @Column(name = "userid", unique = true, nullable = false) public Integer getUserid() { return this.userid; } // Shouldn't be used because auto-incremented by db public void setUserid(Integer userid) { this.userid = userid; } @Column(name = "email", unique = true, nullable = false, length = 100) public String getEmail() { return this.email; } public void setEmail(String email) { this.email = email; } @Column(name = "salt", nullable = false, length = 16) public String getSalt() { return this.salt; } public void setSalt(String salt) { this.salt = salt; } private String generateSalt() { Random r = new SecureRandom(); byte[] saltBytes = new byte[8]; r.nextBytes(saltBytes); return new BigInteger(1, saltBytes).toString(16); } @Column(name = "password", nullable = false, length = 32) public String getPassword() { return this.password; } public void setPassword(String password) { this.password = password; } public boolean checkPassword(String password) { return this.password.equals(HashFunctions.md5(this.salt + password)); } public void updatePassword(String password) { this.setSalt(generateSalt()); this.setPassword(HashFunctions.md5(this.salt + password)); } @Column(name = "first", length = 50) public String getFirst() { return this.first; } public void setFirst(String first) { this.first = first; } @Column(name = "last", length = 200) public String getLast() { return this.last; } public void setLast(String last) { this.last = last; } @Column(name = "institute", length = 200) public String getInstitute() { return this.institute; } public void setInstitute(String institute) { this.institute = institute; } @Temporal(TemporalType.TIMESTAMP) @Column(name = "accessed", nullable = false, length = 19) public Date getAccessed() { return this.accessed; } // Shouldn't be used because it uses default timestamp by db public void setAccessed(Date accessed) { this.accessed = accessed; } // Use this to update timestamp public void updateAccessed() { this.accessed = null; } @OneToMany(fetch = FetchType.LAZY, mappedBy = "user", orphanRemoval = true) // Lists can be removed and propagated here @Cascade({CascadeType.ALL}) public Set<List> getLists() { return this.lists; } public void setLists(Set<List> lists) { this.lists = lists; } @Override public String toString() { // For testing purposes StringBuilder output = new StringBuilder(); output.append("userid: ").append(userid).append(", ") .append("email: ").append(email).append(", ") .append("salt: ").append(salt).append(", ") .append("password: ").append(password); if (first != null) output.append(",").append("first: ").append(first); if (last != null) output.append(", ").append("last: ").append(last); if (institute != null) output.append(", ").append("institute: ").append(institute); output.append(", ").append("accessed: ").append(accessed); return output.toString(); } }