using AutoMapper; using FluentValidation; using Galaeth.Core.Constants; using Galaeth.Core.Dtos; using Galaeth.Core.Entities; using Galaeth.Core.Extensions; using Galaeth.Core.RepositoryInterfaces; using Galaeth.Services.Configuration; using Galaeth.Services.Dtos; using Galaeth.Services.Exceptions; using Galaeth.Services.Interfaces; using Galaeth.Services.Validators; using Injectio.Attributes; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; namespace Galaeth.Services.Services; /// [RegisterScoped] public class UserService : IUserService { private readonly IUserRepository _userRepository; private readonly ICryptographyService _cryptographyService; private readonly IMapper _mapper; private readonly IValidator _createUserValidator; private readonly RegistrationConfiguration _registrationConfiguration; private readonly ILogger _logger; /// /// Initializes a new instance of the class. /// /// Instance of . /// Instance of . /// Instance of . /// Instance of . /// Instance of . /// Instance of . public UserService( IUserRepository userRepository, ICryptographyService cryptographyService, IMapper mapper, IValidator createUserValidator, IOptions registrationConfig, ILogger logger) { _userRepository = userRepository; _cryptographyService = cryptographyService; _mapper = mapper; _createUserValidator = createUserValidator; _registrationConfiguration = registrationConfig.Value; _logger = logger; } /// public async Task CreateNewUser(CreateUserDto createUser) { createUser.Username = createUser.Username.ToLower(); createUser.Email = createUser.Email.ToLowerInvariant(); await _createUserValidator.ValidateAndThrowAsync(createUser); // Check if username is already taken. var existingUser = await _userRepository.FindByUsername(createUser.Username); if (existingUser is not null) { throw new UsernameTakenException(createUser.Username); } // Check if email already registered. existingUser = await _userRepository.FindByEmailAddress(createUser.Email); if (existingUser is not null) { throw new EmailAlreadyRegisteredException(); } var user = new User() { Id = Guid.NewGuid(), Username = createUser.Username, EmailAddress = createUser.Email, CreatedAt = DateTime.Now, CreatorIp = createUser.IpAddress.ToString(), State = UserState.AwaitingEmailActivation, Role = UserRole.Normal, }; var salt = _cryptographyService.GenerateSalt(); var hash = _cryptographyService.HashPassword(createUser.Password, salt); user.PasswordHash = Convert.ToBase64String(hash); user.PasswordSalt = Convert.ToBase64String(salt); _logger.LogInformation("Creating new user {username} ({email}) [{id}]", user.Username, user.EmailAddress.MaskEmailAddress(), user.Id); if (!_registrationConfiguration.RequireEmailActivation || createUser.ActivateImmediately) { user.State = UserState.Normal; } await _userRepository.AddAsync(user); return _mapper.Map(user); } /// public async Task FindById(string userId) { if (!Guid.TryParse(userId, out var userGuid)) { return null; } var user = await _userRepository.FindByIdAsync(userGuid); return _mapper.Map(user); } }