public async Task ResetPassword(string username, string password, string token) { _passwordValidator.Validate(password); var fixedToken = token.Trim().ToLower(); var user = await _userRepository.GetByUsernameAsync(username); var tokens = await _recoveryTokenRepository.GetByUserIdAsync(user.Id); var validTokens = tokens .Where(_ => _.Token == fixedToken) .OrderByDescending(_ => _.CreatedBy); if (validTokens.Count() > 0) { if ((validTokens.First().CreatedAt - DateTime.Now).TotalHours > 24) { throw new GraException($"Token {token} has expired."); } foreach (var request in tokens) { await _recoveryTokenRepository.RemoveSaveAsync(-1, request.Id); } await _userRepository.SetUserPasswordAsync(user.Id, user.Id, password); } else { throw new GraException($"Token {token} is not valid."); } }
public async Task <Models.ServiceResult> ResetPassword(string username, string password, string token) { string trimmedUsername = username.Trim(); _passwordValidator.Validate(password); var fixedToken = token.Trim().ToLowerInvariant(); var user = await _userRepository.GetByUsernameAsync(trimmedUsername); if (user == null) { return(new Models.ServiceResult { Status = Models.ServiceResultStatus.Error, Message = Annotations.Validate.Username, Arguments = new[] { trimmedUsername } }); } var tokens = await _recoveryTokenRepository.GetByUserIdAsync(user.Id); var validTokens = tokens .Where(_ => _.Token == fixedToken) .OrderByDescending(_ => _.CreatedBy); if (validTokens.Any()) { if ((validTokens.First().CreatedAt - _dateTimeProvider.Now).TotalHours > 24) { return(new Models.ServiceResult { Status = Models.ServiceResultStatus.Error, Message = Annotations.Validate.TokenExpired, Arguments = new[] { token } }); } foreach (var request in tokens) { await _recoveryTokenRepository.RemoveSaveAsync(-1, request.Id); } await _userRepository.SetUserPasswordAsync(user.Id, user.Id, password); } else { return(new Models.ServiceResult { Status = Models.ServiceResultStatus.Error, Message = Annotations.Validate.TokenExpired, Arguments = new[] { token } }); } return(new Models.ServiceResult(Models.ServiceResultStatus.Success)); }
public async Task <Models.ServiceResult> GenerateTokenAndEmail(string username, string recoveryUrl) { string trimmedUsername = username.Trim(); var user = await _userRepository.GetByUsernameAsync(trimmedUsername); if (user == null) { _logger.LogInformation("Username {Username} doesn't exist so can't create a recovery token.", trimmedUsername); return(new Models.ServiceResult { Status = Models.ServiceResultStatus.Error, Message = Annotations.Validate.Username, Arguments = new[] { trimmedUsername } }); } if (string.IsNullOrEmpty(user.Email)) { _logger.LogInformation("User {Username} ({UserId}) doesn't have an email address configured so cannot send a recovery token.", user?.Username, user?.Id); return(new Models.ServiceResult { Status = Models.ServiceResultStatus.Error, Message = Annotations.Validate.EmailConfigured, Arguments = new[] { trimmedUsername } }); } // clear any existing tokens var existingRequests = await _recoveryTokenRepository.GetByUserIdAsync(user.Id); foreach (var request in existingRequests) { await _recoveryTokenRepository.RemoveSaveAsync(-1, request.Id); } string tokenString = _tokenGenerator.Generate().ToUpperInvariant().Trim(); // insert new token await _recoveryTokenRepository.AddSaveAsync(-1, new RecoveryToken { Token = tokenString.ToLowerInvariant(), UserId = user.Id }); _logger.LogInformation("Cleared {Existing} existing recovery tokens and inserted a new one for {Username} ({UserId})", existingRequests.Count(), user?.Username, user.Id); var site = await _siteLookupService.GetByIdAsync(GetCurrentSiteId()); var directEmailDetails = new DirectEmailDetails(site.Name) { DirectEmailSystemId = "PasswordRecovery", LanguageId = await _languageService .GetLanguageIdAsync(CultureInfo.CurrentUICulture.Name), SendingUserId = await _userRepository.GetSystemUserId(), ToUserId = user.Id }; directEmailDetails.Tags.Add("RecoveryLink", $"{recoveryUrl}?username={trimmedUsername}&token={tokenString}"); directEmailDetails.Tags.Add("RecoveryBaseLink", recoveryUrl); directEmailDetails.Tags.Add("Username", trimmedUsername); directEmailDetails.Tags.Add("Token", tokenString); var siteLink = await _siteLookupService.GetSiteLinkAsync(site.Id); directEmailDetails.Tags.Add("Sitelink", siteLink.AbsoluteUri); var result = new Models.ServiceResult(); try { var history = await _emailService.SendDirectAsync(directEmailDetails); result.Status = history?.Successful == true ? Models.ServiceResultStatus.Success : Models.ServiceResultStatus.Error; } catch (GraException ex) { if (ex?.InnerException is MimeKit.ParseException) { result.Status = Models.ServiceResultStatus.Error; result.Message = Annotations.Validate.AssociatedEmailAddressInvalid; result.Arguments = new[] { username }; } } return(result); }