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