Implement Login functionality

<UserStory> CUS001:Login </UserStory>

<Changes>
    1. Added login implementation in AuthenticationManagementService to validate username and password from stored user records.
    2. Connected Controller::login() with AuthenticationManagementService login logic.
    3. Added getAuthenticatedUser() integration in Controller for retrieving the logged-in user.
    4. Implemented login flow in UserInterface to collect credentials and validate login.
    5. Added role-based menu navigation for Admin, Technician, and Customer after successful login.
    6. Added error handling to display "Invalid Username or Password" for failed login attempts.
    7. Added required includes and controller member dependency for authentication support.
    8. Added a check to create a default admin automatically if no admin exists in the system on startup
</Changes>

<Test>

Login functionality validation

Precondition:
1. System is running.
2. User records are available in the data store.
3. Valid username and password exist for a registered user.

Steps:
1. Launch the application.
2. Select the login option from the main menu.
3. Enter a valid username and password.
   - Verify that the entered credentials are validated.
   - Verify that access is granted and the correct menu is shown based on user type.
4. Enter an invalid username or password.
   - Verify that the message "Invalid Username or Password" is displayed.

</Test>

<Review>
Sreeja Reghukumar, please review
</Review>
This commit is contained in:
2026-05-19 12:36:29 +05:30
parent 56c5c2dc70
commit df39c0588b
8 changed files with 113 additions and 4 deletions
@@ -171,6 +171,7 @@
<ClInclude Include="services\PaymentManagementService.h" />
<ClInclude Include="services\ServiceManagementService.h" />
<ClInclude Include="services\UserManagementService.h" />
<ClInclude Include="utilities\Config.h" />
<ClInclude Include="utilities\Enums.h" />
<ClInclude Include="utilities\InputHelper.h" />
<ClInclude Include="utilities\Map.h" />
@@ -2,7 +2,7 @@
bool Controller::login(const std::string& username, const std::string& password)
{
return false;
return m_authenticationManagementService.login(username, password);
}
void Controller::logout()
@@ -19,7 +19,7 @@ void Controller::createCustomer(const std::string& username, const std::string&
const User* Controller::getAuthenticatedUser()
{
return nullptr;
return m_authenticationManagementService.getAuthenticatedUser();
}
void Controller::createTechnician(const std::string& username, const std::string& password, const std::string& email, const std::string& phone)
@@ -143,5 +143,6 @@ void Controller::configureNotifications(const std::string& userID, bool paymentN
void Controller::runSystemChecks()
{
m_userManagementService.ensureAdminExists();
}
@@ -2,6 +2,8 @@
#include "Map.h"
#include <string>
#include "Enums.h"
#include "AuthenticationManagementService.h"
#include "UserManagementService.h"
class Service;
class ComboPackage;
@@ -14,6 +16,9 @@ class Notification;
class Controller
{
private:
AuthenticationManagementService m_authenticationManagementService;
UserManagementService m_userManagementService;
public:
bool login(const std::string& username, const std::string& password);
void logout();
@@ -1,3 +1,29 @@
#include "AuthenticationManagementService.h"
#include "User.h"
User* AuthenticationManagementService::m_authenticatedUser = nullptr;
bool AuthenticationManagementService::login(const std::string& username, const std::string& password)
{
util::Map<std::string, User*> users = m_dataStore.getUsers();
int usersMapSize = users.getSize();
for (int index = 0; index < usersMapSize; index++)
{
User* user = users.getValueAt(index);
if (username == user->getUserName())
{
if (password == user->getPassword())
{
m_authenticatedUser = user;
return true;
}
return false;
}
}
return false;
}
User* AuthenticationManagementService::getAuthenticatedUser()
{
return m_authenticatedUser;
}
@@ -1 +1,30 @@
#include "UserManagementService.h"
#include "User.h"
#include "Enums.h"
#include "Config.h"
void UserManagementService::ensureAdminExists()
{
auto& usersMap = m_dataStore.getUsers();
int usersMapSize = usersMap.getSize();
bool isAdminFound = false;
for (int index = 0; index < usersMapSize; index++)
{
User* user = usersMap.getValueAt(index);
if (user && user->getUserType() == util::UserType::ADMIN)
{
isAdminFound = true;
break;
}
}
if (!isAdminFound)
{
createUser(
config::admin::DEFAULT_ADMIN_USERNAME,
config::admin::DEFAULT_ADMIN_NAME,
config::admin::DEFAULT_ADMIN_PASSWORD,
config::admin::DEFAULT_ADMIN_EMAIL,
config::admin::DEFAULT_ADMIN_PHONE,
util::UserType::ADMIN);
}
}
@@ -13,7 +13,7 @@ private:
DataStore& m_dataStore;
public:
UserManagementService() : m_dataStore(DataStore::getInstance()) {}
void createUser(const std::string& username, const std::string& password, const std::string& email, const std::string& phone, util::UserType type);
void createUser(const std::string& username, const std::string& name, const std::string& password, const std::string& email, const std::string& phone, util::UserType type);
void updateUserDetails(const std::string& userID, const std::string& email, const std::string& phone);
util::Map<std::string, User*> getUsers();
util::Map<std::string, User*> getUsers(util::UserType type);
@@ -21,4 +21,5 @@ public:
void removeUser(const std::string& userID);
util::Vector<Notification*> getUserNotifications(const std::string& userID);
void deleteNotification(const std::string& notificationID, const std::string& userID);
void ensureAdminExists();
};
@@ -0,0 +1,13 @@
#pragma once
namespace config
{
namespace admin
{
constexpr const char* DEFAULT_ADMIN_USERNAME = "admin";
constexpr const char* DEFAULT_ADMIN_NAME = "admin";
constexpr const char* DEFAULT_ADMIN_PASSWORD = "";
constexpr const char* DEFAULT_ADMIN_EMAIL = "admin@vss";
constexpr const char* DEFAULT_ADMIN_PHONE = "0000000000";
}
}
@@ -1,6 +1,8 @@
#include "UserInterface.h"
#include "InputHelper.h"
#include "OutputHelper.h"
#include "Enums.h"
#include "User.h"
void UserInterface::run()
{
@@ -48,7 +50,38 @@ bool UserInterface::handleOperation(int choice)
void UserInterface::login()
{
std::string username, password;
util::clear();
std::cout << "Enter username: ";
util::read(username);
std::cout << "Enter password: ";
util::read(password);
if (m_controller.login(username, password))
{
const User* authenticatedUser = m_controller.getAuthenticatedUser();
if (authenticatedUser != nullptr)
{
switch (authenticatedUser->getUserType())
{
case util::UserType::ADMIN:
m_adminMenu.showMenu();
break;
case util::UserType::TECHNICIAN:
m_technicianMenu.showMenu();
break;
case util::UserType::CUSTOMER:
m_customerMenu.showMenu();
break;
default:
std::cout << "\nError: Unknown user type";
break;
}
}
}
else
{
std::cout << "\nError: Invalid Username or Password";
}
}
void UserInterface::registerCustomer()