From 338bcfe42d37f907b6b3f435818be7273dafe3b0 Mon Sep 17 00:00:00 2001 From: Anton Ahlqvist Date: Fri, 12 Dec 2025 15:36:27 +0100 Subject: [PATCH 1/9] feat: add basic login and moon mission listing menu --- src/main/java/com/example/Main.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/example/Main.java b/src/main/java/com/example/Main.java index c67db02..0fa8b38 100644 --- a/src/main/java/com/example/Main.java +++ b/src/main/java/com/example/Main.java @@ -124,4 +124,4 @@ private static String resolveConfig(String propertyKey, String envKey) { } return (v == null || v.trim().isEmpty()) ? null : v.trim(); } -} +} \ No newline at end of file From 5dac824c6b11a192ee6098f4bbedd625b4031a89 Mon Sep 17 00:00:00 2001 From: Anton Ahlqvist Date: Fri, 12 Dec 2025 16:15:30 +0100 Subject: [PATCH 2/9] feat: add basic login and moon mission listing menu --- src/main/java/com/example/Main.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/example/Main.java b/src/main/java/com/example/Main.java index 0fa8b38..c67db02 100644 --- a/src/main/java/com/example/Main.java +++ b/src/main/java/com/example/Main.java @@ -124,4 +124,4 @@ private static String resolveConfig(String propertyKey, String envKey) { } return (v == null || v.trim().isEmpty()) ? null : v.trim(); } -} \ No newline at end of file +} From c0e238555a3b77b1456225dc57677e83974098ca Mon Sep 17 00:00:00 2001 From: Anton Ahlqvist Date: Fri, 12 Dec 2025 17:29:32 +0100 Subject: [PATCH 3/9] feat: extend CLI menu to show details for a specific moon mission --- src/main/java/com/example/Main.java | 53 ++++++++++++++++++++--------- 1 file changed, 36 insertions(+), 17 deletions(-) diff --git a/src/main/java/com/example/Main.java b/src/main/java/com/example/Main.java index c67db02..8460523 100644 --- a/src/main/java/com/example/Main.java +++ b/src/main/java/com/example/Main.java @@ -16,17 +16,17 @@ static void main(String[] args) { /** * Kör huvudflödet för applikationen, inklusive inloggning och enkel meny för att lista månfärder. *

- * Vad som har lagts till i denna version: - *

* Skapar en Scanner för användarinput. * Frågar användaren efter användarnamn och lösenord och kontrollerar dessa mot databasen. * Om inloggning lyckas skrivs "Login successful!" ut, annars avslutas programmet med felmeddelande. - * Efter lyckad inloggning visas en enkel meny med två alternativ: + * Efter lyckad inloggning visas en enkel meny med följande alternativ: *

- * Lista alla månfärder (namn på rymdfarkoster). - * Avsluta programmet. + * 1) Lista alla månfärder (namn på rymdfarkoster) + * 2) Hämta månfärd efter mission_id + * 0) Avsluta programmet *

- * Valet "Lista månfärder" hämtar alla rymdfarkoster från tabellen "moon_mission" och skriver ut dem i ordning eftermission_id. + * Valet "Lista månfärder" hämtar alla rymdfarkoster från tabellen "moon_mission" och skriver ut dem i ordning efter mission_id. + * Valet "Hämta månfärd efter mission_id" skriver ut information om den specifika månfärden om den finns. * Valet "Avsluta" bryter menyn och avslutar metoden. * Ogiltiga val hanteras med ett felmeddelande. */ @@ -74,22 +74,41 @@ public void run() { while (true) { System.out.println("1) List moon missions"); + System.out.println("2) Get mission by ID"); System.out.println("0) Exit"); String choice = scanner.nextLine().trim(); - if ("0".equals(choice)) { - break; - } else if ("1".equals(choice)) { - try (PreparedStatement ps = connection.prepareStatement( - "SELECT spacecraft FROM moon_mission ORDER BY mission_id" - )) { - ResultSet rs = ps.executeQuery(); - while (rs.next()) { - System.out.println(rs.getString("spacecraft")); + + switch (choice) { + case "0" -> { break; } + case "1" -> { + try (PreparedStatement ps = connection.prepareStatement( + "SELECT spacecraft FROM moon_mission ORDER BY mission_id" + )) { + ResultSet rs = ps.executeQuery(); + while (rs.next()) { + System.out.println(rs.getString("spacecraft")); + } + } + } + case "2" -> { + System.out.println("Mission ID:"); + int id = Integer.parseInt(scanner.nextLine().trim()); + + try (PreparedStatement ps = connection.prepareStatement( + "SELECT * FROM moon_mission WHERE mission_id = ?" + )) { + ps.setInt(1, id); + ResultSet rs = ps.executeQuery(); + if (rs.next()) { + + System.out.println(rs.getString("spacecraft")); + } else { + System.out.println("Mission not found"); + } } } - } else { - System.out.println("Invalid option"); + default -> System.out.println("Invalid option"); } } From 221d81e523410e8718507b36552bba5f3f09fd7b Mon Sep 17 00:00:00 2001 From: Anton Ahlqvist Date: Fri, 12 Dec 2025 22:11:27 +0100 Subject: [PATCH 4/9] feat: add CLI option to count moon missions by year --- src/main/java/com/example/Main.java | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/src/main/java/com/example/Main.java b/src/main/java/com/example/Main.java index 8460523..16f7644 100644 --- a/src/main/java/com/example/Main.java +++ b/src/main/java/com/example/Main.java @@ -23,10 +23,12 @@ static void main(String[] args) { *

* 1) Lista alla månfärder (namn på rymdfarkoster) * 2) Hämta månfärd efter mission_id + * 3) Räkna månfärder för ett visst år * 0) Avsluta programmet *

* Valet "Lista månfärder" hämtar alla rymdfarkoster från tabellen "moon_mission" och skriver ut dem i ordning efter mission_id. * Valet "Hämta månfärd efter mission_id" skriver ut information om den specifika månfärden om den finns. + * Valet "Räkna månfärder för ett visst år" skriver ut antalet månfärder för det angivna året. * Valet "Avsluta" bryter menyn och avslutar metoden. * Ogiltiga val hanteras med ett felmeddelande. */ @@ -75,6 +77,7 @@ public void run() { while (true) { System.out.println("1) List moon missions"); System.out.println("2) Get mission by ID"); + System.out.println("3) Count missions for year"); System.out.println("0) Exit"); String choice = scanner.nextLine().trim(); @@ -108,6 +111,24 @@ public void run() { } } } + + case "3" -> { + System.out.println("Year:"); + String yearStr = scanner.nextLine().trim(); + System.out.println(yearStr); + int year = Integer.parseInt(scanner.nextLine().trim()); + + try (PreparedStatement ps = connection.prepareStatement( + "SELECT COUNT(*) FROM moon_mission WHERE year = ?" + )) { + ps.setInt(1, year); + ResultSet rs = ps.executeQuery(); + if (rs.next()) { + System.out.println(rs.getInt(1)); + } + } + } + default -> System.out.println("Invalid option"); } } From 98459f54bf26e6af295723662f268dbf297a6e67 Mon Sep 17 00:00:00 2001 From: Anton Ahlqvist Date: Sat, 13 Dec 2025 02:15:08 +0100 Subject: [PATCH 5/9] feat: add CLI option to create a new account --- src/main/java/com/example/Main.java | 28 +++++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/example/Main.java b/src/main/java/com/example/Main.java index 16f7644..b041cdb 100644 --- a/src/main/java/com/example/Main.java +++ b/src/main/java/com/example/Main.java @@ -14,7 +14,8 @@ static void main(String[] args) { } /** - * Kör huvudflödet för applikationen, inklusive inloggning och enkel meny för att lista månfärder. + * Kör huvudflödet för applikationen, inklusive inloggning och enkel meny för att lista månfärder + * och skapa nya konton. *

* Skapar en Scanner för användarinput. * Frågar användaren efter användarnamn och lösenord och kontrollerar dessa mot databasen. @@ -24,11 +25,13 @@ static void main(String[] args) { * 1) Lista alla månfärder (namn på rymdfarkoster) * 2) Hämta månfärd efter mission_id * 3) Räkna månfärder för ett visst år + * 4) Skapa ett nytt konto (förnamn, efternamn, SSN, lösenord) * 0) Avsluta programmet *

* Valet "Lista månfärder" hämtar alla rymdfarkoster från tabellen "moon_mission" och skriver ut dem i ordning efter mission_id. * Valet "Hämta månfärd efter mission_id" skriver ut information om den specifika månfärden om den finns. * Valet "Räkna månfärder för ett visst år" skriver ut antalet månfärder för det angivna året. + * Valet "Skapa nytt konto" frågar efter namn, SSN och lösenord och sparar informationen i tabellen "account". * Valet "Avsluta" bryter menyn och avslutar metoden. * Ogiltiga val hanteras med ett felmeddelande. */ @@ -129,6 +132,29 @@ public void run() { } } + case "4" -> { + System.out.println("First name:"); + String firstName = scanner.nextLine().trim(); + System.out.println("Last name:"); + String lastName = scanner.nextLine().trim(); + System.out.println("SSN:"); + String ssn = scanner.nextLine().trim(); + System.out.println("Password:"); + String accountPassword = scanner.nextLine().trim(); + + try (PreparedStatement ps = connection.prepareStatement( + "INSERT INTO account(password, first_name, last_name, ssn) VALUES (?, ?, ?, ?)" + )) { + ps.setString(1, accountPassword); + ps.setString(2, firstName); + ps.setString(3, lastName); + ps.setString(4, ssn); + ps.executeUpdate(); + } + + System.out.println("Account created"); + } + default -> System.out.println("Invalid option"); } } From adbc0dbb324eb4fc68c2ee85aa8cd4c2938f21dc Mon Sep 17 00:00:00 2001 From: Anton Ahlqvist Date: Sat, 13 Dec 2025 11:08:09 +0100 Subject: [PATCH 6/9] feat: add CLI option to update account password --- src/main/java/com/example/Main.java | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/src/main/java/com/example/Main.java b/src/main/java/com/example/Main.java index b041cdb..e0bd9c3 100644 --- a/src/main/java/com/example/Main.java +++ b/src/main/java/com/example/Main.java @@ -26,12 +26,14 @@ static void main(String[] args) { * 2) Hämta månfärd efter mission_id * 3) Räkna månfärder för ett visst år * 4) Skapa ett nytt konto (förnamn, efternamn, SSN, lösenord) + * 5) Uppdatera lösenord för ett konto via user_id * 0) Avsluta programmet *

* Valet "Lista månfärder" hämtar alla rymdfarkoster från tabellen "moon_mission" och skriver ut dem i ordning efter mission_id. * Valet "Hämta månfärd efter mission_id" skriver ut information om den specifika månfärden om den finns. * Valet "Räkna månfärder för ett visst år" skriver ut antalet månfärder för det angivna året. * Valet "Skapa nytt konto" frågar efter namn, SSN och lösenord och sparar informationen i tabellen "account". + * Valet "Uppdatera lösenord" frågar efter user_id och nytt lösenord och uppdaterar kontots lösenord i tabellen "account". * Valet "Avsluta" bryter menyn och avslutar metoden. * Ogiltiga val hanteras med ett felmeddelande. */ @@ -81,6 +83,8 @@ public void run() { System.out.println("1) List moon missions"); System.out.println("2) Get mission by ID"); System.out.println("3) Count missions for year"); + System.out.println("4) Create new account"); + System.out.println("5) Update account password"); System.out.println("0) Exit"); String choice = scanner.nextLine().trim(); @@ -155,6 +159,26 @@ public void run() { System.out.println("Account created"); } + case "5" -> { + System.out.println("User ID of account to update:"); + long userId = Long.parseLong(scanner.nextLine().trim()); + System.out.println("New password:"); + String newPassword = scanner.nextLine().trim(); + + try (PreparedStatement ps = connection.prepareStatement( + "UPDATE account SET password = ? WHERE user_id = ?" + )) { + ps.setString(1, newPassword); + ps.setLong(2, userId); + int rows = ps.executeUpdate(); + if (rows > 0) { + System.out.println("Password updated"); + } else { + System.out.println("No account found with that ID"); + } + } + } + default -> System.out.println("Invalid option"); } } From 5c4fc261c203c37103f174a096c3581512b93754 Mon Sep 17 00:00:00 2001 From: Anton Ahlqvist Date: Sat, 13 Dec 2025 12:19:03 +0100 Subject: [PATCH 7/9] feat: add CLI option to remove account --- src/main/java/com/example/Main.java | 33 +++++++++++++++++++++++------ 1 file changed, 27 insertions(+), 6 deletions(-) diff --git a/src/main/java/com/example/Main.java b/src/main/java/com/example/Main.java index e0bd9c3..903b5c5 100644 --- a/src/main/java/com/example/Main.java +++ b/src/main/java/com/example/Main.java @@ -14,8 +14,8 @@ static void main(String[] args) { } /** - * Kör huvudflödet för applikationen, inklusive inloggning och enkel meny för att lista månfärder - * och skapa nya konton. + * Kör huvudflödet för applikationen, inklusive inloggning och enkel meny för att lista månfärder, + * skapa nya konton och ta bort konton. *

* Skapar en Scanner för användarinput. * Frågar användaren efter användarnamn och lösenord och kontrollerar dessa mot databasen. @@ -27,6 +27,7 @@ static void main(String[] args) { * 3) Räkna månfärder för ett visst år * 4) Skapa ett nytt konto (förnamn, efternamn, SSN, lösenord) * 5) Uppdatera lösenord för ett konto via user_id + * 6) Ta bort ett konto via user_id * 0) Avsluta programmet *

* Valet "Lista månfärder" hämtar alla rymdfarkoster från tabellen "moon_mission" och skriver ut dem i ordning efter mission_id. @@ -34,6 +35,7 @@ static void main(String[] args) { * Valet "Räkna månfärder för ett visst år" skriver ut antalet månfärder för det angivna året. * Valet "Skapa nytt konto" frågar efter namn, SSN och lösenord och sparar informationen i tabellen "account". * Valet "Uppdatera lösenord" frågar efter user_id och nytt lösenord och uppdaterar kontots lösenord i tabellen "account". + * Valet "Ta bort konto" frågar efter user_id och tar bort kontot från tabellen "account". * Valet "Avsluta" bryter menyn och avslutar metoden. * Ogiltiga val hanteras med ett felmeddelande. */ @@ -85,6 +87,7 @@ public void run() { System.out.println("3) Count missions for year"); System.out.println("4) Create new account"); System.out.println("5) Update account password"); + System.out.println("6) Delete account"); System.out.println("0) Exit"); String choice = scanner.nextLine().trim(); @@ -121,17 +124,18 @@ public void run() { case "3" -> { System.out.println("Year:"); - String yearStr = scanner.nextLine().trim(); - System.out.println(yearStr); int year = Integer.parseInt(scanner.nextLine().trim()); try (PreparedStatement ps = connection.prepareStatement( - "SELECT COUNT(*) FROM moon_mission WHERE year = ?" + "SELECT COUNT(*) FROM moon_mission WHERE YEAR(launch_date) = ?" )) { ps.setInt(1, year); ResultSet rs = ps.executeQuery(); if (rs.next()) { - System.out.println(rs.getInt(1)); + int count = rs.getInt(1); + System.out.println(year + " missions: " + count); + } else { + System.out.println(year + " missions: 0"); } } } @@ -179,6 +183,23 @@ public void run() { } } + case "6" -> { + System.out.println("User ID of account to delete:"); + long userId = Long.parseLong(scanner.nextLine().trim()); + + try (PreparedStatement ps = connection.prepareStatement( + "DELETE FROM account WHERE user_id = ?" + )) { + ps.setLong(1, userId); + int rows = ps.executeUpdate(); + if (rows > 0) { + System.out.println("Account deleted"); + } else { + System.out.println("No account found with that ID"); + } + } + } + default -> System.out.println("Invalid option"); } } From 0b4dbf000164cef82cd9a2ad206426f559132368 Mon Sep 17 00:00:00 2001 From: Anton Ahlqvist Date: Sat, 13 Dec 2025 13:16:17 +0100 Subject: [PATCH 8/9] chore: apply rabbit's suggestions and tidy up code --- src/main/java/com/example/Main.java | 29 +++++++++++++++++++---------- 1 file changed, 19 insertions(+), 10 deletions(-) diff --git a/src/main/java/com/example/Main.java b/src/main/java/com/example/Main.java index 903b5c5..0dec156 100644 --- a/src/main/java/com/example/Main.java +++ b/src/main/java/com/example/Main.java @@ -93,7 +93,9 @@ public void run() { String choice = scanner.nextLine().trim(); switch (choice) { - case "0" -> { break; } + case "0" -> { + return; + } case "1" -> { try (PreparedStatement ps = connection.prepareStatement( "SELECT spacecraft FROM moon_mission ORDER BY mission_id" @@ -106,10 +108,15 @@ public void run() { } case "2" -> { System.out.println("Mission ID:"); - int id = Integer.parseInt(scanner.nextLine().trim()); - + int id; + try { + id = Integer.parseInt(scanner.nextLine().trim()); + } catch (NumberFormatException e) { + System.out.println("Invalid mission ID"); + break; + } try (PreparedStatement ps = connection.prepareStatement( - "SELECT * FROM moon_mission WHERE mission_id = ?" + "SELECT spacecraft FROM moon_mission WHERE mission_id = ?" )) { ps.setInt(1, id); ResultSet rs = ps.executeQuery(); @@ -124,19 +131,21 @@ public void run() { case "3" -> { System.out.println("Year:"); - int year = Integer.parseInt(scanner.nextLine().trim()); - + int year; + try { + year = Integer.parseInt(scanner.nextLine().trim()); + } catch (NumberFormatException e) { + System.out.println("Invalid year"); + break; + } try (PreparedStatement ps = connection.prepareStatement( "SELECT COUNT(*) FROM moon_mission WHERE YEAR(launch_date) = ?" )) { ps.setInt(1, year); ResultSet rs = ps.executeQuery(); - if (rs.next()) { + rs.next(); int count = rs.getInt(1); System.out.println(year + " missions: " + count); - } else { - System.out.println(year + " missions: 0"); - } } } From e694ea8ea72cbe783b82ab5aea0c356175cf82d9 Mon Sep 17 00:00:00 2001 From: Anton Ahlqvist Date: Tue, 13 Jan 2026 10:54:47 +0100 Subject: [PATCH 9/9] Commit last javadoc --- src/main/java/com/example/Main.java | 44 +++++++++++++++++++---------- 1 file changed, 29 insertions(+), 15 deletions(-) diff --git a/src/main/java/com/example/Main.java b/src/main/java/com/example/Main.java index 0dec156..dadfc78 100644 --- a/src/main/java/com/example/Main.java +++ b/src/main/java/com/example/Main.java @@ -23,30 +23,44 @@ static void main(String[] args) { * Efter lyckad inloggning visas en enkel meny med följande alternativ: *

* 1) Lista alla månfärder (namn på rymdfarkoster) + * Hämtar alla rymdfarkoster från tabellen "moon_mission" och skriver ut dem i ordning + * efter mission_id. Användaren får en snabb översikt över vilka månfärder som finns + * registrerade i databasen. + *

* 2) Hämta månfärd efter mission_id + * Frågar efter ett specifikt mission_id och hämtar information om månfärden med det ID:t. + * Om månfärden finns skrivs namnet på rymdfarkosten ut, annars meddelas att månfärden inte + * hittades. + *

* 3) Räkna månfärder för ett visst år + * Frågar användaren efter ett år och räknar antalet månfärder som har launch_date inom + * det året. Resultatet visar hur många månfärder som genomfördes under det valda året. + *

* 4) Skapa ett nytt konto (förnamn, efternamn, SSN, lösenord) + * Frågar efter användarens förnamn, efternamn, SSN och lösenord och skapar ett nytt konto + * i tabellen "account". Detta gör det möjligt för nya användare att registrera sig. + *

* 5) Uppdatera lösenord för ett konto via user_id + * Frågar efter user_id för kontot som ska uppdateras samt det nya lösenordet. Uppdaterar + * kontots lösenord i databasen om kontot finns, annars meddelas att inget konto med + * angivet ID hittades. + *

* 6) Ta bort ett konto via user_id + * Frågar efter user_id för kontot som ska tas bort och tar bort kontot från tabellen + * "account". Om kontot inte finns meddelas användaren om att inget konto hittades. + *

* 0) Avsluta programmet + * Bryter menyn och avslutar metoden. *

- * Valet "Lista månfärder" hämtar alla rymdfarkoster från tabellen "moon_mission" och skriver ut dem i ordning efter mission_id. - * Valet "Hämta månfärd efter mission_id" skriver ut information om den specifika månfärden om den finns. - * Valet "Räkna månfärder för ett visst år" skriver ut antalet månfärder för det angivna året. - * Valet "Skapa nytt konto" frågar efter namn, SSN och lösenord och sparar informationen i tabellen "account". - * Valet "Uppdatera lösenord" frågar efter user_id och nytt lösenord och uppdaterar kontots lösenord i tabellen "account". - * Valet "Ta bort konto" frågar efter user_id och tar bort kontot från tabellen "account". - * Valet "Avsluta" bryter menyn och avslutar metoden. - * Ogiltiga val hanteras med ett felmeddelande. + * Ogiltiga val hanteras med felmeddelanden. */ 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( + throw new IllegalStateException( "Missing DB configuration. Provide APP_JDBC_URL, APP_DB_USER, APP_DB_PASS " + "as system properties (-Dkey=value) or environment variables."); } @@ -144,8 +158,8 @@ public void run() { ps.setInt(1, year); ResultSet rs = ps.executeQuery(); rs.next(); - int count = rs.getInt(1); - System.out.println(year + " missions: " + count); + int count = rs.getInt(1); + System.out.println(year + " missions: " + count); } } @@ -226,11 +240,11 @@ public void run() { * @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 + 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"); } /**