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. diff --git a/pom.xml b/pom.xml index 002ff66..5bd8e26 100644 --- a/pom.xml +++ b/pom.xml @@ -51,6 +51,11 @@ mysql 1.21.3 + + org.slf4j + slf4j-nop + 2.0.17 + diff --git a/src/main/java/com/example/Main.java b/src/main/java/com/example/Main.java index 6dc6fbd..fdd7ab8 100644 --- a/src/main/java/com/example/Main.java +++ b/src/main/java/com/example/Main.java @@ -1,9 +1,9 @@ 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 { @@ -14,25 +14,6 @@ static void main(String[] args) { 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."); - } - - try (Connection connection = DriverManager.getConnection(jdbcUrl, dbUser, dbPass)) { - } 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. @@ -59,4 +40,312 @@ private static String resolveConfig(String propertyKey, String envKey) { } return (v == null || v.trim().isEmpty()) ? null : v.trim(); } + + 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."); + } + + try (Connection connection = DriverManager.getConnection(jdbcUrl, dbUser, dbPass); + Scanner scanner = new Scanner(System.in)) { + + String loggedInUser = authenticateUser(connection, scanner); + if (loggedInUser == null) { + System.out.println("Invalid username or password. Exiting"); + return; + } + System.out.println("\nWelcome, " + loggedInUser + "!"); + boolean running = true; + while (running) { + System.out.println(""" + + Press a number for next assignment: + + 1) List moon missions. + 2) Get a moon mission. + 3) Count missions for a given year. + 4) Create an account. + 5) Update an account password. + 6) Delete an account. + 0) Exit. + """); + + System.out.print("Choose (0-6): "); + if (!scanner.hasNextLine()) { + running = false; + break; + } + String choiceStr = scanner.nextLine().trim(); + + int choice; + try { + choice = Integer.parseInt(choiceStr); + } catch (NumberFormatException e) { + System.out.println("Invalid input. Please enter a number (0-6)."); + continue; + } + + switch (choice) { + case 0: + System.out.println("Exiting application. Goodbye!"); + running = false; + break; + case 1: + System.out.println("Executing: 1) List moon missions..."); + listMoonMissions(connection); + break; + case 2: + System.out.println("Executing: 2) Get a moon mission by mission_id..."); + moonMissionsById(connection, scanner); + break; + case 3: + System.out.println("Executing: 3) Count missions for a given year..."); + countingMissionsForAGivenYear(connection, scanner); + break; + case 4: + System.out.println("Executing: 4) Create an account..."); + createAnAccount(connection, scanner); + break; + case 5: + System.out.println("Executing: 5) Update an account password..."); + updateAccountPassword(connection, scanner); + break; + case 6: + System.out.println("Executing: 6) Delete an account..."); + deleteAccount(connection, scanner); + break; + default: + System.out.println("Invalid choice. Please enter a number between 0 and 6."); + } + } + + } catch (SQLException e) { + throw new RuntimeException("Database operation failed. " + e.getMessage(), e); + } + } + + + private String authenticateUser(Connection connection, Scanner scanner) { + System.out.print("Username: "); + if (!scanner.hasNextLine()) { + return null; // Hantera EOF i testmiljön + } + String username = scanner.nextLine().trim(); + + System.out.print("Password: "); + if (!scanner.hasNextLine()) { + return null; // Hantera EOF i testmiljön + } + String password = scanner.nextLine().trim(); + + String sql = " select name from account where name = ? and password = ? "; + + try (PreparedStatement stmt = connection.prepareStatement(sql)) { + stmt.setString(1, username); + stmt.setString(2, password); + + try (ResultSet rs = stmt.executeQuery()) { + if (rs.next()) { + return rs.getString("name"); + } else { + return null; + } + } + } catch (SQLException ex) { + throw new RuntimeException(ex); + } + } + + + private void listMoonMissions(Connection connection) { + String sql = " select spacecraft from moon_mission order by spacecraft "; + try (PreparedStatement stmt = connection.prepareStatement(sql); + ResultSet rs = stmt.executeQuery()) { + boolean found = false; + while (rs.next()) { + System.out.println(rs.getString("spacecraft")); + found = true; + } + if (!found) { + System.out.println("No moon missions found."); + } + + } catch (SQLException e) { + throw new RuntimeException("Error executing List Moon Missions: " + e.getMessage(), e); + } + } + + private void moonMissionsById(Connection connection, Scanner scanner) { + System.out.println("Enter moon mission id: "); + if (!scanner.hasNextLine()) { + return; + } + String missionId = scanner.nextLine().trim(); + long id; + try { + id = Long.parseLong(missionId); + } catch (NumberFormatException e) { + System.out.println("Invalid moon mission id."); + return; + } + + String sql = "select spacecraft, mission_id, mission_type, launch_date from moon_mission where mission_id = ?"; + try (PreparedStatement stmt = connection.prepareStatement(sql)) { + stmt.setLong(1, id); + + try (ResultSet rs = stmt.executeQuery()) { + if (rs.next()) { + System.out.println("ID: " + rs.getLong("mission_id")); + System.out.println("Spacecraft: " + rs.getString("spacecraft")); + System.out.println("Mission type: " + rs.getString("mission_type")); + System.out.println("Launch date: " + rs.getString("launch_date")); + } else { + System.out.println("Mission id " + missionId + " not found. Please enter a number"); + } + } + + } catch (SQLException e) { + throw new RuntimeException(e); + } + } + + private void countingMissionsForAGivenYear(Connection connection, Scanner scanner) { + System.out.println("Enter year: "); + if (!scanner.hasNextLine()) { + System.out.println("Invalid year"); + return; + } + String yearString = scanner.nextLine().trim(); + int year; + try { + year = Integer.parseInt(yearString); + } catch (NumberFormatException e) { + System.out.println("Invalid year. Please enter a number (e.g. 1987)."); + return; + } + + String sql = " select count(*) as mission_count from moon_mission where year(launch_date) = ?"; + + try (PreparedStatement stmt = connection.prepareStatement(sql)) { + stmt.setInt(1, year); + + try (ResultSet rs = stmt.executeQuery()) { + if (rs.next()) { + int count = rs.getInt("mission_count"); + System.out.println("Mission count for year: " + year); + System.out.println("Number of moon missions: " + count); + } else + System.out.println("No moon missions for year: " + year); + } + } catch (SQLException e) { + throw new RuntimeException(e); + } + } + + private void createAnAccount(Connection connection, Scanner scanner) { + System.out.println("Creating an account..."); + System.out.print("Enter first name: "); + if (!scanner.hasNextLine()) {return;} + String firstName = scanner.nextLine().trim(); + if (firstName.length() < 3) { + System.out.println("First name must be at least 3 characters long."); return; } + System.out.print("Enter last name: "); + if (!scanner.hasNextLine()) {return;} + String lastName = scanner.nextLine().trim(); + if (lastName.length() < 3) { + System.out.println("Last name must be at least 3 characters long."); return; } + System.out.print("Enter ssn: "); + if (!scanner.hasNextLine()) {return;} + String ssn = scanner.nextLine().trim(); + System.out.print("Enter password: "); + if (!scanner.hasNextLine()) {return;} + String password = scanner.nextLine().trim(); + String name = firstName.substring(0, 3) + lastName.substring(0, 3); + + String sql = "INSERT INTO account (first_name, last_name, ssn, password, name) VALUES (?, ?, ?, ?, ?)"; + try (PreparedStatement stmt = connection.prepareStatement(sql)) { + stmt.setString(1, firstName); + stmt.setString(2, lastName); + stmt.setString(3, ssn); + stmt.setString(4, password); + stmt.setString(5, name); + + int affectedRows = stmt.executeUpdate(); + if (affectedRows > 0) { + System.out.println("Successfully created an account for " + firstName + " " + lastName); + } else + System.out.println("Failed to create an account."); + + } catch (SQLException e) { + throw new RuntimeException("Database operation failed. " + e.getMessage()); + } + } + + private void updateAccountPassword(Connection connection, Scanner scanner) { + System.out.println("Enter user_id: "); + if (!scanner.hasNextLine()) { + return; + } + String userIdStr = scanner.nextLine().trim(); + long userId; + try { + userId = Long.parseLong(userIdStr); + } catch (NumberFormatException e) { + System.out.println("Invalid user_id. Please enter a number"); + return; + } + + System.out.println("Enter new password: "); + if (!scanner.hasNextLine()) { + return; + } + String newPassword = scanner.nextLine(); + + String sql = " update account set password = ? where user_id = ? "; + try (PreparedStatement stmt = connection.prepareStatement(sql)) { + stmt.setString(1, newPassword); + stmt.setLong(2, userId); + + int affectedRows = stmt.executeUpdate(); + + if (affectedRows > 0) { + System.out.println("Account updated successfully."); + } else { + System.out.println("Failed to update account."); + } + + } catch (SQLException e) { + System.err.println("ERROR: Failed to update password."); + throw new RuntimeException("Database operation failed. " + e.getMessage()); + } + } + + private void deleteAccount(Connection connection, Scanner scanner) { + System.out.println("Enter user id, that you wish to delete: "); + if (!scanner.hasNextLine()) { + return; + } + String userId = scanner.nextLine(); + + String sql = " delete from account where user_id = ? "; + try (PreparedStatement stmt = connection.prepareStatement(sql)) { + stmt.setString(1, userId); + + int affectedRows = stmt.executeUpdate(); + if (affectedRows > 0) { + System.out.println("Successfully deleted the account."); + } else { + System.out.println("Failed to delete the account."); + } + } catch (SQLException e) { + throw new RuntimeException("Database operation failed. " + e.getMessage()); + } + } }