package de.srsoftware.widerhall.data; import de.srsoftware.widerhall.Util; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.security.InvalidKeyException; import java.sql.ResultSet; import java.sql.SQLException; import java.time.LocalDate; import java.util.*; import static de.srsoftware.widerhall.data.Database.*; import static de.srsoftware.widerhall.Constants.*; public class User { public static final String TABLE_NAME = "Users"; private static final Logger LOG = LoggerFactory.getLogger(User.class); private String email, salt, hashedPass, name; public User(String email, String name, String salt, String hashedPass) { this.email = email; this.name = name; this.salt = salt; this.hashedPass = hashedPass; } /*********** field accessors ***************/ public String email() { return email; } public String hashedPassword() { return hashedPass; } public String name() { return name; } public String salt(){ return salt; } /************** end of field accessors ****************/ public static User create(String email, String name, String password) throws SQLException { String salt = null; String hashedPass = null; if (password != null) { salt = Util.sha256(email + name + LocalDate.now()); hashedPass = Util.sha256(password + salt); } return new User(email,name,salt,hashedPass).save(); } public static void createTable() throws SQLException { var sql = new StringBuilder() .append("CREATE TABLE ").append(TABLE_NAME) .append(" (") .append(EMAIL).append(" ").append(VARCHAR).append(" NOT NULL PRIMARY KEY, ") .append(SALT).append(" ").append(VARCHAR).append(", ") .append(HASHED_PASS).append(" ").append(VARCHAR).append(", ") .append(NAME).append(" ").append(VARCHAR) .append(");"); Database.open().query(sql).run(); } public boolean is(String test){ if (test == null) return false; return test.equals(name) || test.equals(email); } public static List loadAll() throws SQLException { return loadAll(null); } public static List loadAll(Collection emails) throws SQLException { var userList = new ArrayList(); var query = Database.open().select(TABLE_NAME); if (emails != null && !emails.isEmpty()) query.where(EMAIL,emails); var rs = query.exec(); while (rs.next()) userList.add(new User( rs.getString(EMAIL), rs.getString(NAME), rs.getString(SALT), rs.getString(HASHED_PASS))); return userList; } public static User loadUser(String email, String password) throws InvalidKeyException, SQLException { ResultSet rs = Database.open() .select(TABLE_NAME) .where(EMAIL,email) .exec(); try { if (rs.next()) { email = rs.getString(EMAIL); var name = rs.getString(NAME); var hashedPassword = rs.getString(HASHED_PASS); var salt = rs.getString(SALT); var loadedUser = new User(email, name, salt, hashedPassword); if (loadedUser.matching(password)) return loadedUser; } else if (noUsers()){ return User.create(email,"Admin",password); } } finally { rs.close(); } throw new InvalidKeyException(); } private boolean matching(String password) { if (hashedPass == null) return password == null; return hashedPass.equals(Util.sha256(password+salt)); } public static boolean noUsers() throws SQLException { var rs = Database.open().select(TABLE_NAME,"count(*)").exec(); try { if (rs.next()) { return rs.getInt(1) < 1; } } finally { rs.close(); } return false; } public Map safeMap(){ return Map.of(NAME,name,EMAIL,email,PASSWORD,hashedPassword() == null ? "no" : "yes"); } private User save() throws SQLException { var values = new HashMap(); values.put(EMAIL,email); values.put(NAME,name); if (salt != null) values.put(SALT,salt); if (hashedPass != null) values.put(HASHED_PASS,hashedPass); Database.open().insertInto(TABLE_NAME) .values(values) .run(); return this; } }