Implement user model and migration setup; add user data manipulation in Main class

This commit is contained in:
Dominik Krenn 2025-09-12 12:46:16 +02:00
parent 503b2d35b1
commit dc1b85a774
3 changed files with 161 additions and 1 deletions

View File

@ -1,11 +1,37 @@
import java.sql.Connection;
import java.sql.SQLException;
import java.util.List;
import src.db.Database;
import src.models.UserModel;
import src.models.squirrel.Database;
import src.models.squirrel.ModelManager;
public class Main {
public static void main(String[] args) throws SQLException {
ModelManager.initializeModels();
Database.migrate = conn -> src.Migration.run(conn);
Database.getConnection();
UserModel userModel = ModelManager.get(UserModel.class);
List<UserModel> users = userModel.where(java.util.Collections.emptyMap());
for (UserModel user : users) {
user.set("name", user.get("name") + " Updated");
user.save();
System.out.println(user);
}
Connection conn = Database.getConnection();
// Example: Run a simple SQL query
try (var stmt = conn.createStatement();
var rs = stmt.executeQuery("SELECT COUNT(*) AS user_count FROM users")) {
if (rs.next()) {
int userCount = rs.getInt("user_count");
System.out.println("Total users: " + userCount);
}
} catch (SQLException e) {
e.printStackTrace();
}
Database.close();
}
}

59
src/Migration.java Normal file
View File

@ -0,0 +1,59 @@
package src;
import java.sql.Connection;
import java.sql.Statement;
public class Migration {
public static void run(Connection conn) {
try (Statement stmt = conn.createStatement()) {
stmt.execute("""
CREATE TABLE IF NOT EXISTS users (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT NOT NULL,
email TEXT NOT NULL UNIQUE,
password_hash TEXT NOT NULL
)
""");
stmt.execute("""
CREATE TABLE IF NOT EXISTS accounts (
id INTEGER PRIMARY KEY AUTOINCREMENT,
owner_id INTEGER NOT NULL,
type TEXT CHECK(type IN ('CHECKING','SAVINGS','CREDIT')) NOT NULL,
account_number TEXT NOT NULL UNIQUE,
bank_code TEXT NOT NULL,
balance REAL NOT NULL DEFAULT 0,
FOREIGN KEY(owner_id) REFERENCES users(id)
)
""");
stmt.execute("""
CREATE TABLE IF NOT EXISTS giro_accounts (
id INTEGER PRIMARY KEY,
overdraft_limit REAL DEFAULT 0,
FOREIGN KEY(id) REFERENCES accounts(id) ON DELETE CASCADE
)
""");
stmt.execute("""
CREATE TABLE IF NOT EXISTS spar_accounts (
id INTEGER PRIMARY KEY,
interest_rate REAL DEFAULT 0,
FOREIGN KEY(id) REFERENCES accounts(id) ON DELETE CASCADE
)
""");
stmt.execute("""
CREATE TABLE IF NOT EXISTS kredit_accounts (
id INTEGER PRIMARY KEY,
credit_limit REAL DEFAULT 0,
repayment_plan TEXT,
FOREIGN KEY(id) REFERENCES accounts(id) ON DELETE CASCADE
)
""");
} catch (Exception e) {
e.printStackTrace();
}
}
}

75
src/models/UserModel.java Normal file
View File

@ -0,0 +1,75 @@
package src.models;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.PBEKeySpec;
import src.models.squirrel.Model;
import src.models.squirrel.ModelManager;
import java.security.SecureRandom;
import java.util.Base64;
import java.util.Arrays;
import java.util.Map;
import java.util.List;
public class UserModel extends Model {
{
tableName = "users";
columns.add("id");
columns.add("name");
columns.add("email");
columns.add("password_hash");
}
private static final int ITERATIONS = 65536;
private static final int KEY_LENGTH = 256;
public static UserModel register(String name, String email, String password) {
if (password == null || password.trim().isEmpty()) {
throw new IllegalArgumentException("Password cannot be empty");
}
UserModel userModel = ModelManager.get(UserModel.class);
List<UserModel> existingUser = userModel.where(Map.of("email", email));
if (existingUser != null && !existingUser.isEmpty()) {
throw new IllegalArgumentException("Email already exists");
}
byte[] salt = getSalt();
UserModel user = new UserModel();
user.set("name", name);
user.set("email", email);
user.set("password_hash", hashPassword(password, salt));
user.create();
return user;
}
public static String hashPassword(String password, byte[] salt) {
try {
PBEKeySpec spec = new PBEKeySpec(password.toCharArray(), salt, ITERATIONS, KEY_LENGTH);
SecretKeyFactory skf = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256");
byte[] hash = skf.generateSecret(spec).getEncoded();
return Base64.getEncoder().encodeToString(hash);
} catch (Exception e) {
throw new RuntimeException("Failed to hash password", e);
}
}
public static byte[] getSalt() {
SecureRandom sr = new SecureRandom();
byte[] salt = new byte[16];
sr.nextBytes(salt);
return salt;
}
public static boolean validatePassword(String password, String storedHash, byte[] salt) {
try {
String newHash = hashPassword(password, salt);
return Arrays.equals(Base64.getDecoder().decode(storedHash), Base64.getDecoder().decode(newHash));
} catch (Exception e) {
throw new RuntimeException("Failed to validate password", e);
}
}
}