public Result Change(ChangeInput input) { if (input == null) throw new ArgumentNullException("input"); var errors = new ErrorBuilder(); if (errors.NotValid(input)) { return errors; } string username = this.context.CurrentUserName; UserWrapper user = this.repo.FindUserByName(username); if (errors.Not(user != null, AccountResources.Validation_UserNotExist.FormatInvariant(username)) || errors.Not(this.passServ.PasswordEquals(input.CurrentPassword, user.Password), AccountResources.Validation_CurrentPasswordIncorrect, () => input.CurrentPassword) || !this.passServ.TrySetPassword(user, () => input.NewPassword, errors)) { return errors; } this.repo.UpdateUser(user); return HttpStatusCode.OK; }
OperationResult ChangeImpl(ChangeInput input) { if (input == null) throw new ArgumentNullException("input"); var errors = new ErrorBuilder(); if (errors.NotValid(input)) return errors; UserWrapper user = this.repo.FindUserByName(this.CurrentUserName); string currentEmail = user.Email; string newEmail = input.NewEmail; if (errors.Not(currentEmail.HasValue(), AccountResources.Validation_MissingEmail)) return errors; if (errors.Not(this.passServ.PasswordEquals(input.CurrentPassword, user.Password), AccountResources.Validation_CurrentPasswordIncorrect, () => input.CurrentPassword) | errors.Not(!EmailEquals(currentEmail, newEmail), AccountResources.Validation_NewEmailSameAsCurrent, () => input.NewEmail)) return errors; if (errors.Not(this.repo.FindUserByEmail(newEmail) == null, AccountResources.Validation_EmailAlreadyExists, () => input.NewEmail)) return errors; if (!this.Configuration.EnableEmailVerification) { user.Email = newEmail; this.repo.UpdateUser(user); return HttpStatusCode.OK; } user.EmailChangeTicketExpiration = this.Configuration.GetNow().Add(this.Configuration.EmailChangeTicketExpiration); this.repo.UpdateUser(user); var notifyModel = new NotificationMessageViewModel { SiteName = GetSiteName(), NewEmail = newEmail, OldEmail = currentEmail, HelpResource = this.Configuration.HelpResource }; if (!EmailEquals(currentEmail, user.Username)) notifyModel.Username = user.Username; var notifyMessage = new MailMessage { To = { user.Email }, Subject = AccountResources.Model_EmailChangeNotificationMessageSubject, Body = RenderEmailView(Views.Email.Change._NotificationMessage, notifyModel) }; string verificationTicket = new VerificationData(user.Id, newEmail).GetVerificationTicket(); string verificationUrl = AbsoluteUrl(this.Url.Action(Verify, verificationTicket)); var verifyModel = new VerificationMessageViewModel { SiteName = notifyModel.SiteName, Url = verificationUrl }; var verifyMessage = new MailMessage { To = { newEmail }, Subject = AccountResources.Model_EmailChangeVerificationMessageSubject, Body = RenderEmailView(Views.Email.Change._VerificationMessage, verifyModel) }; SendEmail(notifyMessage); SendEmail(verifyMessage); return new OperationResult(HttpStatusCode.Accepted, new ChangeResult(newEmail)); }
OperationResult<ResetResult> ResetImpl(ResetInput input) { if (input == null) throw new ArgumentNullException("input"); var errors = new ErrorBuilder(); if (errors.NotValid(input)) return errors; UserWrapper user = this.repo.FindUserByEmail(input.Email); MailMessage message; string destinationEmail; bool canResetPassword = user != null && !user.Disabled; if (canResetPassword) { user.PasswordResetTicketExpiration = this.Configuration.GetNow() .Add(this.Configuration.PasswordResetTicketExpiration); this.repo.UpdateUser(user); string verificationTicket = new VerificationData(user.Id, null).GetVerificationTicket(); string verificationUrl = AbsoluteUrl(this.Url.Action(Finish, verificationTicket)); var mailModel = new VerificationMessageViewModel { SiteName = GetSiteName(), Url = verificationUrl }; if (!EmailEquals(user.Email, user.Username)) mailModel.Username = user.Username; destinationEmail = user.Email; message = new MailMessage { To = { destinationEmail }, Subject = AccountResources.Model_PasswordResetVerificationMessageSubject, Body = RenderEmailView(Views.Password.Reset._VerificationMessage, mailModel) }; } else { destinationEmail = input.Email; var mailModel = new ErrorMessageViewModel { SiteName = GetSiteName(), ErrorReason = (user == null) ? ErrorReason.AccountNotFound : ErrorReason.AccountDisabled }; message = new MailMessage { To = { destinationEmail }, Subject = AccountResources.Model_PasswordResetVerificationMessageSubject, Body = RenderEmailView(Views.Password.Reset._ErrorMessage, mailModel) }; } SendEmail(message); return new OperationResult<ResetResult>(HttpStatusCode.Accepted, new ResetResult(destinationEmail)); }
OperationResult FinishImpl(string cipher, FinishInput input) { if (input == null) throw new ArgumentNullException("input"); var canFinishResult = CanFinish(cipher); if (canFinishResult.IsError) return canFinishResult; UserWrapper user = canFinishResult.ValueAsSuccess; var errors = new ErrorBuilder(); if (errors.NotValid(input) || !this.passServ.TrySetPassword(user, () => input.NewPassword, errors)) return errors; user.PasswordResetTicketExpiration = null; this.repo.UpdateUser(user); return HttpStatusCode.OK; }
OperationResult<string> ValidateUser(SignInInput input) { if (input == null) throw new ArgumentNullException("input"); var errors = new ErrorBuilder(); if (errors.NotValid(input)) return errors; string userPassNotMatchMessage = AccountResources.Validation_UserPassNotMatch.FormatInvariant(AccountResources.Model_Username); UserWrapper user = this.repo.FindUserByName(input.Username); if (errors.Not(user != null, userPassNotMatchMessage)) return errors; DateTime now = this.Configuration.GetNow(); if (!user.Password.HasValue()) return new OperationResult<string>(HttpStatusCode.Forbidden, AccountResources.Validation_MissingPasswordCannotAuthenticate); int maxInvalidAttempts = this.Configuration.MaxInvalidSignInAttempts; bool passwordCorrect = this.passServ.PasswordEquals(input.Password, user.Password); int failedAttempts = user.FailedSignInAttempts; if (passwordCorrect) { if (user.Disabled) return new OperationResult<string>(HttpStatusCode.Forbidden, AccountResources.Validation_UserDisabled); } else { if (user.Disabled) return new OperationResult<string>(HttpStatusCode.BadRequest, userPassNotMatchMessage); if (failedAttempts <= maxInvalidAttempts) { failedAttempts++; user.FailedSignInAttempts = failedAttempts; user.FailedSignInAttemptWindowStart = now; if (failedAttempts > maxInvalidAttempts && this.Configuration.DisableOnMaxInvalidSignInAttempts && !user.Disabled) { user.Disabled = true; } this.repo.UpdateUser(user); if (failedAttempts <= maxInvalidAttempts || user.Disabled) { return new OperationResult<string>(HttpStatusCode.BadRequest, userPassNotMatchMessage); } } } if (failedAttempts > maxInvalidAttempts) { DateTime lockEnd = user.FailedSignInAttemptWindowStart.GetValueOrDefault().Add(this.Configuration.SignInAttemptWindow); TimeSpan timeLeft = (lockEnd > now) ? lockEnd.Subtract(now) : TimeSpan.MinValue; double totalMinutes = timeLeft.TotalMinutes; double minutes = Math.Ceiling(totalMinutes); if (minutes > 0) { return new OperationResult<string>( HttpStatusCode.Forbidden, AccountResources.Validation_MaxInvalidSignInAttempts.FormatInvariant(minutes) ); } } if (passwordCorrect) { user.FailedSignInAttempts = 0; user.FailedSignInAttemptWindowStart = null; user.LastSignIn = now; } else { // Window passed but password is incorrect, restart failed attempts count user.FailedSignInAttempts = 1; user.FailedSignInAttemptWindowStart = now; } this.repo.UpdateUser(user); if (!passwordCorrect) return new OperationResult<string>(HttpStatusCode.BadRequest, userPassNotMatchMessage); return user.Username; }