using IOL.GreatOffice.Api.Data.Database.Queues; using Microsoft.Extensions.Localization; namespace IOL.GreatOffice.Api.Services; public class UserService { private readonly PasswordResetService _passwordResetService; private readonly MailService _mailService; private readonly ILogger _logger; private readonly IStringLocalizer _localizer; private readonly MainAppDatabase _database; private readonly string EmailValidationUrl; public UserService(PasswordResetService passwordResetService, MailService mailService, IStringLocalizer localizer, VaultService vaultService, MainAppDatabase database, ILogger logger) { _passwordResetService = passwordResetService; _mailService = mailService; _localizer = localizer; _database = database; _logger = logger; var configuration = vaultService.GetCurrentAppConfiguration(); EmailValidationUrl = configuration.CANONICAL_BACKEND_URL + "/_/validate"; } public async Task LogInUser(HttpContext httpContext, User user, bool persist = false) { var claims = new List { new(AppClaims.USER_ID, user.Id.ToString()), new(AppClaims.NAME, user.Username), }; var identity = new ClaimsIdentity(claims, CookieAuthenticationDefaults.AuthenticationScheme); var principal = new ClaimsPrincipal(identity); var authenticationProperties = new AuthenticationProperties { AllowRefresh = true, IssuedUtc = DateTimeOffset.UtcNow, }; if (persist) { authenticationProperties.ExpiresUtc = DateTimeOffset.UtcNow.AddMonths(6); authenticationProperties.IsPersistent = true; } await httpContext.SignInAsync(principal, authenticationProperties); await _passwordResetService.DeleteRequestsForUserAsync(user.Id); _logger.LogInformation("Logged in user {0}", user.Id); } public async Task LogOutUser(HttpContext httpContext) { await httpContext.SignOutAsync(); _logger.LogInformation("Logged out user {0}", httpContext.User.FindFirst(AppClaims.USER_ID)); } public bool FulfillEmailValidationRequest(Guid id, Guid userId) { var item = _database.ValidationEmails.FirstOrDefault(c => c.Id == id); if (item == default) { _logger.LogDebug("Did not find email validation request with id: {0}", id); return false; } if (item.UserId != userId) { _logger.LogInformation("An unknown user tried to validate the email validation request {0}"); return false; } var user = _database.Users.FirstOrDefault(c => c.Id == item.UserId); if (user == default) { _database.ValidationEmails.Remove(item); _database.SaveChanges(); _logger.LogInformation("Deleting request {0} because user does not exist anymore"); return false; } user.EmailLastValidated = DateTime.UtcNow; user.SetModified(); _database.ValidationEmails.Remove(item); _database.SaveChanges(); _logger.LogInformation("Successfully validated the email for user {0}", user.Id); return true; } public async Task SendValidationEmail(User user) { var queueItem = new ValidationEmail() { UserId = user.Id, Id = Guid.NewGuid() }; var email = new MailService.PostmarkEmail() { To = user.Username, Subject = _localizer["Greatoffice Email Validation"], TextBody = _localizer[""" Hello, {0}. Validate your email address by opening this link in a browser {1} """, user.DisplayName(), EmailValidationUrl + "?id=" + queueItem.Id] }; await _mailService.SendMail(email); queueItem.EmailSentAt = DateTime.UtcNow; _database.ValidationEmails.Add(queueItem); await _database.SaveChangesAsync(); } }