Repository: Interns-2025/StudentManagementSystemService
Pull request #21: Refactor: Correct flow 
Author: login: itsfazalkhan
Created: 2025-04-23T16:22:45Z | Merged: 2025-04-28T17:56:18Z

Implemented only the below: 

User → View → Controller→ Service → DAO → DB

TODO:

- [ ] Add Test Cases
- [ ] Add SLF4J and Logback
- [ ] Add pending functionalities
- [ ] Documentation [Multi-line comments]
- [ ] Declare Constants for all static data [in Constants file]



Diff:
diff --git a/pom.xml b/pom.xml
index 66fa7a2..a6f2e7b 100644
--- a/pom.xml
+++ b/pom.xml
@@ -32,5 +32,21 @@
             <artifactId>jbcrypt</artifactId>
             <version>0.4</version>
         </dependency>
+        <dependency>
+            <groupId>org.junit.jupiter</groupId>
+            <artifactId>junit-jupiter</artifactId>
+            <version>RELEASE</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.slf4j</groupId>
+            <artifactId>slf4j-api</artifactId>
+            <version>2.0.17</version>
+        </dependency>
+        <dependency>
+            <groupId>ch.qos.logback</groupId>
+            <artifactId>logback-classic</artifactId>
+            <version>1.5.18</version>
+        </dependency>
     </dependencies>
 </project>
diff --git a/src/main/java/com/intern/Main.java b/src/main/java/com/intern/Main.java
index 31b7a49..4a025f4 100644
--- a/src/main/java/com/intern/Main.java
+++ b/src/main/java/com/intern/Main.java
@@ -1,5 +1,6 @@
 package com.intern;
 
+import com.intern.sms.util.PrintDB;
 import com.khan.fazal.intern.PrintDash;
 
 import java.util.Scanner;
diff --git a/src/main/java/com/intern/sms/app/App.java b/src/main/java/com/intern/sms/app/App.java
index 81649ba..03ad4af 100644
--- a/src/main/java/com/intern/sms/app/App.java
+++ b/src/main/java/com/intern/sms/app/App.java
@@ -1,11 +1,10 @@
 package com.intern.sms.app;
 
-import com.intern.sms.controller.UserController;
+import com.intern.sms.view.ConsoleView;
 
 public class App {
-    //starting the app
     public static void main(String[] args) {
-        UserController controller = new UserController();
-        controller.start();
+        ConsoleView view = new ConsoleView();
+        view.mainMenu();
     }
 }
diff --git a/src/main/java/com/intern/sms/controller/UserController.java b/src/main/java/com/intern/sms/controller/UserController.java
index 9b640a8..858cf39 100644
--- a/src/main/java/com/intern/sms/controller/UserController.java
+++ b/src/main/java/com/intern/sms/controller/UserController.java
@@ -1,232 +1,72 @@
 package com.intern.sms.controller;
 
-import com.intern.PrintDB;
+import com.intern.sms.util.PrintDB;
 import com.khan.fazal.intern.PrintDash;
-import com.intern.sms.dao.UserDAO;
-import com.intern.sms.service.AuthService;
-import com.intern.sms.service.AuthServiceImpl;
-import com.intern.sms.view.ConsoleView;
-import java.sql.SQLException;
+import com.intern.sms.service.UserService;
+import com.intern.sms.service.UserServiceImpl;
+import java.util.List;
+import static com.intern.sms.util.Constants.*;
 
 public class UserController {
-    private final ConsoleView view = new ConsoleView();
-    private final AuthService authService = new AuthServiceImpl();
-    private UserDAO UserDAO;
-
-    public void start() {
-        while (true) {
-            view.showMenu("User Management Menu", new String[] {"Login", "Sign Up", "Forgot Password", "Exit"});
-            int choice = view.getChoice();
-
-            try {
-                switch (choice) {
-                    case 1 -> login();
-                    case 2 -> signUp();
-                    case 3 -> forgotPassword();
-                    case 4 -> {
-                        view.showMessage("Goodbye!");
-                        return;
-                    }
-                    default -> view.showMessage("Invalid choice.");
-                }
-            } catch (Exception e) {
-                view.showMessage("Error: " + e.getMessage());
-            }
-        }
-    }
-
-    private void login() throws SQLException {
-        String username = view.prompt("Enter username: ");
-        String password = view.prompt("Enter password: ");
-
-        String role = authService.authenticateAndGetRole(username, password);
-
-        if (role == null) {
-            view.showMessage("Invalid credentials.");
-            return;
-        }
-
-        view.showMessage("Login successful! Welcome, " + username);
-
-        switch (role.toLowerCase()) {
-            case "admin" -> adminDashboard();
-            case "teacher" -> teacherDashboard();
-            case "student" -> studentDashboard();
-            case "parent" -> parentDashboard();
-            default -> view.showMessage("Unknown role.");
-        }
-    }
-
-    private void signUp() throws SQLException {
-        String username = view.prompt("Choose a username: ");
-        String password = view.prompt("Choose a password: ");
-        String email = view.prompt("Enter your email: ");
-        String role = view.prompt("Enter role (teacher/student/parent): ");
-        if (role.equals("admin")) {
-            view.showMessage("\n--- Admin Authentication ---");
-            String adminUsername = view.prompt("Enter admin username: ");
-            String adminPassword = view.prompt("Enter admin password: ");
-            authService.authenticateAdmin(adminUsername, adminPassword);
-        }
-        boolean registered = authService.registerUser(username, password, email, role);
-        view.showMessage(registered ? "User registered successfully." : "Username already exists.");
-    }
-
-    private void forgotPassword() throws SQLException {
-        view.showMessage("\n--- Admin Authentication ---");
-        String adminUsername = view.prompt("Enter admin username: ");
-        String adminPassword = view.prompt("Enter admin password: ");
-
-        String targetUsername = view.prompt("Enter username of user to reset password: ");
-        String newPassword = view.prompt("Enter new password for " + targetUsername + ": ");
-
-        boolean reset = authService.resetPassword(adminUsername, adminPassword, targetUsername, newPassword);
-        view.showMessage(reset ? "Password reset successfully." : "Failed to reset password. Either admin auth failed or user not found.");
-    }
-
-    private void adminDashboard() {
-        while (true) {
-            view.showMenu("Admin Dashboard", new String[] {"Manage Users", "Manage System Settings", "Logout"});
-            int choice = view.getChoice();
-            switch (choice) {
-                case 1 -> manageUsers();
-                case 2 -> manageSystemSettings();
-                case 3 -> {
-                    view.showMessage("Logging out...");
-                    return;
-                }
-                default -> view.showMessage("Invalid choice.");
-            }
-        }
-    }
-
-    private void manageUsers() {
-        while (true) {
-            view.showMenu("Manage Users", new String[] {"Add User", "View Users", "Delete User", "Back to Admin Dashboard"});
-            int choice = view.getChoice();
-            switch (choice) {
-                case 1 -> addUser();
-                case 2 -> viewUsers();
-                case 3 -> deleteUser();
-                case 4 -> {
-                    return; // Back to Admin Dashboard
-                }
-                default -> view.showMessage("Invalid choice.");
-            }
-        }
-    }
-
-    private void addUser() {
-        String username = view.prompt("Enter username: ");
-        String password = view.prompt("Enter password: ");
-        String email = view.prompt("Enter email: ");
-        String role = view.prompt("Enter role (admin/teacher/student/parent): ");
-
-        try {
-            boolean success = authService.registerUser(username, password, email, role);
-            view.showMessage(success ? "User added successfully!" : "Failed to add user.");
-        } catch (SQLException e) {
-            view.showMessage("Error: " + e.getMessage());
-        }
-    }
-
-    private void viewUsers() {
-        PrintDash.printTable(PrintDB.fetchTable("user"));
-    }
-
-    private void deleteUser() {
-        int userID = Integer.parseInt(view.prompt("Enter user ID to delete: "));
-        try {
-            UserDAO.deleteUser(userID);
-            view.showMessage("User deleted successfully.");
-        } catch (SQLException e) {
-            view.showMessage("Error: " + e.getMessage());
-        }
-    }
-
-    private void manageSystemSettings() {
-        view.showMessage("System settings are under development.");
-    }
-
-    private void teacherDashboard() {
-        while (true) {
-            view.showMenu("Teacher Dashboard", new String[] {"Manage Courses", "Mark Attendance", "Grade Students", "Logout"});
-            int choice = view.getChoice();
-            switch (choice) {
-                case 1 -> manageCourses();
-                case 2 -> markAttendance();
-                case 3 -> gradeStudents();
-                case 4 -> {
-                    view.showMessage("Logging out...");
-                    return;
-                }
-                default -> view.showMessage("Invalid choice.");
-            }
-        }
-    }
-
-    private void manageCourses() {
-        view.showMessage("Managing courses functionality is under development.");
-    }
-
-    private void markAttendance() {
-        view.showMessage("Marking attendance functionality is under development.");
-    }
-
-    private void gradeStudents() {
-        view.showMessage("Grading students functionality is under development.");
-    }
-
-    private void studentDashboard() {
-        while (true) {
-            view.showMenu("Student Dashboard", new String[] {"View Courses", "Track Attendance", "View Grades", "Logout"});
-            int choice = view.getChoice();
-            switch (choice) {
-                case 1 -> viewCourses();
-                case 2 -> trackAttendance();
-                case 3 -> viewGrades();
-                case 4 -> {
-                    view.showMessage("Logging out...");
-                    return;
-                }
-                default -> view.showMessage("Invalid choice.");
-            }
-        }
-    }
+    private final UserService userService = new UserServiceImpl();
 
-    private void viewCourses() {
-        view.showMessage("Viewing courses functionality is under development.");
+    public String login(String username, String password) {
+        return userService.authenticateAndGetRole(username, password);
     }
 
-    private void trackAttendance() {
-        view.showMessage("Tracking attendance functionality is under development.");
-    }
+    public boolean signUp(String username, String password, String email, String role) {
+        return userService.registerUser(username, password, email, role);
+    }
+
+    public boolean forgotPassword(String targetUsername, String newPassword) {
+        return userService.resetPassword(targetUsername, newPassword);
+    }
+
+    public String addUser(String username, String password, String email, String role) {
+
+        boolean success = userService.registerUser(username, password, email, role);
+        return (success ? SUCCESS_ADD : FAIL_ADD);
+    }
+
+    public void viewUsers() {
+        viewUsers("user");
+    }
+
+    public void viewUsers(String tableName) {
+        List<String[]> table = PrintDB.fetchTable(tableName);
+        PrintDash.printTable(table);
+    }
+
+    public String deleteUser(int userID) {
+        boolean success = userService.deleteUser(userID);
+        return (success ? SUCCESS_DEL : FAIL_DEL);
+
+    }
+
+    public void manageSystemSettings() {
+    }
+
+    public void manageCourses() {
+    }
+
+    public void markAttendance() {
+    }
+
+    public void gradeStudents() {
+    }
+
+    public void viewCourses() {
+    }
 
-    private void viewGrades() {
-        view.showMessage("Viewing grades functionality is under development.");
+    public void trackAttendance() {
     }
 
-    private void parentDashboard() {
-        while (true) {
-            view.showMenu("Parent Dashboard", new String[] {"Monitor Student Progress", "Pay Fees", "Logout"});
-            int choice = view.getChoice();
-            switch (choice) {
-                case 1 -> monitorStudentProgress();
-                case 2 -> payFees();
-                case 3 -> {
-                    view.showMessage("Logging out...");
-                    return;
-                }
-                default -> view.showMessage("Invalid choice.");
-            }
-        }
+    public void viewGrades() {
     }
 
-    private void monitorStudentProgress() {
-        view.showMessage("Monitoring student progress functionality is under development.");
+    public void monitorStudentProgress() {
     }
 
-    private void payFees() {
-        view.showMessage("Paying fees functionality is under development.");
+    public void payFees() {
     }
 }
diff --git a/src/main/java/com/intern/sms/dao/UserDAO.java b/src/main/java/com/intern/sms/dao/UserDAO.java
index 2609cff..e5d3b46 100644
--- a/src/main/java/com/intern/sms/dao/UserDAO.java
+++ b/src/main/java/com/intern/sms/dao/UserDAO.java
@@ -1,19 +1,23 @@
 package com.intern.sms.dao;
 
 import com.intern.sms.model.User;
-
-import java.sql.SQLException;
 import java.util.List;
 
 public interface UserDAO{
 
-    void addUser(User user) throws SQLException;
+    public boolean addUser(String username, String password, String email, String role);
+
+    public boolean authenticateAdmin(String username, String password);
+
+    public boolean resetPassword(String targetUsername, String newPassword);
+
+    public String authenticateAndGetRole(String username, String password);
 
-    User getUserById(int userID) throws SQLException;
+    User getUserById(int userID);
 
-    List<User> getAllUsers() throws SQLException;
+    List<User> getAllUsers();
 
-    void updateUser(User user) throws SQLException;
+    void updateUser(User user);
 
-    void deleteUser(int userID) throws SQLException;
+    boolean deleteUser(int userID);
 }
diff --git a/src/main/java/com/intern/sms/dao/UserDAOimpl.java b/src/main/java/com/intern/sms/dao/UserDAOimpl.java
index d289bac..b356d5e 100644
--- a/src/main/java/com/intern/sms/dao/UserDAOimpl.java
+++ b/src/main/java/com/intern/sms/dao/UserDAOimpl.java
@@ -1,93 +1,179 @@
 package com.intern.sms.dao;
 
-import com.intern.sms.util.DBConnection;
 import com.intern.sms.model.User;
-
+import com.intern.sms.util.DBConnection;
+import org.mindrot.jbcrypt.BCrypt;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 import java.sql.*;
 import java.util.ArrayList;
+import java.util.Collections;
 import java.util.List;
+import static com.intern.sms.util.Constants.*;
+import static com.intern.sms.util.DBConstants.*;
 
 public class UserDAOimpl implements UserDAO {
 
+    private static final Logger logger = LoggerFactory.getLogger(UserDAOimpl.class);
+
     @Override
-    public void addUser(User user) throws SQLException {
-        String sql = "INSERT INTO user (username, password, email, role) VALUES (?, ?, ?, ?)";
-        try (Connection conn = DBConnection.getConnection();
-             PreparedStatement stmt = conn.prepareStatement(sql)) {
-            stmt.setString(1, user.getUsername());
-            stmt.setString(2, user.getPassword());
-            stmt.setString(3, user.getEmail());
-            stmt.setString(4, user.getRole());
-            stmt.executeUpdate();
+    public boolean addUser(String username, String password, String email, String role) {
+        String hashedPassword = BCrypt.hashpw(password, BCrypt.gensalt());
+        try (PreparedStatement stmt = prepare(ADD_USER)) {
+            stmt.setString(1, username);
+            stmt.setString(2, hashedPassword);
+            stmt.setString(3, email);
+            stmt.setString(4, role);
+
+            boolean success = stmt.executeUpdate() > 0;
+            if (success) {
+                logger.info("User '{}' added successfully with role '{}'.", username, role);
+            } else {
+                logger.warn("Failed to add user '{}'.", username);
+            }
+            return success;
+        } catch (Exception e) {
+            logger.error("Exception while adding user '{}': {}", username, e.getMessage(), e);
+            return false;
         }
     }
 
     @Override
-    public User getUserById(int userID) throws SQLException {
-        String sql = "SELECT * FROM user WHERE userID = ?";
-        try (Connection conn = DBConnection.getConnection();
-             PreparedStatement stmt = conn.prepareStatement(sql)) {
+    public boolean authenticateAdmin(String username, String password) {
+        try (PreparedStatement stmt = prepare(AUTH_ADMIN)) {
+            stmt.setString(1, username);
+            ResultSet rs = stmt.executeQuery();
+            if (rs.next()) {
+                String storedHash = rs.getString(PASSWORD);
+                String role = rs.getString(ROLE);
+                if (ADMIN.equals(role) && BCrypt.checkpw(password, storedHash)) {
+                    return true;
+                }
+            }
+        } catch (Exception e) {
+            logger.error("Error authenticating admin '{}': {}", username, e.getMessage(), e);
+        }
+        return false;
+    }
+
+    @Override
+    public boolean resetPassword(String targetUsername, String newPassword) {
+        String hashedNewPassword = BCrypt.hashpw(newPassword, BCrypt.gensalt());
+        try (PreparedStatement stmt = prepare(RESET_PASS)) {
+            stmt.setString(1, hashedNewPassword);
+            stmt.setString(2, targetUsername);
+            int rowsAffected = stmt.executeUpdate();
+            if (rowsAffected > 0) {
+                logger.info("Password reset successful for user '{}'.", targetUsername);
+            } else {
+                logger.warn("Password reset failed for user '{}'.", targetUsername);
+            }
+            return rowsAffected > 0;
+        } catch (Exception e) {
+            logger.error("Error resetting password for '{}': {}", targetUsername, e.getMessage(), e);
+            return false;
+        }
+    }
+
+    @Override
+    public String authenticateAndGetRole(String username, String password) {
+        try (PreparedStatement stmt = prepare(AUTH_AND_ROLE)) {
+            stmt.setString(1, username);
+            ResultSet rs = stmt.executeQuery();
+            if (rs.next()) {
+                String storedHash = rs.getString(PASSWORD);
+                if (BCrypt.checkpw(password, storedHash)) {
+                    String role = rs.getString(ROLE);
+                    logger.info("User '{}' authenticated successfully with role '{}'.", username, role);
+                    return role;
+                }
+            }
+        } catch (Exception e) {
+            logger.error("Error during authentication for '{}': {}", username, e.getMessage(), e);
+        }
+        return null;
+    }
+
+    @Override
+    public User getUserById(int userID) {
+        try (PreparedStatement stmt = prepare(GET_BY_ID)) {
             stmt.setInt(1, userID);
             ResultSet rs = stmt.executeQuery();
             if (rs.next()) {
                 return extractUser(rs);
             }
+        } catch (Exception e) {
+            logger.error("Error fetching user by ID '{}': {}", userID, e.getMessage(), e);
         }
         return null;
     }
 
     @Override
-    public List<User> getAllUsers() throws SQLException {
+    public List<User> getAllUsers() {
         List<User> users = new ArrayList<>();
-        String query = "SELECT * FROM user";
-
-        try (Connection conn = DBConnection.getConnection();
-             Statement stmt = conn.createStatement();
-             ResultSet rs = stmt.executeQuery(query)) {
+        try (PreparedStatement stmt = prepare(GET_ALL_USERS);
+             ResultSet rs = stmt.executeQuery()) {
 
             while (rs.next()) {
-                User user = new User();
-                user.setUserID(rs.getInt("userID"));
-                user.setUsername(rs.getString("username"));
-                user.setEmail(rs.getString("email"));
-                user.setRole(rs.getString("role"));
-                users.add(user);
+                users.add(extractUser(rs));
             }
+        } catch (Exception e) {
+            logger.error("Error fetching all users: {}", e.getMessage(), e);
+            return Collections.emptyList();
         }
         return users;
     }
 
     @Override
-    public void updateUser(User user) throws SQLException {
-        String sql = "UPDATE user SET username = ?, password = ?, email = ?, role = ? WHERE userID = ?";
+    public void updateUser(User user) {
         try (Connection conn = DBConnection.getConnection();
-             PreparedStatement stmt = conn.prepareStatement(sql)) {
+             PreparedStatement stmt = conn.prepareStatement(UPDATE_USER)) {
             stmt.setString(1, user.getUsername());
             stmt.setString(2, user.getPassword());
             stmt.setString(3, user.getEmail());
             stmt.setString(4, user.getRole());
             stmt.setInt(5, user.getUserID());
             stmt.executeUpdate();
+            logger.info("Updated user '{}'.", user.getUsername());
+        } catch (Exception e) {
+            logger.error("Error updating user '{}': {}", user.getUsername(), e.getMessage(), e);
         }
     }
 
     @Override
-    public void deleteUser(int userID) throws SQLException {
-        String sql = "DELETE FROM user WHERE userID = ?";
-        try (Connection conn = DBConnection.getConnection();
-             PreparedStatement stmt = conn.prepareStatement(sql)) {
+    public boolean deleteUser(int userID) {
+        try (PreparedStatement stmt = prepare(DELETE_USER)) {
             stmt.setInt(1, userID);
-            stmt.executeUpdate();
+            int rows = stmt.executeUpdate();
+            if (rows > 0) {
+                logger.info("Deleted user with ID '{}'.", userID);
+            } else {
+                logger.warn("No user found to delete with ID '{}'.", userID);
+            }
+            return rows > 0;
+        } catch (Exception e) {
+            logger.error("Error deleting user with ID '{}': {}", userID, e.getMessage(), e);
+            return false;
+        }
+    }
+
+    private User extractUser(ResultSet rs) {
+        try {
+            return new User(
+                    rs.getInt(USER_ID),
+                    rs.getString(USERNAME),
+                    rs.getString(PASSWORD),
+                    rs.getString(EMAIL),
+                    rs.getString(ROLE)
+            );
+        } catch (Exception e) {
+            logger.error("Error extracting user from ResultSet: {}", e.getMessage(), e);
+            return null;
         }
     }
 
-    private User extractUser(ResultSet rs) throws SQLException {
-        return new User(
-                rs.getInt("userID"),
-                rs.getString("username"),
-                rs.getString("password"),
-                rs.getString("email"),
-                rs.getString("role")
-        );
+    public PreparedStatement prepare(String query) throws SQLException {
+        Connection conn = DBConnection.getConnection();
+        return conn.prepareStatement(query);
     }
 }
diff --git a/src/main/java/com/intern/sms/service/AuthService.java b/src/main/java/com/intern/sms/service/AuthService.java
deleted file mode 100644
index 4527ff4..0000000
--- a/src/main/java/com/intern/sms/service/AuthService.java
+++ /dev/null
@@ -1,14 +0,0 @@
-package com.intern.sms.service;
-
-import java.sql.SQLException;
-
-public interface AuthService {
-
-    boolean registerUser(String username, String password, String email, String role) throws SQLException;
-
-    boolean authenticateAdmin(String username, String password) throws SQLException;
-
-    boolean resetPassword(String adminUsername, String adminPassword, String targetUsername, String newPassword) throws SQLException;
-
-    String authenticateAndGetRole(String username, String password) throws SQLException;
-}
diff --git a/src/main/java/com/intern/sms/service/AuthServiceImpl.java b/src/main/java/com/intern/sms/service/AuthServiceImpl.java
deleted file mode 100644
index dac4007..0000000
--- a/src/main/java/com/intern/sms/service/AuthServiceImpl.java
+++ /dev/null
@@ -1,89 +0,0 @@
-package com.intern.sms.service;
-
-import org.mindrot.jbcrypt.BCrypt;
-import com.intern.sms.util.DBConnection;
-
-import java.sql.*;
-
-public class AuthServiceImpl implements AuthService {
-
-    // Hash the password before saving
-    @Override
-    public boolean registerUser(String username, String password, String email, String role) throws SQLException {
-        String hashedPassword = BCrypt.hashpw(password, BCrypt.gensalt());  // Hash the password
-        String query = "INSERT INTO user (username, password, email, role) VALUES (?, ?, ?, ?)";
-
-        try (Connection conn = DBConnection.getConnection();
-             PreparedStatement stmt = conn.prepareStatement(query)) {
-            stmt.setString(1, username);
-            stmt.setString(2, hashedPassword);  // Save the hashed password
-            stmt.setString(3, email);
-            stmt.setString(4, role);
-
-            return stmt.executeUpdate() > 0;
-        }
-    }
-
-    // Authenticate admin by checking admin credentials
-    @Override
-    public boolean authenticateAdmin(String username, String password) throws SQLException {
-        String query = "SELECT password, role FROM user WHERE username = ?";
-        try (Connection conn = DBConnection.getConnection();
-             PreparedStatement stmt = conn.prepareStatement(query)) {
-            stmt.setString(1, username);
-            ResultSet rs = stmt.executeQuery();
-
-            if (rs.next()) {
-                String storedHash = rs.getString("password");
-                String role = rs.getString("role");
-
-                // Check if the role is 'admin' and compare password
-                if ("admin".equals(role) && BCrypt.checkpw(password, storedHash)) {
-                    return true; // Admin authenticated successfully
-                }
-            }
-        }
-        return false; // Admin authentication failed
-    }
-
-    // Reset a user's password (only if admin is authenticated)
-    @Override
-    public boolean resetPassword(String adminUsername, String adminPassword, String targetUsername, String newPassword) throws SQLException {
-        // First, authenticate the admin user
-        if (!authenticateAdmin(adminUsername, adminPassword)) {
-            return false; // Admin authentication failed
-        }
-
-        // Hash the new password before storing it
-        String hashedNewPassword = BCrypt.hashpw(newPassword, BCrypt.gensalt());
-
-        // Update the target user's password
-        String updateQuery = "UPDATE user SET password = ? WHERE username = ?";
-        try (Connection conn = DBConnection.getConnection();
-             PreparedStatement stmt = conn.prepareStatement(updateQuery)) {
-            stmt.setString(1, hashedNewPassword);  // Set the hashed new password
-            stmt.setString(2, targetUsername);     // Target user's username
-
-            int rowsAffected = stmt.executeUpdate();
-            return rowsAffected > 0; // Return true if password reset was successful
-        }
-    }
-
-    @Override
-    public String authenticateAndGetRole(String username, String password) throws SQLException {
-        String query = "SELECT password, role FROM user WHERE username = ?";
-        try (Connection conn = DBConnection.getConnection();
-             PreparedStatement stmt = conn.prepareStatement(query)) {
-            stmt.setString(1, username);
-            ResultSet rs = stmt.executeQuery();
-
-            if (rs.next()) {
-                String storedHash = rs.getString("password");
-                if (BCrypt.checkpw(password, storedHash)) {
-                    return rs.getString("role"); // return role on successful match
-                }
-            }
-        }
-        return null;
-    }
-}
diff --git a/src/main/java/com/intern/sms/service/UserService.java b/src/main/java/com/intern/sms/service/UserService.java
new file mode 100644
index 0000000..b63ac5d
--- /dev/null
+++ b/src/main/java/com/intern/sms/service/UserService.java
@@ -0,0 +1,16 @@
+package com.intern.sms.service;
+
+import java.sql.SQLException;
+
+public interface UserService {
+
+    boolean registerUser(String username, String password, String email, String role);
+
+    boolean authenticateAdmin(String username, String password);
+
+    boolean resetPassword(String targetUsername, String newPassword);
+
+    String authenticateAndGetRole(String username, String password);
+
+    boolean deleteUser(int userID);
+}
diff --git a/src/main/java/com/intern/sms/service/UserServiceImpl.java b/src/main/java/com/intern/sms/service/UserServiceImpl.java
new file mode 100644
index 0000000..119d049
--- /dev/null
+++ b/src/main/java/com/intern/sms/service/UserServiceImpl.java
@@ -0,0 +1,35 @@
+package com.intern.sms.service;
+
+import com.intern.sms.dao.UserDAO;
+import com.intern.sms.dao.UserDAOimpl;
+
+public class UserServiceImpl implements UserService {
+    UserDAO userDAO = new UserDAOimpl();
+
+    // Hash the password before saving
+    @Override
+    public boolean registerUser(String username, String password, String email, String role) {
+        return userDAO.addUser(username, password, email, role);
+    }
+
+    // Authenticate admin by checking admin credentials
+    @Override
+    public boolean authenticateAdmin(String username, String password) {
+        return userDAO.authenticateAdmin(username, password);
+    }
+
+    // Reset a user's password (only if admin is authenticated)
+    @Override
+    public boolean resetPassword(String targetUsername, String newPassword) {
+        return userDAO.resetPassword(targetUsername, newPassword);
+    }
+
+    @Override
+    public String authenticateAndGetRole(String username, String password) {
+        return userDAO.authenticateAndGetRole(username, password);
+    }
+
+    public boolean deleteUser(int userID) {
+        return userDAO.deleteUser(userID);
+    }
+}
diff --git a/src/main/java/com/intern/sms/util/Constants.java b/src/main/java/com/intern/sms/util/Constants.java
new file mode 100644
index 0000000..4b8d57b
--- /dev/null
+++ b/src/main/java/com/intern/sms/util/Constants.java
@@ -0,0 +1,53 @@
+package com.intern.sms.util;
+
+import java.util.regex.Pattern;
+
+public class Constants {
+    //CLI
+    public static final String CHOOSE_OPTION = "Choose an option: ";
+    //REGEX
+    static final Pattern EMAIL_PATTERN = Pattern.compile("^[A-Za-z0-9+_.-]+@(.+)$");
+    static final Pattern ROLE_PATTERN = Pattern.compile("^(admin|teacher|student|parent)$", Pattern.CASE_INSENSITIVE);
+    // Validate below with Ashwini/Gursimran
+    public static final String TITLE_USER_MANAGEMENT = "User Management Menu";
+    public static final String[] OPTIONS_USER_MANAGEMENT = new String[]{"Login", "Sign Up", "Forgot Password", "Exit"};
+    public static final String TITLE_ADMIN = "Admin Dashboard";
+    public static final String[] OPTIONS_ADMIN = new String[]{"Manage Users", "Manage System Settings", "Logout"};
+    public static final String TITLE_MANAGE_USERS = "Manage Users";
+    public static final String[] OPTIONS_MANAGE_USERS = new String[]{"Add User", "View Users", "Delete User", "Back to Admin Dashboard"};
+    public static final String TITLE_TEACHER = "Teacher Dashboard";
+    public static final String[] OPTIONS_TEACHER = new String[]{"Manage Courses", "Mark Attendance", "Grade Students", "Logout"};
+    public static final String TITLE_STUDENT = "Student Dashboard";
+    public static final String[] OPTIONS_STUDENT =  new String[]{"View Courses", "Track Attendance", "View Grades", "Logout"};
+    public static final String TITLE_PARENT = "Parent Dashboard";
+    public static final String[] OPTIONS_PARENT = new String[]{"Monitor Student Progress", "Pay Fees", "Logout"};
+    //
+    public static final String CONTACT_ADMIN = "Contact Admin to sign up as an Administrator.";
+    public static final String ROLE_ADMIN = "admin";
+    public static final String ROLE_TEACHER = "teacher";
+    public static final String ROLE_STUDENT = "student";
+    public static final String ROLE_PARENT = "parent";
+    public static final String ROLE_UNKNOWN = "Unknown role.";
+    public static final String GREET_MESSAGE = "Login successful! Welcome, ";
+    public static final String LOG_OUT = "Logging out...";
+    public static final String BYE = "Goodbye!";
+    public static final String INVALID_CREDS = "Invalid credentials.";
+    public static final String INVALID_CHOICE = "Invalid choice.";
+    public static final String USERNAME_PROMPT = "Enter username: ";
+    public static final String PASSWORD_PROMPT = "Enter password: ";
+    public static final String EMAIL_PROMPT = "Enter email: ";
+    public static final String ROLE_PROMPT = "Enter role (admin/teacher/student/parent): ";
+    public static final String DELETE_ID_PROMPT = "Enter user ID to delete: ";
+    public static final String SUCCESS_ADD = "User added successfully!";
+    public static final String FAIL_ADD = "Failed to add user.";
+    public static final String SUCCESS_DEL = "User deleted successfully!";
+    public static final String FAIL_DEL = "Failed to delete user.";
+    public static final String SUCCESS_RESET = "Password reset successfully.";
+    public static final String FAIL_RESET = "Failed to reset password. Either admin auth failed or user not found.";
+    public static final String USER_ID = "userID";
+    public static final String USERNAME = "username";
+    public static final String EMAIL = "email";
+    public static final String PASSWORD = "password";
+    public static final String ROLE = "role";
+    public static final String ADMIN = "admin";
+}
diff --git a/src/main/java/com/intern/sms/util/DBConnection.java b/src/main/java/com/intern/sms/util/DBConnection.java
index 9188f83..3a469d6 100644
--- a/src/main/java/com/intern/sms/util/DBConnection.java
+++ b/src/main/java/com/intern/sms/util/DBConnection.java
@@ -1,28 +1,31 @@
 package com.intern.sms.util;
 
+import java.io.IOException;
 import java.io.InputStream;
 import java.sql.Connection;
 import java.sql.DriverManager;
-import java.sql.SQLException;
 import java.util.Properties;
 
+import static com.intern.sms.util.DBConstants.*;
+
 public class DBConnection {
-    public static Connection getConnection() throws SQLException {
+    public static Connection getConnection() {
         try (InputStream input = DBConnection.class.getClassLoader().getResourceAsStream("db_config.properties")) {
             if (input == null) {
-                throw new SQLException("db_config.properties not found in classpath");
+                throw new IOException(CONFIG_PATH_ERROR);
             }
 
             Properties props = new Properties();
             props.load(input);
 
-            String url = props.getProperty("db.url");
-            String user = props.getProperty("db.username");
-            String pass = props.getProperty("db.password");
+            String url = props.getProperty(DB_URL);
+            String user = props.getProperty(DB_USERNAME);
+            String pass = props.getProperty(DB_PASSWORD);
 
             return DriverManager.getConnection(url, user, pass);
         } catch (Exception e) {
-            throw new SQLException("Failed to load database configuration", e);
+            e.printStackTrace();
         }
+        return null;
     }
 }
diff --git a/src/main/java/com/intern/sms/util/DBConstants.java b/src/main/java/com/intern/sms/util/DBConstants.java
new file mode 100644
index 0000000..f66895b
--- /dev/null
+++ b/src/main/java/com/intern/sms/util/DBConstants.java
@@ -0,0 +1,17 @@
+package com.intern.sms.util;
+
+public class DBConstants {
+    public static final String CONFIG_PATH_ERROR = "db_config.properties not found in classpath";
+    public static final String DB_URL = "db.url";
+    public static final String DB_USERNAME = "db.username";
+    public static final String DB_PASSWORD = "db.password";
+
+    public static final String ADD_USER = "INSERT INTO user (username, password, email, role) VALUES (?, ?, ?, ?)";
+    public static final String AUTH_ADMIN = "SELECT password, role FROM user WHERE username = ?";
+    public static final String RESET_PASS = "UPDATE user SET password = ? WHERE username = ?";
+    public static final String AUTH_AND_ROLE = "SELECT password, role FROM user WHERE username = ?";
+    public static final String GET_BY_ID = "SELECT * FROM user WHERE userID = ?";
+    public static final String GET_ALL_USERS = "SELECT * FROM user";
+    public static final String UPDATE_USER = "UPDATE user SET username = ?, password = ?, email = ?, role = ? WHERE userID = ?";
+    public static final String DELETE_USER = "DELETE FROM user WHERE userID = ?";
+}
diff --git a/src/main/java/com/intern/sms/util/InputValidator.java b/src/main/java/com/intern/sms/util/InputValidator.java
new file mode 100644
index 0000000..e83a5ad
--- /dev/null
+++ b/src/main/java/com/intern/sms/util/InputValidator.java
@@ -0,0 +1,20 @@
+package com.intern.sms.util;
+
+import static com.intern.sms.util.Constants.*;
+
+public class InputValidator {
+
+    public static boolean isValidEmail(String email) {
+        if (email == null) return false;
+        return EMAIL_PATTERN.matcher(email).matches();
+    }
+
+    public static boolean isValidRole(String role) {
+        if (role == null) return false;
+        return ROLE_PATTERN.matcher(role).matches();
+    }
+
+    public static boolean isNonEmpty(String input) {
+        return input != null && !input.trim().isEmpty();
+    }
+}
diff --git a/src/main/java/com/intern/PrintDB.java b/src/main/java/com/intern/sms/util/PrintDB.java
similarity index 95%
rename from src/main/java/com/intern/PrintDB.java
rename to src/main/java/com/intern/sms/util/PrintDB.java
index c220143..0d4f8e7 100644
--- a/src/main/java/com/intern/PrintDB.java
+++ b/src/main/java/com/intern/sms/util/PrintDB.java
@@ -1,6 +1,4 @@
-package com.intern;
-
-import com.intern.sms.util.DBConnection;
+package com.intern.sms.util;
 
 import java.sql.*;
 import java.util.ArrayList;
diff --git a/src/main/java/com/intern/sms/view/ConsoleView.java b/src/main/java/com/intern/sms/view/ConsoleView.java
index 568de50..79bb30c 100644
--- a/src/main/java/com/intern/sms/view/ConsoleView.java
+++ b/src/main/java/com/intern/sms/view/ConsoleView.java
@@ -1,44 +1,278 @@
-// ConsoleView.java
 package com.intern.sms.view;
 
+import com.intern.sms.controller.UserController;
 import java.util.Scanner;
+import static com.intern.sms.util.Constants.*;
+import static com.intern.sms.util.InputValidator.isValidEmail;
+import static com.intern.sms.util.InputValidator.isValidRole;
 
 public class ConsoleView {
-    private final Scanner scanner = new Scanner(System.in);
-
+    private static final org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(ConsoleView.class);
+    private final UserController controller = new UserController();
+    Scanner sc;
     public void showMenu(String title, String[] options) {
+
         System.out.println("\n==== " + title + " ====");
         for (int i = 0; i < options.length; i++) {
             System.out.println((i + 1) + ". " + options[i]);
         }
-        System.out.print("Choose an option: ");
+        System.out.print(CHOOSE_OPTION);
+    }
+
+    public void mainMenu() {
+        sc = new Scanner(System.in);
+        while (true) {
+            showMenu(TITLE_USER_MANAGEMENT, OPTIONS_USER_MANAGEMENT);
+            int choice = getChoice();
+
+            try {
+                switch (choice) {
+                    case 1 -> login();
+                    case 2 -> signUp();
+                    case 3 -> forgotPassword();
+                    case 4 -> {
+                        showMessage(BYE);
+                        sc.close();
+                        return;
+                    }
+                    default -> showInvalidChoice();
+                }
+            } catch (Exception e) {
+                showMessage("Error: " + e.getMessage());
+            }
+        }
+    }
+
+    private void login() {
+        String username = prompt(USERNAME_PROMPT);
+        String password = prompt(PASSWORD_PROMPT);
+
+        String role = controller.login(username, password);
+
+        if (role == null) {
+            showMessage(INVALID_CREDS);
+            return;
+        }
+
+        showMessage(GREET_MESSAGE + username);
+
+        switch (role.toLowerCase()) {
+            case ROLE_ADMIN -> adminDashboard();
+            case ROLE_TEACHER -> teacherDashboard();
+            case ROLE_STUDENT -> studentDashboard();
+            case ROLE_PARENT -> parentDashboard();
+            default -> showMessage(ROLE_UNKNOWN);
+        }
+    }
+
+    private void adminDashboard() {
+        while (true) {
+            showMenu(TITLE_ADMIN, OPTIONS_ADMIN);
+            int choice = getChoice();
+            switch (choice) {
+                case 1 -> manageUsers();
+                case 2 -> manageSystemSettings();
+                case 3 -> {
+                    showLoggingOutMessage();
+                    return;
+                }
+                default -> showInvalidChoice();
+            }
+        }
+    }
+
+    private void manageUsers() {
+        while (true) {
+            showMenu(TITLE_MANAGE_USERS, OPTIONS_MANAGE_USERS);
+            int choice = getChoice();
+            switch (choice) {
+                case 1 -> addUser();
+                case 2 -> viewUsers();
+                case 3 -> deleteUser();
+                case 4 -> {
+                    return; // Back to Admin Dashboard
+                }
+                default -> showInvalidChoice();
+            }
+        }
+    }
+
+    private void addUser() {
+        String username = prompt(USERNAME_PROMPT);
+        String password = prompt(PASSWORD_PROMPT);
+        String email = prompt(EMAIL_PROMPT);
+        String role = prompt(ROLE_PROMPT);
+
+        String response = controller.addUser(username, password, email, role);
+        showMessage(response);
+    }
+
+    private void viewUsers() {
+        controller.viewUsers();
+    }
+
+    private void deleteUser() {
+        int userID = Integer.parseInt(prompt(DELETE_ID_PROMPT));
+        String response = controller.deleteUser(userID);
+        showMessage(response);
+    }
+
+    private void manageSystemSettings() {
+        showUnderDevelopment("Managing System Settings");
+    }
+
+    private void teacherDashboard() {
+        while (true) {
+            showMenu(TITLE_TEACHER, OPTIONS_TEACHER);
+            int choice = getChoice();
+            switch (choice) {
+                case 1 -> manageCourses();
+                case 2 -> markAttendance();
+                case 3 -> gradeStudents();
+                case 4 -> {
+                    showLoggingOutMessage();
+                    ;
+                    return;
+                }
+                default -> showInvalidChoice();
+            }
+        }
+    }
+
+    private void manageCourses() {
+        showUnderDevelopment("Managing courses");
+    }
+
+    private void markAttendance() {
+        showUnderDevelopment("Marking attendance");
+    }
+
+    private void gradeStudents() {
+        showUnderDevelopment("Grading students");
+    }
+
+    private void studentDashboard() {
+        while (true) {
+            showMenu(TITLE_STUDENT, OPTIONS_STUDENT);
+            int choice = getChoice();
+            switch (choice) {
+                case 1 -> viewCourses();
+                case 2 -> trackAttendance();
+                case 3 -> viewGrades();
+                case 4 -> {
+                    showLoggingOutMessage();
+                    ;
+                    return;
+                }
+                default -> showInvalidChoice();
+            }
+        }
+    }
+
+    private void viewCourses() {
+        showUnderDevelopment("Viewing courses");
+    }
+
+    private void trackAttendance() {
+        showUnderDevelopment("Tracking attendance");
+    }
+
+    private void viewGrades() {
+        showUnderDevelopment("Viewing grades");
+    }
+
+    private void parentDashboard() {
+        while (true) {
+            showMenu(TITLE_PARENT, OPTIONS_PARENT);
+            int choice = getChoice();
+            switch (choice) {
+                case 1 -> monitorStudentProgress();
+                case 2 -> payFees();
+                case 3 -> {
+                    showLoggingOutMessage();
+                    ;
+                    return;
+                }
+                default -> showInvalidChoice();
+            }
+        }
+    }
+
+    private void monitorStudentProgress() {
+        showUnderDevelopment("Monitoring student progress");
     }
 
+    private void payFees() {
+        showUnderDevelopment("Paying fees");
+    }
+
+    private void signUp() {
+        String username = prompt(USERNAME_PROMPT);
+        String password = prompt(PASSWORD_PROMPT);
+        String email;
+        do {
+            email = prompt(EMAIL_PROMPT);
+            if (!isValidEmail(email)) {
+                showMessage("Invalid email format. Please try again.");
+            }
+        } while (!isValidEmail(email));
+        String role;
+        do {
+            role = prompt(ROLE_PROMPT);
+            if (!isValidRole(role)) {
+                showMessage("Invalid role. Please enter one of: admin, teacher, student, parent.");
+            }
+        } while (!isValidRole(role));
+        if (role.equals(ROLE_ADMIN)) {
+            prompt(CONTACT_ADMIN);
+        }
+        boolean registered = controller.signUp(username, password, email, role);
+        showMessage(registered ? SUCCESS_ADD : FAIL_ADD);
+    }
+
+    private void forgotPassword() {
+        showMessage("\n--- Admin Authentication ---");
+        String adminUsername = prompt(USERNAME_PROMPT);
+        String adminPassword = prompt(PASSWORD_PROMPT);
+        String role = controller.login(adminUsername, adminPassword);
+        if (role.equals(ROLE_ADMIN)) {
+            String targetUsername = prompt("Enter username of user to reset password: ");
+            String newPassword = prompt("Enter new password for " + targetUsername + ": ");
+            boolean reset = controller.forgotPassword(targetUsername, newPassword);
+            showMessage(reset ? SUCCESS_RESET : FAIL_RESET);
+        }
+    }
 
     public void showLoggingOutMessage() {
-        System.out.println("Logging out...");
+        showMessage(LOG_OUT);
     }
 
     public void showInvalidChoice() {
-        System.out.println("Invalid choice.");
+        showMessage(INVALID_CHOICE);
     }
 
     public void showUnderDevelopment(String featureName) {
-        System.out.println(featureName + " functionality is under development.");
+        showMessage(featureName + " functionality is under development.");
     }
 
     public int getChoice() {
-        int choice = scanner.nextInt();
-        scanner.nextLine(); // consume newline
-        return choice;
+        while (true) {
+            try {
+                logger.info("Enter choice: ");
+                return Integer.parseInt(sc.nextLine().trim());
+            } catch (NumberFormatException e) {
+                logger.warn("Invalid input received. Expected a number.");
+                logger.info("Please enter a valid number: ");
+            }
+        }
     }
 
     public String prompt(String message) {
-        System.out.print(message);
-        return scanner.nextLine();
+        logger.info(message);
+        return sc.nextLine();
     }
 
     public void showMessage(String message) {
-        System.out.println(message);
+        logger.info(message);
     }
 }
diff --git a/src/main/java/com/intern/sms/service/db.sql b/src/main/resources/db.sql
similarity index 99%
rename from src/main/java/com/intern/sms/service/db.sql
rename to src/main/resources/db.sql
index aa4c555..dda93d3 100644
--- a/src/main/java/com/intern/sms/service/db.sql
+++ b/src/main/resources/db.sql
@@ -1,4 +1,4 @@
-Alter TABLE User (
+CREATE TABLE User (
                       userID INT PRIMARY KEY AUTO_INCREMENT,
                       username VARCHAR(50) NOT NULL UNIQUE,
                       password VARCHAR(100) NOT NULL,
diff --git a/src/main/resources/logback.xml b/src/main/resources/logback.xml
new file mode 100644
index 0000000..39360fd
--- /dev/null
+++ b/src/main/resources/logback.xml
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<configuration>
+
+    <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
+        <encoder>
+            <pattern>%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n</pattern>
+        </encoder>
+    </appender>
+
+    <root level="info">
+        <appender-ref ref="CONSOLE" />
+    </root>
+
+</configuration>
diff --git a/src/test/java/com/intern/sms/dao/UserDAOimplTest.java b/src/test/java/com/intern/sms/dao/UserDAOimplTest.java
new file mode 100644
index 0000000..81d99ae
--- /dev/null
+++ b/src/test/java/com/intern/sms/dao/UserDAOimplTest.java
@@ -0,0 +1,104 @@
+package com.intern.sms.dao;
+
+import com.intern.sms.model.User;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.Test;
+import org.mindrot.jbcrypt.BCrypt;
+
+import java.util.List;
+import static org.junit.jupiter.api.Assertions.*;
+
+class UserDAOimplTest {
+
+    UserDAO dao = new UserDAOimpl();
+
+    @BeforeAll
+    static void setUp() {
+        UserDAO dao = new UserDAOimpl();
+        boolean res;
+        if (dao.getUserById(1)==null) {
+        res = dao.addUser("admin",encrypt("123456"), "admin@sms.com", "admin");
+        assertTrue(res);}
+    }
+
+    public static String encrypt(String password) {
+        return BCrypt.hashpw(password, BCrypt.gensalt());
+    }
+
+    @Test
+    void addUser() {
+        boolean res;
+
+        res = dao.addUser("test",encrypt("test"), "", "parent");
+        assertTrue(res);
+
+        res = dao.addUser("Test 1",encrypt("test"), "admin@sms.com", "admin");
+        assertFalse(res);
+
+        res = dao.addUser("Test 1",encrypt("test"), "", "admin");
+        assertFalse(res);
+    }
+
+    @Test
+    void authenticateAdmin() {
+        boolean res;
+        res = dao.authenticateAdmin("admin",encrypt("123456"));
+        assertTrue(res);
+
+//        res = dao.authenticateAdmin("admin",encrypt("admin"));
+//        assertFalse(res);
+    }
+
+    @Test
+    void resetPassword() {
+        boolean res;
+        res = dao.resetPassword("test",encrypt("TEST"));
+        assertTrue(res);
+        String role = dao.authenticateAndGetRole("test",encrypt("TEST"));
+        assertEquals("parent", role);
+
+    }
+
+    @Test
+     void authenticateAndGetRole() {
+        String role = dao.authenticateAndGetRole("admin", encrypt("123456"));
+        assertEquals("admin",role);
+
+        role = dao.authenticateAndGetRole("admin", encrypt("wrongpassword"));
+        assertNotEquals("admin",role);
+    }
+
+    @Test
+    void getUserById() {
+        User test = dao.getUserById(1);
+        assertEquals("admin", test.getUsername());
+
+        test = dao.getUserById(1);
+        assertNotEquals("test", test.getUsername());
+    }
+
+    @Test
+    void getAllUsers() {
+        List<User> users = dao.getAllUsers();
+        assertEquals("admin",users.getFirst().getUsername());
+    }
+
+    @Test
+    void updateUser() {
+        User test = new User(1, "admin",encrypt("123456"),"admin_updated@sms.com", "admin");
+        dao.updateUser(test);
+
+        boolean res = dao.authenticateAdmin("admin",encrypt("admin"));
+        assertTrue(res);
+
+        test.setUsername("admin_updated@sms.com");
+        res = dao.authenticateAdmin("admin",encrypt("admin"));
+        assertTrue(res);
+    }
+
+    @Test
+    void deleteUser() {
+        boolean res = dao.deleteUser(2);
+        assertTrue(res);
+    }
+}
\ No newline at end of file
diff --git a/src/test/java/com/intern/sms/service/UserServiceImplTest.java b/src/test/java/com/intern/sms/service/UserServiceImplTest.java
new file mode 100644
index 0000000..1c06aae
--- /dev/null
+++ b/src/test/java/com/intern/sms/service/UserServiceImplTest.java
@@ -0,0 +1,58 @@
+package com.intern.sms.service;
+
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+class UserServiceImplTest {
+
+    UserServiceImpl userService = new UserServiceImpl();
+
+    @BeforeEach
+    void setUp() {
+
+    }
+
+    @Test
+    void registerUser() {
+        boolean success;
+//        boolean success = userService.registerUser("UserA", "password", "userA@sms.com", "student" );
+//        assertTrue(success);
+
+        success = userService.registerUser("UserB", "password", "userA@sms.com", "student" );
+        assertFalse(success);
+    }
+
+    @Test
+    void authenticateAdmin() {
+        boolean success = userService.authenticateAdmin("admin", "123456");
+        assertTrue(success);
+
+        success = userService.authenticateAdmin("admin", "password");
+        assertFalse(success);
+    }
+
+    @Test
+    void resetPassword() {
+        boolean success = userService.resetPassword("admin", "123456");
+        assertTrue(success);
+
+        success = userService.resetPassword("admin1", "password");
+        assertFalse(success);
+    }
+
+    @Test
+    void authenticateAndGetRole() {
+        String role;
+        role = userService.authenticateAndGetRole("userA", "password");
+        assertEquals("student", role);
+    }
+
+    @Test
+    void deleteUser() {
+        boolean success = userService.deleteUser(2);
+        assertTrue(success);
+    }
+}
\ No newline at end of file


Reviews:
user: login: copilot-pull-request-reviewer[bot]
body: ## Pull Request Overview

This PR refactors the flow of the application by streamlining user interactions from view to DAO and removing the legacy AuthService implementation. Key changes include:
- Replacing AuthService with a unified UserService in controllers and DAOs.
- Updating exception handling and return types in database and DAO methods.
- Improving the ConsoleView to support new navigation flows and test capabilities.

### Reviewed Changes

Copilot reviewed 13 out of 14 changed files in this pull request and generated 2 comments.

<details>
<summary>Show a summary per file</summary>

| File | Description |
| ---- | ----------- |
| src/test/java/com/intern/sms/dao/UserDAOimplTest.java | Added test stubs for DAO functionality. |
| src/main/java/com/intern/sms/view/ConsoleView.java | Updated menu and input handling, with refactored user flows. |
| src/main/java/com/intern/sms/util/DBConnection.java | Adjusted exception handling and return type. |
| src/main/java/com/intern/sms/service/* | Refactored user service to remove the legacy AuthService and streamline calls. |
| src/main/java/com/intern/sms/dao/UserDAOimpl.java | Modified DAO methods to return boolean values and updated error handling. |
| src/main/java/com/intern/sms/controller/UserController.java | Refactored methods to use UserService and simplified flow. |
| src/main/java/com/intern/sms/app/App.java | Adjusted main application entry point to use ConsoleView. |
</details>


<details>
<summary>Files not reviewed (1)</summary>

* **pom.xml**: Language not supported
</details>

<details>
<summary>Comments suppressed due to low confidence (1)</summary>

**src/main/java/com/intern/sms/view/ConsoleView.java:1**
* [nitpick] The file comment appears to have a typo; it might be intended to read 'ConsoleView.java'.
```
+// Consolejava
```
</details>


state: COMMENTED
author_association: NONE
submitted_at: 2025-04-24T08:38:47Z
user: login: Fiend-Star
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-24T08:53:35Z
user: login: Fiend-Star
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-24T08:54:43Z
user: login: Fiend-Star
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-24T08:55:29Z
user: login: Fiend-Star
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-24T08:56:09Z
user: login: Fiend-Star
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-24T08:57:00Z
user: login: Fiend-Star
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-24T08:57:34Z
user: login: Fiend-Star
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-24T08:58:01Z
user: login: Fiend-Star
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-24T08:58:48Z
user: login: Fiend-Star
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-24T09:01:39Z
user: login: Fiend-Star
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-24T09:02:10Z
user: login: Fiend-Star
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-24T09:02:57Z
user: login: Fiend-Star
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-24T09:03:36Z
user: login: Fiend-Star
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-24T09:04:37Z
user: login: Fiend-Star
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-24T09:07:11Z
user: login: itsfazalkhan
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-25T05:12:41Z
user: login: itsfazalkhan
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-25T05:13:42Z
user: login: itsfazalkhan
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-25T05:16:41Z
user: login: copilot-pull-request-reviewer[bot]
body: ## Pull Request Overview

This PR refactors the application’s flow by streamlining the path from the user interface through the controller, service, DAO, and DB layers while removing the redundant AuthService layer. Key changes include the introduction of new test stubs, updates to DAO and service method signatures to handle exceptions internally, and modifications to the controller and view for a more cohesive structure.

### Reviewed Changes

Copilot reviewed 13 out of 14 changed files in this pull request and generated 2 comments.

<details>
<summary>Show a summary per file</summary>

| File                                      | Description                                                                                    |
| ----------------------------------------- | ---------------------------------------------------------------------------------------------- |
| src/test/java/com/intern/sms/dao/UserDAOimplTest.java | Added basic unit tests for UserDAO methods.                                                  |
| src/main/java/com/intern/sms/view/ConsoleView.java         | Updated the UI flow and refactored method implementations (including forgotPassword).          |
| src/main/java/com/intern/sms/util/PrintDB.java              | Adjusted package declaration.                                                                  |
| src/main/java/com/intern/sms/util/DBConnection.java         | Refactored exception handling; now returns null on failure instead of throwing exceptions.      |
| src/main/java/com/intern/sms/service/*.java                 | Introduced service abstraction for user operations, replacing AuthService.                     |
| src/main/java/com/intern/sms/dao/UserDAOimpl.java            | Revised method signatures and exception handling; return values refactored for better flow.      |
| src/main/java/com/intern/sms/controller/UserController.java  | Updated controller logic to integrate with the new service layer and UI changes.               |
| src/main/java/com/intern/sms/app/App.java & Main.java        | Adjusted application startup to call the new UI mainMenu.                                       |
</details>


<details>
<summary>Files not reviewed (1)</summary>

* **pom.xml**: Language not supported
</details>

<details>
<summary>Comments suppressed due to low confidence (1)</summary>

**src/test/java/com/intern/sms/dao/UserDAOimplTest.java:7**
* [nitpick] Consider renaming the class to 'UserDAOImplTest' to follow standard Java naming conventions for implementation classes.
```
class UserDAOimplTest {
```
</details>


state: COMMENTED
author_association: NONE
submitted_at: 2025-04-25T06:18:46Z
user: login: itsfazalkhan
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-25T06:52:31Z
user: login: Fiend-Star
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-25T22:55:01Z
user: login: itsfazalkhan
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-26T05:58:51Z
user: login: OlixIgnacious
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-26T18:44:07Z

Review comments:
diff_hunk: @@ -22,7 +23,8 @@ public static Connection getConnection() throws SQLException {
 
             return DriverManager.getConnection(url, user, pass);
         } catch (Exception e) {
-            throw new SQLException("Failed to load database configuration", e);
+            e.printStackTrace();
+            return null;
path: src/main/java/com/intern/sms/util/DBConnection.java
user: login: Copilot
body: Returning null from getConnection() may lead to NullPointerExceptions in the calling code. Consider propagating the exception or handling the null case appropriately.
```suggestion
            throw new RuntimeException("Failed to establish database connection", e);
```
created_at: 2025-04-24T08:38:46Z
author_association: NONE
diff_hunk: @@ -68,26 +145,37 @@ public void updateUser(User user) throws SQLException {
             stmt.setString(4, user.getRole());
             stmt.setInt(5, user.getUserID());
             stmt.executeUpdate();
+        } catch (Exception e) {
+            e.printStackTrace();
         }
     }
 
     @Override
-    public void deleteUser(int userID) throws SQLException {
+    public boolean deleteUser(int userID) {
         String sql = "DELETE FROM user WHERE userID = ?";
         try (Connection conn = DBConnection.getConnection();
              PreparedStatement stmt = conn.prepareStatement(sql)) {
             stmt.setInt(1, userID);
             stmt.executeUpdate();
+        } catch (Exception e) {
+            e.printStackTrace();
+            return false;
         }
+        return false;
path: src/main/java/com/intern/sms/dao/UserDAOimpl.java
user: login: Copilot
body: The deleteUser() method always returns false even after a successful deletion. Change the final return to true when no exception is thrown.
created_at: 2025-04-24T08:38:46Z
author_association: NONE
diff_hunk: @@ -1,11 +1,11 @@
 package com.intern.sms.app;
 
-import com.intern.sms.controller.UserController;
+import com.intern.sms.view.ConsoleView;
 
 public class App {
     //starting the app
path: src/main/java/com/intern/sms/app/App.java
user: login: Fiend-Star
body: This comment isn't required

created_at: 2025-04-24T08:53:35Z
author_association: CONTRIBUTOR
diff_hunk: @@ -2,28 +2,99 @@
 
 import com.intern.sms.util.DBConnection;
 import com.intern.sms.model.User;
-
+import org.mindrot.jbcrypt.BCrypt;
 import java.sql.*;
 import java.util.ArrayList;
 import java.util.List;
 
 public class UserDAOimpl implements UserDAO {
 
     @Override
-    public void addUser(User user) throws SQLException {
-        String sql = "INSERT INTO user (username, password, email, role) VALUES (?, ?, ?, ?)";
+    public boolean addUser(String username, String password, String email, String role) {
+        String hashedPassword = BCrypt.hashpw(password, BCrypt.gensalt());  // Hash the password
+        String query = "INSERT INTO user (username, password, email, role) VALUES (?, ?, ?, ?)";
+
         try (Connection conn = DBConnection.getConnection();
-             PreparedStatement stmt = conn.prepareStatement(sql)) {
-            stmt.setString(1, user.getUsername());
-            stmt.setString(2, user.getPassword());
-            stmt.setString(3, user.getEmail());
-            stmt.setString(4, user.getRole());
-            stmt.executeUpdate();
+             PreparedStatement stmt = conn.prepareStatement(query)) {
+            stmt.setString(1, username);
+            stmt.setString(2, hashedPassword);  // Save the hashed password
path: src/main/java/com/intern/sms/dao/UserDAOimpl.java
user: login: Fiend-Star
body: Comment isn't required here
created_at: 2025-04-24T08:54:43Z
author_association: CONTRIBUTOR
diff_hunk: @@ -2,28 +2,99 @@
 
 import com.intern.sms.util.DBConnection;
 import com.intern.sms.model.User;
-
+import org.mindrot.jbcrypt.BCrypt;
 import java.sql.*;
 import java.util.ArrayList;
 import java.util.List;
 
 public class UserDAOimpl implements UserDAO {
 
     @Override
-    public void addUser(User user) throws SQLException {
-        String sql = "INSERT INTO user (username, password, email, role) VALUES (?, ?, ?, ?)";
+    public boolean addUser(String username, String password, String email, String role) {
+        String hashedPassword = BCrypt.hashpw(password, BCrypt.gensalt());  // Hash the password
+        String query = "INSERT INTO user (username, password, email, role) VALUES (?, ?, ?, ?)";
+
         try (Connection conn = DBConnection.getConnection();
path: src/main/java/com/intern/sms/dao/UserDAOimpl.java
user: login: Fiend-Star
body: is DBConnection auto closeable resource or do we need to add finally in the try catch here?
created_at: 2025-04-24T08:55:29Z
author_association: CONTRIBUTOR
diff_hunk: @@ -2,28 +2,99 @@
 
 import com.intern.sms.util.DBConnection;
 import com.intern.sms.model.User;
-
+import org.mindrot.jbcrypt.BCrypt;
 import java.sql.*;
 import java.util.ArrayList;
 import java.util.List;
 
 public class UserDAOimpl implements UserDAO {
 
     @Override
-    public void addUser(User user) throws SQLException {
-        String sql = "INSERT INTO user (username, password, email, role) VALUES (?, ?, ?, ?)";
+    public boolean addUser(String username, String password, String email, String role) {
+        String hashedPassword = BCrypt.hashpw(password, BCrypt.gensalt());  // Hash the password
+        String query = "INSERT INTO user (username, password, email, role) VALUES (?, ?, ?, ?)";
+
         try (Connection conn = DBConnection.getConnection();
-             PreparedStatement stmt = conn.prepareStatement(sql)) {
-            stmt.setString(1, user.getUsername());
-            stmt.setString(2, user.getPassword());
-            stmt.setString(3, user.getEmail());
-            stmt.setString(4, user.getRole());
-            stmt.executeUpdate();
+             PreparedStatement stmt = conn.prepareStatement(query)) {
+            stmt.setString(1, username);
+            stmt.setString(2, hashedPassword);  // Save the hashed password
+            stmt.setString(3, email);
+            stmt.setString(4, role);
+
+            return stmt.executeUpdate() > 0;
+        }
+        catch (Exception e) {
+            e.printStackTrace();
+            return false;
+        }
+    }
+
+    public boolean authenticateAdmin(String username, String password){
+        String query = "SELECT password, role FROM user WHERE username = ?";
+        try (Connection conn = DBConnection.getConnection();
path: src/main/java/com/intern/sms/dao/UserDAOimpl.java
user: login: Fiend-Star
body: is DBConnection auto closeable resource or do we need to add finally in the try catch here?
created_at: 2025-04-24T08:56:09Z
author_association: CONTRIBUTOR
diff_hunk: @@ -32,12 +103,15 @@ public User getUserById(int userID) throws SQLException {
             if (rs.next()) {
                 return extractUser(rs);
             }
+        } catch (Exception e) {
+            e.printStackTrace();
+            return null;
path: src/main/java/com/intern/sms/dao/UserDAOimpl.java
user: login: Fiend-Star
body: Why are we returning Null?
created_at: 2025-04-24T08:57:00Z
author_association: CONTRIBUTOR
diff_hunk: @@ -32,12 +103,15 @@ public User getUserById(int userID) throws SQLException {
             if (rs.next()) {
                 return extractUser(rs);
             }
+        } catch (Exception e) {
+            e.printStackTrace();
+            return null;
         }
         return null;
     }
 
     @Override
-    public List<User> getAllUsers() throws SQLException {
+    public List<User> getAllUsers() {
         List<User> users = new ArrayList<>();
         String query = "SELECT * FROM user";
path: src/main/java/com/intern/sms/dao/UserDAOimpl.java
user: login: Fiend-Star
body: Move All the sql queries to a constants file and the other hardcoded strings as well
created_at: 2025-04-24T08:57:34Z
author_association: CONTRIBUTOR
diff_hunk: @@ -53,12 +127,15 @@ public List<User> getAllUsers() throws SQLException {
                 user.setRole(rs.getString("role"));
                 users.add(user);
             }
+        } catch (Exception e) {
+            e.printStackTrace();
path: src/main/java/com/intern/sms/dao/UserDAOimpl.java
user: login: Fiend-Star
body: log the error instead of printStacktrace via loggers (for all instances)
created_at: 2025-04-24T08:58:01Z
author_association: CONTRIBUTOR
diff_hunk: @@ -1,16 +1,17 @@
 package com.intern.sms.util;
 
+import java.io.IOException;
 import java.io.InputStream;
 import java.sql.Connection;
 import java.sql.DriverManager;
 import java.sql.SQLException;
 import java.util.Properties;
 
 public class DBConnection {
-    public static Connection getConnection() throws SQLException {
+    public static Connection getConnection() {
         try (InputStream input = DBConnection.class.getClassLoader().getResourceAsStream("db_config.properties")) {
path: src/main/java/com/intern/sms/util/DBConnection.java
user: login: Fiend-Star
body: move the file name string to its own constant
created_at: 2025-04-24T08:58:48Z
author_association: CONTRIBUTOR
diff_hunk: @@ -1,41 +1,255 @@
-// ConsoleView.java
+// Consolejava
 package com.intern.sms.view;
 
+import com.intern.sms.controller.UserController;
+
 import java.util.Scanner;
 
 public class ConsoleView {
-    private final Scanner scanner = new Scanner(System.in);
-
+    private final UserController controller = new UserController();
+    Scanner sc;
     public void showMenu(String title, String[] options) {
+
         System.out.println("\n==== " + title + " ====");
         for (int i = 0; i < options.length; i++) {
             System.out.println((i + 1) + ". " + options[i]);
         }
         System.out.print("Choose an option: ");
     }
 
+    public void mainMenu() {
+        sc = new Scanner(System.in);
+        while (true) {
+            showMenu("User Management Menu", new String[]{"Login", "Sign Up", "Forgot Password", "Exit"});
+            int choice = getChoice();
+
+            try {
+                switch (choice) {
+                    case 1 -> login();
+                    case 2 -> signUp();
+                    case 3 -> forgotPassword();
+                    case 4 -> {
+                        showMessage("Goodbye!");
path: src/main/java/com/intern/sms/view/ConsoleView.java
user: login: Fiend-Star
body: close scanner at this point?
created_at: 2025-04-24T09:01:39Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,43 @@
+package com.intern.sms.dao;
+
+import org.junit.jupiter.api.Test;
+import org.junit.platform.commons.annotation.Testable;
+
+import static org.junit.jupiter.api.Assertions.*;
+class UserDAOimplTest {
+
+    @org.junit.jupiter.api.Test
+    void addUser() {
+    }
+
+    @org.junit.jupiter.api.Test
+    void authenticateAdmin() {
+    }
+
+    @org.junit.jupiter.api.Test
+    void resetPassword() {
+    }
+
+    @Testable
+     void authenticateAndGetRole() {
+        UserDAO userDAO = new UserDAOimpl();
+        String role = userDAO.authenticateAndGetRole("admin", "123456");
+        assertNotNull(role);
+    }
+
+    @org.junit.jupiter.api.Test
path: src/test/java/com/intern/sms/dao/UserDAOimplTest.java
user: login: Fiend-Star
body: use @Test instead of @org.junit.jupiter.api.Test
created_at: 2025-04-24T09:02:10Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,35 @@
+package com.intern.sms.service;
+
+import com.intern.sms.dao.UserDAO;
+import com.intern.sms.dao.UserDAOimpl;
+
+public class UserServiceImpl implements UserService {
+    UserDAO userDAO = new UserDAOimpl();
+
+    // Hash the password before saving
+    @Override
+    public boolean registerUser(String username, String password, String email, String role) {
+        return userDAO.addUser(username, password, email, role);
+    }
+
+    // Authenticate admin by checking admin credentials
+    @Override
+    public boolean authenticateAdmin(String username, String password) {
+        return userDAO.authenticateAdmin(username, password);
+    }
path: src/main/java/com/intern/sms/service/UserServiceImpl.java
user: login: Fiend-Star
body: Use proper way to comment
```
/**
* comment
*/
```
created_at: 2025-04-24T09:02:57Z
author_association: CONTRIBUTOR
diff_hunk: @@ -68,26 +145,37 @@ public void updateUser(User user) throws SQLException {
             stmt.setString(4, user.getRole());
             stmt.setInt(5, user.getUserID());
             stmt.executeUpdate();
+        } catch (Exception e) {
+            e.printStackTrace();
         }
     }
 
     @Override
-    public void deleteUser(int userID) throws SQLException {
+    public boolean deleteUser(int userID) {
         String sql = "DELETE FROM user WHERE userID = ?";
         try (Connection conn = DBConnection.getConnection();
              PreparedStatement stmt = conn.prepareStatement(sql)) {
             stmt.setInt(1, userID);
             stmt.executeUpdate();
+        } catch (Exception e) {
+            e.printStackTrace();
+            return false;
         }
+        return false;
     }
 
-    private User extractUser(ResultSet rs) throws SQLException {
-        return new User(
-                rs.getInt("userID"),
-                rs.getString("username"),
-                rs.getString("password"),
-                rs.getString("email"),
-                rs.getString("role")
-        );
+    private User extractUser(ResultSet rs) {
+        try {
+            return new User(
+                    rs.getInt("userID"),
+                    rs.getString("username"),
path: src/main/java/com/intern/sms/dao/UserDAOimpl.java
user: login: Fiend-Star
body: use meaningful naming
created_at: 2025-04-24T09:03:35Z
author_association: CONTRIBUTOR
diff_hunk: @@ -68,26 +145,37 @@ public void updateUser(User user) throws SQLException {
             stmt.setString(4, user.getRole());
             stmt.setInt(5, user.getUserID());
             stmt.executeUpdate();
+        } catch (Exception e) {
+            e.printStackTrace();
         }
     }
 
     @Override
-    public void deleteUser(int userID) throws SQLException {
+    public boolean deleteUser(int userID) {
         String sql = "DELETE FROM user WHERE userID = ?";
         try (Connection conn = DBConnection.getConnection();
path: src/main/java/com/intern/sms/dao/UserDAOimpl.java
user: login: Fiend-Star
body: use meaningful variable names
some examples
: sql-> query
conn-> connection
stmt -> statement?


created_at: 2025-04-24T09:04:37Z
author_association: CONTRIBUTOR
diff_hunk: @@ -68,26 +145,37 @@ public void updateUser(User user) throws SQLException {
             stmt.setString(4, user.getRole());
             stmt.setInt(5, user.getUserID());
             stmt.executeUpdate();
+        } catch (Exception e) {
+            e.printStackTrace();
         }
     }
 
     @Override
-    public void deleteUser(int userID) throws SQLException {
+    public boolean deleteUser(int userID) {
         String sql = "DELETE FROM user WHERE userID = ?";
         try (Connection conn = DBConnection.getConnection();
path: src/main/java/com/intern/sms/dao/UserDAOimpl.java
user: login: Fiend-Star
body: Or move two lines in every try method to another method that handles a string query.
created_at: 2025-04-24T09:07:11Z
author_association: CONTRIBUTOR
diff_hunk: @@ -2,28 +2,99 @@
 
 import com.intern.sms.util.DBConnection;
 import com.intern.sms.model.User;
-
+import org.mindrot.jbcrypt.BCrypt;
 import java.sql.*;
 import java.util.ArrayList;
 import java.util.List;
 
 public class UserDAOimpl implements UserDAO {
 
     @Override
-    public void addUser(User user) throws SQLException {
-        String sql = "INSERT INTO user (username, password, email, role) VALUES (?, ?, ?, ?)";
+    public boolean addUser(String username, String password, String email, String role) {
+        String hashedPassword = BCrypt.hashpw(password, BCrypt.gensalt());  // Hash the password
+        String query = "INSERT INTO user (username, password, email, role) VALUES (?, ?, ?, ?)";
+
         try (Connection conn = DBConnection.getConnection();
path: src/main/java/com/intern/sms/dao/UserDAOimpl.java
user: login: itsfazalkhan
body: `try-with-resource` ensures that each resource is closed at the end of the statement. Any object that implements `java.lang.AutoCloseable`

Connection and PreparedStatement implements `AutoClosable` interface

created_at: 2025-04-25T05:12:41Z
author_association: CONTRIBUTOR
diff_hunk: @@ -2,28 +2,99 @@
 
 import com.intern.sms.util.DBConnection;
 import com.intern.sms.model.User;
-
+import org.mindrot.jbcrypt.BCrypt;
 import java.sql.*;
 import java.util.ArrayList;
 import java.util.List;
 
 public class UserDAOimpl implements UserDAO {
 
     @Override
-    public void addUser(User user) throws SQLException {
-        String sql = "INSERT INTO user (username, password, email, role) VALUES (?, ?, ?, ?)";
+    public boolean addUser(String username, String password, String email, String role) {
+        String hashedPassword = BCrypt.hashpw(password, BCrypt.gensalt());  // Hash the password
+        String query = "INSERT INTO user (username, password, email, role) VALUES (?, ?, ?, ?)";
+
         try (Connection conn = DBConnection.getConnection();
-             PreparedStatement stmt = conn.prepareStatement(sql)) {
-            stmt.setString(1, user.getUsername());
-            stmt.setString(2, user.getPassword());
-            stmt.setString(3, user.getEmail());
-            stmt.setString(4, user.getRole());
-            stmt.executeUpdate();
+             PreparedStatement stmt = conn.prepareStatement(query)) {
+            stmt.setString(1, username);
+            stmt.setString(2, hashedPassword);  // Save the hashed password
+            stmt.setString(3, email);
+            stmt.setString(4, role);
+
+            return stmt.executeUpdate() > 0;
+        }
+        catch (Exception e) {
+            e.printStackTrace();
+            return false;
+        }
+    }
+
+    public boolean authenticateAdmin(String username, String password){
+        String query = "SELECT password, role FROM user WHERE username = ?";
+        try (Connection conn = DBConnection.getConnection();
path: src/main/java/com/intern/sms/dao/UserDAOimpl.java
user: login: itsfazalkhan
body: `try-with-resource` ensures that each resource is closed at the end of the statement. Any object that implements `java.lang.AutoCloseable`

Connection and PreparedStatement implements `AutoClosable` interface
created_at: 2025-04-25T05:13:41Z
author_association: CONTRIBUTOR
diff_hunk: @@ -32,12 +103,15 @@ public User getUserById(int userID) throws SQLException {
             if (rs.next()) {
                 return extractUser(rs);
             }
+        } catch (Exception e) {
+            e.printStackTrace();
+            return null;
path: src/main/java/com/intern/sms/dao/UserDAOimpl.java
user: login: itsfazalkhan
body: My bad, I misunderstood it that execution wouldn't continue beyond this block. Which makes this `return null;` redundant, so removing it.
created_at: 2025-04-25T05:16:40Z
author_association: CONTRIBUTOR
diff_hunk: @@ -1,41 +1,255 @@
-// ConsoleView.java
+// Consolejava
 package com.intern.sms.view;
 
+import com.intern.sms.controller.UserController;
+
 import java.util.Scanner;
 
 public class ConsoleView {
-    private final Scanner scanner = new Scanner(System.in);
-
+    private final UserController controller = new UserController();
+    Scanner sc;
     public void showMenu(String title, String[] options) {
+
         System.out.println("\n==== " + title + " ====");
         for (int i = 0; i < options.length; i++) {
             System.out.println((i + 1) + ". " + options[i]);
         }
         System.out.print("Choose an option: ");
     }
 
+    public void mainMenu() {
+        sc = new Scanner(System.in);
+        while (true) {
+            showMenu("User Management Menu", new String[]{"Login", "Sign Up", "Forgot Password", "Exit"});
+            int choice = getChoice();
+
+            try {
+                switch (choice) {
+                    case 1 -> login();
+                    case 2 -> signUp();
+                    case 3 -> forgotPassword();
+                    case 4 -> {
+                        showMessage("Goodbye!");
+                        return;
+                    }
+                    default -> showMessage("Invalid choice.");
+                }
+            } catch (Exception e) {
+                showMessage("Error: " + e.getMessage());
+            }
+        }
+    }
+
+    private void login() {
+        String username = prompt("Enter username: ");
+        String password = prompt("Enter password: ");
+
+        String role = controller.login(username, password);
+
+        if (role == null) {
+            showMessage("Invalid credentials.");
+            return;
+        }
+
+        showMessage("Login successful! Welcome, " + username);
+
+        switch (role.toLowerCase()) {
+            case "admin" -> adminDashboard();
+            case "teacher" -> teacherDashboard();
+            case "student" -> studentDashboard();
+            case "parent" -> parentDashboard();
+            default -> showMessage("Unknown role.");
+        }
+    }
+
+    private void adminDashboard() {
+        while (true) {
+            showMenu("Admin Dashboard", new String[]{"Manage Users", "Manage System Settings", "Logout"});
+            int choice = getChoice();
+            switch (choice) {
+                case 1 -> manageUsers();
+                case 2 -> manageSystemSettings();
+                case 3 -> {
+                    showLoggingOutMessage();
+                    ;
+                    return;
+                }
+                default -> showInvalidChoice();
+            }
+        }
+    }
+
+    private void manageUsers() {
+        while (true) {
+            showMenu("Manage Users", new String[]{"Add User", "View Users", "Delete User", "Back to Admin Dashboard"});
+            int choice = getChoice();
+            switch (choice) {
+                case 1 -> addUser();
+                case 2 -> viewUsers();
+                case 3 -> deleteUser();
+                case 4 -> {
+                    return; // Back to Admin Dashboard
+                }
+                default -> showMessage("Invalid choice.");
+            }
+        }
+    }
+
+    private void addUser() {
+        String username = prompt("Enter username: ");
+        String password = prompt("Enter password: ");
+        String email = prompt("Enter email: ");
+        String role = prompt("Enter role (admin/teacher/student/parent): ");
+
+        String response = controller.addUser(username, password, email, role);
+        showMessage(response);
+    }
+
+    private void viewUsers() {
+        controller.viewUsers();
+    }
+
+    private void deleteUser() {
+        int userID = Integer.parseInt(prompt("Enter user ID to delete: "));
+        String response = controller.deleteUser(userID);
+        showMessage(response);
+    }
+
+    private void manageSystemSettings() {
+        showUnderDevelopment("Managing System Settings");
+    }
+
+    private void teacherDashboard() {
+        while (true) {
+            showMenu("Teacher Dashboard", new String[]{"Manage Courses", "Mark Attendance", "Grade Students", "Logout"});
+            int choice = getChoice();
+            switch (choice) {
+                case 1 -> manageCourses();
+                case 2 -> markAttendance();
+                case 3 -> gradeStudents();
+                case 4 -> {
+                    showLoggingOutMessage();
+                    ;
+                    return;
+                }
+                default -> showInvalidChoice();
+            }
+        }
+    }
+
+    private void manageCourses() {
+        showUnderDevelopment("Managing courses");
+    }
+
+    private void markAttendance() {
+        showUnderDevelopment("Marking attendance");
+    }
+
+    private void gradeStudents() {
+        showUnderDevelopment("Grading students");
+    }
+
+    private void studentDashboard() {
+        while (true) {
+            showMenu("Student Dashboard", new String[]{"View Courses", "Track Attendance", "View Grades", "Logout"});
+            int choice = getChoice();
+            switch (choice) {
+                case 1 -> viewCourses();
+                case 2 -> trackAttendance();
+                case 3 -> viewGrades();
+                case 4 -> {
+                    showLoggingOutMessage();
+                    ;
+                    return;
+                }
+                default -> showInvalidChoice();
+            }
+        }
+    }
+
+    private void viewCourses() {
+        showUnderDevelopment("Viewing courses");
+    }
+
+    private void trackAttendance() {
+        showUnderDevelopment("Tracking attendance");
+    }
+
+    private void viewGrades() {
+        showUnderDevelopment("Viewing grades");
+    }
+
+    private void parentDashboard() {
+        while (true) {
+            showMenu("Parent Dashboard", new String[]{"Monitor Student Progress", "Pay Fees", "Logout"});
+            int choice = getChoice();
+            switch (choice) {
+                case 1 -> monitorStudentProgress();
+                case 2 -> payFees();
+                case 3 -> {
+                    showLoggingOutMessage();
+                    ;
+                    return;
+                }
+                default -> showInvalidChoice();
+            }
+        }
+    }
+
+    private void monitorStudentProgress() {
+        showUnderDevelopment("Monitoring student progress");
+    }
+
+    private void payFees() {
+        showUnderDevelopment("Paying fees");
+    }
+
+    private void signUp() {
+        String username = prompt("Choose a username: ");
+        String password = prompt("Choose a password: ");
+        String email = prompt("Enter your email: ");
+        String role = prompt("Enter role (teacher/student/parent): ");
+        if (role.equals("admin")) {
+            prompt("Contact Admin to sign up as an Administrator.");
+        }
+        boolean registered = controller.signUp(username, password, email, role);
+        showMessage(registered ? "User registered successfully." : "Username already exists.");
+    }
+
+    private void forgotPassword() {
+        showMessage("\n--- Admin Authentication ---");
+        String adminUsername = prompt("Enter admin username: ");
+        String adminPassword = prompt("Enter admin password: ");
+        String role = controller.login(adminUsername, adminPassword);
+        if (role == "admin") {
path: src/main/java/com/intern/sms/view/ConsoleView.java
user: login: Copilot
body: Use .equals() for string comparison instead of '==' to avoid potential errors when comparing String values.
```suggestion
        if ("admin".equals(role)) {
```
created_at: 2025-04-25T06:18:45Z
author_association: NONE
diff_hunk: @@ -68,26 +145,37 @@ public void updateUser(User user) throws SQLException {
             stmt.setString(4, user.getRole());
             stmt.setInt(5, user.getUserID());
             stmt.executeUpdate();
+        } catch (Exception e) {
+            e.printStackTrace();
         }
     }
 
     @Override
-    public void deleteUser(int userID) throws SQLException {
+    public boolean deleteUser(int userID) {
         String sql = "DELETE FROM user WHERE userID = ?";
         try (Connection conn = DBConnection.getConnection();
              PreparedStatement stmt = conn.prepareStatement(sql)) {
             stmt.setInt(1, userID);
             stmt.executeUpdate();
+        } catch (Exception e) {
+            e.printStackTrace();
+            return false;
         }
+        return false;
path: src/main/java/com/intern/sms/dao/UserDAOimpl.java
user: login: Copilot
body: The deleteUser method always returns false; update it to return true if the deletion succeeds (e.g., by checking if stmt.executeUpdate() > 0).
```suggestion
            return stmt.executeUpdate() > 0; // Return true if at least one row was deleted
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
```
created_at: 2025-04-25T06:18:46Z
author_association: NONE
diff_hunk: @@ -68,26 +145,37 @@ public void updateUser(User user) throws SQLException {
             stmt.setString(4, user.getRole());
             stmt.setInt(5, user.getUserID());
             stmt.executeUpdate();
+        } catch (Exception e) {
+            e.printStackTrace();
         }
     }
 
     @Override
-    public void deleteUser(int userID) throws SQLException {
+    public boolean deleteUser(int userID) {
         String sql = "DELETE FROM user WHERE userID = ?";
         try (Connection conn = DBConnection.getConnection();
              PreparedStatement stmt = conn.prepareStatement(sql)) {
             stmt.setInt(1, userID);
             stmt.executeUpdate();
+        } catch (Exception e) {
+            e.printStackTrace();
+            return false;
         }
+        return false;
     }
 
-    private User extractUser(ResultSet rs) throws SQLException {
-        return new User(
-                rs.getInt("userID"),
-                rs.getString("username"),
-                rs.getString("password"),
-                rs.getString("email"),
-                rs.getString("role")
-        );
+    private User extractUser(ResultSet rs) {
+        try {
+            return new User(
+                    rs.getInt("userID"),
+                    rs.getString("username"),
path: src/main/java/com/intern/sms/dao/UserDAOimpl.java
user: login: itsfazalkhan
body: Okay, what do you suggest? 
created_at: 2025-04-25T06:52:30Z
author_association: CONTRIBUTOR
diff_hunk: @@ -1,4 +1,4 @@
-Alter TABLE User (
+CREATE TABLE User (
path: src/main/resources/db.sql
user: login: Fiend-Star
body: Does this auto setup db? If yes so lets use create if not exists
created_at: 2025-04-25T22:55:01Z
author_association: CONTRIBUTOR
diff_hunk: @@ -1,4 +1,4 @@
-Alter TABLE User (
+CREATE TABLE User (
path: src/main/resources/db.sql
user: login: itsfazalkhan
body: No, it doesn't update.
created_at: 2025-04-26T05:58:51Z
author_association: CONTRIBUTOR
diff_hunk: @@ -1,4 +1,4 @@
-Alter TABLE User (
+CREATE TABLE User (
path: src/main/resources/db.sql
user: login: OlixIgnacious
body: https://www.baeldung.com/hibernate-naming-strategy

- For now its ok, but sql naming strategy is different than java naming conventions. 
created_at: 2025-04-26T18:44:07Z
author_association: CONTRIBUTOR

PR comments:
user: login: OlixIgnacious
created_at: 2025-04-23T16:31:59Z
body: LGTM
author_association: CONTRIBUTOR
user: login: Fiend-Star
created_at: 2025-04-28T17:58:03Z
body: Merged this for now due to other high priority items.
author_association: CONTRIBUTOR