public async Task Add_Should_Add_New_Login_Just_After_UserManager_CreateAsync_Get_Called()
        {
            const string userName = "******";
            const string loginProvider = "Twitter";
            const string providerKey = "12345678";

            using (IDocumentStore store = CreateEmbeddableStore())
            {
                using (IAsyncDocumentSession ses = store.OpenAsyncSession())
                {
                    ses.Advanced.UseOptimisticConcurrency = true;
                    RavenUserStore<RavenUser> userStore = new RavenUserStore<RavenUser>(ses);
                    UserManager<RavenUser> userManager = new UserManager<RavenUser>(userStore);

                    RavenUser user = new RavenUser(userName);
                    UserLoginInfo loginToAdd = new UserLoginInfo(loginProvider, providerKey);
                    await userManager.CreateAsync(user);
                    await userManager.AddLoginAsync(user.Id, loginToAdd);
                    await ses.SaveChangesAsync();
                }

                using (IAsyncDocumentSession ses = store.OpenAsyncSession())
                {
                    ses.Advanced.UseOptimisticConcurrency = true;
                    IUserLoginStore<RavenUser, string> userLoginStore = new RavenUserStore<RavenUser>(ses);
                    RavenUser user = await ses.LoadAsync<RavenUser>(RavenUser.GenerateKey(userName));
                    RavenUserLogin foundLogin = await ses.LoadAsync<RavenUserLogin>(RavenUserLogin.GenerateKey(loginProvider, providerKey));

                    // Assert
                    Assert.Equal(1, user.Logins.Count());
                    Assert.NotNull(foundLogin);
                }
            }
        }
        public async Task RavenUserStore_Users_Should_Expose_IQueryable_Over_IRavenQueryable()
        {
            using (IDocumentStore store = CreateEmbeddableStore())
            {
                const string userName = "******";
                const string userNameToSearch = "TugberkUgurlu";

                using (IAsyncDocumentSession ses = store.OpenAsyncSession())
                {
                    ses.Advanced.UseOptimisticConcurrency = true;
                    RavenUser user = new RavenUser(userName);
                    RavenUser userToSearch = new RavenUser(userNameToSearch);
                    await ses.StoreAsync(user);
                    await ses.StoreAsync(userToSearch);
                    await ses.SaveChangesAsync();
                }

                using (IAsyncDocumentSession ses = store.OpenAsyncSession())
                {
                    // Act
                    ses.Advanced.UseOptimisticConcurrency = true;
                    RavenUserStore<RavenUser> userStore = new RavenUserStore<RavenUser>(ses);
                    RavenUser retrievedUser = await userStore.Users.FirstOrDefaultAsync(user => user.UserName == userNameToSearch);

                    // Assert
                    Assert.NotNull(retrievedUser);
                    Assert.Equal(userNameToSearch, retrievedUser.UserName);
                }
            }
        }
        public async Task GetUserClaims_Should_Retrieve_Correct_Claims_For_User()
        {
            string userName = "******";
            string userId = "RavenUsers/1";

            using (IDocumentStore store = CreateEmbeddableStore())
            using (IAsyncDocumentSession ses = store.OpenAsyncSession())
            {
                IUserClaimStore<RavenUser> userClaimStore = new RavenUserStore<RavenUser>(ses);
                IEnumerable<RavenUserClaim> claims = new List<RavenUserClaim>
                {
                    new RavenUserClaim { ClaimType = "Scope", ClaimValue = "Read" },
                    new RavenUserClaim { ClaimType = "Scope", ClaimValue = "Write" }
                };
                RavenUser user = new RavenUser
                {
                    Id = userId,
                    UserName = userName
                };

                foreach (var claim in claims)
                {
                    user.Claims.Add(claim);
                }

                await ses.StoreAsync(user);
                await ses.SaveChangesAsync();

                IEnumerable<Claim> retrievedClaims = await userClaimStore.GetClaimsAsync(user);

                Assert.Equal(2, claims.Count());
                Assert.Equal("Read", claims.ElementAt(0).ClaimValue);
                Assert.Equal("Write", claims.ElementAt(1).ClaimValue);
            }
        }
        public async Task GetUserClaims_Should_Not_Return_Null_If_User_Has_No_Claims()
        {
            string userName = "******";
            string userId = "RavenUsers/1";

            using (IDocumentStore store = CreateEmbeddableStore())
            using (IAsyncDocumentSession ses = store.OpenAsyncSession())
            {
                IUserClaimStore<RavenUser> userClaimStore = new RavenUserStore<RavenUser>(ses, false);
                RavenUser user = new RavenUser
                {
                    Id = userId,
                    UserName = userName
                };

                await ses.StoreAsync(user);
                await ses.SaveChangesAsync();

                // Act
                IEnumerable<Claim> retrievedClaims = await userClaimStore.GetClaimsAsync(user);

                // Assert
                Assert.Equal(0, retrievedClaims.Count());
            }
        }
        public async Task SetTwoFactorEnabledAsync_Should_Set_IsTwoFactorEnabled_Value()
        {
            using (IDocumentStore store = CreateEmbeddableStore())
            {
                const string userName = "******";
                const string userId = "RavenUsers/Tugberk";

                using (IAsyncDocumentSession ses = store.OpenAsyncSession())
                {
                    ses.Advanced.UseOptimisticConcurrency = true;
                    RavenUser user = new RavenUser(userName);
                    user.EnableTwoFactorAuthentication();
                    await ses.StoreAsync(user);
                    await ses.SaveChangesAsync();
                }

                using (IAsyncDocumentSession ses = store.OpenAsyncSession())
                {
                    // Act
                    ses.Advanced.UseOptimisticConcurrency = true;
                    RavenUser user = await ses.LoadAsync<RavenUser>(userId);
                    IUserTwoFactorStore<RavenUser, string> userTwoFactorStore = new RavenUserStore<RavenUser>(ses);
                    await userTwoFactorStore.SetTwoFactorEnabledAsync(user, enabled: true);

                    // Assert
                    Assert.True(user.IsTwoFactorEnabled);
                }
            }
        }
        public async Task FindByEmailAsync_Should_Return_Null_If_User_Is_Not_Available()
        {
            const string userName = "******";
            const string email = "*****@*****.**";
            const string emailToLookFor = "*****@*****.**";

            using (IDocumentStore store = CreateEmbeddableStore())
            {
                using (IAsyncDocumentSession ses = store.OpenAsyncSession())
                {
                    ses.Advanced.UseOptimisticConcurrency = true;
                    RavenUser user = new RavenUser(userName, email);
                    RavenUserEmail userEmail = new RavenUserEmail(email, user.Id);
                    await ses.StoreAsync(user);
                    await ses.StoreAsync(userEmail);
                    await ses.SaveChangesAsync();
                }

                using (IAsyncDocumentSession ses = store.OpenAsyncSession())
                {
                    ses.Advanced.UseOptimisticConcurrency = true;
                    IUserEmailStore<RavenUser> userEmailStore = new RavenUserStore<RavenUser>(ses);
                    RavenUser user = await userEmailStore.FindByEmailAsync(emailToLookFor);

                    Assert.Null(user);
                }
            }
        }
        public async Task Add_Should_Add_New_Login_If_User_Exists()
        {
            string userName = "******";

            using (IDocumentStore store = CreateEmbeddableStore())
            using (IAsyncDocumentSession ses = store.OpenAsyncSession())
            {
                IUserLoginStore<RavenUser> userLoginStore = new RavenUserStore<RavenUser>(ses);
                RavenUser user = new RavenUser { Id = "RavenUsers/1", UserName = userName };
                await ses.StoreAsync(user);
                await ses.SaveChangesAsync();

                // Act
                UserLoginInfo loginToAdd = new UserLoginInfo("Local", userName);
                await userLoginStore.AddLoginAsync(user, new UserLoginInfo("Local", userName));

                // Assert
                Assert.Equal(1, user.Logins.Count);
            }
        }
        public async Task GetUserClaims_Should_Retrieve_Correct_Claims_For_User()
        {
            string userName = "******";

            using (IDocumentStore store = CreateEmbeddableStore())
            {
                RavenUser user = new RavenUser(userName);
                IEnumerable<RavenUserClaim> claims = new List<RavenUserClaim>
                {
                    new RavenUserClaim("Scope", "Read"),
                    new RavenUserClaim("Scope", "Write")
                };

                foreach (RavenUserClaim claim in claims)
                {
                    user.AddClaim(claim);
                }

                using (IAsyncDocumentSession ses = store.OpenAsyncSession())
                {
                    ses.Advanced.UseOptimisticConcurrency = true;
                    IUserClaimStore<RavenUser> userClaimStore = new RavenUserStore<RavenUser>(ses);

                    await ses.StoreAsync(user);
                    await ses.SaveChangesAsync();
                }

                using (IAsyncDocumentSession ses = store.OpenAsyncSession())
                {
                    ses.Advanced.UseOptimisticConcurrency = true;
                    IUserClaimStore<RavenUser> userClaimStore = new RavenUserStore<RavenUser>(ses);
                    IEnumerable<Claim> retrievedClaims = await userClaimStore.GetClaimsAsync(user);

                    Assert.Equal(2, claims.Count());
                    Assert.Equal("Read", claims.ElementAt(0).ClaimValue);
                    Assert.Equal("Write", claims.ElementAt(1).ClaimValue);
                }
            }
        }
        public async Task RemoveClaimAsync_Should_Remove_Claim_From_The_User_Claims_Collection()
        {
            string userName = "******";

            using (IDocumentStore store = CreateEmbeddableStore())
            using(IAsyncDocumentSession ses = store.OpenAsyncSession())
            {
                // Arrange
                ses.Advanced.UseOptimisticConcurrency = true;
                IUserClaimStore<RavenUser> userClaimStore = new RavenUserStore<RavenUser>(ses, false);
                RavenUser user = new RavenUser(userName);

                Claim claimToAddAndRemove = new Claim(ClaimTypes.Role, "Customer");
                user.AddClaim(new RavenUserClaim(claimToAddAndRemove));

                await ses.StoreAsync(user);
                await ses.SaveChangesAsync();

                // Act
                await userClaimStore.RemoveClaimAsync(user, claimToAddAndRemove);

                // Assert
                Assert.Equal(0, user.Claims.Count());
            }
        }
        public async Task FindAsync_Should_Find_The_User_If_Login_Exists()
        {
            const string userName = "******";
            const string loginProvider = "Twitter";
            const string providerKey = "12345678";

            using (IDocumentStore store = CreateEmbeddableStore())
            {
                // Arrange
                using (IAsyncDocumentSession ses = store.OpenAsyncSession())
                {
                    ses.Advanced.UseOptimisticConcurrency = true;
                    IUserLoginStore<RavenUser, string> userLoginStore = new RavenUserStore<RavenUser>(ses);
                    RavenUser user = new RavenUser(userName);
                    RavenUserLogin userLogin = new RavenUserLogin(user.Id, new UserLoginInfo(loginProvider, providerKey));
                    user.AddLogin(userLogin);
                    await ses.StoreAsync(user);
                    await ses.StoreAsync(userLogin);
                    await ses.SaveChangesAsync();
                }

                using (IAsyncDocumentSession ses = store.OpenAsyncSession())
                {
                    ses.Advanced.UseOptimisticConcurrency = true;
                    IUserLoginStore<RavenUser, string> userLoginStore = new RavenUserStore<RavenUser>(ses);

                    // Act
                    UserLoginInfo loginInfo = new UserLoginInfo(loginProvider, providerKey);
                    RavenUser foundUser = await userLoginStore.FindAsync(loginInfo);

                    // Assert
                    Assert.NotNull(foundUser);
                    Assert.Equal(userName, foundUser.UserName);
                }
            }
        }
        public async Task SetEmailAsync_Should_Set_The_Email_Correctly()
        {
            const string userName = "******";
            const string userId = "RavenUsers/Tugberk";
            const string emailToSave = "*****@*****.**";

            using (IDocumentStore store = CreateEmbeddableStore())
            {
                using (IAsyncDocumentSession ses = store.OpenAsyncSession())
                {
                    ses.Advanced.UseOptimisticConcurrency = true;
                    RavenUser user = new RavenUser(userName) { UserName = userName };
                    await ses.StoreAsync(user);
                    await ses.SaveChangesAsync();
                }

                using (IAsyncDocumentSession ses = store.OpenAsyncSession())
                {
                    ses.Advanced.UseOptimisticConcurrency = true;
                    IUserEmailStore<RavenUser> userEmailStore = new RavenUserStore<RavenUser>(ses);
                    RavenUser ravenUser = await ses.LoadAsync<RavenUser>(userId);
                    await userEmailStore.SetEmailAsync(ravenUser, emailToSave);
                    await ses.SaveChangesAsync();
                }

                using (IAsyncDocumentSession ses = store.OpenAsyncSession())
                {
                    ses.Advanced.UseOptimisticConcurrency = true;
                    string keyToLookFor = RavenUserEmail.GenerateKey(emailToSave);
                    RavenUser ravenUser = await ses.LoadAsync<RavenUser>(userId);
                    RavenUserEmail userEmail = await ses.LoadAsync<RavenUserEmail>(keyToLookFor);

                    Assert.NotNull(userEmail);
                    Assert.Equal(emailToSave, ravenUser.Email);
                    Assert.Equal(emailToSave, userEmail.Email);
                    Assert.Equal(userId, userEmail.UserId);
                }
            }
        }
        public async Task GetEmailAsync_Should_Return_User_Email_If_Available()
        {
            const string userName = "******";
            const string userId = "RavenUsers/Tugberk";
            const string email = "*****@*****.**";

            using (IDocumentStore store = CreateEmbeddableStore())
            {
                using (IAsyncDocumentSession ses = store.OpenAsyncSession())
                {
                    ses.Advanced.UseOptimisticConcurrency = true;
                    RavenUser user = new RavenUser(userName, email);
                    RavenUserEmail userEmail = new RavenUserEmail(email, user.Id);
                    await ses.StoreAsync(user);
                    await ses.StoreAsync(userEmail);
                    await ses.SaveChangesAsync();
                }

                using (IAsyncDocumentSession ses = store.OpenAsyncSession())
                {
                    ses.Advanced.UseOptimisticConcurrency = true;
                    IUserEmailStore<RavenUser> userEmailStore = new RavenUserStore<RavenUser>(ses);
                    RavenUser ravenUser = await ses.LoadAsync<RavenUser>(userId);
                    string userEmail = await userEmailStore.GetEmailAsync(ravenUser);

                    Assert.NotNull(userEmail);
                    Assert.Equal(email, userEmail);
                }
            }
        }
        public async Task SetEmailConfirmedAsync_Should_Throw_InvalidOperationException_If_User_Email_Property_Is_Available_But_UserEmail_Document_Not()
        {
            const string userName = "******";
            const string userId = "RavenUsers/Tugberk";
            const string email = "*****@*****.**";

            using (IDocumentStore store = CreateEmbeddableStore())
            {
                using (IAsyncDocumentSession ses = store.OpenAsyncSession())
                {
                    ses.Advanced.UseOptimisticConcurrency = true;
                    RavenUser user = new RavenUser(userName, email);
                    await ses.StoreAsync(user);
                    await ses.SaveChangesAsync();
                }

                using (IAsyncDocumentSession ses = store.OpenAsyncSession())
                {
                    ses.Advanced.UseOptimisticConcurrency = true;
                    IUserEmailStore<RavenUser> userEmailStore = new RavenUserStore<RavenUser>(ses);
                    RavenUser ravenUser = await ses.LoadAsync<RavenUser>(userId);

                    await Assert.ThrowsAsync<InvalidOperationException>(async () =>
                    {
                        await userEmailStore.SetEmailConfirmedAsync(ravenUser, confirmed: true);
                    });
                }
            }
        }
        public async Task SetEmailConfirmedAsync_With_Confirmed_Param_False_Should_Set_The_Email_As_Not_Confirmed_If_Confirmed_Already()
        {
            const string userName = "******";
            const string userId = "RavenUsers/Tugberk";
            const string email = "*****@*****.**";

            using (IDocumentStore store = CreateEmbeddableStore())
            {
                using (IAsyncDocumentSession ses = store.OpenAsyncSession())
                {
                    ses.Advanced.UseOptimisticConcurrency = true;
                    RavenUser user = new RavenUser(userName, email);
                    RavenUserEmail userEmail = new RavenUserEmail(email, user.Id);
                    userEmail.SetConfirmed();
                    await ses.StoreAsync(user);
                    await ses.StoreAsync(userEmail);
                    await ses.SaveChangesAsync();
                }

                using (IAsyncDocumentSession ses = store.OpenAsyncSession())
                {
                    ses.Advanced.UseOptimisticConcurrency = true;
                    IUserEmailStore<RavenUser> userEmailStore = new RavenUserStore<RavenUser>(ses);
                    RavenUser ravenUser = await ses.LoadAsync<RavenUser>(userId);
                    await userEmailStore.SetEmailConfirmedAsync(ravenUser, confirmed: false);
                    await ses.SaveChangesAsync();
                }

                using (IAsyncDocumentSession ses = store.OpenAsyncSession())
                {
                    ses.Advanced.UseOptimisticConcurrency = true;
                    string keyToLookFor = RavenUserEmail.GenerateKey(email);
                    RavenUserEmail userEmail = await ses.LoadAsync<RavenUserEmail>(keyToLookFor);

                    Assert.Null(userEmail.ConfirmationRecord);
                }
            }
        }
        public async Task SetEmailAsync_Should_Set_Email_And_SaveChangesAsync_Should_Throw_ConcurrencyException_If_The_Email_Already_Exists()
        {
            const string userName = "******";
            const string email = "*****@*****.**";
            const string userName2 = "Tugberk2";
            const string userId2 = "RavenUsers/Tugberk2";

            using (IDocumentStore store = CreateEmbeddableStore())
            {
                using (IAsyncDocumentSession ses = store.OpenAsyncSession())
                {
                    ses.Advanced.UseOptimisticConcurrency = true;
                    RavenUser user = new RavenUser(userName, email);
                    RavenUser user2 = new RavenUser(userName2);
                    RavenUserEmail userEmail = new RavenUserEmail(email, user.Id);
                    await ses.StoreAsync(user);
                    await ses.StoreAsync(user2);
                    await ses.StoreAsync(userEmail);
                    await ses.SaveChangesAsync();
                }

                using (IAsyncDocumentSession ses = store.OpenAsyncSession())
                {
                    ses.Advanced.UseOptimisticConcurrency = true;
                    IUserEmailStore<RavenUser> userEmailStore = new RavenUserStore<RavenUser>(ses);
                    RavenUser ravenUser = await ses.LoadAsync<RavenUser>(userId2);
                    await userEmailStore.SetEmailAsync(ravenUser, email);

                    await Assert.ThrowsAsync<ConcurrencyException>(async () =>
                    {
                        await ses.SaveChangesAsync();
                    });
                }

                using (IAsyncDocumentSession ses = store.OpenAsyncSession())
                {
                    RavenUser ravenUser = await ses.LoadAsync<RavenUser>(userId2);
                    Assert.Null(ravenUser.Email);
                }
            }
        }
        public async Task AddClaimAsync_Should_Add_The_Claim_Into_The_User_Claims_Collection()
        {
            string userName = "******";

            using (IDocumentStore store = base.CreateEmbeddableStore())
            using(IAsyncDocumentSession ses = store.OpenAsyncSession())
            {
                ses.Advanced.UseOptimisticConcurrency = true;
                IUserClaimStore<RavenUser> userClaimStore = new RavenUserStore<RavenUser>(ses, false);
                RavenUser user = new RavenUser(userName);

                await ses.StoreAsync(user);
                await ses.SaveChangesAsync();

                Claim claimToAdd = new Claim(ClaimTypes.Role, "Customer");
                await userClaimStore.AddClaimAsync(user, claimToAdd);

                Assert.Equal(1, user.Claims.Count());
                Assert.Equal(claimToAdd.Value, user.Claims.FirstOrDefault().ClaimValue);
                Assert.Equal(claimToAdd.Type, user.Claims.FirstOrDefault().ClaimType);
            }
        }
        public async Task GetEmailConfirmedAsync_Should_Throw_InvalidOperationException_If_Email_Is_Not_Available()
        {
            const string userName = "******";
            const string userId = "RavenUsers/Tugberk";

            using (IDocumentStore store = CreateEmbeddableStore())
            {
                using (IAsyncDocumentSession ses = store.OpenAsyncSession())
                {
                    ses.Advanced.UseOptimisticConcurrency = true;
                    RavenUser user = new RavenUser(userName) { UserName = userName };
                    await ses.StoreAsync(user);
                    await ses.SaveChangesAsync();
                }

                using (IAsyncDocumentSession ses = store.OpenAsyncSession())
                {
                    ses.Advanced.UseOptimisticConcurrency = true;
                    IUserEmailStore<RavenUser> userEmailStore = new RavenUserStore<RavenUser>(ses);
                    RavenUser ravenUser = await ses.LoadAsync<RavenUser>(userId);
                    
                    await Assert.ThrowsAsync<InvalidOperationException>(async () => 
                    {
                        bool isConfirmed = await userEmailStore.GetEmailConfirmedAsync(ravenUser);
                    });
                }
            }
        }