using API.DTO.Base; using API.DTO.Login; using API.Hashing.Interfaces; using API.Services.Interfaces; using DAL.Models; namespace API.Services { public class UserManager : IUserManager { private readonly IHashingFactory _hashingFactory; private readonly ILogger _logger; private readonly HashingType _preferredHashingType; private readonly UserService _userService; public UserManager(UserService userService, IHashingFactory hashingFactory, ILogger logger, HashingType preferredHashingType) { _userService = userService; _hashingFactory = hashingFactory; _logger = logger; _preferredHashingType = preferredHashingType; } public UserDTO? authenticateUser(UserLoginDTO loginDTO) { User? user = _userService.getNoAuthentication(x => x.phoneNumber.Equals(loginDTO.phoneNumber)).FirstOrDefault(); if (user == null) return null; IHashingAlgorithm? hashingAlgorithm = _hashingFactory.getAlgorithm(user.hashingType); if (hashingAlgorithm == null) { _logger.Log(LogLevel.Warning, "User id '{id}' has a hashing type '{hashingType}' that isn't recognized by factory '{factory}'. Not logging in.", user.id, user.hashingType, nameof(_hashingFactory)); return null; } string hashedPassword = hashingAlgorithm.hash(loginDTO.password, user.salt); if (!hashedPassword.Equals(user.password)) { _logger.Log(LogLevel.Information, "Failed login attempt for user id '{id}.", user.id); return null; } if (user.hashingType != _preferredHashingType) { // todo The user is logged in at this point. Their hashing type needs to be updated, we need to rehash & salt the password and save it now. } UserDTO dto = new UserDTO(); dto.adaptFromModel(user); return dto; } public UserDTO? registerUser(UserRegisterDTO registerDTO) { if (_userService.getNoAuthentication(x => x.phoneNumber.Equals(registerDTO.phoneNumber) || x.firstName.Equals(registerDTO.firstName) && x.lastName.Equals(registerDTO.lastName)) .Any()) { return null; } IHashingAlgorithm? hashingAlgorithm = _hashingFactory.getAlgorithm(_preferredHashingType); if (hashingAlgorithm == null) { _logger.Log(LogLevel.Error, "Preferred hashing type '{hashingType}' that isn't recognized by factory '{factory}'.", _preferredHashingType, nameof(_hashingFactory)); return null; } byte[] salt; string hashedPassword = hashingAlgorithm.hash(registerDTO.password, out salt); User user = _userService.add(registerDTO, hashedPassword, salt); UserDTO dto = new UserDTO(); dto.adaptFromModel(user); return dto; } } }