using back.DataModels; using back.persistance.blob; using back.persistance.data.repositories.Abstracts; using back.services.engine.Crypto; using back.services.engine.mailing; using System.Text; using System.Text.Json; namespace back.services.bussines.UserService; public class UserService( IUserRepository userRepository, ICryptoService cryptoService, IEmailService emailService, IBlobStorageService blobStorageService, JsonSerializerOptions jsonSerializerOptions ) : IUserService { private readonly IUserRepository _repository = userRepository ?? throw new ArgumentNullException(nameof(userRepository)); private readonly ICryptoService _cryptoService = cryptoService; private readonly IEmailService _emailService = emailService; private readonly IBlobStorageService _blobStorageService = blobStorageService; public async Task Create(string clientId, User user) { ArgumentNullException.ThrowIfNull(user); if (user.Id != null && await _repository.Exists(user.Id)) { return await _repository.GetById(user.Id); } if (string.IsNullOrEmpty(user.Email) || string.IsNullOrEmpty(user.Password)) { return null; } if (await _repository.Exists(user.Email)) { return await _repository.GetByEmail(user.Email); } if (string.IsNullOrEmpty(user.Salt)) { user.Salt = _cryptoService.Salt(); } user.Password = _cryptoService.Decrypt(clientId, user.Password) ?? string.Empty; user.Password = _cryptoService.HashPassword(user.Password, user.Salt) ?? string.Empty; user.CreatedAt = DateTimeOffset.UtcNow.ToString("dd-MM-yyyy HH:mm:ss zz"); //user.Roles.Add(Role.UserRole); await _repository.Insert(user); await _repository.SaveChanges(); return user; } public async Task Update(User user) { ArgumentNullException.ThrowIfNull(user); if (user.Id == null || !await _repository.Exists(user.Id)) { return null; } var existingUser = await _repository.GetById(user.Id); if (existingUser == null) return null; existingUser.Email = user.Email; await _repository.Update(existingUser); await _repository.SaveChanges(); return existingUser; } public async Task Login(string email, string decryptedPass) { var salt = await _repository.GetUserSaltByEmail(email); var hashedPassword = _cryptoService.HashPassword(decryptedPass, salt); var user = await _repository.Login(email, hashedPassword ?? string.Empty); return user; } public async Task Login(string email, string password, string clientId) { if (string.IsNullOrEmpty(email) || string.IsNullOrEmpty(password)) return null; try { var decryptedPass = _cryptoService.Decrypt(clientId, password); var user = await Login(email, decryptedPass ?? string.Empty); return user; } catch { return null; } } public async Task SendResetPassword(string email) { var exists = await _repository.ExistsByEmail(email); if (!exists) { return; } await _emailService.SendEmailAsync( tos: email, from: "admin@mmorales.photo", subject: "Reset Password", body: "If you received this email, it means that you have requested a password reset. Please follow the instructions in the email to reset your password." ); } public async Task ValidateSystemUser(string email, string password, string systemKey, string clientId) { var decryptedPassword = _cryptoService.Decrypt(clientId, password) ?? string.Empty; var decryptedsystemKey = _cryptoService.Decrypt(clientId, systemKey) ?? string.Empty; if (string.IsNullOrEmpty(email) || string.IsNullOrEmpty(decryptedPassword) || string.IsNullOrEmpty(decryptedsystemKey)) { return null; } if (!email.Equals(User.SystemUser.Email, StringComparison.InvariantCultureIgnoreCase)) { return null; } var systemKeyBytes = await _blobStorageService.GetBytes("systemkey.lock"); var systemKeyString = Encoding.UTF8.GetString(systemKeyBytes ?? []); var systemKeyObject = JsonSerializer.Deserialize(systemKeyString, jsonSerializerOptions); if (systemKeyObject == null || !systemKeyObject.IsValid(email, decryptedPassword, decryptedsystemKey)) { return null; } if (!await _repository.ExistsByEmail(email)) { return null; } var user = await _repository.GetByEmail(email); if (user == null) { return null; } return await Login(user.Email!, decryptedPassword); } }