CSR/CSR.Domain/Entities/User.cs

188 lines
4.9 KiB
C#

namespace CSR.Domain.Entities;
using System.Net.Mail;
using CSR.Domain.Interfaces;
public class User
{
public int Id { get; private set; }
public string Username { get; private set; }
public string Email { get; private set; }
public string PasswordHash { get; private set; }
public int RoleId { get; private set; }
public Role Role { get; private set; }
private User(int id, string username, string email, string passwordHash, int roleId, Role role)
{
Id = id;
Username = username;
Email = email;
PasswordHash = passwordHash;
RoleId = roleId;
Role = role;
}
// This role is used when a new user is created
public static readonly Role DefaultRole = Role.User;
internal static User LoadExisting(int id, string username, string email, string passwordHash, int roleId, Role role)
{
return new User(id, username, email, passwordHash, roleId, role);
}
public static User CreateNew(string username, string email, string password, IPasswordHasher passwordHasher)
{
if (!IsValidUsername(username).IsValid)
{
throw new ArgumentException("Invalid username.");
}
if (!IsValidEmail(email))
{
throw new ArgumentException("Invalid email.");
}
if (!IsValidPassword(password).IsValid)
{
throw new ArgumentException("Invalid password.");
}
var user = new User(0, username, email, password, DefaultRole.Id, DefaultRole);
user.PasswordHash = passwordHasher.HashPassword(user, password);
return user;
}
public (bool Success, IEnumerable<string>? Errors) UpdatePassword(string password, IPasswordHasher passwordHasher, User requestingUser)
{
if (requestingUser.Id != Id || requestingUser.Role.Name != "Admin")
{
throw new UnauthorizedAccessException("Only admins or the same user can update passwords.");
}
var validityCheck = IsValidPassword(password);
if (validityCheck.IsValid)
{
PasswordHash = passwordHasher.HashPassword(this, password);
}
return validityCheck;
}
public bool VerifyPasswordAgainstHash(string providedPassword, IPasswordHasher passwordHasher)
{
return passwordHasher.VerifyHashedPassword(this, PasswordHash, providedPassword);
}
public static (bool IsValid, IEnumerable<string>? Errors) IsValidPassword(string password)
{
var Errors = new List<string>();
if (password.Length < 8 || password.Length > 32)
{
Errors.Add("Password must be between 8 and 32 characters long.");
}
if (!password.Any(char.IsUpper))
{
Errors.Add("Password must contain at least one uppercase letter.");
}
if (!password.Any(char.IsLower))
{
Errors.Add("Password must contain at least one lowercase letter.");
}
if (!password.Any(char.IsDigit))
{
Errors.Add("Password must contain at least one digit.");
}
if (Errors.Count > 0)
{
return (false, Errors);
}
return (true, null);
}
public (bool Success, IEnumerable<string>? Errors) UpdateEmail(string email, User requestingUser)
{
if (requestingUser.Id != Id || requestingUser.Role.Name != "Admin")
{
throw new UnauthorizedAccessException("Only admins or the same user can update email.");
}
if (IsValidEmail(email))
{
Email = email;
return (true, null);
}
return (false, new List<string> { "Invalid email format." });
}
public static bool IsValidEmail(string email)
{
try
{
var mailAddress = new MailAddress(email);
return true;
}
catch (FormatException)
{
return false;
}
}
public (bool Success, IEnumerable<string>? Errors) UpdateUsername(string username, User requestingUser)
{
if (requestingUser.Role.Name != "Admin")
{
throw new UnauthorizedAccessException("Only admins can update username.");
}
var validityCheck = IsValidUsername(username);
if (validityCheck.IsValid)
{
Username = username;
}
return validityCheck;
}
public static (bool IsValid, IEnumerable<string>? Errors) IsValidUsername(string username)
{
var Errors = new List<string>();
if (!username.All(char.IsLetterOrDigit))
{
Errors.Add("Username must be alphanumeric.");
}
if (string.IsNullOrWhiteSpace(username) || username.Length < 3)
{
Errors.Add("Username must be at least 3 characters long.");
}
if (username.Length > 32)
{
Errors.Add("Username must be less than 32 characters long.");
}
if (Errors.Count > 0)
{
return (false, Errors);
}
return (true, null);
}
public void UpdateRole(Role role, User requestingUser)
{
if (requestingUser.Role.Name != "Admin")
{
throw new UnauthorizedAccessException("Only admins can assign roles.");
}
Role = role;
RoleId = role.Id;
}
}