#8: Setup Model, DAO & Fixtures

Signed-off-by: Dominik Säume <Dominik.Saeume@hmmh.de>
This commit is contained in:
Dominik Säume 2024-05-19 23:15:43 +02:00 committed by Dominik Säume
parent ed6a19b6af
commit 375fbe4826
Signed by: SZUT-Dominik
GPG key ID: 67D15BB250B41E7C
10 changed files with 404 additions and 7 deletions

Binary file not shown.

View file

@ -34,8 +34,8 @@ public class Main extends Application {
@Override
public void start(Stage primaryStage) {
this.primaryStage = primaryStage;
executePassword();
//executeMainApplication();
//executePassword();
executeMainApplication();
}
private void executePassword() {

View file

@ -1,5 +1,6 @@
package de.hitec.nhplus.datastorage;
import de.hitec.nhplus.login.database.UserDao;
import de.hitec.nhplus.medication.database.MedicationDao;
import de.hitec.nhplus.nurse.database.NurseDao;
import de.hitec.nhplus.patient.database.PatientDao;
@ -63,4 +64,12 @@ public class DaoFactory {
public MedicationDao createMedicationDAO() {
return new MedicationDao(ConnectionBuilder.getConnection());
}
/**
* @return A new {@link UserDao} instance with a database connection.
* @see de.hitec.nhplus.login.User User
*/
public UserDao createUserDAO() {
return new UserDao(ConnectionBuilder.getConnection());
}
}

View file

@ -46,6 +46,11 @@ public class Fixtures {
medicationFixture.setupTable(connection);
medicationFixture.load();
UserFixture userFixture = new UserFixture();
userFixture.dropTable(connection);
userFixture.setupTable(connection);
userFixture.load();
} catch (Exception exception) {
System.out.println(exception.getMessage());
}

View file

@ -0,0 +1,83 @@
package de.hitec.nhplus.fixtures;
import de.hitec.nhplus.Main;
import de.hitec.nhplus.datastorage.DaoFactory;
import de.hitec.nhplus.login.User;
import de.hitec.nhplus.login.database.UserDao;
import de.hitec.nhplus.medication.Medication;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.*;
public class UserFixture implements Fixture<User>{
private static final String SCHEMA = "/de/hitec/nhplus/login/database/User.sql";
private static final String PERMISSION_SCHEMA = "/de/hitec/nhplus/login/database/UserPermission.sql";
private static final String TO_NURSE_SCHEMA = "/de/hitec/nhplus/login/database/UserToNurse.sql";
@Override
public void dropTable(Connection connection) throws SQLException {
connection.createStatement().execute("DROP TABLE IF EXISTS user");
connection.createStatement().execute("DROP TABLE IF EXISTS user__permissions");
connection.createStatement().execute("DROP TABLE IF EXISTS user__nurse");
}
@Override
public void setupTable(Connection connection) throws SQLException {
final InputStream schema = Main.class.getResourceAsStream(SCHEMA);
final InputStream permissionSchema = Main.class.getResourceAsStream(PERMISSION_SCHEMA);
final InputStream toNurseSchema = Main.class.getResourceAsStream(TO_NURSE_SCHEMA);
assert schema != null;
assert permissionSchema != null;
assert toNurseSchema != null;
String SQL = new Scanner(schema, StandardCharsets.UTF_8)
.useDelimiter("\\A")
.next();
String permissionSQL = new Scanner(permissionSchema, StandardCharsets.UTF_8)
.useDelimiter("\\A")
.next();
String toNurseSQL = new Scanner(toNurseSchema, StandardCharsets.UTF_8)
.useDelimiter("\\A")
.next();
connection.createStatement().execute(SQL);
connection.createStatement().execute(permissionSQL);
connection.createStatement().execute(toNurseSQL);
}
@Override
public Map<String, User> load() throws SQLException {
List<User> users = new ArrayList<>();
User udo = new User(
"udo",
null,
null,
Integer.parseInt("00000001", 2),
null
);
udo.setPassword("uD0_187!");
users.add(udo);
User maria = new User(
"maria",
null,
null,
0,
null
);
maria.setPassword("H!mm3lf4hrt");
users.add(maria);
UserDao dao = DaoFactory.getInstance().createUserDAO();
Map<String, User> usersByUsername = new HashMap<>();
for (User user : users){
dao.create(user);
usersByUsername.put(user.getUsername(), user);
}
return usersByUsername;
}
}

View file

@ -0,0 +1,98 @@
package de.hitec.nhplus.login;
import de.hitec.nhplus.nurse.Nurse;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
public class User {
private int id;
private String username;
private byte[] passwordSalt;
private byte[] passwordHash;
private int permissions = 0;
private Nurse nurse;
public User(
int id,
String username,
byte[] passwordSalt,
byte[] passwordHash,
int permissions,
Nurse nurse
) {
this.id = id;
this.username = username;
this.passwordSalt = passwordSalt;
this.passwordHash = passwordHash;
this.permissions = permissions;
this.nurse = nurse;
}
public User(
String username,
byte[] passwordSalt,
byte[] passwordHash,
int permissions,
Nurse nurse
) {
this.username = username;
this.passwordSalt = passwordSalt;
this.passwordHash = passwordHash;
this.permissions = permissions;
this.nurse = nurse;
}
public int getId() {
return id;
}
public byte[] getPasswordSalt() {
return passwordSalt;
}
public byte[] getPasswordHash() {
return passwordHash;
}
public void setPassword(String password) {
try {
SecureRandom random = new SecureRandom();
byte[] salt = new byte[32];
random.nextBytes(salt);
this.passwordSalt = salt;
MessageDigest md = MessageDigest.getInstance("SHA-512");
md.update(salt);
this.passwordHash = md.digest(password.getBytes(StandardCharsets.UTF_8));
}catch (NoSuchAlgorithmException exception){
exception.printStackTrace();
}
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public int getPermissions() {
return permissions;
}
public void setPermissions(int permissions) {
this.permissions = permissions;
}
public Nurse getNurse() {
return nurse;
}
public void setNurse(Nurse nurse) {
this.nurse = nurse;
}
}

View file

@ -0,0 +1,202 @@
package de.hitec.nhplus.login.database;
import de.hitec.nhplus.datastorage.Dao;
import de.hitec.nhplus.datastorage.DaoFactory;
import de.hitec.nhplus.login.User;
import de.hitec.nhplus.nurse.Nurse;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
public class UserDao implements Dao<User> {
protected final Connection connection;
public UserDao(Connection connection) {
this.connection = connection;
}
public int readUserId(String username) throws SQLException {
final String SQL = "SELECT id FROM user WHERE username = ?";
PreparedStatement statement = this.connection.prepareStatement(SQL);
statement.setString(1, username);
return statement.executeQuery().getInt(1);
}
public byte[] readPasswordSalt(int id) throws SQLException {
final String SQL = "SELECT passwordSalt FROM user WHERE id = ?";
PreparedStatement statement = this.connection.prepareStatement(SQL);
statement.setInt(1, id);
return statement.executeQuery().getBytes(1);
}
public byte[] readPasswordHash(int id) throws SQLException {
final String SQL = "SELECT passwordHash FROM user WHERE id = ?";
PreparedStatement statement = this.connection.prepareStatement(SQL);
statement.setInt(1, id);
return statement.executeQuery().getBytes(1);
}
@Override
public User read(int id) throws SQLException {
final String SQL = """
SELECT user.username, user.passwordSalt, user.passwordHash, user__permissions.permissions, user__nurse.nurseId
FROM user
LEFT JOIN user__permissions ON user.id = user__permissions.userId
LEFT JOIN user__nurse ON user.id = user__nurse.userId
WHERE user.id = ?;
""";
PreparedStatement statement = this.connection.prepareStatement(SQL);
statement.setInt(1, id);
ResultSet result = statement.executeQuery();
int nurseId = result.getInt(5);
Nurse nurse = null;
if (!result.wasNull()) {
nurse = DaoFactory.getInstance().createNurseDAO().read(nurseId);
}
return new User(
id,
result.getString(1),
result.getBytes(2),
result.getBytes(3),
result.getInt(4),
nurse
);
}
@Override
public void create(User user) throws SQLException {
connection.setAutoCommit(false); //Switch to Manual Commit, to do an SQL Transaction
final String userSQL = """
INSERT INTO user
(username, passwordSalt, passwordHash)
VALUES (?, ?, ?);
""";
PreparedStatement statement = this.connection.prepareStatement(userSQL);
statement.setString(1, user.getUsername());
statement.setBytes(2, user.getPasswordSalt());
statement.setBytes(3, user.getPasswordHash());
statement.execute();
ResultSet generatedKeys = connection.createStatement().executeQuery("SELECT id FROM user");
connection.commit(); //Finish SQL Transaction
connection.setAutoCommit(true); //Switch back Mode
if (!generatedKeys.next()) {
return;
}
int newId = generatedKeys.getInt(1);
final String permissionSQL = """
INSERT INTO user__permissions
(userId, permissions)
VALUES (?, ?);
""";
PreparedStatement permissionStatement = this.connection.prepareStatement(permissionSQL);
permissionStatement.setInt(1, newId);
permissionStatement.setInt(2, user.getPermissions());
permissionStatement.execute();
if (user.getNurse() == null) {
return;
}
final String nurseSQL = """
INSERT INTO user__nurse
(userId, nurseId)
VALUES (?, ?);
""";
PreparedStatement nurseStatement = this.connection.prepareStatement(nurseSQL);
permissionStatement.setInt(1, newId);
permissionStatement.setInt(2, user.getNurse().getId());
permissionStatement.execute();
}
@Override
public void update(User user) throws SQLException {
final String userSQL = """
UPDATE user SET
username = ?,
passwordSalt = ?,
passwordHash = ?
WHERE id = ?
""";
PreparedStatement statement = this.connection.prepareStatement(userSQL);
statement.setString(1, user.getUsername());
statement.setBytes(2, user.getPasswordSalt());
statement.setBytes(3, user.getPasswordHash());
statement.setInt(3, user.getId());
statement.executeUpdate();
final String permissionSQL = """
UPDATE user__permissions SET
permissions = ?
WHERE userId = ?
""";
PreparedStatement permissionStatement = this.connection.prepareStatement(permissionSQL);
permissionStatement.setInt(1, user.getPermissions());
permissionStatement.setInt(2, user.getId());
permissionStatement.executeUpdate();
if (user.getNurse() == null) {
final String nurseSQL = """
DELETE FROM user__nurse WHERE userId = ?
""";
this.connection.prepareStatement(nurseSQL).executeUpdate();
return;
}
final String nurseSQL = """
UPDATE user__nurse set
nurseId = ?
WHERE userId = ?
""";
PreparedStatement nurseStatement = this.connection.prepareStatement(nurseSQL);
nurseStatement.setInt(1, user.getNurse().getId());
nurseStatement.setInt(2, user.getId());
permissionStatement.executeUpdate();
}
@Override
public void delete(int id) throws SQLException {
final String SQL = """
DELETE FROM user WHERE user.id = ?;
""";
PreparedStatement preparedStatement = this.connection.prepareStatement(SQL);
preparedStatement.setInt(1, id);
preparedStatement.executeUpdate();
}
@Override
public List<User> readAll() throws SQLException {
final String SQL = """
SELECT user.id, user.username, user.passwordSalt, user.passwordHash, user__permissions.permissions, user__nurse.nurseId
FROM user
LEFT JOIN user__permissions ON user.id = user__permissions.userId
LEFT JOIN user__nurse ON user.id = user__nurse.userId
""";
ResultSet result = connection.prepareStatement(SQL).executeQuery();
List<User> users = new ArrayList<>();
while (result.next()) {
int nurseId = result.getInt(6);
Nurse nurse = null;
if (!result.wasNull()) {
nurse = DaoFactory.getInstance().createNurseDAO().read(nurseId);
}
users.add(new User(
result.getInt(1),
result.getString(2),
result.getBytes(3),
result.getBytes(4),
result.getInt(5),
nurse
));
}
return users;
}
}

View file

@ -1,7 +1,7 @@
CREATE TABLE user
(
id INTEGER PRIMARY KEY AUTOINCREMENT,
username TEXT NOT NULL,
username TEXT NOT NULL UNIQUE,
passwordSalt BLOB NOT NULL,
passwordHash BLOB NOT NULL
)

View file

@ -1,6 +1,6 @@
CREATE TABLE user__permissions
(
userId INTEGER NOT NULL,
permissions INTEGER, -- Binary Bitmask for Permissions
userId INTEGER NOT NULL UNIQUE,
permissions INTEGER NOT NULL, -- Binary Bitmask for Permissions
FOREIGN KEY (userId) REFERENCES user (id) ON DELETE CASCADE
)

View file

@ -1,7 +1,7 @@
CREATE TABLE user__nurse
(
userId INTEGER NOT NULL,
nurseId INTEGER NOT NULL,
userId INTEGER NOT NULL UNIQUE,
nurseId INTEGER NOT NULL UNIQUE,
FOREIGN KEY (userId) REFERENCES user (id) ON DELETE CASCADE,
FOREIGN KEY (nurseId) REFERENCES nurse (id) ON DELETE CASCADE
)