Users.java
package org.flasby.entity;
import java.security.Principal;
import java.util.HashSet;
import java.util.Objects;
import java.util.Properties;
import java.util.Set;
import org.mindrot.jbcrypt.BCrypt;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.nulabinc.zxcvbn.Strength;
import com.nulabinc.zxcvbn.Zxcvbn;
import jakarta.persistence.ElementCollection;
import jakarta.persistence.Entity;
import jakarta.persistence.EnumType;
import jakarta.persistence.Enumerated;
import jakarta.persistence.FetchType;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.Id;
import jakarta.persistence.Table;
import lombok.Getter;
@Getter
@Entity
@Table(name = "users")
public class Users<Role> implements Principal {
@Id @GeneratedValue Long id;
public int hashCode() {
return Objects.hash(id);
}
// Roles are excluded from equality testing
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (!getClass().isAssignableFrom(obj.getClass()))
return false;
@SuppressWarnings("unchecked")
Users<Role> other = (Users<Role>) obj;
return Objects.equals(id, other.getId());
}
private Properties properties = new Properties();
public Properties getProperties() {
return new Properties(properties);
}
protected String name;
protected String alias;
protected boolean disabled;
protected int failedLoginAttempts;
protected void setDisabled( boolean disabled ) {
this.disabled = disabled;
}
protected void setOnline( boolean online ) {
this.online = online;
}
@JsonIgnore
String password;
boolean online = false;
@Enumerated(EnumType.STRING)
@ElementCollection(fetch = FetchType.EAGER)
public Set<Role> roles = new HashSet<>();
protected Users() {
}
/**
* sets the password and returns the password strength.<br>
* 0 is very poor<br>
* 5 is as good as it gets<br>
*/
public int setPassword(final String plaintext) {
Zxcvbn zxcvbn = new Zxcvbn();
Strength strength = zxcvbn.measure(plaintext);
this.password = BCrypt.hashpw(plaintext, BCrypt.gensalt());
return strength.getScore();
}
public boolean checkPassword( final String plaintext ) {
boolean ok = BCrypt.checkpw(plaintext, getPassword() );
if ( !ok ) {
failedLoginAttempts++;
if ( failedLoginAttempts > 10 ) {
disabled = true;
}
} else {
failedLoginAttempts = 0;
}
return ok;
}
@SafeVarargs
public Users(final String name, final String alias, final String password, final boolean disabled, final Role ...roles) {
this.name = name;
this.alias = alias;
setPassword( password );
this.disabled = disabled;
for (Role role : roles) {
this.roles.add(role);
}
failedLoginAttempts = 0;
}
public String getProperty( String key ) {
return properties.getProperty(key);
}
public void setProperty( String key, String value ) {
properties.setProperty(key, value);
}
@Override
public String toString() {
return "User [alias=" + alias + ", disabled=" + disabled + ", failedLoginAttempts=" + failedLoginAttempts
+ ", id=" + id + ", name=" + name + ", online=" + online + ", password=<elided>>, properties="
+ properties + ", roles=" + roles + "]";
}
}