private async Task <ResultWithError <ErrorData> > Process(
            RequestPasswordResetCommand request, CancellationToken cancellationToken)
        {
            var userMaybe = await this._userRepository.FindByEmailAddress(request.EmailAddress, cancellationToken);

            if (userMaybe.HasNoValue)
            {
                return(ResultWithError.Fail(new ErrorData(ErrorCodes.UserNotFound)));
            }

            var user = userMaybe.Value;

            if (!user.IsVerified)
            {
                return(ResultWithError.Fail(new ErrorData(ErrorCodes.AccountNotVerified)));
            }

            if (user.IsDisabled)
            {
                return(ResultWithError.Fail(new ErrorData(ErrorCodes.AccountIsDisabled)));
            }

            var whenHappened = this._clock.GetCurrentInstant().ToDateTimeUtc();

            var token = user.GenerateNewPasswordResetToken(
                whenHappened,
                TimeSpan.FromHours(this._securitySettings.PasswordTokenLifetime));

            user.AddDomainEvent(new PasswordResetTokenGeneratedEvent(user.EmailAddress, user.Profile.FirstName, user.Profile.LastName, token));

            this._userRepository.Update(user);
            return(ResultWithError.Ok <ErrorData>());
        }
        private async Task <ResultWithError <ErrorData> > Process(RequestPasswordResetCommand request, CancellationToken cancellationToken)
        {
            var whenHappened = this._clock.GetCurrentInstant().ToDateTimeUtc();

            var userMaybe = await this._userRepository.FindByEmailAddress(request.EmailAddress, cancellationToken);

            if (userMaybe.HasNoValue)
            {
                return(ResultWithError.Fail(new ErrorData(ErrorCodes.UserNotFound)));
            }

            var user = userMaybe.Value;

            if (!user.IsVerified)
            {
                return(ResultWithError.Fail(new ErrorData(
                                                ErrorCodes.UserIsNotVerified)));
            }

            var token = user.GenerateNewPasswordResetToken(
                whenHappened,
                whenHappened.AddHours(this._identitySettings.PasswordTokenLifetime));

            this._userRepository.Update(user);
            return(ResultWithError.Ok <ErrorData>());
        }
        public async Task Handle_GivenUserIsNotFound_ExpectFailedResult()
        {
            var clock          = new Mock <IClock>();
            var userRepository = new Mock <IUserRepository>();
            var unitOfWork     = new Mock <IUnitOfWork>();

            unitOfWork.Setup(x => x.SaveEntitiesAsync(It.IsAny <CancellationToken>())).ReturnsAsync(() => true);
            userRepository.Setup(x => x.UnitOfWork).Returns(unitOfWork.Object);
            userRepository.Setup(x => x.FindByEmailAddress(It.IsAny <string>(), It.IsAny <CancellationToken>()))
            .ReturnsAsync(() => Maybe <IUser> .Nothing);

            var securitySettings = new Mock <IOptions <SecuritySettings> >();

            securitySettings.Setup(x => x.Value).Returns(new SecuritySettings
            {
                PasswordTokenLifetime = 3,
            });

            var handler =
                new RequestPasswordResetCommandHandler(userRepository.Object, clock.Object, securitySettings.Object);
            var cmd    = new RequestPasswordResetCommand("email-address");
            var result = await handler.Handle(cmd, CancellationToken.None);

            Assert.True(result.IsFailure);
            Assert.Equal(ErrorCodes.UserNotFound, result.Error.Code);
        }
        public async Task Handle_GivenSavingSucceeds_ExpectSuccessfulResult()
        {
            var user = new Mock <IUser>();

            user.Setup(x => x.Profile).Returns(new Profile(Guid.NewGuid(), "first-name", "last-name"));
            user.Setup(x => x.IsDisabled).Returns(false);
            user.Setup(x => x.IsVerified).Returns(true);
            var clock          = new Mock <IClock>();
            var userRepository = new Mock <IUserRepository>();
            var unitOfWork     = new Mock <IUnitOfWork>();

            unitOfWork.Setup(x => x.SaveEntitiesAsync(It.IsAny <CancellationToken>())).ReturnsAsync(() => true);
            userRepository.Setup(x => x.UnitOfWork).Returns(unitOfWork.Object);
            userRepository.Setup(x => x.FindByEmailAddress(It.IsAny <string>(), It.IsAny <CancellationToken>()))
            .ReturnsAsync(() => Maybe.From(user.Object));

            var securitySettings = new Mock <IOptions <SecuritySettings> >();

            securitySettings.Setup(x => x.Value).Returns(new SecuritySettings
            {
                PasswordTokenLifetime = 3,
            });

            var handler =
                new RequestPasswordResetCommandHandler(userRepository.Object, clock.Object, securitySettings.Object);
            var cmd    = new RequestPasswordResetCommand("email-address");
            var result = await handler.Handle(cmd, CancellationToken.None);

            Assert.True(result.IsSuccess);
        }
        public async Task Handle_GivenUserIsFound_ExpectCallToGenerateTokenAndSuccessfulResultAndDomainEventRaised()
        {
            var user = new Mock <IUser>();

            user.Setup(x => x.Profile).Returns(new Profile(Guid.NewGuid(), "first-name", "last-name"));
            user.Setup(x => x.IsDisabled).Returns(false);
            user.Setup(x => x.IsVerified).Returns(true);
            var clock          = new Mock <IClock>();
            var userRepository = new Mock <IUserRepository>();
            var unitOfWork     = new Mock <IUnitOfWork>();

            unitOfWork.Setup(x => x.SaveEntitiesAsync(It.IsAny <CancellationToken>())).ReturnsAsync(() => true);
            userRepository.Setup(x => x.UnitOfWork).Returns(unitOfWork.Object);

            userRepository.Setup(x => x.FindByEmailAddress(It.IsAny <string>(), It.IsAny <CancellationToken>()))
            .ReturnsAsync(() => Maybe.From(user.Object));

            var securitySettings = new Mock <IOptions <SecuritySettings> >();

            securitySettings.Setup(x => x.Value).Returns(new SecuritySettings
            {
                PasswordTokenLifetime = 3,
            });

            var handler =
                new RequestPasswordResetCommandHandler(userRepository.Object, clock.Object, securitySettings.Object);
            var cmd    = new RequestPasswordResetCommand("email-address");
            var result = await handler.Handle(cmd, CancellationToken.None);

            Assert.True(result.IsSuccess);
            user.Verify(x => x.GenerateNewPasswordResetToken(It.IsAny <DateTime>(), It.IsAny <TimeSpan>()), Times.Once);
            userRepository.Verify(x => x.Update(It.IsAny <IUser>()), Times.Once);
            user.Verify(x => x.AddDomainEvent(It.IsAny <PasswordResetTokenGeneratedEvent>()));
        }
        public void Validate_GivenAllPropertiesAreValid_ExpectValidationSuccess()
        {
            var cmd       = new RequestPasswordResetCommand("*****@*****.**");
            var validator = new RequestPasswordResetCommandValidator();
            var result    = validator.Validate(cmd);

            Assert.True(result.IsValid);
        }
示例#7
0
        public async Task WhenEmailDoesNotExist_ItShouldDoNothing()
        {
            var command = new RequestPasswordResetCommand(ValidEmail.Parse(EmailAddress), null);

            this.userManager.Setup(_ => _.FindByEmailAsync(EmailAddress)).ReturnsAsync(null);

            await this.target.HandleAsync(command);
        }
示例#8
0
        public async Task WhenUsernameDoesNotExist_ItShouldDoNothing()
        {
            var command = new RequestPasswordResetCommand(null, ValidUsername.Parse(Username));

            this.userManager.Setup(_ => _.FindByNameAsync(Username)).ReturnsAsync(null);

            await this.target.HandleAsync(command);
        }
        public void Validate_GivenEmailAddressIsNull_ExpectValidationFailure()
        {
            var cmd       = new RequestPasswordResetCommand(null);
            var validator = new RequestPasswordResetCommandValidator();
            var result    = validator.Validate(cmd);

            Assert.False(result.IsValid);
            Assert.Contains(
                result.Errors,
                failure => failure.ErrorCode.Equals(ValidationCodes.FieldIsRequired) &&
                failure.PropertyName == "EmailAddress");
        }
示例#10
0
        public async Task WhenUsernameExists_ItShouldSendEmail()
        {
            var command = new RequestPasswordResetCommand(null, ValidUsername.Parse(Username));

            this.userManager.Setup(_ => _.FindByNameAsync(Username)).ReturnsAsync(new FifthweekUser()
            {
                Id       = UserId,
                UserName = Username
            });

            await this.AssertEmailSent(command);
        }
        public void Validate_GivenEmailAddressIsNotAnEmailAddress_ExpectValidationFailure()
        {
            var cmd       = new RequestPasswordResetCommand("email-address");
            var validator = new RequestPasswordResetCommandValidator();
            var result    = validator.Validate(cmd);

            Assert.False(result.IsValid);
            Assert.Contains(
                result.Errors,
                failure => failure.ErrorCode.Equals(ValidationCodes.ValueMustBeAnEmailAddress) &&
                failure.PropertyName == "EmailAddress");
        }
示例#12
0
        public async Task WhenEmailExists_ItShouldSendEmail()
        {
            var command = new RequestPasswordResetCommand(ValidEmail.Parse(EmailAddress), null);

            this.userManager.Setup(_ => _.FindByEmailAsync(EmailAddress)).ReturnsAsync(new FifthweekUser()
            {
                Id       = UserId,
                UserName = Username
            });

            await this.AssertEmailSent(command);
        }
示例#13
0
        public async Task <IHttpActionResult> PostPasswordResetRequestAsync(PasswordResetRequestData passwordResetRequestData)
        {
            passwordResetRequestData.AssertBodyProvided("passwordResetRequestData");
            var passwordResetRequest = passwordResetRequestData.Parse();

            var command = new RequestPasswordResetCommand(
                passwordResetRequest.Email,
                passwordResetRequest.Username);

            await this.requestPasswordReset.HandleAsync(command);

            return(this.Ok());
        }
        public async Task <ResultWithError <ErrorData> > Handle(RequestPasswordResetCommand request, CancellationToken cancellationToken)
        {
            var result = await this.Process(request, cancellationToken);

            var dbResult = await this._userRepository.UnitOfWork.SaveEntitiesAsync(cancellationToken);

            if (!dbResult)
            {
                return(ResultWithError.Fail(new ErrorData(
                                                ErrorCodes.SavingChanges, "Failed To Save Database")));
            }

            return(result);
        }
示例#15
0
        private async Task AssertEmailSent(RequestPasswordResetCommand command)
        {
            this.userManager.Setup(_ => _.GeneratePasswordResetTokenAsync(UserId)).ReturnsAsync(Token);

            this.userManager.Setup(_ =>
                                   _.SendEmailAsync(
                                       UserId,
                                       EmailSubject,
                                       It.Is <string>(emailBody => emailBody.Contains(activationLink) && emailBody.Contains(Username))))
            .Returns(Task.FromResult(0))
            .Verifiable();

            await this.target.HandleAsync(command);

            this.userManager.Verify();
        }
示例#16
0
        public void Constructor_GiveValidArguments_PropertiesAreSet()
        {
            var requestPasswordResetCommand = new RequestPasswordResetCommand("email-address");

            Assert.Equal("email-address", requestPasswordResetCommand.EmailAddress);
        }
示例#17
0
        public async Task WhenUsernameAndEmailAreNotProvided_ItShouldDoNothing()
        {
            var command = new RequestPasswordResetCommand(null, null);

            await this.target.HandleAsync(command);
        }