Sql Store

This commit is contained in:
Hao Kung 2014-05-07 12:48:56 -07:00
parent 078ba45477
commit 6ca38a31c0
15 changed files with 937 additions and 39 deletions

View File

@ -0,0 +1,194 @@
// Copyright (c) Microsoft Open Technologies, Inc.
// All Rights Reserved
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR
// CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING
// WITHOUT LIMITATION ANY IMPLIED WARRANTIES OR CONDITIONS OF
// TITLE, FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR
// NON-INFRINGEMENT.
// See the Apache 2 License for the specific language governing
// permissions and limitations under the License.
using System;
using System.Linq;
using System.Linq.Expressions;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Data.Entity;
namespace Microsoft.AspNet.Identity.Entity
{
public class EntityRoleStore<TRole> : EntityRoleStore<TRole, string> where TRole : EntityRole
{
public EntityRoleStore(DbContext context) : base(context) { }
}
public class EntityRoleStore<TRole, TKey> :
IQueryableRoleStore<TRole>
where TRole : EntityRole
where TKey : IEquatable<TKey>
{
private bool _disposed;
public EntityRoleStore(DbContext context)
{
if (context == null)
{
throw new ArgumentNullException("context");
}
Context = context;
AutoSaveChanges = true;
}
public DbContext Context { get; private set; }
/// <summary>
/// If true will call SaveChanges after CreateAsync/UpdateAsync/DeleteAsync
/// </summary>
public bool AutoSaveChanges { get; set; }
private async Task SaveChanges(CancellationToken cancellationToken)
{
if (AutoSaveChanges)
{
await Context.SaveChangesAsync(cancellationToken);
}
}
public virtual Task<TRole> GetRoleAggregate(Expression<Func<TRole, bool>> filter, CancellationToken cancellationToken = default(CancellationToken))
{
// TODO: return Roles.SingleOrDefaultAsync(filter, cancellationToken);
return Task.FromResult(Roles.SingleOrDefault(filter));
}
public async virtual Task CreateAsync(TRole role, CancellationToken cancellationToken = default(CancellationToken))
{
cancellationToken.ThrowIfCancellationRequested();
ThrowIfDisposed();
if (role == null)
{
throw new ArgumentNullException("role");
}
await Context.AddAsync(role, cancellationToken);
await SaveChanges(cancellationToken);
}
public async virtual Task UpdateAsync(TRole role, CancellationToken cancellationToken = default(CancellationToken))
{
cancellationToken.ThrowIfCancellationRequested();
ThrowIfDisposed();
if (role == null)
{
throw new ArgumentNullException("role");
}
await Context.UpdateAsync(role, cancellationToken);
await SaveChanges(cancellationToken);
}
public async virtual Task DeleteAsync(TRole role, CancellationToken cancellationToken = default(CancellationToken))
{
cancellationToken.ThrowIfCancellationRequested();
ThrowIfDisposed();
if (role == null)
{
throw new ArgumentNullException("role");
}
Context.Delete(role);
await SaveChanges(cancellationToken);
}
public Task<string> GetRoleIdAsync(TRole role, CancellationToken cancellationToken = new CancellationToken())
{
cancellationToken.ThrowIfCancellationRequested();
ThrowIfDisposed();
if (role == null)
{
throw new ArgumentNullException("role");
}
return Task.FromResult(role.Id);
}
public Task<string> GetRoleNameAsync(TRole role, CancellationToken cancellationToken = new CancellationToken())
{
cancellationToken.ThrowIfCancellationRequested();
ThrowIfDisposed();
if (role == null)
{
throw new ArgumentNullException("role");
}
return Task.FromResult(role.Name);
}
public Task SetRoleNameAsync(TRole role, string roleName, CancellationToken cancellationToken = new CancellationToken())
{
cancellationToken.ThrowIfCancellationRequested();
ThrowIfDisposed();
if (role == null)
{
throw new ArgumentNullException("role");
}
role.Name = roleName;
return Task.FromResult(0);
}
public virtual TKey ConvertId(string userId)
{
return (TKey)Convert.ChangeType(userId, typeof(TKey));
}
/// <summary>
/// Find a role by id
/// </summary>
/// <param name="id"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public virtual Task<TRole> FindByIdAsync(string id, CancellationToken cancellationToken = default(CancellationToken))
{
cancellationToken.ThrowIfCancellationRequested();
ThrowIfDisposed();
var roleId = ConvertId(id);
return GetRoleAggregate(u => u.Id.Equals(roleId), cancellationToken);
}
/// <summary>
/// Find a role by name
/// </summary>
/// <param name="name"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public virtual Task<TRole> FindByNameAsync(string name, CancellationToken cancellationToken = default(CancellationToken))
{
cancellationToken.ThrowIfCancellationRequested();
ThrowIfDisposed();
return GetRoleAggregate(u => u.Name.ToUpper() == name.ToUpper(), cancellationToken);
}
private void ThrowIfDisposed()
{
if (_disposed)
{
throw new ObjectDisposedException(GetType().Name);
}
}
/// <summary>
/// Dispose the store
/// </summary>
public void Dispose()
{
_disposed = true;
}
public IQueryable<TRole> Roles
{
get { return Context.Set<TRole>(); }
}
}
}

View File

@ -45,7 +45,6 @@ namespace Microsoft.AspNet.Identity.Entity
Claims = new List<TClaim>();
Roles = new List<TRole>();
Logins = new List<TLogin>();
}
public virtual TKey Id { get; set; }

View File

@ -9,11 +9,19 @@ namespace Microsoft.AspNet.Identity
where TUser : EntityUser
where TRole : EntityRole
{
builder.Services.AddScoped<IUserStore<TUser>, UserStore<TUser>>();
builder.Services.AddScoped<IUserStore<TUser>, InMemoryUserStore<TUser>>();
builder.Services.AddScoped<UserManager<TUser>, UserManager<TUser>>();
builder.Services.AddScoped<IRoleStore<TRole>, RoleStore<TRole>>();
builder.Services.AddScoped<IRoleStore<TRole>, EntityRoleStore<TRole>>();
builder.Services.AddScoped<RoleManager<TRole>, RoleManager<TRole>>();
return builder;
}
public static IdentityBuilder<TUser, IdentityRole> AddEntity<TUser>(this IdentityBuilder<TUser, IdentityRole> builder)
where TUser : User
{
builder.Services.AddScoped<IUserStore<TUser>, UserStore<TUser>>();
builder.Services.AddScoped<UserManager<TUser>>();
return builder;
}
}
}

View File

@ -52,7 +52,7 @@ namespace Microsoft.AspNet.Identity.Entity
protected override void OnConfiguring(DbContextOptions builder)
{
//#if NET45
// builder.UseSqlServer(@"Server=(localdb)\v11.0;Database=IdentityDb3;Trusted_Connection=True;");
// builder.SqlServerConnectionString(@"Server=(localdb)\v11.0;Database=IdentityEF5-5-1;Trusted_Connection=True;");
//#else
builder.UseInMemoryStore();
//#endif

View File

@ -0,0 +1,60 @@
// Copyright (c) Microsoft Open Technologies, Inc.
// All Rights Reserved
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR
// CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING
// WITHOUT LIMITATION ANY IMPLIED WARRANTIES OR CONDITIONS OF
// TITLE, FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR
// NON-INFRINGEMENT.
// See the Apache 2 License for the specific language governing
// permissions and limitations under the License.
using System;
using Microsoft.Framework.DependencyInjection;
using Microsoft.Framework.DependencyInjection.Fallback;
using Microsoft.Data.Entity;
using Microsoft.Data.Entity.SqlServer;
using Microsoft.Data.Entity.Metadata;
namespace Microsoft.AspNet.Identity.Entity
{
public class IdentitySqlContext :
IdentitySqlContext<User>
{
public IdentitySqlContext() { }
public IdentitySqlContext(IServiceProvider serviceProvider) : base(serviceProvider) { }
}
public class IdentitySqlContext<TUser> : DbContext
where TUser : User
{
public DbSet<TUser> Users { get; set; }
//public DbSet<TRole> Roles { get; set; }
public IdentitySqlContext(IServiceProvider serviceProvider)
: base(serviceProvider) { }
public IdentitySqlContext() { }
protected override void OnConfiguring(DbContextOptions builder)
{
// TODO: pull connection string from config
builder.UseSqlServer(@"Server=(localdb)\v11.0;Database=SimpleIdentity3;Trusted_Connection=True;");
}
protected override void OnModelCreating(ModelBuilder builder)
{
builder.Entity<TUser>()
.Key(u => u.Id)
.Properties(ps => ps.Property(u => u.UserName))
.ToTable("AspNetUsers");
}
}
}

View File

@ -27,18 +27,18 @@ using Microsoft.Data.Entity;
namespace Microsoft.AspNet.Identity.Entity
{
public class UserStore :
UserStore<EntityUser>
public class InMemoryInMemoryUserStore :
InMemoryUserStore<EntityUser>
{
public UserStore(DbContext context) : base(context) { }
public InMemoryInMemoryUserStore(DbContext context) : base(context) { }
}
public class UserStore<TUser> : UserStore<TUser, EntityRole, string, IdentityUserLogin, IdentityUserRole, IdentityUserClaim> where TUser:EntityUser
public class InMemoryUserStore<TUser> : InMemoryUserStore<TUser, EntityRole, string, IdentityUserLogin, IdentityUserRole, IdentityUserClaim> where TUser:EntityUser
{
public UserStore(DbContext context) : base(context) { }
public InMemoryUserStore(DbContext context) : base(context) { }
}
public class UserStore<TUser, TRole, TKey, TUserLogin, TUserRole, TUserClaim> :
public class InMemoryUserStore<TUser, TRole, TKey, TUserLogin, TUserRole, TUserClaim> :
IUserLoginStore<TUser>,
IUserClaimStore<TUser>,
IUserRoleStore<TUser>,
@ -58,7 +58,7 @@ namespace Microsoft.AspNet.Identity.Entity
{
private bool _disposed;
public UserStore(DbContext context)
public InMemoryUserStore(DbContext context)
{
if (context == null)
{

View File

@ -0,0 +1,351 @@
// Copyright (c) Microsoft Open Technologies, Inc.
// All Rights Reserved
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR
// CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING
// WITHOUT LIMITATION ANY IMPLIED WARRANTIES OR CONDITIONS OF
// TITLE, FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR
// NON-INFRINGEMENT.
// See the Apache 2 License for the specific language governing
// permissions and limitations under the License.
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Linq.Expressions;
using System.Security.Claims;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Data.Entity;
namespace Microsoft.AspNet.Identity.Entity
{
// Real Sql implementation
public class SqlUserStore :
UserStore<User>
{
public SqlUserStore(DbContext context) : base(context) { }
}
public class UserStore<TUser> :
//IUserRoleStore<TUser>,
IUserPasswordStore<TUser>,
IQueryableUserStore<TUser>
where TUser : User
{
private bool _disposed;
public UserStore(DbContext context)
{
if (context == null)
{
throw new ArgumentNullException("context");
}
Context = context;
AutoSaveChanges = true;
}
public DbContext Context { get; private set; }
/// <summary>
/// If true will call SaveChanges after CreateAsync/UpdateAsync/DeleteAsync
/// </summary>
public bool AutoSaveChanges { get; set; }
private Task SaveChanges(CancellationToken cancellationToken)
{
return AutoSaveChanges ? Context.SaveChangesAsync(cancellationToken) : Task.FromResult(0);
}
protected virtual Task<TUser> GetUserAggregate(Expression<Func<TUser, bool>> filter, CancellationToken cancellationToken = default(CancellationToken))
{
return Task.FromResult(Users.SingleOrDefault(filter));
// TODO: return Users.SingleOrDefaultAsync(filter, cancellationToken);
//Include(u => u.Roles)
//.Include(u => u.Claims)
//.Include(u => u.Logins)
}
public Task<string> GetUserIdAsync(TUser user, CancellationToken cancellationToken = new CancellationToken())
{
cancellationToken.ThrowIfCancellationRequested();
ThrowIfDisposed();
if (user == null)
{
throw new ArgumentNullException("user");
}
return Task.FromResult(Convert.ToString(user.Id, CultureInfo.InvariantCulture));
}
public Task<string> GetUserNameAsync(TUser user, CancellationToken cancellationToken = new CancellationToken())
{
cancellationToken.ThrowIfCancellationRequested();
ThrowIfDisposed();
if (user == null)
{
throw new ArgumentNullException("user");
}
return Task.FromResult(user.UserName);
}
public Task SetUserNameAsync(TUser user, string userName, CancellationToken cancellationToken = new CancellationToken())
{
cancellationToken.ThrowIfCancellationRequested();
ThrowIfDisposed();
if (user == null)
{
throw new ArgumentNullException("user");
}
user.UserName = userName;
return Task.FromResult(0);
}
public async virtual Task CreateAsync(TUser user, CancellationToken cancellationToken = default(CancellationToken))
{
cancellationToken.ThrowIfCancellationRequested();
ThrowIfDisposed();
if (user == null)
{
throw new ArgumentNullException("user");
}
await Context.AddAsync(user, cancellationToken);
await SaveChanges(cancellationToken);
}
public async virtual Task UpdateAsync(TUser user, CancellationToken cancellationToken = default(CancellationToken))
{
cancellationToken.ThrowIfCancellationRequested();
ThrowIfDisposed();
if (user == null)
{
throw new ArgumentNullException("user");
}
await Context.UpdateAsync(user, cancellationToken);
await SaveChanges(cancellationToken);
}
public async virtual Task DeleteAsync(TUser user, CancellationToken cancellationToken = default(CancellationToken))
{
cancellationToken.ThrowIfCancellationRequested();
ThrowIfDisposed();
if (user == null)
{
throw new ArgumentNullException("user");
}
Context.Delete(user);
await SaveChanges(cancellationToken);
}
/// <summary>
/// Find a user by id
/// </summary>
/// <param name="userId"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public virtual Task<TUser> FindByIdAsync(string userId, CancellationToken cancellationToken = default(CancellationToken))
{
cancellationToken.ThrowIfCancellationRequested();
ThrowIfDisposed();
return GetUserAggregate(u => u.Id.Equals(userId), cancellationToken);
}
/// <summary>
/// Find a user by name
/// </summary>
/// <param name="userName"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public virtual Task<TUser> FindByNameAsync(string userName, CancellationToken cancellationToken = default(CancellationToken))
{
cancellationToken.ThrowIfCancellationRequested();
ThrowIfDisposed();
return GetUserAggregate(u => u.UserName.ToUpper() == userName.ToUpper(), cancellationToken);
}
public IQueryable<TUser> Users
{
get { return Context.Set<TUser>(); }
}
/// <summary>
/// Set the password hash for a user
/// </summary>
/// <param name="user"></param>
/// <param name="passwordHash"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public virtual Task SetPasswordHashAsync(TUser user, string passwordHash, CancellationToken cancellationToken = default(CancellationToken))
{
cancellationToken.ThrowIfCancellationRequested();
ThrowIfDisposed();
if (user == null)
{
throw new ArgumentNullException("user");
}
user.PasswordHash = passwordHash;
return Task.FromResult(0);
}
/// <summary>
/// Get the password hash for a user
/// </summary>
/// <param name="user"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public virtual Task<string> GetPasswordHashAsync(TUser user, CancellationToken cancellationToken = default(CancellationToken))
{
cancellationToken.ThrowIfCancellationRequested();
ThrowIfDisposed();
if (user == null)
{
throw new ArgumentNullException("user");
}
return Task.FromResult(user.PasswordHash);
}
/// <summary>
/// Returns true if the user has a password set
/// </summary>
/// <param name="user"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public virtual Task<bool> HasPasswordAsync(TUser user, CancellationToken cancellationToken = default(CancellationToken))
{
cancellationToken.ThrowIfCancellationRequested();
return Task.FromResult(user.PasswordHash != null);
}
///// <summary>
///// Add a user to a role
///// </summary>
///// <param name="user"></param>
///// <param name="roleName"></param>
///// <param name="cancellationToken"></param>
///// <returns></returns>
//public virtual Task AddToRoleAsync(TUser user, string roleName, CancellationToken cancellationToken = default(CancellationToken))
//{
// cancellationToken.ThrowIfCancellationRequested();
// ThrowIfDisposed();
// if (user == null)
// {
// throw new ArgumentNullException("user");
// }
// // TODO:
// //if (String.IsNullOrWhiteSpace(roleName))
// //{
// // throw new ArgumentException(IdentityResources.ValueCannotBeNullOrEmpty, "roleName");
// //}
// var roleEntity = Context.Set<TRole>().SingleOrDefault(r => r.Name.ToUpper() == roleName.ToUpper());
// if (roleEntity == null)
// {
// throw new InvalidOperationException("Role Not Found");
// //TODO: String.Format(CultureInfo.CurrentCulture, IdentityResources.RoleNotFound, roleName));
// }
// var ur = new TUserRole { UserId = user.Id, RoleId = roleEntity.Id };
// user.Roles.Add(ur);
// roleEntity.Users.Add(ur);
// return Task.FromResult(0);
//}
///// <summary>
///// Remove a user from a role
///// </summary>
///// <param name="user"></param>
///// <param name="roleName"></param>
///// <param name="cancellationToken"></param>
///// <returns></returns>
//public virtual Task RemoveFromRoleAsync(TUser user, string roleName, CancellationToken cancellationToken = default(CancellationToken))
//{
// cancellationToken.ThrowIfCancellationRequested();
// ThrowIfDisposed();
// if (user == null)
// {
// throw new ArgumentNullException("user");
// }
// //if (String.IsNullOrWhiteSpace(roleName))
// //{
// // throw new ArgumentException(IdentityResources.ValueCannotBeNullOrEmpty, "roleName");
// //}
// var roleEntity = Context.Set<TRole>().SingleOrDefault(r => r.Name.ToUpper() == roleName.ToUpper());
// if (roleEntity != null)
// {
// var userRole = user.Roles.FirstOrDefault(r => roleEntity.Id.Equals(r.RoleId));
// if (userRole != null)
// {
// user.Roles.Remove(userRole);
// roleEntity.Users.Remove(userRole);
// }
// }
// return Task.FromResult(0);
//}
///// <summary>
///// Get the names of the roles a user is a member of
///// </summary>
///// <param name="user"></param>
///// <param name="cancellationToken"></param>
///// <returns></returns>
//public virtual Task<IList<string>> GetRolesAsync(TUser user, CancellationToken cancellationToken = default(CancellationToken))
//{
// cancellationToken.ThrowIfCancellationRequested();
// ThrowIfDisposed();
// if (user == null)
// {
// throw new ArgumentNullException("user");
// }
// var query = from userRoles in user.Roles
// join roles in Context.Set<TRole>()
// on userRoles.RoleId equals roles.Id
// select roles.Name;
// return Task.FromResult<IList<string>>(query.ToList());
//}
///// <summary>
///// Returns true if the user is in the named role
///// </summary>
///// <param name="user"></param>
///// <param name="roleName"></param>
///// <param name="cancellationToken"></param>
///// <returns></returns>
//public virtual Task<bool> IsInRoleAsync(TUser user, string roleName, CancellationToken cancellationToken = default(CancellationToken))
//{
// cancellationToken.ThrowIfCancellationRequested();
// ThrowIfDisposed();
// if (user == null)
// {
// throw new ArgumentNullException("user");
// }
// //if (String.IsNullOrWhiteSpace(roleName))
// //{
// // throw new ArgumentException(IdentityResources.ValueCannotBeNullOrEmpty, "roleName");
// //}
// var any =
// Context.Set<TRole>().Where(r => r.Name.ToUpper() == roleName.ToUpper())
// .Where(r => r.Users.Any(ur => ur.UserId.Equals(user.Id)))
// .Count() > 0;
// return Task.FromResult(any);
//}
private void ThrowIfDisposed()
{
if (_disposed)
{
throw new ObjectDisposedException(GetType().Name);
}
}
/// <summary>
/// Dispose the store
/// </summary>
public void Dispose()
{
_disposed = true;
}
}
}

View File

@ -0,0 +1,46 @@
// Copyright (c) Microsoft Open Technologies, Inc.
// All Rights Reserved
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR
// CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING
// WITHOUT LIMITATION ANY IMPLIED WARRANTIES OR CONDITIONS OF
// TITLE, FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR
// NON-INFRINGEMENT.
// See the Apache 2 License for the specific language governing
// permissions and limitations under the License.
using System;
namespace Microsoft.AspNet.Identity.Entity
{
public class User
{
public User()
{
Id = Guid.NewGuid().ToString();
// TODO: remove when bug is fixed
UserName = "";
PasswordHash = "";
}
public User(string userName) : this()
{
UserName = userName;
}
public virtual string Id { get; set; }
public virtual string UserName { get; set; }
/// <summary>
/// The salted/hashed form of the user password
/// </summary>
public virtual string PasswordHash { get; set; }
}
}

View File

@ -14,7 +14,8 @@
"net45": {
"dependencies": {
"System.Runtime": "",
"System.Collections": ""
"System.Collections": "",
"System.Data": ""
}
},
"k10": {

View File

@ -49,7 +49,7 @@ namespace Microsoft.AspNet.Identity
Errors = errors;
}
private IdentityResult(bool success)
protected IdentityResult(bool success)
{
Succeeded = success;
Errors = new string[0];

View File

@ -15,23 +15,24 @@
// See the Apache 2 License for the specific language governing
// permissions and limitations under the License.
using Microsoft.AspNet.Identity.Test;
using Microsoft.AspNet.Testing;
using Microsoft.Data.Entity;
using Microsoft.Data.Entity.Metadata;
using Microsoft.Data.Entity.InMemory;
using Microsoft.Data.Entity.SqlServer;
using Microsoft.Framework.DependencyInjection;
using Microsoft.Framework.DependencyInjection.Fallback;
using System;
using System.Linq;
using System.Security.Claims;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Framework.DependencyInjection;
using Microsoft.Framework.DependencyInjection.Fallback;
using Xunit;
namespace Microsoft.AspNet.Identity.Entity.Test
{
public class UserStoreTest
public class InMemoryUserStoreTest
{
class ApplicationUserManager : UserManager<EntityUser>
{
@ -49,7 +50,7 @@ namespace Microsoft.AspNet.Identity.Entity.Test
#endif
services.AddSingleton<IOptionsAccessor<IdentityOptions>, OptionsAccessor<IdentityOptions>>();
services.AddInstance<DbContext>(new IdentityContext());
services.AddTransient<IUserStore<EntityUser>, UserStore>();
services.AddTransient<IUserStore<EntityUser>, InMemoryInMemoryUserStore>();
services.AddSingleton<ApplicationUserManager, ApplicationUserManager>();
var provider = services.BuildServiceProvider();
var manager = provider.GetService<ApplicationUserManager>();
@ -67,7 +68,7 @@ namespace Microsoft.AspNet.Identity.Entity.Test
services.AddEntityFramework(s => s.AddInMemoryStore());
#endif
// TODO: this needs to construct a new instance of InMemoryStore
var store = new UserStore(new IdentityContext());
var store = new InMemoryInMemoryUserStore(new IdentityContext());
services.AddIdentity<EntityUser, EntityRole>(s =>
{
s.AddUserStore(() => store);
@ -84,7 +85,7 @@ namespace Microsoft.AspNet.Identity.Entity.Test
//public async Task CanUseSingletonGenericManagerInstance()
//{
// var services = new ServiceCollection();
// var store = new UserStore(new IdentityContext());
// var store = new EntityUserStore(new IdentityContext());
// services.AddIdentity<EntityUser>(s =>
// {
// s.UseStore(() => store);
@ -98,9 +99,9 @@ namespace Microsoft.AspNet.Identity.Entity.Test
//}
[Fact]
public async Task UserStoreMethodsThrowWhenDisposedTest()
public async Task EntityUserStoreMethodsThrowWhenDisposedTest()
{
var store = new UserStore(new IdentityContext());
var store = new InMemoryInMemoryUserStore(new IdentityContext());
store.Dispose();
await Assert.ThrowsAsync<ObjectDisposedException>(async () => await store.AddClaimAsync(null, null));
await Assert.ThrowsAsync<ObjectDisposedException>(async () => await store.AddLoginAsync(null, null));
@ -130,10 +131,10 @@ namespace Microsoft.AspNet.Identity.Entity.Test
}
[Fact]
public async Task UserStorePublicNullCheckTest()
public async Task EntityUserStorePublicNullCheckTest()
{
Assert.Throws<ArgumentNullException>("context", () => new UserStore(null));
var store = new UserStore(new IdentityContext());
Assert.Throws<ArgumentNullException>("context", () => new InMemoryInMemoryUserStore(null));
var store = new InMemoryInMemoryUserStore(new IdentityContext());
await Assert.ThrowsAsync<ArgumentNullException>("user", async () => await store.GetUserIdAsync(null));
await Assert.ThrowsAsync<ArgumentNullException>("user", async () => await store.GetUserNameAsync(null));
await Assert.ThrowsAsync<ArgumentNullException>("user", async () => await store.SetUserNameAsync(null, null));

View File

@ -42,7 +42,7 @@ namespace Microsoft.AspNet.Identity.Entity.Test
services.AddEntityFramework(s => s.AddInMemoryStore());
#endif
// TODO: this should construct a new instance of InMemoryStore
var store = new RoleStore<EntityRole>(new IdentityContext());
var store = new EntityRoleStore<EntityRole>(new IdentityContext());
services.AddIdentity<EntityUser, EntityRole>(s =>
{
s.AddRoleStore(() => store);
@ -64,7 +64,7 @@ namespace Microsoft.AspNet.Identity.Entity.Test
services.AddEntityFramework(s => s.AddInMemoryStore());
#endif
services.AddTransient<DbContext, IdentityContext>();
services.AddTransient<IRoleStore<EntityRole>, RoleStore<EntityRole>>();
services.AddTransient<IRoleStore<EntityRole>, EntityRoleStore<EntityRole>>();
//todo: services.AddSingleton<RoleManager<EntityRole>, RoleManager<EntityRole>>();
// TODO: How to configure SqlServer?
services.AddSingleton<ApplicationRoleManager, ApplicationRoleManager>();
@ -77,7 +77,7 @@ namespace Microsoft.AspNet.Identity.Entity.Test
[Fact]
public async Task RoleStoreMethodsThrowWhenDisposedTest()
{
var store = new RoleStore<EntityRole, string>(new IdentityContext());
var store = new EntityRoleStore<EntityRole, string>(new IdentityContext());
store.Dispose();
await Assert.ThrowsAsync<ObjectDisposedException>(async () => await store.FindByIdAsync(null));
await Assert.ThrowsAsync<ObjectDisposedException>(async () => await store.FindByNameAsync(null));
@ -92,8 +92,8 @@ namespace Microsoft.AspNet.Identity.Entity.Test
[Fact]
public async Task RoleStorePublicNullCheckTest()
{
Assert.Throws<ArgumentNullException>("context", () => new RoleStore<EntityRole, string>(null));
var store = new RoleStore<EntityRole, string>(new IdentityContext());
Assert.Throws<ArgumentNullException>("context", () => new EntityRoleStore<EntityRole, string>(null));
var store = new EntityRoleStore<EntityRole, string>(new IdentityContext());
await Assert.ThrowsAsync<ArgumentNullException>("role", async () => await store.GetRoleIdAsync(null));
await Assert.ThrowsAsync<ArgumentNullException>("role", async () => await store.GetRoleNameAsync(null));
await Assert.ThrowsAsync<ArgumentNullException>("role", async () => await store.SetRoleNameAsync(null, null));

View File

@ -0,0 +1,232 @@
//// Copyright (c) Microsoft Open Technologies, Inc.
//// All Rights Reserved
////
//// Licensed under the Apache License, Version 2.0 (the "License");
//// you may not use this file except in compliance with the License.
//// You may obtain a copy of the License at
////
//// http://www.apache.org/licenses/LICENSE-2.0
////
//// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR
//// CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING
//// WITHOUT LIMITATION ANY IMPLIED WARRANTIES OR CONDITIONS OF
//// TITLE, FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR
//// NON-INFRINGEMENT.
//// See the Apache 2 License for the specific language governing
//// permissions and limitations under the License.
using Microsoft.AspNet.Builder;
using Microsoft.AspNet.Testing;
using Microsoft.Data.Entity;
using Microsoft.Data.Entity.Metadata;
using Microsoft.Data.Entity.InMemory;
using Microsoft.Data.Entity.SqlServer;
using Microsoft.Framework.DependencyInjection;
using Microsoft.Framework.DependencyInjection.Fallback;
using System;
using System.Linq;
using System.Security.Claims;
using System.Threading;
using System.Threading.Tasks;
using Xunit;
namespace Microsoft.AspNet.Identity.Entity.Test
{
public class SqlUserStoreTest
{
public class ApplicationUser : User { }
public class ApplicationUserManager : UserManager<ApplicationUser>
{
public ApplicationUserManager(IServiceProvider services, IUserStore<ApplicationUser> store, IOptionsAccessor<IdentityOptions> options) : base(services, store, options) { }
}
public class ApplicationRoleManager : RoleManager<EntityRole>
{
public ApplicationRoleManager(IServiceProvider services, IRoleStore<EntityRole> store) : base(services, store) { }
}
public class ApplicationDbContext : IdentitySqlContext<ApplicationUser>
{
public ApplicationDbContext(IServiceProvider services) : base(services) { }
}
[Fact]
public async Task EnsureStartupUsageWorks()
{
IBuilder builder = new Microsoft.AspNet.Builder.Builder(new ServiceCollection().BuildServiceProvider());
//builder.UseServices(services => services.AddIdentity<ApplicationUser>(s =>
// s.AddEntity<ApplicationDbContext>()
//{
builder.UseServices(services =>
{
services.AddEntityFramework();
services.AddInstance<DbContext>(CreateAppContext());
services.AddIdentity<ApplicationUser>(s =>
{
s.AddEntity();
s.AddUserManager<ApplicationUserManager>();
});
});
var userStore = builder.ApplicationServices.GetService<IUserStore<ApplicationUser>>();
var userManager = builder.ApplicationServices.GetService<ApplicationUserManager>();
Assert.NotNull(userStore);
Assert.NotNull(userManager);
const string userName = "admin";
const string password = "1qaz@WSX";
var user = new ApplicationUser { UserName = userName };
IdentityResultAssert.IsSuccess(await userManager.CreateAsync(user, password));
IdentityResultAssert.IsSuccess(await userManager.DeleteAsync(user));
}
[Fact]
public async Task CanCreateUserUsingEF()
{
using (var db = CreateContext())
{
var guid = Guid.NewGuid().ToString();
db.Users.Add(new User {Id = guid, UserName = guid});
db.SaveChanges();
Assert.NotNull(db.Users.FirstOrDefault(u => u.UserName == guid));
}
}
public static IdentitySqlContext CreateContext()
{
var serviceProvider = new ServiceCollection()
.AddEntityFramework(s => s.AddSqlServer())
.BuildServiceProvider();
var db = new IdentitySqlContext(serviceProvider);
// TODO: Recreate DB, doesn't support String ID or Identity context yet
if (!db.Database.Exists())
{
db.Database.Create();
}
// TODO: CreateAsync DB?
return db;
}
public static ApplicationDbContext CreateAppContext()
{
var serviceProvider = new ServiceCollection()
.AddEntityFramework(s => s.AddSqlServer())
.BuildServiceProvider();
var db = new ApplicationDbContext(serviceProvider);
// TODO: Recreate DB, doesn't support String ID or Identity context yet
if (!db.Database.Exists())
{
db.Database.Create();
}
// TODO: CreateAsync DB?
return db;
}
public static UserManager<User> CreateManager(DbContext context)
{
var services = new ServiceCollection();
services.AddTransient<IUserValidator<User>, UserValidator<User>>();
services.AddTransient<IPasswordValidator<User>, PasswordValidator<User>>();
//services.AddInstance<IUserStore<User>>(new UserStore<User>(context));
//services.AddSingleton<UserManager<User>>();
var options = new IdentityOptions
{
Password = new PasswordOptions
{
RequireDigit = false,
RequireLowercase = false,
RequireNonLetterOrDigit = false,
RequireUppercase = false
},
User = new UserOptions
{
AllowOnlyAlphanumericNames = false
}
};
var optionsAccessor = new OptionsAccessor<IdentityOptions>(new[] { new TestIdentityFactory.TestSetup(options) });
//services.AddInstance<IOptionsAccessor<IdentityOptions>>(new OptionsAccessor<IdentityOptions>(new[] { new TestSetup(options) }));
//return services.BuildServiceProvider().GetService<UserManager<User>>();
return new UserManager<User>(services.BuildServiceProvider(), new UserStore<User>(context), optionsAccessor);
}
public static UserManager<User> CreateManager()
{
return CreateManager(CreateContext());
}
[Fact]
public async Task CanCreateUsingManager()
{
var manager = CreateManager();
var guid = Guid.NewGuid().ToString();
var user = new User { UserName = "New"+guid };
IdentityResultAssert.IsSuccess(await manager.CreateAsync(user));
IdentityResultAssert.IsSuccess(await manager.DeleteAsync(user));
}
[Fact]
public async Task CanDeleteUser()
{
var manager = CreateManager();
var user = new User("DeleteAsync");
IdentityResultAssert.IsSuccess(await manager.CreateAsync(user));
IdentityResultAssert.IsSuccess(await manager.DeleteAsync(user));
Assert.Null(await manager.FindByIdAsync(user.Id));
}
[Fact]
public async Task CanUpdateUserName()
{
var manager = CreateManager();
var user = new User("UpdateAsync");
IdentityResultAssert.IsSuccess(await manager.CreateAsync(user));
Assert.Null(await manager.FindByNameAsync("New"));
user.UserName = "New";
IdentityResultAssert.IsSuccess(await manager.UpdateAsync(user));
Assert.NotNull(await manager.FindByNameAsync("New"));
Assert.Null(await manager.FindByNameAsync("UpdateAsync"));
IdentityResultAssert.IsSuccess(await manager.DeleteAsync(user));
}
[Fact]
public async Task CanSetUserName()
{
var manager = CreateManager();
var user = new User("UpdateAsync");
IdentityResultAssert.IsSuccess(await manager.CreateAsync(user));
Assert.Null(await manager.FindByNameAsync("New"));
IdentityResultAssert.IsSuccess(await manager.SetUserNameAsync(user, "New"));
Assert.NotNull(await manager.FindByNameAsync("New"));
Assert.Null(await manager.FindByNameAsync("UpdateAsync"));
IdentityResultAssert.IsSuccess(await manager.DeleteAsync(user));
}
[Fact]
public async Task CanChangePassword()
{
var manager = TestIdentityFactory.CreateManager();
var user = new EntityUser("ChangePasswordTest");
const string password = "password";
const string newPassword = "newpassword";
IdentityResultAssert.IsSuccess(await manager.CreateAsync(user, password));
//Assert.Equal(manager.Users.Count(), 1);
//var stamp = user.SecurityStamp;
//Assert.NotNull(stamp);
IdentityResultAssert.IsSuccess(await manager.ChangePasswordAsync(user, password, newPassword));
Assert.Null(await manager.FindByUserNamePasswordAsync(user.UserName, password));
Assert.Equal(user, await manager.FindByUserNamePasswordAsync(user.UserName, newPassword));
//Assert.NotEqual(stamp, user.SecurityStamp);
IdentityResultAssert.IsSuccess(await manager.DeleteAsync(user));
}
}
}

View File

@ -33,7 +33,7 @@ namespace Microsoft.AspNet.Identity.Entity.Test
{
public static class TestIdentityFactory
{
public static DbContext CreateContext()
public static IdentityContext CreateContext()
{
var serviceProvider = new ServiceCollection()
//#if NET45
@ -46,10 +46,10 @@ namespace Microsoft.AspNet.Identity.Entity.Test
var db = new IdentityContext(serviceProvider);
// TODO: Recreate DB, doesn't support String ID or Identity context yet
//if (!db.Database.Exists())
//{
// db.Database.Create();
//}
if (!db.Database.Exists())
{
db.Database.Create();
}
// TODO: CreateAsync DB?
return db;
@ -77,7 +77,7 @@ namespace Microsoft.AspNet.Identity.Entity.Test
var services = new ServiceCollection();
services.AddTransient<IUserValidator<EntityUser>, UserValidator<EntityUser>>();
services.AddTransient<IPasswordValidator<IdentityUser>, PasswordValidator<IdentityUser>>();
services.AddInstance<IUserStore<EntityUser>>(new UserStore<EntityUser>(context));
services.AddInstance<IUserStore<EntityUser>>(new InMemoryUserStore<EntityUser>(context));
services.AddSingleton<UserManager<EntityUser>, UserManager<EntityUser>>();
var options = new IdentityOptions
{
@ -92,7 +92,7 @@ namespace Microsoft.AspNet.Identity.Entity.Test
var optionsAccessor = new OptionsAccessor<IdentityOptions>(new[] { new TestSetup(options) });
//services.AddInstance<IOptionsAccessor<IdentityOptions>>(new OptionsAccessor<IdentityOptions>(new[] { new TestSetup(options) }));
//return services.BuildServiceProvider().GetService<UserManager<EntityUser>>();
return new UserManager<EntityUser>(services.BuildServiceProvider(), new UserStore<EntityUser>(context), optionsAccessor);
return new UserManager<EntityUser>(services.BuildServiceProvider(), new InMemoryUserStore<EntityUser>(context), optionsAccessor);
}
public static UserManager<EntityUser> CreateManager()
@ -104,9 +104,9 @@ namespace Microsoft.AspNet.Identity.Entity.Test
{
var services = new ServiceCollection();
services.AddTransient<IRoleValidator<EntityRole>, RoleValidator<EntityRole>>();
services.AddInstance<IRoleStore<EntityRole>>(new RoleStore<EntityRole, string>(context));
services.AddInstance<IRoleStore<EntityRole>>(new EntityRoleStore<EntityRole, string>(context));
// return services.BuildServiceProvider().GetService<RoleManager<EntityRole>>();
return new RoleManager<EntityRole>(services.BuildServiceProvider(), new RoleStore<EntityRole, string>(context));
return new RoleManager<EntityRole>(services.BuildServiceProvider(), new EntityRoleStore<EntityRole, string>(context));
}
public static RoleManager<EntityRole> CreateRoleManager()

View File

@ -2,12 +2,17 @@
"version": "0.1-alpha-*",
"dependencies": {
"Microsoft.AspNet.Http": "0.1-alpha-*",
"Microsoft.AspNet.Identity": "",
"Microsoft.AspNet.Identity.Entity": "",
"Microsoft.AspNet.PipelineCore": "0.1-alpha-*",
"Microsoft.AspNet.RequestContainer": "0.1-alpha-*",
"Microsoft.AspNet.Security.DataProtection": "0.1-alpha-*",
"Microsoft.AspNet.Testing": "0.1-alpha-*",
"Microsoft.Bcl.Immutable": "1.1.18-beta-*",
"Microsoft.Data.Common": "0.1-alpha-*",
"Microsoft.Data.Entity": "0.1-alpha-*",
"Microsoft.Data.Entity.Relational": "0.1-alpha-*",
"Microsoft.Data.Entity.SqlServer": "0.1-alpha-*",
"Microsoft.Data.Entity.InMemory": "0.1-alpha-*",
"Microsoft.Framework.ConfigurationModel": "0.1-alpha-*",
"Microsoft.Framework.DependencyInjection": "0.1-alpha-*",
"Microsoft.Framework.Logging": "0.1-alpha-*",
@ -28,6 +33,7 @@
}
}
},
"code": "**\\*.cs;..\\Shared\\*.cs",
"commands": {
"test": "Xunit.KRunner"
}