-
Notifications
You must be signed in to change notification settings - Fork 59
lagalaga #14
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
lagalaga #14
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,10 @@ | ||
| package com.example; | ||
|
|
||
| public record Account( | ||
| int userId, | ||
| String name, | ||
| String password, | ||
| String firstName, | ||
| String lastName, | ||
| String ssn | ||
| ) {} | ||
|
Comment on lines
+3
to
+10
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Critical: don’t model/store |
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,9 @@ | ||
| package com.example; | ||
| import java.util.Optional; | ||
|
|
||
| public interface AccountRepository { | ||
| Optional<Account> findByNameAndPassword(String name, String password); | ||
| Account create(Account account); | ||
| boolean updatePassword(int userId, String newPassword); | ||
| boolean delete(int userId); | ||
| } | ||
|
Comment on lines
+1
to
+9
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Critical: 🤖 Prompt for AI Agents |
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,90 @@ | ||
| package com.example; | ||
|
|
||
|
|
||
| import com.example.SimpleDriverManagerDataSource; | ||
|
|
||
| import java.sql.*; | ||
| import java.util.Optional; | ||
|
|
||
| public class AccountRepositoryJdbc implements AccountRepository { | ||
| private final SimpleDriverManagerDataSource ds; | ||
|
|
||
| public AccountRepositoryJdbc(SimpleDriverManagerDataSource ds) { | ||
| this.ds = ds; | ||
| } | ||
|
|
||
| @Override | ||
| public Optional<Account> findByNameAndPassword(String name, String password) { | ||
| String sql = "SELECT * FROM account WHERE name = ? AND password = ?"; | ||
| try (Connection conn = ds.getConnection(); | ||
| PreparedStatement ps = conn.prepareStatement(sql)) { | ||
| ps.setString(1, name); | ||
| ps.setString(2, password); | ||
| try (ResultSet rs = ps.executeQuery()) { | ||
| if (rs.next()) { | ||
| return Optional.of(new Account( | ||
| rs.getInt("user_id"), | ||
| rs.getString("name"), | ||
| rs.getString("password"), | ||
| rs.getString("first_name"), | ||
| rs.getString("last_name"), | ||
| rs.getString("ssn") | ||
| )); | ||
| } | ||
| } | ||
| } catch (SQLException e) { | ||
| e.printStackTrace(); | ||
| } | ||
| return Optional.empty(); | ||
| } | ||
|
Comment on lines
+17
to
+39
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧩 Analysis chain🏁 Script executed: # First, find and examine the full AccountRepositoryJdbc class
find . -name "AccountRepositoryJdbc.java" -type fRepository: ithsjava25/ithsjava25-java-databas-jdbc-javafx-classrom Length of output: 153 🏁 Script executed: # Search for any bcrypt, argon2, or password hashing libraries in the project
rg -i "bcrypt|argon2|scrypt|password.*hash|messageDigest" --type javaRepository: ithsjava25/ithsjava25-java-databas-jdbc-javafx-classrom Length of output: 81 🏁 Script executed: # Check for imports related to password hashing
rg "import.*security|import.*crypto" --type javaRepository: ithsjava25/ithsjava25-java-databas-jdbc-javafx-classrom Length of output: 81 🏁 Script executed: # Look for any test files that might show password handling
fd -e java -path "*/test/*" | head -20Repository: ithsjava25/ithsjava25-java-databas-jdbc-javafx-classrom Length of output: 267 🌐 Web query:
💡 Result: Short answer — recommended libraries and best practices (2025): Recommended Java libraries
Sources: [1][3][4][6] Core best practices
Security caveats & recent notes (2025)
Quick implementation tips (JDBC + Spring)
References
If you want, I can:
🏁 Script executed: # Read the full AccountRepositoryJdbc class
cat -n ./src/main/java/com/example/AccountRepositoryJdbc.javaRepository: ithsjava25/ithsjava25-java-databas-jdbc-javafx-classrom Length of output: 3975 🏁 Script executed: # Check if Account class has any password-sensitive methods or constructors
find . -name "Account.java" -type fRepository: ithsjava25/ithsjava25-java-databas-jdbc-javafx-classrom Length of output: 139 🏁 Script executed: # Quick check of Account.java to confirm it returns password/ssn
cat ./src/main/java/com/example/Account.javaRepository: ithsjava25/ithsjava25-java-databas-jdbc-javafx-classrom Length of output: 284 Plaintext password authentication is a critical security flaw affecting all auth methods. Recommended approach for JDBC: |
||
|
|
||
| @Override | ||
| public Account create(Account account) { | ||
| String sql = "INSERT INTO account (name, password, first_name, last_name, ssn) VALUES (?, ?, ?, ?, ?)"; | ||
| try (Connection conn = ds.getConnection(); | ||
| PreparedStatement ps = conn.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS)) { | ||
| ps.setString(1, account.name()); | ||
| ps.setString(2, account.password()); | ||
| ps.setString(3, account.firstName()); | ||
| ps.setString(4, account.lastName()); | ||
| ps.setString(5, account.ssn()); | ||
| ps.executeUpdate(); | ||
| try (ResultSet keys = ps.getGeneratedKeys()) { | ||
| if (keys.next()) { | ||
| return new Account(keys.getInt(1), account.name(), account.password(), | ||
| account.firstName(), account.lastName(), account.ssn()); | ||
| } | ||
| } | ||
| } catch (SQLException e) { | ||
| e.printStackTrace(); | ||
| } | ||
| return account; | ||
| } | ||
|
Comment on lines
+42
to
+62
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
🤖 Prompt for AI Agents |
||
|
|
||
| @Override | ||
| public boolean updatePassword(int userId, String newPassword) { | ||
| String sql = "UPDATE account SET password = ? WHERE user_id = ?"; | ||
| try (Connection conn = ds.getConnection(); | ||
| PreparedStatement ps = conn.prepareStatement(sql)) { | ||
| ps.setString(1, newPassword); | ||
| ps.setInt(2, userId); | ||
| return ps.executeUpdate() > 0; | ||
| } catch (SQLException e) { | ||
| e.printStackTrace(); | ||
| } | ||
| return false; | ||
| } | ||
|
Comment on lines
+65
to
+76
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Password update should follow the same hashing approach (and ideally enforce policy). 🤖 Prompt for AI Agents |
||
|
|
||
| @Override | ||
| public boolean delete(int userId) { | ||
| String sql = "DELETE FROM account WHERE user_id = ?"; | ||
| try (Connection conn = ds.getConnection(); | ||
| PreparedStatement ps = conn.prepareStatement(sql)) { | ||
| ps.setInt(1, userId); | ||
| return ps.executeUpdate() > 0; | ||
| } catch (SQLException e) { | ||
| e.printStackTrace(); | ||
| } | ||
| return false; | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -16,9 +16,11 @@ public static void start() { | |
| .withInitScript("init.sql"); | ||
| mysql.start(); | ||
|
|
||
|
|
||
| System.setProperty("APP_JDBC_URL", mysql.getJdbcUrl()); | ||
| System.setProperty("APP_DB_USER", mysql.getUsername()); | ||
| System.setProperty("APP_DB_PASS", mysql.getPassword()); | ||
| System.out.println("Init script loaded, JDBC URL: " + mysql.getJdbcUrl()); | ||
|
Comment on lines
+19
to
+23
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Avoid printing connection details to stdout (even in dev) unless you’re sure logs won’t be shared. 🤖 Prompt for AI Agents |
||
| } | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,57 +1,130 @@ | ||
| package com.example; | ||
|
|
||
| import java.sql.Connection; | ||
| import java.sql.DriverManager; | ||
| import java.sql.SQLException; | ||
| import com.example.Account; | ||
| import com.example.AccountRepository; | ||
| import com.example.AccountRepositoryJdbc; | ||
| import com.example.MoonMissionRepository; | ||
| import com.example.MoonMissionRepositoryJdbc; | ||
|
|
||
| import java.util.Arrays; | ||
| import java.util.Scanner; | ||
|
|
||
| public class Main { | ||
|
|
||
| static void main(String[] args) { | ||
| public static void main(String[] args) { | ||
| if (isDevMode(args)) { | ||
| DevDatabaseInitializer.start(); | ||
| } | ||
| new Main().run(); | ||
| } | ||
|
|
||
| public void run() { | ||
| // Resolve DB settings with precedence: System properties -> Environment variables | ||
| String jdbcUrl = resolveConfig("APP_JDBC_URL", "APP_JDBC_URL"); | ||
| String dbUser = resolveConfig("APP_DB_USER", "APP_DB_USER"); | ||
| String dbPass = resolveConfig("APP_DB_PASS", "APP_DB_PASS"); | ||
|
|
||
| if (jdbcUrl == null || dbUser == null || dbPass == null) { | ||
| throw new IllegalStateException( | ||
| "Missing DB configuration. Provide APP_JDBC_URL, APP_DB_USER, APP_DB_PASS " + | ||
| "as system properties (-Dkey=value) or environment variables."); | ||
| throw new IllegalStateException("Missing DB configuration..."); | ||
| } | ||
|
|
||
| try (Connection connection = DriverManager.getConnection(jdbcUrl, dbUser, dbPass)) { | ||
| } catch (SQLException e) { | ||
| throw new RuntimeException(e); | ||
| SimpleDriverManagerDataSource ds = new SimpleDriverManagerDataSource(jdbcUrl, dbUser, dbPass); | ||
| AccountRepository accountRepo = new AccountRepositoryJdbc(ds); | ||
| MoonMissionRepository missionRepo = new MoonMissionRepositoryJdbc(ds); | ||
|
|
||
| Scanner sc = new Scanner(System.in); | ||
|
|
||
| System.out.println("Username:"); | ||
| String username = sc.nextLine(); | ||
| System.out.println("Password:"); | ||
| String password = sc.nextLine(); | ||
|
|
||
| if (accountRepo.findByNameAndPassword(username, password).isPresent()) { | ||
| System.out.println("username accepted"); | ||
| menuLoop(accountRepo, missionRepo, sc); | ||
| } else { | ||
| System.out.println("Invalid username or password"); | ||
| System.out.println("0) Exit"); | ||
| String opt = sc.nextLine(); | ||
| if ("0".equals(opt)) { | ||
| return; | ||
| } | ||
| } | ||
| } | ||
|
Comment on lines
25
to
+51
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Major: login flow implies plaintext passwords and has a “dead-end” invalid-login UX. 🤖 Prompt for AI Agents |
||
|
|
||
| private void menuLoop(AccountRepository accountRepo, MoonMissionRepository missionRepo, Scanner sc) { | ||
| boolean running = true; | ||
| while (running) { | ||
| System.out.println("Menu:"); | ||
| System.out.println("1) List moon missions"); | ||
| System.out.println("2) Get mission by id"); | ||
| System.out.println("3) Count missions by year"); | ||
| System.out.println("4) Create account"); | ||
| System.out.println("5) Update account password"); | ||
| System.out.println("6) Delete account"); | ||
| System.out.println("0) Exit"); | ||
|
|
||
| String choice = sc.nextLine(); | ||
| switch (choice) { | ||
| case "1": | ||
| missionRepo.findAll().forEach(m -> System.out.println(m.spacecraft())); | ||
| break; | ||
| case "2": | ||
| System.out.println("mission_id:"); | ||
| int id = Integer.parseInt(sc.nextLine()); | ||
| missionRepo.findById(id).ifPresentOrElse( | ||
| m -> System.out.println("Mission " + m.missionId() + ": " + m.spacecraft()), | ||
| () -> System.out.println("No mission found") | ||
| ); | ||
| break; | ||
| case "3": | ||
| System.out.println("year:"); | ||
| int year = Integer.parseInt(sc.nextLine()); | ||
| int count = missionRepo.countByYear(year); | ||
| System.out.println(count + " missions in " + year); | ||
| break; | ||
| case "4": | ||
| System.out.println("first name:"); | ||
| String fn = sc.nextLine(); | ||
| System.out.println("last name:"); | ||
| String ln = sc.nextLine(); | ||
| System.out.println("ssn:"); | ||
| String ssn = sc.nextLine(); | ||
| System.out.println("password:"); | ||
| String pw = sc.nextLine(); | ||
| String name = fn.substring(0,3) + ln.substring(0,3); | ||
| accountRepo.create(new Account(0, name, pw, fn, ln, ssn)); | ||
| System.out.println("account created"); | ||
| break; | ||
| case "5": | ||
| System.out.println("user_id:"); | ||
| int uid = Integer.parseInt(sc.nextLine()); | ||
| System.out.println("new password:"); | ||
| String newPw = sc.nextLine(); | ||
| if (accountRepo.updatePassword(uid, newPw)) { | ||
| System.out.println("updated"); | ||
| } | ||
| break; | ||
| case "6": | ||
| System.out.println("user_id:"); | ||
| int delId = Integer.parseInt(sc.nextLine()); | ||
| if (accountRepo.delete(delId)) { | ||
| System.out.println("deleted"); | ||
| } | ||
| break; | ||
| case "0": | ||
| running = false; | ||
| break; | ||
| default: | ||
| System.out.println("Invalid option"); | ||
| } | ||
|
Comment on lines
+53
to
+118
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Major: menu can crash on bad input ( @@
- case "2":
+ case "2":
System.out.println("mission_id:");
- int id = Integer.parseInt(sc.nextLine());
+ Integer id = tryParseInt(sc.nextLine());
+ if (id == null) { System.out.println("Invalid number"); break; }
missionRepo.findById(id).ifPresentOrElse(
@@
- case "3":
+ case "3":
System.out.println("year:");
- int year = Integer.parseInt(sc.nextLine());
+ Integer year = tryParseInt(sc.nextLine());
+ if (year == null) { System.out.println("Invalid year"); break; }
int count = missionRepo.countByYear(year);
@@
case "4":
@@
- String name = fn.substring(0,3) + ln.substring(0,3);
+ String name = safePrefix(fn, 3) + safePrefix(ln, 3);
accountRepo.create(new Account(0, name, pw, fn, ln, ssn));
System.out.println("account created");
break;
case "5":
System.out.println("user_id:");
- int uid = Integer.parseInt(sc.nextLine());
+ Integer uid = tryParseInt(sc.nextLine());
+ if (uid == null) { System.out.println("Invalid user_id"); break; }
System.out.println("new password:");
String newPw = sc.nextLine();
- if (accountRepo.updatePassword(uid, newPw)) {
- System.out.println("updated");
- }
+ System.out.println(accountRepo.updatePassword(uid, newPw) ? "updated" : "not found");
break;
case "6":
System.out.println("user_id:");
- int delId = Integer.parseInt(sc.nextLine());
- if (accountRepo.delete(delId)) {
- System.out.println("deleted");
- }
+ Integer delId = tryParseInt(sc.nextLine());
+ if (delId == null) { System.out.println("Invalid user_id"); break; }
+ System.out.println(accountRepo.delete(delId) ? "deleted" : "not found");
break;
@@
}
+
+ private static Integer tryParseInt(String s) {
+ try { return Integer.parseInt(s.trim()); }
+ catch (Exception e) { return null; }
+ }
+
+ private static String safePrefix(String s, int n) {
+ if (s == null) return "";
+ String t = s.trim();
+ return t.length() <= n ? t : t.substring(0, n);
+ }🤖 Prompt for AI Agents |
||
| } | ||
| //Todo: Starting point for your code | ||
| } | ||
|
|
||
| /** | ||
| * Determines if the application is running in development mode based on system properties, | ||
| * environment variables, or command-line arguments. | ||
| * | ||
| * @param args an array of command-line arguments | ||
| * @return {@code true} if the application is in development mode; {@code false} otherwise | ||
| */ | ||
| private static boolean isDevMode(String[] args) { | ||
| if (Boolean.getBoolean("devMode")) //Add VM option -DdevMode=true | ||
| return true; | ||
| if ("true".equalsIgnoreCase(System.getenv("DEV_MODE"))) //Environment variable DEV_MODE=true | ||
| return true; | ||
| return Arrays.asList(args).contains("--dev"); //Argument --dev | ||
| if (Boolean.getBoolean("devMode")) return true; | ||
| if ("true".equalsIgnoreCase(System.getenv("DEV_MODE"))) return true; | ||
| return Arrays.asList(args).contains("--dev"); | ||
| } | ||
|
|
||
| /** | ||
| * Reads configuration with precedence: Java system property first, then environment variable. | ||
| * Returns trimmed value or null if neither source provides a non-empty value. | ||
| */ | ||
| private static String resolveConfig(String propertyKey, String envKey) { | ||
| String v = System.getProperty(propertyKey); | ||
| if (v == null || v.trim().isEmpty()) { | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,14 @@ | ||
| package com.example; | ||
|
|
||
| import java.time.LocalDate; | ||
|
|
||
| public record MoonMission( | ||
| int missionId, | ||
| String spacecraft, | ||
| LocalDate launchDate, | ||
| String carrierRocket, | ||
| String operator, | ||
| String missionType, | ||
| String outcome | ||
| ) {} | ||
|
|
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,11 @@ | ||
| package com.example; | ||
|
|
||
| import com.example.MoonMission; | ||
| import java.util.List; | ||
| import java.util.Optional; | ||
|
|
||
| public interface MoonMissionRepository { | ||
| List<MoonMission> findAll(); | ||
| Optional<MoonMission> findById(int missionId); | ||
| int countByYear(int year); | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
🌐 Web query:
SLF4J 2.x recommended bindings backends Maven projects best practices💡 Result:
Summary best practices for SLF4J 2.x bindings in Maven projects
org.slf4j:slf4j-api:2.x. [1]
...logback-classicruntime. [1][4]
References
If you want, I can produce example Maven snippets (library POM + application POM) for Logback and Log4j2.
🏁 Script executed:
Repository: ithsjava25/ithsjava25-java-databas-jdbc-javafx-classrom
Length of output: 126
🏁 Script executed:
cat pom.xml | head -50Repository: ithsjava25/ithsjava25-java-databas-jdbc-javafx-classrom
Length of output: 2049
Remove
slf4j-nopor scope it totestonly; libraries should depend only onslf4j-api.slf4j-nopsilently discards all SLF4J logs, hiding problems in production. Since this appears to be a library project, it should declare onlyorg.slf4j:slf4j-api(without binding). Applications that depend on this library will then provide their own SLF4J backend (e.g., Logback, Log4j2) with<scope>runtime</scope>.If logging is needed for tests, scope
slf4j-noptotest. For production logging, allow the consuming application to inject a real backend.🤖 Prompt for AI Agents