Implement user model and migration setup; add user data manipulation in Main class
This commit is contained in:
parent
503b2d35b1
commit
dc1b85a774
28
Main.java
28
Main.java
@ -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
59
src/Migration.java
Normal 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
75
src/models/UserModel.java
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user