public AuthenticationResult Authenticate(Credentials credentials)
        {
            try
            {
                var user = GetUser(credentials.Email);
                var authCollection = GetUserAuthCollection(user);
                var validateResult = ValidateCredentials(authCollection, credentials.Password);

                switch (validateResult)
                {
                    case ValidateResult.Valid:
                        ResetLoginAttempts(authCollection);
                        return new AuthenticationResult
                        {
                            WasSuccessful = true,
                            UserAccount = _translateDataUserToUserAccount.Translate(user)
                        };
                    case ValidateResult.Invalid:
                        ProcessFailedAttempt(authCollection);
                        break;
                    case ValidateResult.LockAccount:
                        LockAccount(authCollection);
                        break;
                }
            }
            catch (Exception ex)
            {
                //TODO: Do Logging
            }

            return new AuthenticationResult
            {
                WasSuccessful = false
            };
        }
        /// <summary>
        /// Business Requirements:
        /// 1. Should not create account if email is in use.
        /// 2. Should use repository to get new user model.
        /// 3. Should call Create on repository.
        /// 4. Should call Save on repository.
        /// 5. Should assign email, first name, and last name to new user model.
        /// 6. Should setup new credentials.
        /// </summary>
        public UserAccount CreateAccount(UserAccount newAccount, Credentials newCredentials)
        {
            VerifyEmailIsntInUse(newAccount);

            var newUser = _userCreator.New();
            newUser.Email = newAccount.Email;
            newUser.FirstName = newAccount.FirstName;
            newUser.LastName = newAccount.LastName;

            _userCreator.Create(newUser);
            _userCreator.Save();

            var userAccount = _translateDataUserToUserAccount.Translate(newUser);

            _userAuthProvider.SetupNewCredentials(userAccount, newCredentials);

            return userAccount;
        }
        public void Should_Return_Account()
        {
            //Data Layer Arrange
            var dataUser = new User
            {
                CreationDate = new DateTime(2000, 01, 20),
                Email = "*****@*****.**",
                FirstName = "Jack",
                LastName = "Hoffman",
                UserId = "551581bf90eb291bd0e97fb2",
                LastLogin = new DateTime(2012, 10, 31)
            };

            MockRetrievableUserById
                .Setup(x => x.Retrieve(It.IsAny<ByUserId>()))
                .Returns(dataUser);

            MockRetrievableUserByEmail
                .Setup(x => x.Retrieve(It.IsAny<ByUserEmail>()))
                .Returns(dataUser);

            MockRetrievableAuthyId
                .Setup(x => x.RetrieveAll(It.IsAny<ByEncodedUserId>()))
                .Returns(new List<UserAuthentication>
                {
                    new UserAuthentication
                    {
                        AccountActive = true,
                        AccountType = AccountType.ActualAccount,
                        EncodedPassword = "******",
                        EncodedUserId = "Yvf08ew7hUptyomgslYIYhQmJ+jhUM/nrgQtbJgnW50=",
                        EncryptionKey = "ApplePear",
                        FailedLoginAttemptCount = 0
                    },
                    new UserAuthentication
                    {
                        AccountActive = true,
                        AccountType = AccountType.Trap1Account,
                        EncodedPassword = "******",
                        EncodedUserId = "Yvf08ew7hUptyomgslYIYhQmJ+jhUM/nrgQtbJgnW50=",
                        EncryptionKey = "PearBanana",
                        FailedLoginAttemptCount = 0
                    },
                    new UserAuthentication
                    {
                        AccountActive = true,
                        AccountType = AccountType.Trap2Account,
                        EncodedPassword = "******",
                        EncodedUserId = "Yvf08ew7hUptyomgslYIYhQmJ+jhUM/nrgQtbJgnW50=",
                        EncryptionKey = "BananaGrape",
                        FailedLoginAttemptCount = 0
                    },
                    new UserAuthentication
                    {
                        AccountActive = true,
                        AccountType = AccountType.Trap3Account,
                        EncodedPassword = "******",
                        EncodedUserId = "Yvf08ew7hUptyomgslYIYhQmJ+jhUM/nrgQtbJgnW50=",
                        EncryptionKey = "GrapeApple",
                        FailedLoginAttemptCount = 0
                    }
                });

            //arrange
            MockSystemTime
                .Setup(x => x.Current())
                .Returns(new DateTime(2015, 12, 2, 0, 0, 0, DateTimeKind.Utc));

            var input = new Credentials
            {
                Email = "*****@*****.**",
                Password = "******"
            };

            var expected = new UserAccount
            {
                Email = "*****@*****.**",
                FirstName = "Jack",
                LastName = "Hoffman",
                UserId = "551581bf90eb291bd0e97fb2"
            };

            UserAccount actual;

            //act
            actual = Subject.RetrieveAccount(input);

            //assert
            Assert.AreEqual(expected.Email, actual.Email, string.Format("Expected Email of {0}, actual was {1}", expected.Email, actual.Email));
            Assert.AreEqual(expected.FirstName, actual.FirstName, string.Format("Expected FirstName of {0}, actual was {1}", expected.FirstName, actual.FirstName));
            Assert.AreEqual(expected.LastName, actual.LastName, string.Format("Expected LastName of {0}, actual was {1}", expected.LastName, actual.LastName));
            Assert.AreEqual(expected.UserId, actual.UserId, string.Format("Expected UserId of {0}, actual was {1}", expected.UserId, actual.UserId));
        }
        public void Should_Process_Failed_Attempt()
        {
            var dataUser = new User
            {
                CreationDate = new DateTime(2000, 01, 20),
                Email = "*****@*****.**",
                FirstName = "Jack",
                LastName = "Hoffman",
                UserId = "551581bf90eb291bd0e97fb2",
                LastLogin = new DateTime(2012, 10, 31)
            };

            MockRetrievableUserById
                .Setup(x => x.Retrieve(It.IsAny<ByUserId>()))
                .Returns(dataUser);

            MockRetrievableUserByEmail
                .Setup(x => x.Retrieve(It.IsAny<ByUserEmail>()))
                .Returns(dataUser);

            MockRetrievableAuthyId
                .Setup(x => x.RetrieveAll(It.IsAny<ByEncodedUserId>()))
                .Returns(new List<UserAuthentication>
                {
                    new UserAuthentication
                    {
                        AccountActive = true,
                        AccountType = AccountType.ActualAccount,
                        EncodedPassword = "******",
                        EncodedUserId = "Yvf08ew7hUptyomgslYIYhQmJ+jhUM/nrgQtbJgnW50=",
                        EncryptionKey = "ApplePear",
                        FailedLoginAttemptCount = 0
                    },
                    new UserAuthentication
                    {
                        AccountActive = true,
                        AccountType = AccountType.Trap1Account,
                        EncodedPassword = "******",
                        EncodedUserId = "Yvf08ew7hUptyomgslYIYhQmJ+jhUM/nrgQtbJgnW50=",
                        EncryptionKey = "PearBanana",
                        FailedLoginAttemptCount = 0
                    },
                    new UserAuthentication
                    {
                        AccountActive = true,
                        AccountType = AccountType.Trap2Account,
                        EncodedPassword = "******",
                        EncodedUserId = "Yvf08ew7hUptyomgslYIYhQmJ+jhUM/nrgQtbJgnW50=",
                        EncryptionKey = "BananaGrape",
                        FailedLoginAttemptCount = 0
                    },
                    new UserAuthentication
                    {
                        AccountActive = true,
                        AccountType = AccountType.Trap3Account,
                        EncodedPassword = "******",
                        EncodedUserId = "Yvf08ew7hUptyomgslYIYhQmJ+jhUM/nrgQtbJgnW50=",
                        EncryptionKey = "GrapeApple",
                        FailedLoginAttemptCount = 0
                    }
                });

            //arrange
            MockSystemTime
                .Setup(x => x.Current())
                .Returns(new DateTime(2015, 12, 2, 0, 0, 0, DateTimeKind.Utc));

            var input = new Credentials
            {
                Email = "*****@*****.**",
                Password = "******"
            };

            UserAccount actual;

            //act
            actual = Subject.RetrieveAccount(input);

            //assert
            MockUpdatableAuth.Verify(x=>x.Update(It.Is<UserAuthentication>(i=> i.FailedLoginAttemptCount == 1)), Times.Exactly(4));
            MockUpdatableAuth.Verify(x=>x.Save(),Times.Once);
        }
        public void DeleteAccount(UserAccount existingAccount, Credentials existCredentials)
        {
            var authenticationResult = _userAuthProvider.Authenticate(existCredentials);
            if (authenticationResult.WasSuccessful)
            {
                _userAuthProvider.DeleteCredentials(existCredentials);

                var query = new ByUserId
                {
                    UserId = existingAccount.UserId
                };

                var existingUser = _userGetByUserId.Retrieve(query);
                _userDeleter.Delete(existingUser);
            }
        }
        public UserAccount UpdateAccount(UserAccount existingAccount, Credentials existCredentials)
        {
            var query = new ByUserId
            {
                UserId = existingAccount.UserId
            };

            var updatedUser = _userGetByUserId.Retrieve(query);

            updatedUser.Email = existingAccount.Email;
            updatedUser.FirstName = existingAccount.FirstName;
            updatedUser.LastName = existingAccount.LastName;

            _userUpdater.Update(updatedUser);
            _userUpdater.Save();

            return _translateDataUserToUserAccount.Translate(updatedUser);
        }
 public UserAccount RetrieveAccount(Credentials existingCredentials)
 {
     var authenticationResult = _userAuthProvider.Authenticate(existingCredentials);
     if (authenticationResult.WasSuccessful)
     {
         UpdateLastLogin(authenticationResult.UserAccount.UserId);
         return authenticationResult.UserAccount;
     }
     return null;
 }
        public void SetupNewCredentials(UserAccount userAccount, Credentials credentials)
        {
            string encodedUserId = EncryptionHandler.Encrypt(userAccount.UserId, userAccount.UserId);

            var actualCredentials = _userAuthCreator.New();
            actualCredentials.AccountType = AccountType.ActualAccount;
            actualCredentials.EncodedUserId = encodedUserId;
            actualCredentials.EncodedPassword = EncryptionHandler.Encrypt(credentials.Password, actualCredentials.EncryptionKey);
            _userAuthCreator.Create(actualCredentials);

            var trap1Credentials = _userAuthCreator.New();
            trap1Credentials.AccountType = AccountType.Trap1Account;
            trap1Credentials.EncodedUserId = encodedUserId;
            trap1Credentials.EncodedPassword = EncryptionHandler.Encrypt(_passwords.GeneratePassword(8,2), trap1Credentials.EncryptionKey);
            _userAuthCreator.Create(trap1Credentials);

            var trap2Credentials = _userAuthCreator.New();
            trap2Credentials.AccountType = AccountType.Trap2Account;
            trap2Credentials.EncodedUserId = encodedUserId;
            trap2Credentials.EncodedPassword = EncryptionHandler.Encrypt(_passwords.GeneratePassword(10, 3), trap2Credentials.EncryptionKey);
            _userAuthCreator.Create(trap2Credentials);

            var trap3Credentials = _userAuthCreator.New();
            trap3Credentials.AccountType = AccountType.Trap3Account;
            trap3Credentials.EncodedUserId = encodedUserId;
            trap3Credentials.EncodedPassword = EncryptionHandler.Encrypt(_passwords.GeneratePassword(7, 1), trap3Credentials.EncryptionKey);
            _userAuthCreator.Create(trap3Credentials);
        }
        public void DeleteCredentials(Credentials credentials)
        {
            try
            {
                var user = GetUser(credentials.Email);
                var authCollection = GetUserAuthCollection(user);
                var validateResult = ValidateCredentials(authCollection, credentials.Password);

                if (validateResult == ValidateResult.Valid)
                {
                    foreach (var authCredential in authCollection)
                    {
                        _userAuthDeleter.Delete(authCredential);
                    }
                }
            }
            catch (Exception ex)
            {
                //TODO: Do Logging
            }
        }