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.Connection;
|
||||||
import java.sql.SQLException;
|
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 class Main {
|
||||||
public static void main(String[] args) throws SQLException {
|
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();
|
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();
|
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