Skip to content

Commit

Permalink
Refactor LoginViewModel to improve readability
Browse files Browse the repository at this point in the history
Separate the Login() method in LoginViewModel into smaller methods focused on specific actions like authentication, handling failed attempts, and starting a session. This improves readability and maintainability of the code.

Signed-off-by: russkyc <[email protected]>
  • Loading branch information
russkyc committed Jun 26, 2023
1 parent 97f4681 commit 2afc9dc
Showing 1 changed file with 151 additions and 125 deletions.
276 changes: 151 additions & 125 deletions Russkyc.GroomWise/ViewModels/App/LoginViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,159 +3,185 @@
// Unauthorized copying or redistribution of all files, in source and binary forms via any medium
// without written, signed consent from the author is strictly prohibited.

namespace GroomWise.ViewModels.App;

public partial class LoginViewModel : ViewModelBase, ILoginViewModel
namespace GroomWise.ViewModels.App
{
private readonly ILogger _logger;
private readonly IDbContext _dbContext;
private readonly IConfigProvider _configProvider;
private readonly IEncryptionService _encryptionService;
private readonly IApplicationService _applicationService;
private readonly ISessionManagerService _sessionManagerService;

private readonly IFactory<Session> _sessionFactory;

public string AppVersion => _configProvider.Version;

[ObservableProperty]
private SynchronizedObservableCollection<Notification> _notifications;

[ObservableProperty]
[NotifyDataErrorInfo]
[Required(ErrorMessage = "Password cannot be blank.")]
private string? _password;

[ObservableProperty]
[NotifyDataErrorInfo]
[Required(ErrorMessage = "Username cannot be blank.")]
[RegularExpression("^[a-zA-Z0-9_-]{1,16}$", ErrorMessage = "Invalid Username format.")]
private string? _username;

public LoginViewModel(
ILogger logger,
IDbContext dbContext,
ISessionManagerService sessionManagerService,
IApplicationService applicationService,
IEncryptionService encryptionService,
IConfigProvider configProvider,
IFactory<Session> sessionFactory
)
public partial class LoginViewModel : ViewModelBase, ILoginViewModel
{
_logger = logger;
_sessionManagerService = sessionManagerService;
_applicationService = applicationService;
_encryptionService = encryptionService;
_sessionFactory = sessionFactory;
_configProvider = configProvider;
_dbContext = dbContext;

Notifications = new SynchronizedObservableCollection<Notification>();
}
private readonly ILogger _logger;
private readonly IDbContext _dbContext;
private readonly IConfigProvider _configProvider;
private readonly IEncryptionService _encryptionService;
private readonly IApplicationService _applicationService;
private readonly ISessionManagerService _sessionManagerService;

private readonly IFactory<Session> _sessionFactory;

public string AppVersion => _configProvider.Version;

[ObservableProperty]
private SynchronizedObservableCollection<Notification> _notifications;

[ObservableProperty]
[NotifyDataErrorInfo]
[Required(ErrorMessage = "Password cannot be blank.")]
private string? _password;

[ObservableProperty]
[NotifyDataErrorInfo]
[Required(ErrorMessage = "Username cannot be blank.")]
[RegularExpression("^[a-zA-Z0-9_-]{1,16}$", ErrorMessage = "Invalid Username format.")]
private string? _username;

public LoginViewModel(
ILogger logger,
IDbContext dbContext,
ISessionManagerService sessionManagerService,
IApplicationService applicationService,
IEncryptionService encryptionService,
IConfigProvider configProvider,
IFactory<Session> sessionFactory
)
{
_logger = logger;
_dbContext = dbContext;
_sessionManagerService = sessionManagerService;
_applicationService = applicationService;
_encryptionService = encryptionService;
_sessionFactory = sessionFactory;
_configProvider = configProvider;

Notifications = new SynchronizedObservableCollection<Notification>();
}

[RelayCommand]
private void Login()
{
// Force data validation of all fields
ValidateAllProperties();
[RelayCommand]
private void Login()
{
ValidateAllProperties();

if (HasErrors)
return;

// Check if validation has errors
if (HasErrors)
return;
var encryptedUsername = _encryptionService.Encrypt(Username!);
var account = _dbContext.AccountsRepository.Find(a => a.Username == encryptedUsername);

var account = _dbContext.AccountsRepository.Find(
a => a.Username == _encryptionService.Encrypt(Username!)
);
if (account is null)
HandleNonexistentAccount();
else
AuthenticateUser(account);
}

// Check if account is null
if (account is null)
private void HandleNonexistentAccount()
{
BuilderServices.Resolve<ILoginView>().ClearFields();
ClearFields();
ShowNotification("Account does not exist", NotificationType.Danger);
_logger.Log(this, "unsuccessful login attempt, account does not exist");
return;
_logger.Log(this, "Unsuccessful login attempt, account does not exist");
}

private void ClearFields(string field = "")
{
BuilderServices.Resolve<ILoginView>().ClearFields(field);
}

private void AuthenticateUser(Account account)
{
if (_encryptionService.Hash(Password!) != account.Password)
HandleIncorrectPassword();
else
CreateSession(account);
}

// Check if account password is equal to input password
if (_encryptionService.Hash(Password!) != account.Password)
private void HandleIncorrectPassword()
{
BuilderServices.Resolve<ILoginView>().ClearFields("Password");
ClearFields("Password");
ShowNotification("Password is incorrect", NotificationType.Danger);
_logger.Log(this, "Unsuccessful login attempt, wrong password");
return;
}

var employeeAccount = _dbContext.EmployeeAccountRepository.Find(
e => e.AccountId == account.Id
);

// Check if employee account is null
if (employeeAccount == null)
private void CreateSession(Account account)
{
ShowNotification("Account does not match any employee record", NotificationType.Danger);
_logger.Log(
this,
"Unsuccessful login attempt, account does not match any employee record"
var employeeAccount = _dbContext.EmployeeAccountRepository.Find(
e => e.AccountId == account.Id
);
return;
}

var employee = _dbContext.EmployeeRepository.Find(
employee => employee.Id == employeeAccount.EmployeeId
);
if (employeeAccount != null)
{
var employee = _dbContext.EmployeeRepository.Find(
e => e.Id == employeeAccount.EmployeeId
);

if (employee != null)
{
var employeeRole = _dbContext.EmployeeRoleRepository.Find(
er => er.EmployeeId == employee.Id
);

if (employeeRole != null)
StartSession(employee, employeeRole);
else
_logger.Log(this, "Employee is not assigned any role");
}
else
{
ShowNotification("Employee does not exist", NotificationType.Danger);
_logger.Log(this, "Unsuccessful login attempt, employee does not exist");
}
}
else
{
ShowNotification(
"Account does not match any employee record",
NotificationType.Danger
);
_logger.Log(
this,
"Unsuccessful login attempt, account does not match any employee record"
);
}
}

// Check if employee is null
if (employee == null)
private void StartSession(Employee employee, EmployeeRole employeeRole)
{
ShowNotification("Employee does not exist", NotificationType.Danger);
_logger.Log(this, "Unsuccessful login attempt, employee does not exist");
return;
var role = _dbContext.RoleRepository.Find(er => er.Id == employeeRole.RoleId);

if (role != null)
{
var session = _sessionFactory.Create(s =>
{
s.SessionUser = employee;
s.SessionRole = role;
});

_sessionManagerService.StartSession(session);
_applicationService.BuildNavItems();

RemoveNotification();
ToggleViews();
}
else
{
_logger.Log(this, "Role is non-existent");
}
}

var employeeRole = _dbContext.EmployeeRoleRepository.Find(
employeeRole => employeeRole.EmployeeId == employee.Id
);
if (employeeRole == null)
private void ToggleViews()
{
_logger.Log(this, "Employee is not assigned any role");
return;
BuilderServices.Resolve<IMainView>().Show();
BuilderServices.Resolve<ILoginView>().Hide();
}

var role = _dbContext.RoleRepository.Find(role => role.Id == employeeRole.RoleId);

// Check if role is null
if (role == null)
[RelayCommand]
void RemoveNotification()
{
_logger.Log(this, "Role is non-existent");
return;
Notifications.Clear();
}

var session = _sessionFactory.Create(session =>
void ShowNotification(string description, NotificationType type)
{
session.SessionUser = employee;
session.SessionRole = role;
});

_sessionManagerService.StartSession(session);
_applicationService.BuildNavItems();

RemoveNotification();
BuilderServices.Resolve<IMainView>().Show();
BuilderServices.Resolve<ILoginView>().Hide();
}

[RelayCommand]
void RemoveNotification()
{
Notifications.Clear();
}

void ShowNotification(string description, NotificationType type)
{
var notification = new Notification { Description = description, Type = type };
if (Notifications.Count > 0)
Notifications[0] = notification;
else
Notifications.Add(notification);
var notification = new Notification { Description = description, Type = type };
if (Notifications.Any())
Notifications[0] = notification;
else
Notifications.Add(notification);
}
}
}

0 comments on commit 2afc9dc

Please sign in to comment.