From ec08a35adce20d0f2db29cc855e7363ea4523650 Mon Sep 17 00:00:00 2001 From: "github-classroom[bot]" <66690702+github-classroom[bot]@users.noreply.github.com> Date: Tue, 9 Dec 2025 10:59:25 +0000 Subject: [PATCH 1/5] add deadline --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index d20aaf9..7071577 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,4 @@ +[![Review Assignment Due Date](https://classroom.github.com/assets/deadline-readme-button-22041afd0340ce965d47ae6ef1cefeee28c7c493a6346c4f15d667ab976d596c.svg)](https://classroom.github.com/a/339Lr3BJ) ### How the tests work (and Docker requirement) This project ships with an end‑to‑end CLI integration test suite that uses Testcontainers to spin up a temporary MySQL database. From 01e0bfed61a71eff8e04df7c52f598fb28e25c85 Mon Sep 17 00:00:00 2001 From: Mattias Barth Date: Sun, 14 Dec 2025 17:41:45 +0100 Subject: [PATCH 2/5] add lots of stuff --- .../com/example/DevDatabaseInitializer.java | 2 +- src/main/java/com/example/Main.java | 252 ++++++++++++++++-- 2 files changed, 234 insertions(+), 20 deletions(-) diff --git a/src/main/java/com/example/DevDatabaseInitializer.java b/src/main/java/com/example/DevDatabaseInitializer.java index e8a45fe..5526da9 100644 --- a/src/main/java/com/example/DevDatabaseInitializer.java +++ b/src/main/java/com/example/DevDatabaseInitializer.java @@ -21,4 +21,4 @@ public static void start() { System.setProperty("APP_DB_PASS", mysql.getPassword()); } } -} +} \ No newline at end of file diff --git a/src/main/java/com/example/Main.java b/src/main/java/com/example/Main.java index 6dc6fbd..46d97ba 100644 --- a/src/main/java/com/example/Main.java +++ b/src/main/java/com/example/Main.java @@ -1,9 +1,8 @@ package com.example; -import java.sql.Connection; -import java.sql.DriverManager; -import java.sql.SQLException; +import java.sql.*; import java.util.Arrays; +import java.util.Scanner; public class Main { @@ -26,32 +25,247 @@ public void run() { "as system properties (-Dkey=value) or environment variables."); } - try (Connection connection = DriverManager.getConnection(jdbcUrl, dbUser, dbPass)) { + try (Connection connection = + DriverManager.getConnection(jdbcUrl, dbUser, dbPass)) { + + //Todo: Starting point for your code + runApplication(connection); + } catch (SQLException e) { throw new RuntimeException(e); } - //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 final + Scanner scanner = new Scanner(System.in); + private boolean exitAfterLogin = false; + + private void runApplication(Connection connection) throws SQLException { + if (loginFlow(connection)) { + menuLoop(connection); + } + } + + private boolean loginFlow(Connection connection) throws SQLException { + while (true) { + System.out.print("Input username: "); + String username = scanner.nextLine().strip(); + + System.out.print("Input password: "); + String password = scanner.nextLine().strip(); + + if (checkCredentials(connection, username, password)) { + System.out.println("Login Successful!"); + return true; + } + + System.out.print("Credentials invalid. Try again (Enter) or Exit? (0): "); + if ("0".equals(scanner.nextLine().strip())) { + exitAfterLogin = true; + return false; + } + } + } + + private boolean checkCredentials(Connection connection, String user, String pass) + throws SQLException { + + String sql = "SELECT 1 FROM account WHERE name=? AND password=?"; + try (PreparedStatement ps = connection.prepareStatement(sql)) { + ps.setString(1, user); + ps.setString(2, pass); + return ps.executeQuery().next(); + } + } + + private void menuLoop(Connection connection) throws SQLException { + boolean running = !exitAfterLogin; + + while (running) { + printMenu(); + System.out.print("Choose option: "); + String command = scanner.nextLine().strip(); + + switch (command) { + case "1", "list" -> listMissions(connection); + case "2", "get" -> getMissionById(connection); + case "3", "count" -> countMissionsByYear(connection); + case "4", "create" -> createAccount(connection); + case "5", "update" -> updateAccountPassword(connection); + case "6", "delete" -> deleteAccount(connection); + case "0", "exit" -> running = false; + default -> System.out.println("Invalid choice."); + } + + System.out.println(); + } + } + + private void printMenu() { + System.out.println(""" + + ========================== + 1) List moon missions + 2) Get mission by id + 3) Count missions by year + 4) Create account + 5) Update account password + 6) Delete account + 0) Exit + ========================== + """); + } + + private void listMissions(Connection connection) throws SQLException { + String sql = "SELECT spacecraft FROM moon_mission"; + + try (PreparedStatement ps = connection.prepareStatement(sql); + ResultSet rs = ps.executeQuery()) { + + while (rs.next()) { + System.out.println(rs.getString("spacecraft")); + } + } + } + + private void getMissionById(Connection connection) throws SQLException { + System.out.print("Mission id: "); + String id = scanner.nextLine(); + + String sql = "SELECT * FROM moon_mission WHERE mission_id=?"; + try (PreparedStatement ps = connection.prepareStatement(sql)) { + ps.setString(1, id); + + ResultSet rs = ps.executeQuery(); + while (rs.next()) { + for (int i = 1; i <= rs.getMetaData().getColumnCount(); i++) { + System.out.print(rs.getString(i) + " "); + } + System.out.println(); + } + } + } + + private void countMissionsByYear(Connection connection) throws SQLException { + System.out.print("Year: "); + String year = scanner.nextLine(); + + String sql = "SELECT COUNT(*) FROM moon_mission WHERE YEAR(launch_date)=?"; + try (PreparedStatement ps = connection.prepareStatement(sql)) { + ps.setString(1, year); + + ResultSet rs = ps.executeQuery(); + if (rs.next()) { + System.out.println("Missions launched in " + year + ": " + rs.getInt(1)); + } + } + } + + private void createAccount(Connection connection) throws SQLException { + String first = readRequired("First name"); + String last = readRequired("Last name"); + String ssn = readRequired("SSN"); + String password = readRequired("Password"); + + String username = + first.substring(0, Math.min(2, first.length())) + + last.substring(0, Math.min(2, last.length())); + + String checkSql = "SELECT COUNT(*) FROM account WHERE name=? OR ssn=?"; + try (PreparedStatement ps = connection.prepareStatement(checkSql)) { + ps.setString(1, username); + ps.setString(2, ssn); + + ResultSet rs = ps.executeQuery(); + if (rs.next() && rs.getInt(1) > 0) { + System.out.println("Account already exists."); + return; + } + } + + String insertSql = """ + INSERT INTO account (first_name, last_name, ssn, password, name) + VALUES (?, ?, ?, ?, ?) + """; + + try (PreparedStatement ps = connection.prepareStatement(insertSql)) { + ps.setString(1, first); + ps.setString(2, last); + ps.setString(3, ssn); + ps.setString(4, password); + ps.setString(5, username); + ps.executeUpdate(); + } + + System.out.println("Account successfully created."); + } + + private void updateAccountPassword(Connection connection) throws SQLException { + System.out.print("User id: "); + String id = scanner.nextLine(); + + if (!accountExists(connection, id)) { + System.out.println("User not found."); + return; + } + + System.out.print("New password: "); + String newPassword = scanner.nextLine(); + + String sql = "UPDATE account SET password=? WHERE user_id=?"; + try (PreparedStatement ps = connection.prepareStatement(sql)) { + ps.setString(1, newPassword); + ps.setString(2, id); + ps.executeUpdate(); + } + + System.out.println("Password updated."); + } + + private void deleteAccount(Connection connection) throws SQLException { + System.out.print("User id to delete: "); + String id = scanner.nextLine(); + + if (!accountExists(connection, id)) { + System.out.println("Account does not exist."); + return; + } + + String sql = "DELETE FROM account WHERE user_id=?"; + try (PreparedStatement ps = connection.prepareStatement(sql)) { + ps.setString(1, id); + int rows = ps.executeUpdate(); + System.out.println("Deleted rows: " + rows); + } + } + + private boolean accountExists(Connection connection, String id) throws SQLException { + String sql = "SELECT 1 FROM account WHERE user_id=?"; + try (PreparedStatement ps = connection.prepareStatement(sql)) { + ps.setString(1, id); + return ps.executeQuery().next(); + } + } + + private String readRequired(String label) { + while (true) { + System.out.print(label + ": "); + String value = scanner.nextLine().strip(); + if (!value.isEmpty()) { + return value; + } + System.out.println(label + " cannot be empty."); + } + } + private static boolean isDevMode(String[] args) { - if (Boolean.getBoolean("devMode")) //Add VM option -DdevMode=true + if (Boolean.getBoolean("devMode")) return true; - if ("true".equalsIgnoreCase(System.getenv("DEV_MODE"))) //Environment variable DEV_MODE=true + if ("true".equalsIgnoreCase(System.getenv("DEV_MODE"))) return true; - return Arrays.asList(args).contains("--dev"); //Argument --dev + 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()) { From 4373b4d75e7e1cd0cf1d019757374bf6680a4a66 Mon Sep 17 00:00:00 2001 From: Mattias Barth Date: Sun, 14 Dec 2025 17:52:23 +0100 Subject: [PATCH 3/5] remove one commented code --- src/main/java/com/example/Main.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/java/com/example/Main.java b/src/main/java/com/example/Main.java index 46d97ba..c8ccf61 100644 --- a/src/main/java/com/example/Main.java +++ b/src/main/java/com/example/Main.java @@ -36,7 +36,6 @@ public void run() { } } - //private final Scanner scanner = new Scanner(System.in); private boolean exitAfterLogin = false; From b2f0ada5a5c7d5eb0716473d267de07a89e03eed Mon Sep 17 00:00:00 2001 From: Mattias Barth Date: Sun, 14 Dec 2025 18:13:49 +0100 Subject: [PATCH 4/5] add comments to code --- src/main/java/com/example/Main.java | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/example/Main.java b/src/main/java/com/example/Main.java index c8ccf61..37f0a2f 100644 --- a/src/main/java/com/example/Main.java +++ b/src/main/java/com/example/Main.java @@ -45,6 +45,7 @@ private void runApplication(Connection connection) throws SQLException { } } + //User login private boolean loginFlow(Connection connection) throws SQLException { while (true) { System.out.print("Input username: "); @@ -58,6 +59,7 @@ private boolean loginFlow(Connection connection) throws SQLException { return true; } + //If the login is invalid, print a message containing the word invalid and allow exiting via option 0 System.out.print("Credentials invalid. Try again (Enter) or Exit? (0): "); if ("0".equals(scanner.nextLine().strip())) { exitAfterLogin = true; @@ -66,6 +68,8 @@ private boolean loginFlow(Connection connection) throws SQLException { } } + //Used for a lab exercise + //Check of user credentials private boolean checkCredentials(Connection connection, String user, String pass) throws SQLException { @@ -100,6 +104,7 @@ private void menuLoop(Connection connection) throws SQLException { } } + //Menu with options private void printMenu() { System.out.println(""" @@ -257,14 +262,25 @@ private String readRequired(String label) { } } + /** + * 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")) + if (Boolean.getBoolean("devMode")) //Add VM option -DdevMode=true return true; - if ("true".equalsIgnoreCase(System.getenv("DEV_MODE"))) + if ("true".equalsIgnoreCase(System.getenv("DEV_MODE"))) //Environment variable DEV_MODE=true return true; - return Arrays.asList(args).contains("--dev"); + return Arrays.asList(args).contains("--dev"); //Argument --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()) { From 28f4bde21d64f6110afb622560a42495adfb3528 Mon Sep 17 00:00:00 2001 From: Mattias Barth Date: Sun, 14 Dec 2025 18:34:41 +0100 Subject: [PATCH 5/5] add check for blank password --- src/main/java/com/example/Main.java | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/example/Main.java b/src/main/java/com/example/Main.java index 37f0a2f..e118796 100644 --- a/src/main/java/com/example/Main.java +++ b/src/main/java/com/example/Main.java @@ -56,6 +56,7 @@ private boolean loginFlow(Connection connection) throws SQLException { if (checkCredentials(connection, username, password)) { System.out.println("Login Successful!"); + System.out.println(); return true; } @@ -107,7 +108,6 @@ private void menuLoop(Connection connection) throws SQLException { //Menu with options private void printMenu() { System.out.println(""" - ========================== 1) List moon missions 2) Get mission by id @@ -213,8 +213,8 @@ private void updateAccountPassword(Connection connection) throws SQLException { return; } - System.out.print("New password: "); - String newPassword = scanner.nextLine(); + //Ask for a valid password ie not blank + String newPassword = readRequired("New password"); String sql = "UPDATE account SET password=? WHERE user_id=?"; try (PreparedStatement ps = connection.prepareStatement(sql)) { @@ -224,6 +224,8 @@ private void updateAccountPassword(Connection connection) throws SQLException { } System.out.println("Password updated."); + System.out.println("Press Enter to continue"); + scanner.nextLine(); } private void deleteAccount(Connection connection) throws SQLException {