|
|
|
@ -1,8 +1,6 @@
@@ -1,8 +1,6 @@
|
|
|
|
|
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; |
|
|
|
@ -10,21 +8,31 @@ import java.sql.SQLException;
@@ -10,21 +8,31 @@ import java.sql.SQLException;
|
|
|
|
|
import java.time.LocalDate; |
|
|
|
|
import java.util.*; |
|
|
|
|
|
|
|
|
|
import static de.srsoftware.widerhall.data.Database.*; |
|
|
|
|
import static de.srsoftware.widerhall.Constants.*; |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* @author Stephan Richter |
|
|
|
|
* This class represents User objects of the widerhall db. |
|
|
|
|
*/ |
|
|
|
|
public class User { |
|
|
|
|
public static final String TABLE_NAME = "Users"; |
|
|
|
|
private static final Logger LOG = LoggerFactory.getLogger(User.class); |
|
|
|
|
private static final HashMap<String,User> users = new HashMap<>(); |
|
|
|
|
public static final int PERMISSION_ADMIN = 1; |
|
|
|
|
public static final int PERMISSION_CREATE_LISTS = 2; |
|
|
|
|
public static final String SALT = "salt"; |
|
|
|
|
public static final String HASHED_PASS = "hashedPassword"; |
|
|
|
|
public static final String SALT = "salt"; |
|
|
|
|
private static final HashMap<String,User> users = new HashMap<>(); |
|
|
|
|
|
|
|
|
|
private String email, salt, hashedPass, name; |
|
|
|
|
private int permissions; |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* create a new user object |
|
|
|
|
* @param email |
|
|
|
|
* @param name |
|
|
|
|
* @param salt |
|
|
|
|
* @param hashedPass |
|
|
|
|
* @param permissions |
|
|
|
|
*/ |
|
|
|
|
public User(String email, String name, String salt, String hashedPass, int permissions) { |
|
|
|
|
this.email = email; |
|
|
|
|
this.name = name; |
|
|
|
@ -56,6 +64,12 @@ public class User {
@@ -56,6 +64,12 @@ public class User {
|
|
|
|
|
|
|
|
|
|
/************** end of field accessors ****************/ |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* Add a new permission to the current user object. |
|
|
|
|
* Also updates the corresponding db entry |
|
|
|
|
* @param newPermission |
|
|
|
|
* @throws SQLException |
|
|
|
|
*/ |
|
|
|
|
public void addPermission(int newPermission) throws SQLException { |
|
|
|
|
permissions |= newPermission; |
|
|
|
|
Database.open() |
|
|
|
@ -67,6 +81,15 @@ public class User {
@@ -67,6 +81,15 @@ public class User {
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* Create a new user object by hashing it's password and storing user data, salt and hashed password to the db. |
|
|
|
|
* Initially, the user is created without any permissions. |
|
|
|
|
* @param email |
|
|
|
|
* @param name |
|
|
|
|
* @param password |
|
|
|
|
* @return |
|
|
|
|
* @throws SQLException |
|
|
|
|
*/ |
|
|
|
|
public static User create(String email, String name, String password) throws SQLException { |
|
|
|
|
String salt = null; |
|
|
|
|
String hashedPass = null; |
|
|
|
@ -77,6 +100,10 @@ public class User {
@@ -77,6 +100,10 @@ public class User {
|
|
|
|
|
return new User(email,name,salt,hashedPass,0).save(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* create user table |
|
|
|
|
* @throws SQLException |
|
|
|
|
*/ |
|
|
|
|
public static void createTable() throws SQLException { |
|
|
|
|
var sql = new StringBuilder() |
|
|
|
|
.append("CREATE TABLE ").append(TABLE_NAME) |
|
|
|
@ -91,29 +118,61 @@ public class User {
@@ -91,29 +118,61 @@ public class User {
|
|
|
|
|
Database.open().query(sql).compile().run(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* Withdraw a specific permission from the user object. |
|
|
|
|
* Updated permission flag will be written to db. |
|
|
|
|
* @param newPermission |
|
|
|
|
* @throws SQLException |
|
|
|
|
*/ |
|
|
|
|
public void dropPermission(int newPermission) throws SQLException { |
|
|
|
|
permissions ^= (permissions & newPermission); |
|
|
|
|
Database.open().update(TABLE_NAME).set(PERMISSIONS,permissions).compile().run(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* check, if User object has requested permission(s). |
|
|
|
|
* @param permission |
|
|
|
|
* @return |
|
|
|
|
*/ |
|
|
|
|
public boolean hashPermission(int permission){ |
|
|
|
|
return (permissions & permission) > 0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* Load the list of all users. Internally calls loadAll(null) |
|
|
|
|
* @return |
|
|
|
|
* @throws SQLException |
|
|
|
|
*/ |
|
|
|
|
public static List<User> loadAll() throws SQLException { |
|
|
|
|
return loadAll(null); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* Load the list of all users identified by the provided email list. |
|
|
|
|
* If emails is null, all users are loaded. |
|
|
|
|
* If emails is empty, an empty list well be returned. |
|
|
|
|
* @param emails |
|
|
|
|
* @return |
|
|
|
|
* @throws SQLException |
|
|
|
|
*/ |
|
|
|
|
public static List<User> loadAll(Collection<String> emails) throws SQLException { |
|
|
|
|
if (emails != null && emails.isEmpty()) return List.of(); |
|
|
|
|
var userList = new ArrayList<User>(); |
|
|
|
|
var query = Database.open().select(TABLE_NAME); |
|
|
|
|
if (emails != null && !emails.isEmpty()) query.where(EMAIL,emails); |
|
|
|
|
if (emails != null) query.where(EMAIL,emails); |
|
|
|
|
var rs = query.compile().exec(); |
|
|
|
|
while (rs.next()) userList.add(User.from(rs)); |
|
|
|
|
return userList; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* Create a new User object from a ResultSet. |
|
|
|
|
* This method is cached: If a User object with an identifying email has been loaded before, the already-loaded object will be returned. |
|
|
|
|
* @param rs |
|
|
|
|
* @return |
|
|
|
|
* @throws SQLException |
|
|
|
|
*/ |
|
|
|
|
private static User from(ResultSet rs) throws SQLException { |
|
|
|
|
var email = rs.getString(EMAIL); |
|
|
|
|
var user = users.get(email); |
|
|
|
@ -127,6 +186,14 @@ public class User {
@@ -127,6 +186,14 @@ public class User {
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* Loads the user identified by it's email, but only if the provided password matches. |
|
|
|
|
* @param email |
|
|
|
|
* @param password |
|
|
|
|
* @return |
|
|
|
|
* @throws InvalidKeyException |
|
|
|
|
* @throws SQLException |
|
|
|
|
*/ |
|
|
|
|
public static User loadUser(String email, String password) throws InvalidKeyException, SQLException { |
|
|
|
|
ResultSet rs = Database.open() |
|
|
|
|
.select(TABLE_NAME) |
|
|
|
@ -146,24 +213,36 @@ public class User {
@@ -146,24 +213,36 @@ public class User {
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* checks, if the provided password matches the User obejcts's original password by comparing hashes. |
|
|
|
|
* @param password |
|
|
|
|
* @return |
|
|
|
|
*/ |
|
|
|
|
private boolean matching(String password) { |
|
|
|
|
if (hashedPass == null) return password == null; |
|
|
|
|
return hashedPass.equals(Util.sha256(password+salt)); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* Checks, whether the user table is empty |
|
|
|
|
* @return |
|
|
|
|
* @throws SQLException |
|
|
|
|
*/ |
|
|
|
|
public static boolean noUsers() throws SQLException { |
|
|
|
|
var rs = Database.open().select(TABLE_NAME,"count(*)").compile().exec(); |
|
|
|
|
try { |
|
|
|
|
if (rs.next()) { |
|
|
|
|
return rs.getInt(1) < 1; |
|
|
|
|
} |
|
|
|
|
if (rs.next()) return rs.getInt(1) < 1; |
|
|
|
|
} finally { |
|
|
|
|
rs.close(); |
|
|
|
|
} |
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* creates a readable permission list from the permission flag. |
|
|
|
|
* @return |
|
|
|
|
*/ |
|
|
|
|
public String permissionList(){ |
|
|
|
|
var list = new ArrayList<String>(); |
|
|
|
|
if (hashPermission(PERMISSION_ADMIN)) list.add("admin"); |
|
|
|
@ -171,20 +250,24 @@ public class User {
@@ -171,20 +250,24 @@ public class User {
|
|
|
|
|
return String.join(", ",list); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* creates a map containing all of the Users data but the password. |
|
|
|
|
* @return |
|
|
|
|
*/ |
|
|
|
|
public Map<String,String> safeMap(){ |
|
|
|
|
return Map.of(NAME,name,EMAIL,email,PERMISSIONS,permissionList(),PASSWORD,hashedPassword() == null ? "no" : "yes"); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* sae the current User object to the database |
|
|
|
|
* @return |
|
|
|
|
* @throws SQLException |
|
|
|
|
*/ |
|
|
|
|
private User save() throws SQLException { |
|
|
|
|
var values = new HashMap<String,Object>(); |
|
|
|
|
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) |
|
|
|
|
.compile() |
|
|
|
|
.run(); |
|
|
|
|
var req = Database.open().insertInto(TABLE_NAME).set(EMAIL,email).set(NAME,name); |
|
|
|
|
if (salt != null) req.set(SALT,salt); |
|
|
|
|
if (hashedPass != null) req.set(HASHED_PASS,hashedPass); |
|
|
|
|
req.compile().run(); |
|
|
|
|
return this; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|