예제 #1
0
        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));
        }
예제 #3
0
        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);
        }