Initial DI changes from app building
Incorporate feedback and make identity DI friendly everywhere Also start using the new OptionsSetup
This commit is contained in:
parent
8e5ac31889
commit
31f76b8d58
|
|
@ -0,0 +1,19 @@
|
|||
using Microsoft.AspNet.Identity.Entity;
|
||||
using Microsoft.AspNet.DependencyInjection;
|
||||
|
||||
namespace Microsoft.AspNet.Identity
|
||||
{
|
||||
public static class IdentityBuilderExtensions
|
||||
{
|
||||
public static IdentityBuilder<TUser, TRole> AddEntity<TUser, TRole>(this IdentityBuilder<TUser, TRole> builder)
|
||||
where TUser : EntityUser
|
||||
where TRole : EntityRole
|
||||
{
|
||||
builder.Services.AddScoped<IUserStore<TUser>, UserStore<TUser>>();
|
||||
builder.Services.AddScoped<UserManager<TUser>, UserManager<TUser>>();
|
||||
builder.Services.AddScoped<IRoleStore<TRole>, RoleStore<TRole>>();
|
||||
builder.Services.AddScoped<RoleManager<TRole>, RoleManager<TRole>>();
|
||||
return builder;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -19,6 +19,7 @@ using System;
|
|||
using Microsoft.AspNet.DependencyInjection;
|
||||
using Microsoft.AspNet.DependencyInjection.Fallback;
|
||||
using Microsoft.Data.Entity;
|
||||
using Microsoft.Data.SqlServer;
|
||||
using Microsoft.Data.InMemory;
|
||||
using Microsoft.Data.Entity.Metadata;
|
||||
|
||||
|
|
@ -33,7 +34,7 @@ namespace Microsoft.AspNet.Identity.Entity
|
|||
|
||||
public class IdentityContext<TUser, TRole, TKey, TUserLogin, TUserRole, TUserClaim> : DbContext
|
||||
where TUser : EntityUser<TKey, TUserLogin, TUserRole, TUserClaim>
|
||||
where TRole : EntityRole<TKey, TUserRole> /*, TUserRole*/
|
||||
where TRole : EntityRole<TKey, TUserRole>
|
||||
where TUserLogin : IdentityUserLogin<TKey>
|
||||
where TUserRole : IdentityUserRole<TKey>
|
||||
where TUserClaim : IdentityUserClaim<TKey>
|
||||
|
|
@ -51,7 +52,7 @@ namespace Microsoft.AspNet.Identity.Entity
|
|||
protected override void OnConfiguring(EntityConfigurationBuilder builder)
|
||||
{
|
||||
//#if NET45
|
||||
// builder.SqlServerConnectionString(@"Server=(localdb)\v11.0;Database=IdentityDb;Trusted_Connection=True;");
|
||||
// builder.SqlServerConnectionString(@"Server=(localdb)\v11.0;Database=IdentityDb3;Trusted_Connection=True;");
|
||||
//#else
|
||||
builder.UseInMemoryStore();
|
||||
//#endif
|
||||
|
|
|
|||
|
|
@ -20,20 +20,14 @@
|
|||
<Content Include="Project.json" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<<<<<<< HEAD
|
||||
<Compile Include="IdentityContext.cs" />
|
||||
<Compile Include="IdentityRole.cs" />
|
||||
<Compile Include="IdentityUser.cs" />
|
||||
<Compile Include="IdentityUserClaim.cs" />
|
||||
<Compile Include="IdentityUserLogin.cs" />
|
||||
<Compile Include="IdentityUserRole.cs" />
|
||||
=======
|
||||
<Compile Include="EntityRole.cs" />
|
||||
<Compile Include="EntityUser.cs" />
|
||||
<Compile Include="IdentityContext.cs" />
|
||||
>>>>>>> POCO
|
||||
<Compile Include="RoleStore.cs" />
|
||||
<Compile Include="UserStore.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Folder Include="Properties\" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VSToolsPath)\ProjectK\Microsoft.Web.ProjectK.targets" Condition="'$(VSToolsPath)' != ''" />
|
||||
</Project>
|
||||
|
|
@ -24,6 +24,11 @@ using Microsoft.Data.Entity;
|
|||
|
||||
namespace Microsoft.AspNet.Identity.Entity
|
||||
{
|
||||
public class RoleStore<TRole> : RoleStore<TRole, string> where TRole : EntityRole
|
||||
{
|
||||
public RoleStore(DbContext context) : base(context) { }
|
||||
}
|
||||
|
||||
public class RoleStore<TRole, TKey> :
|
||||
IQueryableRoleStore<TRole>
|
||||
where TRole : EntityRole
|
||||
|
|
|
|||
|
|
@ -4,9 +4,9 @@
|
|||
"Microsoft.AspNet.ConfigurationModel": "0.1-alpha-*",
|
||||
"Microsoft.AspNet.DependencyInjection": "0.1-alpha-*",
|
||||
"Microsoft.AspNet.Identity": "0.1-alpha-*",
|
||||
"Microsoft.AspNet.Logging": "0.1-alpha-*",
|
||||
"Microsoft.Data.Entity": "0.1-alpha-*",
|
||||
"Microsoft.Data.Relational": "0.1-alpha-*",
|
||||
"Microsoft.Data.SqlServer": "0.1-alpha-*",
|
||||
"Microsoft.Data.InMemory": "0.1-alpha-*",
|
||||
"System.Security.Claims" : "0.1-alpha-*"
|
||||
},
|
||||
|
|
|
|||
|
|
@ -0,0 +1,19 @@
|
|||
using Microsoft.AspNet.Identity.InMemory;
|
||||
using Microsoft.AspNet.DependencyInjection;
|
||||
|
||||
namespace Microsoft.AspNet.Identity
|
||||
{
|
||||
public static class IdentityBuilderExtensions
|
||||
{
|
||||
public static IdentityBuilder<TUser, TRole> AddInMemory<TUser, TRole>(this IdentityBuilder<TUser, TRole> builder)
|
||||
where TUser : IdentityUser
|
||||
where TRole : IdentityRole
|
||||
{
|
||||
builder.Services.AddScoped<IUserStore<TUser>, InMemoryUserStore<TUser>>();
|
||||
builder.Services.AddScoped<UserManager<TUser>, UserManager<TUser>>();
|
||||
builder.Services.AddScoped<IRoleStore<TRole>, InMemoryRoleStore<TRole>>();
|
||||
builder.Services.AddScoped<RoleManager<TRole>, RoleManager<TRole>>();
|
||||
return builder;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -23,5 +23,8 @@
|
|||
<Compile Include="InMemoryRoleStore.cs" />
|
||||
<Compile Include="InMemoryUserStore.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Folder Include="Properties\" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VSToolsPath)\ProjectK\Microsoft.Web.ProjectK.targets" Condition="'$(VSToolsPath)' != ''" />
|
||||
</Project>
|
||||
|
|
@ -2,10 +2,7 @@
|
|||
"version": "0.1-alpha-*",
|
||||
"dependencies": {
|
||||
"Microsoft.AspNet.Identity": "0.1-alpha-*",
|
||||
"Microsoft.AspNet.Abstractions" : "0.1-alpha-*",
|
||||
"Microsoft.AspNet.ConfigurationModel" : "0.1-alpha-*",
|
||||
"Microsoft.AspNet.DependencyInjection" : "0.1-alpha-*",
|
||||
"Microsoft.AspNet.RequestContainer" : "0.1-alpha-*",
|
||||
"System.Security.Claims": "0.1-alpha-*"
|
||||
},
|
||||
"configurations": {
|
||||
|
|
|
|||
|
|
@ -19,6 +19,6 @@ namespace Microsoft.AspNet.Identity.Security
|
|||
{
|
||||
public static class DefaultAuthenticationTypes
|
||||
{
|
||||
public const string ApplicationCookie = "Microsoft.Aspnet.Identity.Security.Application";
|
||||
public static readonly string ApplicationCookie = typeof(DefaultAuthenticationTypes).Namespace+".Application";
|
||||
}
|
||||
}
|
||||
|
|
@ -20,8 +20,13 @@
|
|||
<Content Include="Project.json" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="DefaultAuthenticationTypes.cs" />
|
||||
<Compile Include="IdentityExtensions.cs" />
|
||||
<Compile Include="SignInManager.cs" />
|
||||
<Compile Include="SignInStatus.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Folder Include="Properties\" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VSToolsPath)\ProjectK\Microsoft.Web.ProjectK.targets" Condition="'$(VSToolsPath)' != ''" />
|
||||
</Project>
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
// Copyright (c) Microsoft Open Technologies, Inc.
|
||||
// Copyright (c) Microsoft Open Technologies, Inc.
|
||||
// All Rights Reserved
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
|
|
@ -17,13 +17,37 @@
|
|||
|
||||
using Microsoft.AspNet.Abstractions;
|
||||
using Microsoft.AspNet.Abstractions.Security;
|
||||
using Microsoft.AspNet.DependencyInjection;
|
||||
using System;
|
||||
using System.Security.Claims;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Microsoft.AspNet.Identity.Security
|
||||
{
|
||||
public class SignInManager<TUser> where TUser : class
|
||||
public class SignInManager<TUser> : SignInManager<UserManager<TUser>, TUser> where TUser : class
|
||||
{
|
||||
public SignInManager(UserManager<TUser> userManager, IContextAccessor<HttpContext> contextAccessor)
|
||||
: base(userManager, contextAccessor) { }
|
||||
}
|
||||
|
||||
|
||||
public class SignInManager<TManager, TUser> where TManager : UserManager<TUser> where TUser : class
|
||||
{
|
||||
public SignInManager(TManager userManager, IContextAccessor<HttpContext> contextAccessor)
|
||||
{
|
||||
if (userManager == null)
|
||||
{
|
||||
throw new ArgumentNullException("userManager");
|
||||
}
|
||||
if (contextAccessor == null || contextAccessor.Value == null)
|
||||
{
|
||||
throw new ArgumentNullException("contextAccessor");
|
||||
}
|
||||
UserManager = userManager;
|
||||
Context = contextAccessor.Value;
|
||||
}
|
||||
|
||||
// TODO: this should go into some kind of Options/setup
|
||||
private string _authType;
|
||||
public string AuthenticationType
|
||||
{
|
||||
|
|
@ -31,25 +55,16 @@ namespace Microsoft.AspNet.Identity.Security
|
|||
set { _authType = value; }
|
||||
}
|
||||
|
||||
public UserManager<TUser> UserManager { get; set; }
|
||||
public HttpContext Context { get; set; }
|
||||
public TManager UserManager { get; private set; }
|
||||
public HttpContext Context { get; private set; }
|
||||
|
||||
public virtual async Task<ClaimsIdentity> CreateUserIdentityAsync(TUser user)
|
||||
{
|
||||
if (UserManager == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
return await UserManager.CreateIdentityAsync(user, AuthenticationType);
|
||||
}
|
||||
|
||||
public virtual async Task SignInAsync(TUser user, bool isPersistent, bool rememberBrowser)
|
||||
{
|
||||
if (Context == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO: all the two factor logic/external/rememberBrowser
|
||||
var userIdentity = await CreateUserIdentityAsync(user);
|
||||
Context.Response.SignIn(userIdentity, new AuthenticationProperties { IsPersistent = isPersistent });
|
||||
|
|
@ -57,10 +72,6 @@ namespace Microsoft.AspNet.Identity.Security
|
|||
|
||||
public virtual void SignOut()
|
||||
{
|
||||
if (Context == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
Context.Response.SignOut(AuthenticationType);
|
||||
}
|
||||
|
||||
|
|
@ -151,10 +162,6 @@ namespace Microsoft.AspNet.Identity.Security
|
|||
|
||||
public virtual async Task<SignInStatus> PasswordSignInAsync(string userName, string password, bool isPersistent, bool shouldLockout)
|
||||
{
|
||||
if (UserManager == null)
|
||||
{
|
||||
return SignInStatus.Failure;
|
||||
}
|
||||
var user = await UserManager.FindByNameAsync(userName);
|
||||
if (user == null)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -0,0 +1,60 @@
|
|||
using System;
|
||||
using System.ComponentModel;
|
||||
using System.Security.Claims;
|
||||
using Microsoft.AspNet.ConfigurationModel;
|
||||
|
||||
namespace Microsoft.AspNet.Identity
|
||||
{
|
||||
public class ClaimTypeOptions
|
||||
{
|
||||
/// <summary>
|
||||
/// ClaimType used for the security stamp by default
|
||||
/// </summary>
|
||||
public static readonly string DefaultSecurityStampClaimType = "AspNet.Identity.SecurityStamp";
|
||||
|
||||
public ClaimTypeOptions()
|
||||
{
|
||||
Role = ClaimTypes.Role;
|
||||
SecurityStamp = DefaultSecurityStampClaimType;
|
||||
UserId = ClaimTypes.NameIdentifier;
|
||||
UserName = ClaimTypes.Name;
|
||||
}
|
||||
|
||||
public ClaimTypeOptions(IConfiguration config) : this()
|
||||
{
|
||||
IdentityOptions.Read(this, config);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Claim type used for role claims
|
||||
/// </summary>
|
||||
public string Role { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Claim type used for the user name
|
||||
/// </summary>
|
||||
public string UserName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Claim type used for the user id
|
||||
/// </summary>
|
||||
public string UserId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Claim type used for the user security stamp
|
||||
/// </summary>
|
||||
public string SecurityStamp { get; set; }
|
||||
|
||||
public virtual void Copy(ClaimTypeOptions options)
|
||||
{
|
||||
if (options == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
Role = options.Role;
|
||||
SecurityStamp = options.SecurityStamp;
|
||||
UserId = options.UserId;
|
||||
UserName = options.UserName;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -19,6 +19,7 @@ using System;
|
|||
using System.Security.Claims;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNet.DependencyInjection;
|
||||
|
||||
namespace Microsoft.AspNet.Identity
|
||||
{
|
||||
|
|
@ -29,42 +30,6 @@ namespace Microsoft.AspNet.Identity
|
|||
public class ClaimsIdentityFactory<TUser> : IClaimsIdentityFactory<TUser>
|
||||
where TUser : class
|
||||
{
|
||||
/// <summary>
|
||||
/// ClaimType used for the security stamp by default
|
||||
/// </summary>
|
||||
public const string DefaultSecurityStampClaimType = "AspNet.Identity.SecurityStamp";
|
||||
|
||||
/// <summary>
|
||||
/// Constructor
|
||||
/// </summary>
|
||||
public ClaimsIdentityFactory()
|
||||
{
|
||||
RoleClaimType = ClaimsIdentity.DefaultRoleClaimType;
|
||||
UserIdClaimType = ClaimTypes.NameIdentifier;
|
||||
UserNameClaimType = ClaimsIdentity.DefaultNameClaimType;
|
||||
SecurityStampClaimType = DefaultSecurityStampClaimType;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Claim type used for role claims
|
||||
/// </summary>
|
||||
public string RoleClaimType { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Claim type used for the user name
|
||||
/// </summary>
|
||||
public string UserNameClaimType { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Claim type used for the user id
|
||||
/// </summary>
|
||||
public string UserIdClaimType { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Claim type used for the user security stamp
|
||||
/// </summary>
|
||||
public string SecurityStampClaimType { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// CreateAsync a ClaimsIdentity from a user
|
||||
/// </summary>
|
||||
|
|
@ -86,19 +51,19 @@ namespace Microsoft.AspNet.Identity
|
|||
}
|
||||
var userId = await manager.GetUserIdAsync(user, cancellationToken);
|
||||
var userName = await manager.GetUserNameAsync(user, cancellationToken);
|
||||
var id = new ClaimsIdentity(authenticationType, UserNameClaimType, RoleClaimType);
|
||||
id.AddClaim(new Claim(UserIdClaimType, userId));
|
||||
id.AddClaim(new Claim(UserNameClaimType, userName, ClaimValueTypes.String));
|
||||
var id = new ClaimsIdentity(authenticationType, manager.Options.ClaimType.UserName, manager.Options.ClaimType.Role);
|
||||
id.AddClaim(new Claim(manager.Options.ClaimType.UserId, userId));
|
||||
id.AddClaim(new Claim(manager.Options.ClaimType.UserName, userName, ClaimValueTypes.String));
|
||||
if (manager.SupportsUserSecurityStamp)
|
||||
{
|
||||
id.AddClaim(new Claim(SecurityStampClaimType, await manager.GetSecurityStampAsync(user, cancellationToken)));
|
||||
id.AddClaim(new Claim(manager.Options.ClaimType.SecurityStamp, await manager.GetSecurityStampAsync(user, cancellationToken)));
|
||||
}
|
||||
if (manager.SupportsUserRole)
|
||||
{
|
||||
var roles = await manager.GetRolesAsync(user, cancellationToken);
|
||||
foreach (var roleName in roles)
|
||||
{
|
||||
id.AddClaim(new Claim(RoleClaimType, roleName, ClaimValueTypes.String));
|
||||
id.AddClaim(new Claim(manager.Options.ClaimType.Role, roleName, ClaimValueTypes.String));
|
||||
}
|
||||
}
|
||||
if (manager.SupportsUserClaim)
|
||||
|
|
|
|||
|
|
@ -23,12 +23,12 @@ namespace Microsoft.AspNet.Identity
|
|||
/// <summary>
|
||||
/// Used to validate passwords
|
||||
/// </summary>
|
||||
public interface IPasswordValidator
|
||||
public interface IPasswordValidator<TUser> where TUser : class
|
||||
{
|
||||
/// <summary>
|
||||
/// Validate the item
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
Task<IdentityResult> ValidateAsync(string password, CancellationToken cancellationToken = default(CancellationToken));
|
||||
Task<IdentityResult> ValidateAsync(string password, UserManager<TUser> manager, CancellationToken cancellationToken = default(CancellationToken));
|
||||
}
|
||||
}
|
||||
|
|
@ -22,55 +22,82 @@ namespace Microsoft.AspNet.Identity
|
|||
{
|
||||
public class IdentityBuilder<TUser, TRole> where TUser : class where TRole : class
|
||||
{
|
||||
private ServiceCollection Services { get; set; }
|
||||
public ServiceCollection Services { get; private set; }
|
||||
|
||||
public IdentityBuilder(ServiceCollection services)
|
||||
{
|
||||
Services = services;
|
||||
}
|
||||
|
||||
public IdentityBuilder<TUser, TRole> Use<T>(Func<T> func)
|
||||
// Rename to Add
|
||||
|
||||
public IdentityBuilder<TUser, TRole> AddInstance<T>(Func<T> func)
|
||||
{
|
||||
Services.AddInstance<T>(func());
|
||||
Services.AddInstance(func());
|
||||
return this;
|
||||
}
|
||||
|
||||
public IdentityBuilder<TUser, TRole> UseIdentity()
|
||||
public IdentityBuilder<TUser, TRole> AddUserStore(Func<IUserStore<TUser>> func)
|
||||
{
|
||||
Services.Add(IdentityServices.GetDefaultUserServices<TUser>());
|
||||
Services.Add(IdentityServices.GetDefaultRoleServices<TRole>());
|
||||
return AddInstance(func);
|
||||
}
|
||||
|
||||
public IdentityBuilder<TUser, TRole> AddRoleStore(Func<IRoleStore<TRole>> func)
|
||||
{
|
||||
return AddInstance(func);
|
||||
}
|
||||
|
||||
public IdentityBuilder<TUser, TRole> AddPasswordValidator(Func<IPasswordValidator<TUser>> func)
|
||||
{
|
||||
return AddInstance(func);
|
||||
}
|
||||
|
||||
public IdentityBuilder<TUser, TRole> AddUserValidator(Func<IUserValidator<TUser>> func)
|
||||
{
|
||||
return AddInstance(func);
|
||||
}
|
||||
|
||||
public class OptionsSetup<TOptions> : IOptionsSetup<TOptions>
|
||||
{
|
||||
public Action<TOptions> SetupAction { get; private set; }
|
||||
|
||||
public OptionsSetup(Action<TOptions> setupAction)
|
||||
{
|
||||
if (setupAction == null)
|
||||
{
|
||||
throw new ArgumentNullException("setupAction");
|
||||
}
|
||||
SetupAction = setupAction;
|
||||
}
|
||||
|
||||
public void Setup(TOptions options)
|
||||
{
|
||||
SetupAction(options);
|
||||
}
|
||||
|
||||
public int Order { get; set; }
|
||||
}
|
||||
|
||||
public IdentityBuilder<TUser, TRole> SetupOptions(Action<IdentityOptions> action, int order)
|
||||
{
|
||||
Services.AddSetup(new OptionsSetup<IdentityOptions>(action) {Order = order});
|
||||
return this;
|
||||
}
|
||||
|
||||
public IdentityBuilder<TUser, TRole> UseUserStore(Func<IUserStore<TUser>> func)
|
||||
public IdentityBuilder<TUser, TRole> SetupOptions(Action<IdentityOptions> action)
|
||||
{
|
||||
return Use(func);
|
||||
return SetupOptions(action, 0);
|
||||
}
|
||||
|
||||
public IdentityBuilder<TUser, TRole> UseRoleStore(Func<IRoleStore<TRole>> func)
|
||||
public IdentityBuilder<TUser, TRole> AddUserManager<TManager>() where TManager : UserManager<TUser>
|
||||
{
|
||||
return Use(func);
|
||||
}
|
||||
|
||||
public IdentityBuilder<TUser, TRole> UsePasswordValidator(Func<IPasswordValidator> func)
|
||||
{
|
||||
return Use(func);
|
||||
}
|
||||
|
||||
public IdentityBuilder<TUser, TRole> UseUserValidator(Func<IUserValidator<TUser>> func)
|
||||
{
|
||||
return Use(func);
|
||||
}
|
||||
|
||||
public IdentityBuilder<TUser, TRole> UseUserManager<TManager>() where TManager : UserManager<TUser>
|
||||
{
|
||||
Services.AddScoped<TManager, TManager>();
|
||||
Services.AddScoped<TManager>();
|
||||
return this;
|
||||
}
|
||||
|
||||
public IdentityBuilder<TUser, TRole> UseRoleManager<TManager>() where TManager : RoleManager<TRole>
|
||||
public IdentityBuilder<TUser, TRole> AddRoleManager<TManager>() where TManager : RoleManager<TRole>
|
||||
{
|
||||
Services.AddScoped<TManager, TManager>();
|
||||
Services.AddScoped<TManager>();
|
||||
return this;
|
||||
}
|
||||
|
||||
|
|
@ -79,10 +106,5 @@ namespace Microsoft.AspNet.Identity
|
|||
// return Use(func);
|
||||
//}
|
||||
|
||||
public IdentityBuilder<TUser, TRole> UseLockoutPolicy(Func<LockoutPolicy> func)
|
||||
{
|
||||
return Use(func);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,89 @@
|
|||
using System.Reflection;
|
||||
using Microsoft.AspNet.ConfigurationModel;
|
||||
|
||||
namespace Microsoft.AspNet.Identity
|
||||
{
|
||||
/// <summary>
|
||||
/// Configuration for lockout
|
||||
/// </summary>
|
||||
public class IdentityOptions
|
||||
{
|
||||
|
||||
public IdentityOptions()
|
||||
{
|
||||
// TODO: Split into sub options
|
||||
ClaimType = new ClaimTypeOptions();
|
||||
User = new UserOptions();
|
||||
Password = new PasswordOptions();
|
||||
Lockout = new LockoutOptions();
|
||||
}
|
||||
|
||||
public IdentityOptions(IConfiguration config)
|
||||
{
|
||||
ClaimType = new ClaimTypeOptions(config.GetSubKey("identity:claimtype"));
|
||||
User = new UserOptions(config.GetSubKey("identity:user"));
|
||||
Password = new PasswordOptions(config.GetSubKey("identity:password"));
|
||||
//Lockout = new LockoutOptions(config.GetSubKey("identity:lockout"));
|
||||
}
|
||||
|
||||
public static void Read(object obj, IConfiguration config)
|
||||
{
|
||||
var type = obj.GetType();
|
||||
var props = type.GetTypeInfo().DeclaredProperties;
|
||||
foreach (var prop in props)
|
||||
{
|
||||
// TODO: handle non string types?
|
||||
if (!prop.CanWrite)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
var configValue = config.Get(prop.Name);
|
||||
if (configValue == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (prop.PropertyType == typeof(string))
|
||||
{
|
||||
prop.SetValue(obj, configValue);
|
||||
}
|
||||
else if (prop.PropertyType == typeof(int))
|
||||
{
|
||||
// todo: TryParse/ errors?
|
||||
prop.SetValue(obj, int.Parse(configValue));
|
||||
}
|
||||
else if (prop.PropertyType == typeof(bool))
|
||||
{
|
||||
// todo: TryParse/ errors?
|
||||
prop.SetValue(obj, bool.Parse(configValue));
|
||||
}
|
||||
//else if (prop.PropertyType == typeof(TimeSpan))
|
||||
//{
|
||||
// // todo: TryParse/ errors?
|
||||
// prop.SetValue(obj, TimeSpan.Parse(configValue));
|
||||
//}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public ClaimTypeOptions ClaimType { get; set; }
|
||||
|
||||
public UserOptions User { get; set; }
|
||||
|
||||
public PasswordOptions Password { get; set; }
|
||||
|
||||
public LockoutOptions Lockout { get; set; }
|
||||
|
||||
// TODO: maybe make this internal as its only for tests
|
||||
public void Copy(IdentityOptions options)
|
||||
{
|
||||
if (options == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
User.Copy(options.User);
|
||||
Password.Copy(options.Password);
|
||||
Lockout.Copy(options.Lockout);
|
||||
ClaimType.Copy(options.ClaimType);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -28,6 +28,7 @@ namespace Microsoft.AspNet.DependencyInjection
|
|||
{
|
||||
services.Add(IdentityServices.GetDefaultUserServices<TUser>());
|
||||
services.Add(IdentityServices.GetDefaultRoleServices<TRole>());
|
||||
services.AddSingleton<IOptionsAccessor<IdentityOptions>, OptionsAccessor<IdentityOptions>>();
|
||||
actionBuilder(new IdentityBuilder<TUser, TRole>(services));
|
||||
return services;
|
||||
}
|
||||
|
|
@ -35,10 +36,7 @@ namespace Microsoft.AspNet.DependencyInjection
|
|||
public static ServiceCollection AddIdentity<TUser>(this ServiceCollection services, Action<IdentityBuilder<TUser, IdentityRole>> actionBuilder)
|
||||
where TUser : class
|
||||
{
|
||||
services.Add(IdentityServices.GetDefaultUserServices<TUser>());
|
||||
services.Add(IdentityServices.GetDefaultRoleServices<IdentityRole>());
|
||||
actionBuilder(new IdentityBuilder<TUser, IdentityRole>(services));
|
||||
return services;
|
||||
return services.AddIdentity<TUser, IdentityRole>(actionBuilder);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -38,26 +38,12 @@ namespace Microsoft.AspNet.Identity
|
|||
var describe = new ServiceDescriber(configuration);
|
||||
|
||||
// TODO: review defaults for validators should get picked up from config?
|
||||
yield return describe.Instance<IUserValidator<TUser>>(new UserValidator<TUser>());
|
||||
yield return describe.Instance<IPasswordValidator>(new PasswordValidator()
|
||||
{
|
||||
RequiredLength = 6,
|
||||
RequireDigit = true,
|
||||
RequireLowercase = true,
|
||||
RequireNonLetterOrDigit = true,
|
||||
RequireUppercase = true
|
||||
});
|
||||
yield return describe.Instance<IPasswordHasher>(new PasswordHasher());
|
||||
yield return describe.Instance<IClaimsIdentityFactory<TUser>>(new ClaimsIdentityFactory<TUser>());
|
||||
yield return describe.Instance<LockoutPolicy>(new LockoutPolicy
|
||||
{
|
||||
UserLockoutEnabledByDefault = false,
|
||||
DefaultAccountLockoutTimeSpan = TimeSpan.FromMinutes(5),
|
||||
MaxFailedAccessAttemptsBeforeLockout = 5
|
||||
});
|
||||
yield return describe.Transient<IUserValidator<TUser>, UserValidator<TUser>>();
|
||||
yield return describe.Transient<IPasswordValidator<TUser>, PasswordValidator<TUser>>();
|
||||
yield return describe.Transient<IPasswordHasher, PasswordHasher>();
|
||||
yield return describe.Transient<IClaimsIdentityFactory<TUser>, ClaimsIdentityFactory<TUser>>();
|
||||
|
||||
// TODO: rationalize email/sms/usertoken services
|
||||
// TODO: configure lockout from config?
|
||||
}
|
||||
|
||||
public static IEnumerable<IServiceDescriptor> GetDefaultRoleServices<TRole>() where TRole : class
|
||||
|
|
|
|||
|
|
@ -0,0 +1,42 @@
|
|||
using System;
|
||||
|
||||
namespace Microsoft.AspNet.Identity
|
||||
{
|
||||
public class LockoutOptions
|
||||
{
|
||||
public LockoutOptions()
|
||||
{
|
||||
DefaultLockoutTimeSpan = TimeSpan.FromMinutes(5);
|
||||
EnabledByDefault = false;
|
||||
MaxFailedAccessAttempts = 5;
|
||||
}
|
||||
public void Copy(LockoutOptions options)
|
||||
{
|
||||
if (options == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
DefaultLockoutTimeSpan = options.DefaultLockoutTimeSpan;
|
||||
EnabledByDefault = options.EnabledByDefault;
|
||||
MaxFailedAccessAttempts = options.MaxFailedAccessAttempts;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// If true, will enable user lockout when users are created
|
||||
/// </summary>
|
||||
public bool EnabledByDefault { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Number of access attempts allowed for a user before lockout (if enabled)
|
||||
/// </summary>
|
||||
public int MaxFailedAccessAttempts { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Default amount of time an user is locked out for after MaxFailedAccessAttempsBeforeLockout is reached
|
||||
/// </summary>
|
||||
public TimeSpan DefaultLockoutTimeSpan { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
@ -24,8 +24,18 @@
|
|||
<Compile Include="ClaimsIdentityFactory.cs" />
|
||||
<Compile Include="Crypto.cs" />
|
||||
<Compile Include="IClaimsIdentityFactory.cs" />
|
||||
<Compile Include="IdentityBuilder.cs" />
|
||||
<Compile Include="IdentityMessage.cs" />
|
||||
<Compile Include="IdentityOptions.cs" />
|
||||
<Compile Include="IdentityResult.cs" />
|
||||
<Compile Include="IdentityRole.cs" />
|
||||
<Compile Include="IdentityServiceCollectionExtensions.cs" />
|
||||
<Compile Include="IdentityServices.cs" />
|
||||
<Compile Include="IdentitySetup.cs" />
|
||||
<Compile Include="IdentityUser.cs" />
|
||||
<Compile Include="IdentityUserClaim.cs" />
|
||||
<Compile Include="IdentityUserLogin.cs" />
|
||||
<Compile Include="IdentityUserRole.cs" />
|
||||
<Compile Include="IIdentityMessageService.cs" />
|
||||
<Compile Include="IPasswordHasher.cs" />
|
||||
<Compile Include="IPasswordValidator.cs" />
|
||||
|
|
@ -56,5 +66,8 @@
|
|||
<Compile Include="UserManager.cs" />
|
||||
<Compile Include="UserValidator.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Folder Include="Properties\" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VSToolsPath)\ProjectK\Microsoft.Web.ProjectK.targets" Condition="'$(VSToolsPath)' != ''" />
|
||||
</Project>
|
||||
|
|
@ -0,0 +1,59 @@
|
|||
using Microsoft.AspNet.ConfigurationModel;
|
||||
|
||||
namespace Microsoft.AspNet.Identity
|
||||
{
|
||||
public class PasswordOptions
|
||||
{
|
||||
public PasswordOptions()
|
||||
{
|
||||
RequireDigit = true;
|
||||
RequireLowercase = true;
|
||||
RequireNonLetterOrDigit = true;
|
||||
RequireUppercase = true;
|
||||
RequiredLength = 6;
|
||||
}
|
||||
|
||||
public PasswordOptions(IConfiguration config) : this()
|
||||
{
|
||||
IdentityOptions.Read(this, config);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Minimum required length
|
||||
/// </summary>
|
||||
public int RequiredLength { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Require a non letter or digit character
|
||||
/// </summary>
|
||||
public bool RequireNonLetterOrDigit { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Require a lower case letter ('a' - 'z')
|
||||
/// </summary>
|
||||
public bool RequireLowercase { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Require an upper case letter ('A' - 'Z')
|
||||
/// </summary>
|
||||
public bool RequireUppercase { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Require a digit ('0' - '9')
|
||||
/// </summary>
|
||||
public bool RequireDigit { get; set; }
|
||||
|
||||
public virtual void Copy(PasswordOptions options)
|
||||
{
|
||||
if (options == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
RequireDigit = options.RequireDigit;
|
||||
RequireLowercase = options.RequireLowercase;
|
||||
RequireNonLetterOrDigit = options.RequireNonLetterOrDigit;
|
||||
RequireUppercase = options.RequireUppercase;
|
||||
RequiredLength = options.RequiredLength;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -27,63 +27,44 @@ namespace Microsoft.AspNet.Identity
|
|||
/// <summary>
|
||||
/// Used to validate some basic password policy like length and number of non alphanumerics
|
||||
/// </summary>
|
||||
public class PasswordValidator : IPasswordValidator
|
||||
public class PasswordValidator<TUser> : IPasswordValidator<TUser> where TUser : class
|
||||
{
|
||||
/// <summary>
|
||||
/// Minimum required length
|
||||
/// Ensures that the password is of the required length and meets the configured requirements
|
||||
/// </summary>
|
||||
public int RequiredLength { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Require a non letter or digit character
|
||||
/// </summary>
|
||||
public bool RequireNonLetterOrDigit { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Require a lower case letter ('a' - 'z')
|
||||
/// </summary>
|
||||
public bool RequireLowercase { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Require an upper case letter ('A' - 'Z')
|
||||
/// </summary>
|
||||
public bool RequireUppercase { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Require a digit ('0' - '9')
|
||||
/// </summary>
|
||||
public bool RequireDigit { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Ensures that the string is of the required length and meets the configured requirements
|
||||
/// </summary>
|
||||
/// <param name="item"></param>
|
||||
/// <param name="password"></param>
|
||||
/// <param name="manager"></param>
|
||||
/// <param name="cancellationToken"></param>
|
||||
/// <returns></returns>
|
||||
public virtual Task<IdentityResult> ValidateAsync(string item, CancellationToken cancellationToken = default(CancellationToken))
|
||||
public virtual Task<IdentityResult> ValidateAsync(string password, UserManager<TUser> manager, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
if (item == null)
|
||||
if (password == null)
|
||||
{
|
||||
throw new ArgumentNullException("item");
|
||||
throw new ArgumentNullException("password");
|
||||
}
|
||||
if (manager == null)
|
||||
{
|
||||
throw new ArgumentNullException("manager");
|
||||
}
|
||||
var errors = new List<string>();
|
||||
if (string.IsNullOrWhiteSpace(item) || item.Length < RequiredLength)
|
||||
var options = manager.Options.Password;
|
||||
if (string.IsNullOrWhiteSpace(password) || password.Length < options.RequiredLength)
|
||||
{
|
||||
errors.Add(String.Format(CultureInfo.CurrentCulture, Resources.PasswordTooShort, RequiredLength));
|
||||
errors.Add(String.Format(CultureInfo.CurrentCulture, Resources.PasswordTooShort, options.RequiredLength));
|
||||
}
|
||||
if (RequireNonLetterOrDigit && item.All(IsLetterOrDigit))
|
||||
if (options.RequireNonLetterOrDigit && password.All(IsLetterOrDigit))
|
||||
{
|
||||
errors.Add(Resources.PasswordRequireNonLetterOrDigit);
|
||||
}
|
||||
if (RequireDigit && !item.Any(IsDigit))
|
||||
if (options.RequireDigit && !password.Any(IsDigit))
|
||||
{
|
||||
errors.Add(Resources.PasswordRequireDigit);
|
||||
}
|
||||
if (RequireLowercase && !item.Any(IsLower))
|
||||
if (options.RequireLowercase && !password.Any(IsLower))
|
||||
{
|
||||
errors.Add(Resources.PasswordRequireLower);
|
||||
}
|
||||
if (RequireUppercase && !item.Any(IsUpper))
|
||||
if (options.RequireUppercase && !password.Any(IsUpper))
|
||||
{
|
||||
errors.Add(Resources.PasswordRequireUpper);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -32,24 +32,23 @@ namespace Microsoft.AspNet.Identity
|
|||
{
|
||||
private bool _disposed;
|
||||
|
||||
public RoleManager(IServiceProvider services)
|
||||
{
|
||||
Initialize(services);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructor
|
||||
/// Constructor
|
||||
/// </summary>
|
||||
/// <param name="services"></param>
|
||||
/// <param name="store">The IRoleStore is responsible for commiting changes via the UpdateAsync/CreateAsync methods</param>
|
||||
public RoleManager(IRoleStore<TRole> store)
|
||||
public RoleManager(IServiceProvider services, IRoleStore<TRole> store)
|
||||
{
|
||||
if (store == null)
|
||||
{
|
||||
throw new ArgumentNullException("store");
|
||||
}
|
||||
var services = new ServiceCollection { IdentityServices.GetDefaultRoleServices<TRole>() };
|
||||
services.AddInstance<IRoleStore<TRole>>(store);
|
||||
Initialize(services.BuildServiceProvider());
|
||||
if (services == null)
|
||||
{
|
||||
throw new ArgumentNullException("services");
|
||||
}
|
||||
RoleValidator = services.GetService<IRoleValidator<TRole>>() ?? new RoleValidator<TRole>();
|
||||
Store = store;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -90,21 +89,6 @@ namespace Microsoft.AspNet.Identity
|
|||
}
|
||||
}
|
||||
|
||||
public void Initialize(IServiceProvider services)
|
||||
{
|
||||
if (services == null)
|
||||
{
|
||||
throw new ArgumentNullException("services");
|
||||
}
|
||||
Store = services.GetService<IRoleStore<TRole>>();
|
||||
if (Store == null)
|
||||
{
|
||||
// TODO: what is the right way to enforce required services
|
||||
throw new InvalidOperationException();
|
||||
}
|
||||
RoleValidator = services.GetService<IRoleValidator<TRole>>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Dispose this object
|
||||
/// </summary>
|
||||
|
|
|
|||
|
|
@ -41,52 +41,34 @@ namespace Microsoft.AspNet.Identity
|
|||
private TimeSpan _defaultLockout = TimeSpan.Zero;
|
||||
private bool _disposed;
|
||||
private IPasswordHasher _passwordHasher;
|
||||
private LockoutPolicy _lockoutPolicy;
|
||||
|
||||
// Needed for mock unit tests
|
||||
public UserManager() { }
|
||||
private IdentityOptions _options;
|
||||
|
||||
/// <summary>
|
||||
/// Constructor which takes a service provider
|
||||
/// Constructor which takes a service provider and user store
|
||||
/// </summary>
|
||||
/// <param name="serviceProvider"></param>
|
||||
public UserManager(IServiceProvider serviceProvider)
|
||||
{
|
||||
Initialize(serviceProvider);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructor
|
||||
/// </summary>
|
||||
/// <param name="store">The IUserStore is responsible for commiting changes via the UpdateAsync/CreateAsync methods</param>
|
||||
public UserManager(IUserStore<TUser> store)
|
||||
{
|
||||
if (store == null)
|
||||
{
|
||||
throw new ArgumentNullException("store");
|
||||
}
|
||||
var services = new ServiceCollection { IdentityServices.GetDefaultUserServices<TUser>() };
|
||||
services.AddInstance<IUserStore<TUser>>(store);
|
||||
Initialize(services.BuildServiceProvider());
|
||||
}
|
||||
|
||||
public void Initialize(IServiceProvider serviceProvider)
|
||||
/// <param name="store"></param>
|
||||
/// <param name="optionsAccessor"></param>
|
||||
public UserManager(IServiceProvider serviceProvider, IUserStore<TUser> store, IOptionsAccessor<IdentityOptions> optionsAccessor)
|
||||
{
|
||||
if (serviceProvider == null)
|
||||
{
|
||||
throw new ArgumentNullException("serviceProvider");
|
||||
}
|
||||
PasswordHasher = serviceProvider.GetService<IPasswordHasher>();
|
||||
UserValidator = serviceProvider.GetService<IUserValidator<TUser>>();
|
||||
PasswordValidator = serviceProvider.GetService<IPasswordValidator>();
|
||||
ClaimsIdentityFactory = serviceProvider.GetService<IClaimsIdentityFactory<TUser>>();
|
||||
LockoutPolicy = serviceProvider.GetService<LockoutPolicy>();
|
||||
Store = serviceProvider.GetService<IUserStore<TUser>>();
|
||||
if (Store == null)
|
||||
if (store == null)
|
||||
{
|
||||
// TODO: what is the right way to enforce required services
|
||||
throw new InvalidOperationException();
|
||||
throw new ArgumentNullException("store");
|
||||
}
|
||||
if (optionsAccessor == null || optionsAccessor.Options == null)
|
||||
{
|
||||
throw new ArgumentNullException("optionsAccessor");
|
||||
}
|
||||
Store = store;
|
||||
Options = optionsAccessor.Options;
|
||||
PasswordHasher = serviceProvider.GetService<IPasswordHasher>() ?? new PasswordHasher();
|
||||
UserValidator = serviceProvider.GetService<IUserValidator<TUser>>() ?? new UserValidator<TUser>();
|
||||
PasswordValidator = serviceProvider.GetService<IPasswordValidator<TUser>>() ?? new PasswordValidator<TUser>();
|
||||
ClaimsIdentityFactory = serviceProvider.GetService<IClaimsIdentityFactory<TUser>>() ?? new ClaimsIdentityFactory<TUser>();
|
||||
// TODO: Email/Sms/Token services
|
||||
}
|
||||
|
||||
|
|
@ -124,7 +106,7 @@ namespace Microsoft.AspNet.Identity
|
|||
/// <summary>
|
||||
/// Used to validate passwords before persisting changes
|
||||
/// </summary>
|
||||
public IPasswordValidator PasswordValidator { get; set; }
|
||||
public IPasswordValidator<TUser> PasswordValidator { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Used to create claims identities from users
|
||||
|
|
@ -162,30 +144,23 @@ namespace Microsoft.AspNet.Identity
|
|||
/// </summary>
|
||||
public IUserTokenProvider<TUser> UserTokenProvider { get; set; }
|
||||
|
||||
public LockoutPolicy LockoutPolicy { get; set; }
|
||||
|
||||
private bool UserLockoutEnabledByDefault
|
||||
public IdentityOptions Options
|
||||
{
|
||||
get
|
||||
{
|
||||
return LockoutPolicy != null && LockoutPolicy.UserLockoutEnabledByDefault;
|
||||
ThrowIfDisposed();
|
||||
return _options;
|
||||
}
|
||||
}
|
||||
|
||||
private int MaxFailedAccessAttemptsBeforeLockout
|
||||
{
|
||||
get
|
||||
set
|
||||
{
|
||||
return LockoutPolicy != null ? LockoutPolicy.MaxFailedAccessAttemptsBeforeLockout : 0;
|
||||
}
|
||||
}
|
||||
|
||||
private TimeSpan DefaultAccountLockoutTimeSpan
|
||||
{
|
||||
get
|
||||
{
|
||||
return LockoutPolicy != null ? LockoutPolicy.DefaultAccountLockoutTimeSpan : TimeSpan.FromMinutes(5);
|
||||
ThrowIfDisposed();
|
||||
if (value == null)
|
||||
{
|
||||
throw new ArgumentNullException("value");
|
||||
}
|
||||
_options = value;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -380,7 +355,7 @@ namespace Microsoft.AspNet.Identity
|
|||
{
|
||||
return result;
|
||||
}
|
||||
if (UserLockoutEnabledByDefault && SupportsUserLockout)
|
||||
if (Options.Lockout.EnabledByDefault && SupportsUserLockout)
|
||||
{
|
||||
await GetUserLockoutStore().SetLockoutEnabledAsync(user, true, cancellationToken);
|
||||
}
|
||||
|
|
@ -673,7 +648,7 @@ namespace Microsoft.AspNet.Identity
|
|||
{
|
||||
if (PasswordValidator != null)
|
||||
{
|
||||
var result = await PasswordValidator.ValidateAsync(newPassword, cancellationToken);
|
||||
var result = await PasswordValidator.ValidateAsync(newPassword, this, cancellationToken);
|
||||
if (!result.Succeeded)
|
||||
{
|
||||
return result;
|
||||
|
|
@ -1757,12 +1732,12 @@ namespace Microsoft.AspNet.Identity
|
|||
}
|
||||
// If this puts the user over the threshold for lockout, lock them out and reset the access failed count
|
||||
var count = await store.IncrementAccessFailedCountAsync(user, cancellationToken);
|
||||
if (count < MaxFailedAccessAttemptsBeforeLockout)
|
||||
if (count < Options.Lockout.MaxFailedAccessAttempts)
|
||||
{
|
||||
return await UpdateAsync(user, cancellationToken);
|
||||
}
|
||||
await
|
||||
store.SetLockoutEndDateAsync(user, DateTimeOffset.UtcNow.Add(DefaultAccountLockoutTimeSpan), cancellationToken);
|
||||
store.SetLockoutEndDateAsync(user, DateTimeOffset.UtcNow.Add(Options.Lockout.DefaultLockoutTimeSpan), cancellationToken);
|
||||
await store.ResetAccessFailedCountAsync(user, cancellationToken);
|
||||
return await UpdateAsync(user, cancellationToken);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,38 @@
|
|||
using Microsoft.AspNet.ConfigurationModel;
|
||||
|
||||
namespace Microsoft.AspNet.Identity
|
||||
{
|
||||
public class UserOptions
|
||||
{
|
||||
public UserOptions()
|
||||
{
|
||||
AllowOnlyAlphanumericNames = true;
|
||||
//User.RequireUniqueEmail = true; // TODO: app decision?
|
||||
}
|
||||
|
||||
public UserOptions(IConfiguration config) : this()
|
||||
{
|
||||
IdentityOptions.Read(this, config);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Only allow [A-Za-z0-9@_] in UserNames
|
||||
/// </summary>
|
||||
public bool AllowOnlyAlphanumericNames { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// If set, enforces that emails are non empty, valid, and unique
|
||||
/// </summary>
|
||||
public bool RequireUniqueEmail { get; set; }
|
||||
|
||||
public virtual void Copy(UserOptions options)
|
||||
{
|
||||
if (options == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
AllowOnlyAlphanumericNames = options.AllowOnlyAlphanumericNames;
|
||||
RequireUniqueEmail = options.RequireUniqueEmail;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -33,24 +33,6 @@ namespace Microsoft.AspNet.Identity
|
|||
/// <typeparam name="TUser"></typeparam>
|
||||
public class UserValidator<TUser> : IUserValidator<TUser> where TUser : class
|
||||
{
|
||||
/// <summary>
|
||||
/// Constructor
|
||||
/// </summary>
|
||||
public UserValidator()
|
||||
{
|
||||
AllowOnlyAlphanumericUserNames = true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Only allow [A-Za-z0-9@_] in UserNames
|
||||
/// </summary>
|
||||
public bool AllowOnlyAlphanumericUserNames { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// If set, enforces that emails are non empty, valid, and unique
|
||||
/// </summary>
|
||||
public bool RequireUniqueEmail { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Validates a user before saving
|
||||
/// </summary>
|
||||
|
|
@ -70,7 +52,7 @@ namespace Microsoft.AspNet.Identity
|
|||
}
|
||||
var errors = new List<string>();
|
||||
await ValidateUserName(manager, user, errors);
|
||||
if (RequireUniqueEmail)
|
||||
if (manager.Options.User.RequireUniqueEmail)
|
||||
{
|
||||
await ValidateEmail(manager, user, errors);
|
||||
}
|
||||
|
|
@ -126,7 +108,7 @@ namespace Microsoft.AspNet.Identity
|
|||
{
|
||||
errors.Add(String.Format(CultureInfo.CurrentCulture, Resources.PropertyTooShort, "UserName"));
|
||||
}
|
||||
else if (AllowOnlyAlphanumericUserNames && !userName.All(IsAlphaNumeric))
|
||||
else if (manager.Options.User.AllowOnlyAlphanumericNames && !userName.All(IsAlphaNumeric))
|
||||
{
|
||||
// If any characters are not letters or digits, its an illegal user name
|
||||
errors.Add(String.Format(CultureInfo.CurrentCulture, Resources.InvalidUserName, userName));
|
||||
|
|
|
|||
|
|
@ -3,9 +3,9 @@
|
|||
"dependencies": {
|
||||
"Microsoft.AspNet.ConfigurationModel": "0.1-alpha-*",
|
||||
"Microsoft.AspNet.DependencyInjection" : "0.1-alpha-*",
|
||||
"System.Security.Claims" : "0.1-alpha-*",
|
||||
"Microsoft.AspNet.HttpFeature" : "0.1-alpha-*",
|
||||
"Microsoft.AspNet.Security.DataProtection" : "0.1-alpha-*"
|
||||
"Microsoft.AspNet.Security.DataProtection" : "0.1-alpha-*",
|
||||
"System.Security.Claims" : "0.1-alpha-*"
|
||||
},
|
||||
"configurations": {
|
||||
"net45": {},
|
||||
|
|
@ -20,6 +20,7 @@
|
|||
"System.Linq.Expressions": "4.0.0.0",
|
||||
"System.Linq.Queryable": "4.0.0.0",
|
||||
"System.Reflection": "4.0.10.0",
|
||||
"System.Reflection.Extensions": "4.0.0.0",
|
||||
"System.Resources.ResourceManager": "4.0.0.0",
|
||||
"System.Runtime": "4.0.20.0",
|
||||
"System.Runtime.Extensions": "4.0.10.0",
|
||||
|
|
|
|||
|
|
@ -26,5 +26,8 @@
|
|||
<Compile Include="TestIdentityFactory.cs" />
|
||||
<Compile Include="UserStoreTest.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Folder Include="Properties\" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VSToolsPath)\ProjectK\Microsoft.Web.ProjectK.targets" Condition="'$(VSToolsPath)' != ''" />
|
||||
</Project>
|
||||
|
|
@ -17,12 +17,64 @@
|
|||
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNet.DependencyInjection;
|
||||
using Microsoft.AspNet.DependencyInjection.Fallback;
|
||||
using Microsoft.AspNet.Identity.Test;
|
||||
using Microsoft.Data.Entity;
|
||||
using Microsoft.Data.InMemory;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.AspNet.Identity.Entity.Test
|
||||
{
|
||||
public class RoleStoreTest
|
||||
{
|
||||
class ApplicationRoleManager : RoleManager<EntityRole>
|
||||
{
|
||||
public ApplicationRoleManager(IServiceProvider services, IRoleStore<EntityRole> store) : base(services, store) { }
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task CanCreateUsingAddRoleManager()
|
||||
{
|
||||
var services = new ServiceCollection();
|
||||
#if NET45
|
||||
// services.AddEntityFramework(s => s.AddSqlServer());
|
||||
//#else
|
||||
services.AddEntityFramework(s => s.AddInMemoryStore());
|
||||
#endif
|
||||
// TODO: this should construct a new instance of InMemoryStore
|
||||
var store = new RoleStore<EntityRole>(new IdentityContext());
|
||||
services.AddIdentity<EntityUser, EntityRole>(s =>
|
||||
{
|
||||
s.AddRoleStore(() => store);
|
||||
s.AddRoleManager<ApplicationRoleManager>();
|
||||
});
|
||||
|
||||
var provider = services.BuildServiceProvider();
|
||||
var manager = provider.GetService<ApplicationRoleManager>();
|
||||
Assert.NotNull(manager);
|
||||
IdentityResultAssert.IsSuccess(await manager.CreateAsync(new EntityRole("arole")));
|
||||
}
|
||||
[Fact]
|
||||
public async Task CanCreateRoleWithSingletonManager()
|
||||
{
|
||||
var services = new ServiceCollection();
|
||||
#if NET45
|
||||
// services.AddEntityFramework(s => s.AddSqlServer());
|
||||
//#else
|
||||
services.AddEntityFramework(s => s.AddInMemoryStore());
|
||||
#endif
|
||||
services.AddTransient<DbContext, IdentityContext>();
|
||||
services.AddTransient<IRoleStore<EntityRole>, RoleStore<EntityRole>>();
|
||||
//todo: services.AddSingleton<RoleManager<EntityRole>, RoleManager<EntityRole>>();
|
||||
// TODO: How to configure SqlServer?
|
||||
services.AddSingleton<ApplicationRoleManager, ApplicationRoleManager>();
|
||||
var provider = services.BuildServiceProvider();
|
||||
var manager = provider.GetService<ApplicationRoleManager>();
|
||||
Assert.NotNull(manager);
|
||||
IdentityResultAssert.IsSuccess(await manager.CreateAsync(new EntityRole("someRole")));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task RoleStoreMethodsThrowWhenDisposedTest()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -0,0 +1,121 @@
|
|||
using Microsoft.AspNet.Abstractions;
|
||||
using Microsoft.AspNet.DependencyInjection;
|
||||
using Microsoft.AspNet.DependencyInjection.Fallback;
|
||||
using Microsoft.AspNet.Identity.Entity;
|
||||
using Microsoft.AspNet.Identity.Test;
|
||||
using Microsoft.AspNet.PipelineCore;
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Data.Entity;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.AspNet.Identity.Entity.Test
|
||||
{
|
||||
public class StartupTest
|
||||
{
|
||||
public class ApplicationUser : EntityUser { }
|
||||
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 PasswordsNegativeLengthSetup : IOptionsSetup<IdentityOptions>
|
||||
{
|
||||
public int Order { get { return 0; } }
|
||||
public void Setup(IdentityOptions options)
|
||||
{
|
||||
options.Password.RequiredLength = -1;
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CanCustomizeIdentityOptions()
|
||||
{
|
||||
IBuilder builder = new Builder(new ServiceCollection().BuildServiceProvider());
|
||||
builder.UseServices(services => {
|
||||
services.AddIdentity<IdentityUser>(identityServices => { });
|
||||
services.AddSetup<PasswordsNegativeLengthSetup>();
|
||||
});
|
||||
|
||||
var setup = builder.ApplicationServices.GetService<IOptionsSetup<IdentityOptions>>();
|
||||
Assert.IsType(typeof(PasswordsNegativeLengthSetup), setup);
|
||||
var optionsGetter = builder.ApplicationServices.GetService<IOptionsAccessor<IdentityOptions>>();
|
||||
Assert.NotNull(optionsGetter);
|
||||
setup.Setup(optionsGetter.Options);
|
||||
|
||||
var myOptions = optionsGetter.Options;
|
||||
Assert.True(myOptions.Password.RequireLowercase);
|
||||
Assert.True(myOptions.Password.RequireDigit);
|
||||
Assert.True(myOptions.Password.RequireNonLetterOrDigit);
|
||||
Assert.True(myOptions.Password.RequireUppercase);
|
||||
Assert.Equal(-1, myOptions.Password.RequiredLength);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CanSetupIdentityOptions()
|
||||
{
|
||||
IBuilder app = new Builder(new ServiceCollection().BuildServiceProvider());
|
||||
app.UseServices(services => services.AddIdentity<IdentityUser>(identityServices => identityServices.SetupOptions(options => options.User.RequireUniqueEmail = true)));
|
||||
|
||||
var optionsGetter = app.ApplicationServices.GetService<IOptionsAccessor<IdentityOptions>>();
|
||||
Assert.NotNull(optionsGetter);
|
||||
|
||||
var myOptions = optionsGetter.Options;
|
||||
Assert.True(myOptions.User.RequireUniqueEmail);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task EnsureStartupUsageWorks()
|
||||
{
|
||||
IBuilder builder = new Builder(new ServiceCollection().BuildServiceProvider());
|
||||
|
||||
//builder.UseServices(services => services.AddIdentity<ApplicationUser>(s =>
|
||||
// s.AddEntity<ApplicationDbContext>()
|
||||
//{
|
||||
|
||||
builder.UseServices(services =>
|
||||
{
|
||||
services.AddEntityFramework();
|
||||
services.AddTransient<DbContext, IdentityContext>();
|
||||
services.AddIdentity<ApplicationUser, EntityRole>(s =>
|
||||
{
|
||||
s.AddEntity();
|
||||
s.AddUserManager<ApplicationUserManager>();
|
||||
s.AddRoleManager<ApplicationRoleManager>();
|
||||
});
|
||||
});
|
||||
|
||||
var userStore = builder.ApplicationServices.GetService<IUserStore<ApplicationUser>>();
|
||||
var roleStore = builder.ApplicationServices.GetService<IRoleStore<EntityRole>>();
|
||||
var userManager = builder.ApplicationServices.GetService<ApplicationUserManager>();
|
||||
//TODO: var userManager = builder.ApplicationServices.GetService<UserManager<IdentityUser>();
|
||||
var roleManager = builder.ApplicationServices.GetService<ApplicationRoleManager>();
|
||||
|
||||
Assert.NotNull(userStore);
|
||||
Assert.NotNull(userManager);
|
||||
Assert.NotNull(roleStore);
|
||||
Assert.NotNull(roleManager);
|
||||
|
||||
//await CreateAdminUser(builder.ApplicationServices);
|
||||
}
|
||||
|
||||
private static async Task CreateAdminUser(IServiceProvider serviceProvider)
|
||||
{
|
||||
const string userName = "admin";
|
||||
const string roleName = "Admins";
|
||||
const string password = "1qaz@WSX";
|
||||
var userManager = serviceProvider.GetService<ApplicationUserManager>();
|
||||
var roleManager = serviceProvider.GetService<ApplicationRoleManager>();
|
||||
|
||||
var user = new ApplicationUser { UserName = userName };
|
||||
IdentityResultAssert.IsSuccess(await userManager.CreateAsync(user, password));
|
||||
IdentityResultAssert.IsSuccess(await roleManager.CreateAsync(new EntityRole { Name = roleName }));
|
||||
IdentityResultAssert.IsSuccess(await userManager.AddToRoleAsync(user, roleName));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -36,74 +36,63 @@ namespace Microsoft.AspNet.Identity.Entity.Test
|
|||
public static DbContext CreateContext()
|
||||
{
|
||||
var serviceProvider = new ServiceCollection()
|
||||
.AddEntityFramework(s => s.AddInMemoryStore())
|
||||
.BuildServiceProvider();
|
||||
//#if NET45
|
||||
// .AddEntityFramework(s => s.AddSqlServer())
|
||||
//#else
|
||||
.AddEntityFramework(s => s.AddInMemoryStore())
|
||||
//#endif
|
||||
.BuildServiceProvider();
|
||||
|
||||
var db = new IdentityContext(serviceProvider);
|
||||
// var sql = db.Configuration.DataStore as SqlServerDataStore;
|
||||
// if (sql != null)
|
||||
// {
|
||||
//#if NET45
|
||||
// var builder = new DbConnectionStringBuilder {ConnectionString = sql.ConnectionString};
|
||||
// var targetDatabase = builder["Database"].ToString();
|
||||
|
||||
// // Connect to master, check if database exists, and create if not
|
||||
// builder.Add("Database", "master");
|
||||
// using (var masterConnection = new SqlConnection(builder.ConnectionString))
|
||||
// {
|
||||
// masterConnection.Open();
|
||||
|
||||
// var masterCommand = masterConnection.CreateCommand();
|
||||
// masterCommand.CommandText = "SELECT COUNT(*) FROM sys.databases WHERE [name]=N'" + targetDatabase +
|
||||
// "'";
|
||||
// if ((int?) masterCommand.ExecuteScalar() < 1)
|
||||
// {
|
||||
// masterCommand.CommandText = "CREATE DATABASE [" + targetDatabase + "]";
|
||||
// masterCommand.ExecuteNonQuery();
|
||||
|
||||
// using (var conn = new SqlConnection(sql.ConnectionString))
|
||||
// {
|
||||
// conn.Open();
|
||||
// var command = conn.CreateCommand();
|
||||
// command.CommandText = @"
|
||||
//CREATE TABLE [dbo].[AspNetUsers] (
|
||||
//[Id] NVARCHAR (128) NOT NULL,
|
||||
//[Email] NVARCHAR (256) NULL,
|
||||
//[EmailConfirmed] BIT NOT NULL,
|
||||
//[PasswordHash] NVARCHAR (MAX) NULL,
|
||||
//[SecurityStamp] NVARCHAR (MAX) NULL,
|
||||
//[PhoneNumber] NVARCHAR (MAX) NULL,
|
||||
//[PhoneNumberConfirmed] BIT NOT NULL,
|
||||
//[TwoFactorEnabled] BIT NOT NULL,
|
||||
//[LockoutEndDateUtc] DATETIME NULL,
|
||||
//[LockoutEnabled] BIT NOT NULL,
|
||||
//[AccessFailedCount] INT NOT NULL,
|
||||
//[UserName] NVARCHAR (256) NOT NULL
|
||||
//) ";
|
||||
// //CONSTRAINT [PK_dbo.AspNetUsers] PRIMARY KEY CLUSTERED ([Id] ASC)
|
||||
// command.ExecuteNonQuery();
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//#else
|
||||
// throw new NotSupportedException("SQL Server is not yet supported when running against K10.");
|
||||
//#endif
|
||||
|
||||
// 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 class TestSetup : IOptionsSetup<IdentityOptions>
|
||||
{
|
||||
private readonly IdentityOptions _options;
|
||||
|
||||
public TestSetup(IdentityOptions options)
|
||||
{
|
||||
_options = options;
|
||||
}
|
||||
|
||||
public int Order { get { return 0; } }
|
||||
public void Setup(IdentityOptions options)
|
||||
{
|
||||
options.Copy(_options);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static UserManager<EntityUser> CreateManager(DbContext context)
|
||||
{
|
||||
var manager = new UserManager<EntityUser>(new UserStore(context))
|
||||
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.AddSingleton<UserManager<EntityUser>, UserManager<EntityUser>>();
|
||||
var options = new IdentityOptions
|
||||
{
|
||||
UserValidator = new UserValidator<EntityUser>(),
|
||||
PasswordValidator = new PasswordValidator()
|
||||
Password = new PasswordOptions
|
||||
{
|
||||
RequireDigit = false,
|
||||
RequireLowercase = false,
|
||||
RequireNonLetterOrDigit = false,
|
||||
RequireUppercase = false
|
||||
}
|
||||
};
|
||||
return manager;
|
||||
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);
|
||||
}
|
||||
|
||||
public static UserManager<EntityUser> CreateManager()
|
||||
|
|
@ -113,7 +102,11 @@ namespace Microsoft.AspNet.Identity.Entity.Test
|
|||
|
||||
public static RoleManager<EntityRole> CreateRoleManager(DbContext context)
|
||||
{
|
||||
return new RoleManager<EntityRole>(new RoleStore<EntityRole, string>(context));
|
||||
var services = new ServiceCollection();
|
||||
services.AddTransient<IRoleValidator<EntityRole>, RoleValidator<EntityRole>>();
|
||||
services.AddInstance<IRoleStore<EntityRole>>(new RoleStore<EntityRole, string>(context));
|
||||
// return services.BuildServiceProvider().GetService<RoleManager<EntityRole>>();
|
||||
return new RoleManager<EntityRole>(services.BuildServiceProvider(), new RoleStore<EntityRole, string>(context));
|
||||
}
|
||||
|
||||
public static RoleManager<EntityRole> CreateRoleManager()
|
||||
|
|
|
|||
|
|
@ -17,11 +17,12 @@
|
|||
|
||||
using Microsoft.AspNet.DependencyInjection;
|
||||
using Microsoft.AspNet.DependencyInjection.Fallback;
|
||||
using Microsoft.AspNet.Identity.Test;
|
||||
using Microsoft.AspNet.Testing;
|
||||
using Microsoft.Data.Entity;
|
||||
using Microsoft.Data.Entity.Metadata;
|
||||
using Microsoft.Data.Entity.Storage;
|
||||
using Microsoft.Data.InMemory;
|
||||
using Microsoft.Data.SqlServer;
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Security.Claims;
|
||||
|
|
@ -35,37 +36,49 @@ namespace Microsoft.AspNet.Identity.Entity.Test
|
|||
{
|
||||
class ApplicationUserManager : UserManager<EntityUser>
|
||||
{
|
||||
public ApplicationUserManager(IServiceProvider services) : base(services) { }
|
||||
public ApplicationUserManager(IServiceProvider services, IUserStore<EntityUser> store, IOptionsAccessor<IdentityOptions> options) : base(services, store, options) { }
|
||||
}
|
||||
|
||||
// [Fact] Disabled - see issue #48
|
||||
[Fact]
|
||||
public async Task CanUseAddedManagerInstance()
|
||||
{
|
||||
var services = new ServiceCollection();
|
||||
var store = new UserStore(new IdentityContext());
|
||||
services.AddInstance<UserManager<EntityUser>>(new UserManager<EntityUser>(store));
|
||||
#if NET45
|
||||
// services.AddEntityFramework(s => s.AddSqlServer());
|
||||
//#else
|
||||
services.AddEntityFramework(s => s.AddInMemoryStore());
|
||||
#endif
|
||||
services.AddSingleton<IOptionsAccessor<IdentityOptions>, OptionsAccessor<IdentityOptions>>();
|
||||
services.AddInstance<DbContext>(new IdentityContext());
|
||||
services.AddTransient<IUserStore<EntityUser>, UserStore>();
|
||||
services.AddSingleton<ApplicationUserManager, ApplicationUserManager>();
|
||||
var provider = services.BuildServiceProvider();
|
||||
var manager = provider.GetService<UserManager<EntityUser>>();
|
||||
var manager = provider.GetService<ApplicationUserManager>();
|
||||
Assert.NotNull(manager);
|
||||
IdentityResultAssert.IsSuccess(await manager.CreateAsync(new EntityUser("hello")));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task CanUseSingletonManagerInstance()
|
||||
public async Task CanCreateUsingAddUserManager()
|
||||
{
|
||||
var services = new ServiceCollection();
|
||||
#if NET45
|
||||
// services.AddEntityFramework(s => s.AddSqlServer());
|
||||
//#else
|
||||
services.AddEntityFramework(s => s.AddInMemoryStore());
|
||||
#endif
|
||||
// TODO: this needs to construct a new instance of InMemoryStore
|
||||
var store = new UserStore(new IdentityContext());
|
||||
services.AddIdentity<EntityUser, EntityRole>(s =>
|
||||
{
|
||||
s.UseUserStore(() => store);
|
||||
s.UseUserManager<ApplicationUserManager>();
|
||||
s.AddUserStore(() => store);
|
||||
s.AddUserManager<ApplicationUserManager>();
|
||||
});
|
||||
//services.AddSingleton<ApplicationUserManager, ApplicationUserManager>();
|
||||
|
||||
var provider = services.BuildServiceProvider();
|
||||
var manager = provider.GetService<ApplicationUserManager>();
|
||||
Assert.NotNull(manager);
|
||||
IdentityResultAssert.IsSuccess(await manager.CreateAsync(new EntityUser("hello")));
|
||||
IdentityResultAssert.IsSuccess(await manager.CreateAsync(new EntityUser("hello2")));
|
||||
}
|
||||
|
||||
//[Fact]
|
||||
|
|
@ -146,30 +159,30 @@ namespace Microsoft.AspNet.Identity.Entity.Test
|
|||
Assert.ThrowsAsync<ArgumentNullException>("user",
|
||||
async () => await store.SetPasswordHashAsync(null, null));
|
||||
await Assert.ThrowsAsync<ArgumentNullException>("user", async () => await store.GetSecurityStampAsync(null));
|
||||
await Assert.ThrowsAsync<ArgumentNullException>("user",
|
||||
await Assert.ThrowsAsync<ArgumentNullException>("user",
|
||||
async () => await store.SetSecurityStampAsync(null, null));
|
||||
await Assert.ThrowsAsync<ArgumentNullException>("claim",
|
||||
await Assert.ThrowsAsync<ArgumentNullException>("claim",
|
||||
async () => await store.AddClaimAsync(new EntityUser("fake"), null));
|
||||
await Assert.ThrowsAsync<ArgumentNullException>("claim",
|
||||
await Assert.ThrowsAsync<ArgumentNullException>("claim",
|
||||
async () => await store.RemoveClaimAsync(new EntityUser("fake"), null));
|
||||
await Assert.ThrowsAsync<ArgumentNullException>("login",
|
||||
await Assert.ThrowsAsync<ArgumentNullException>("login",
|
||||
async () => await store.AddLoginAsync(new EntityUser("fake"), null));
|
||||
await Assert.ThrowsAsync<ArgumentNullException>("login",
|
||||
await Assert.ThrowsAsync<ArgumentNullException>("login",
|
||||
async () => await store.RemoveLoginAsync(new EntityUser("fake"), null));
|
||||
await Assert.ThrowsAsync<ArgumentNullException>("login", async () => await store.FindByLoginAsync(null));
|
||||
await Assert.ThrowsAsync<ArgumentNullException>("user", async () => await store.GetEmailConfirmedAsync(null));
|
||||
await Assert.ThrowsAsync<ArgumentNullException>("user",
|
||||
await Assert.ThrowsAsync<ArgumentNullException>("user",
|
||||
async () => await store.SetEmailConfirmedAsync(null, true));
|
||||
await Assert.ThrowsAsync<ArgumentNullException>("user", async () => await store.GetEmailAsync(null));
|
||||
await Assert.ThrowsAsync<ArgumentNullException>("user", async () => await store.SetEmailAsync(null, null));
|
||||
await Assert.ThrowsAsync<ArgumentNullException>("user", async () => await store.GetPhoneNumberAsync(null));
|
||||
await Assert.ThrowsAsync<ArgumentNullException>("user", async () => await store.SetPhoneNumberAsync(null, null));
|
||||
await Assert.ThrowsAsync<ArgumentNullException>("user",
|
||||
await Assert.ThrowsAsync<ArgumentNullException>("user",
|
||||
async () => await store.GetPhoneNumberConfirmedAsync(null));
|
||||
await Assert.ThrowsAsync<ArgumentNullException>("user",
|
||||
await Assert.ThrowsAsync<ArgumentNullException>("user",
|
||||
async () => await store.SetPhoneNumberConfirmedAsync(null, true));
|
||||
await Assert.ThrowsAsync<ArgumentNullException>("user", async () => await store.GetTwoFactorEnabledAsync(null));
|
||||
await Assert.ThrowsAsync<ArgumentNullException>("user",
|
||||
await Assert.ThrowsAsync<ArgumentNullException>("user",
|
||||
async () => await store.SetTwoFactorEnabledAsync(null, true));
|
||||
await Assert.ThrowsAsync<ArgumentNullException>("user", async () => await store.GetAccessFailedCountAsync(null));
|
||||
await Assert.ThrowsAsync<ArgumentNullException>("user", async () => await store.GetLockoutEnabledAsync(null));
|
||||
|
|
@ -308,7 +321,7 @@ namespace Microsoft.AspNet.Identity.Entity.Test
|
|||
{
|
||||
var manager = TestIdentityFactory.CreateManager();
|
||||
var user = new EntityUser("UpdateBlocked") { Email = email };
|
||||
manager.UserValidator = new UserValidator<EntityUser> { RequireUniqueEmail = true };
|
||||
manager.Options.User.RequireUniqueEmail = true;
|
||||
IdentityResultAssert.IsFailure(await manager.CreateAsync(user), "Email cannot be null or empty.");
|
||||
}
|
||||
|
||||
|
|
@ -320,7 +333,7 @@ namespace Microsoft.AspNet.Identity.Entity.Test
|
|||
{
|
||||
var manager = TestIdentityFactory.CreateManager();
|
||||
var user = new EntityUser("UpdateBlocked") { Email = email };
|
||||
manager.UserValidator = new UserValidator<EntityUser> { RequireUniqueEmail = true };
|
||||
manager.Options.User.RequireUniqueEmail = true;
|
||||
IdentityResultAssert.IsFailure(await manager.CreateAsync(user), "Email '" + email + "' is invalid.");
|
||||
}
|
||||
#endif
|
||||
|
|
@ -523,7 +536,7 @@ namespace Microsoft.AspNet.Identity.Entity.Test
|
|||
public async Task AddDupeEmailFallsWhenUniqueEmailRequired()
|
||||
{
|
||||
var manager = TestIdentityFactory.CreateManager();
|
||||
manager.UserValidator = new UserValidator<EntityUser> { RequireUniqueEmail = true };
|
||||
manager.Options.User.RequireUniqueEmail = true;
|
||||
var user = new EntityUser("dupe") { Email = "yup@yup.com" };
|
||||
var user2 = new EntityUser("dupeEmail") { Email = "yup@yup.com" };
|
||||
IdentityResultAssert.IsSuccess(await manager.CreateAsync(user));
|
||||
|
|
@ -618,10 +631,10 @@ namespace Microsoft.AspNet.Identity.Entity.Test
|
|||
var claims = identity.Claims.ToList();
|
||||
Assert.NotNull(claims);
|
||||
Assert.True(
|
||||
claims.Any(c => c.Type == claimsFactory.UserNameClaimType && c.Value == user.UserName));
|
||||
Assert.True(claims.Any(c => c.Type == claimsFactory.UserIdClaimType && c.Value == user.Id));
|
||||
Assert.True(claims.Any(c => c.Type == claimsFactory.RoleClaimType && c.Value == "Admin"));
|
||||
Assert.True(claims.Any(c => c.Type == claimsFactory.RoleClaimType && c.Value == "Local"));
|
||||
claims.Any(c => c.Type == manager.Options.ClaimType.UserName && c.Value == user.UserName));
|
||||
Assert.True(claims.Any(c => c.Type == manager.Options.ClaimType.UserId && c.Value == user.Id.ToString()));
|
||||
Assert.True(claims.Any(c => c.Type == manager.Options.ClaimType.Role && c.Value == "Admin"));
|
||||
Assert.True(claims.Any(c => c.Type == manager.Options.ClaimType.Role && c.Value == "Local"));
|
||||
foreach (var cl in userClaims)
|
||||
{
|
||||
Assert.True(claims.Any(c => c.Type == cl.Type && c.Value == cl.Value));
|
||||
|
|
@ -790,11 +803,9 @@ namespace Microsoft.AspNet.Identity.Entity.Test
|
|||
public async Task SingleFailureLockout()
|
||||
{
|
||||
var mgr = TestIdentityFactory.CreateManager();
|
||||
mgr.LockoutPolicy = new LockoutPolicy
|
||||
{
|
||||
DefaultAccountLockoutTimeSpan = TimeSpan.FromHours(1),
|
||||
UserLockoutEnabledByDefault = true,
|
||||
};
|
||||
mgr.Options.Lockout.DefaultLockoutTimeSpan = TimeSpan.FromHours(1);
|
||||
mgr.Options.Lockout.EnabledByDefault = true;
|
||||
mgr.Options.Lockout.MaxFailedAccessAttempts = 0;
|
||||
var user = new EntityUser("fastLockout");
|
||||
IdentityResultAssert.IsSuccess(await mgr.CreateAsync(user));
|
||||
Assert.True(await mgr.GetLockoutEnabledAsync(user));
|
||||
|
|
@ -810,12 +821,9 @@ namespace Microsoft.AspNet.Identity.Entity.Test
|
|||
public async Task TwoFailureLockout()
|
||||
{
|
||||
var mgr = TestIdentityFactory.CreateManager();
|
||||
mgr.LockoutPolicy = new LockoutPolicy
|
||||
{
|
||||
DefaultAccountLockoutTimeSpan = TimeSpan.FromHours(1),
|
||||
UserLockoutEnabledByDefault = true,
|
||||
MaxFailedAccessAttemptsBeforeLockout = 2
|
||||
};
|
||||
mgr.Options.Lockout.DefaultLockoutTimeSpan = TimeSpan.FromHours(1);
|
||||
mgr.Options.Lockout.EnabledByDefault = true;
|
||||
mgr.Options.Lockout.MaxFailedAccessAttempts = 2;
|
||||
var user = new EntityUser("twoFailureLockout");
|
||||
IdentityResultAssert.IsSuccess(await mgr.CreateAsync(user));
|
||||
Assert.True(await mgr.GetLockoutEnabledAsync(user));
|
||||
|
|
@ -835,12 +843,9 @@ namespace Microsoft.AspNet.Identity.Entity.Test
|
|||
public async Task ResetAccessCountPreventsLockout()
|
||||
{
|
||||
var mgr = TestIdentityFactory.CreateManager();
|
||||
mgr.LockoutPolicy = new LockoutPolicy
|
||||
{
|
||||
DefaultAccountLockoutTimeSpan = TimeSpan.FromHours(1),
|
||||
UserLockoutEnabledByDefault = true,
|
||||
MaxFailedAccessAttemptsBeforeLockout = 2
|
||||
};
|
||||
mgr.Options.Lockout.DefaultLockoutTimeSpan = TimeSpan.FromHours(1);
|
||||
mgr.Options.Lockout.EnabledByDefault = true;
|
||||
mgr.Options.Lockout.MaxFailedAccessAttempts = 2;
|
||||
var user = new EntityUser("resetLockout");
|
||||
IdentityResultAssert.IsSuccess(await mgr.CreateAsync(user));
|
||||
Assert.True(await mgr.GetLockoutEnabledAsync(user));
|
||||
|
|
@ -864,11 +869,8 @@ namespace Microsoft.AspNet.Identity.Entity.Test
|
|||
public async Task CanEnableLockoutManuallyAndLockout()
|
||||
{
|
||||
var mgr = TestIdentityFactory.CreateManager();
|
||||
mgr.LockoutPolicy = new LockoutPolicy
|
||||
{
|
||||
DefaultAccountLockoutTimeSpan = TimeSpan.FromHours(1),
|
||||
MaxFailedAccessAttemptsBeforeLockout = 2
|
||||
};
|
||||
mgr.Options.Lockout.DefaultLockoutTimeSpan = TimeSpan.FromHours(1);
|
||||
mgr.Options.Lockout.MaxFailedAccessAttempts = 2;
|
||||
var user = new EntityUser("manualLockout");
|
||||
IdentityResultAssert.IsSuccess(await mgr.CreateAsync(user));
|
||||
Assert.False(await mgr.GetLockoutEnabledAsync(user));
|
||||
|
|
@ -891,10 +893,7 @@ namespace Microsoft.AspNet.Identity.Entity.Test
|
|||
public async Task UserNotLockedOutWithNullDateTimeAndIsSetToNullDate()
|
||||
{
|
||||
var mgr = TestIdentityFactory.CreateManager();
|
||||
mgr.LockoutPolicy = new LockoutPolicy
|
||||
{
|
||||
UserLockoutEnabledByDefault = true,
|
||||
};
|
||||
mgr.Options.Lockout.EnabledByDefault = true;
|
||||
var user = new EntityUser("LockoutTest");
|
||||
IdentityResultAssert.IsSuccess(await mgr.CreateAsync(user));
|
||||
Assert.True(await mgr.GetLockoutEnabledAsync(user));
|
||||
|
|
@ -922,10 +921,7 @@ namespace Microsoft.AspNet.Identity.Entity.Test
|
|||
public async Task LockoutEndToUtcNowMinus1SecInUserShouldNotBeLockedOut()
|
||||
{
|
||||
var mgr = TestIdentityFactory.CreateManager();
|
||||
mgr.LockoutPolicy = new LockoutPolicy
|
||||
{
|
||||
UserLockoutEnabledByDefault = true,
|
||||
};
|
||||
mgr.Options.Lockout.EnabledByDefault = true;
|
||||
var user = new EntityUser("LockoutUtcNowTest") { LockoutEnd = DateTime.UtcNow.AddSeconds(-1) };
|
||||
IdentityResultAssert.IsSuccess(await mgr.CreateAsync(user));
|
||||
Assert.True(await mgr.GetLockoutEnabledAsync(user));
|
||||
|
|
@ -937,10 +933,7 @@ namespace Microsoft.AspNet.Identity.Entity.Test
|
|||
public async Task LockoutEndToUtcNowSubOneSecondWithManagerShouldNotBeLockedOut()
|
||||
{
|
||||
var mgr = TestIdentityFactory.CreateManager();
|
||||
mgr.LockoutPolicy = new LockoutPolicy
|
||||
{
|
||||
UserLockoutEnabledByDefault = true,
|
||||
};
|
||||
mgr.Options.Lockout.EnabledByDefault = true;
|
||||
var user = new EntityUser("LockoutUtcNowTest");
|
||||
IdentityResultAssert.IsSuccess(await mgr.CreateAsync(user));
|
||||
Assert.True(await mgr.GetLockoutEnabledAsync(user));
|
||||
|
|
@ -953,10 +946,7 @@ namespace Microsoft.AspNet.Identity.Entity.Test
|
|||
public async Task LockoutEndToUtcNowPlus5ShouldBeLockedOut()
|
||||
{
|
||||
var mgr = TestIdentityFactory.CreateManager();
|
||||
mgr.LockoutPolicy = new LockoutPolicy
|
||||
{
|
||||
UserLockoutEnabledByDefault = true,
|
||||
};
|
||||
mgr.Options.Lockout.EnabledByDefault = true;
|
||||
var user = new EntityUser("LockoutUtcNowTest") { LockoutEnd = DateTime.UtcNow.AddMinutes(5) };
|
||||
IdentityResultAssert.IsSuccess(await mgr.CreateAsync(user));
|
||||
Assert.True(await mgr.GetLockoutEnabledAsync(user));
|
||||
|
|
@ -968,10 +958,7 @@ namespace Microsoft.AspNet.Identity.Entity.Test
|
|||
public async Task UserLockedOutWithDateTimeLocalKindNowPlus30()
|
||||
{
|
||||
var mgr = TestIdentityFactory.CreateManager();
|
||||
mgr.LockoutPolicy = new LockoutPolicy
|
||||
{
|
||||
UserLockoutEnabledByDefault = true,
|
||||
};
|
||||
mgr.Options.Lockout.EnabledByDefault = true;
|
||||
var user = new EntityUser("LockoutTest");
|
||||
IdentityResultAssert.IsSuccess(await mgr.CreateAsync(user));
|
||||
Assert.True(await mgr.GetLockoutEnabledAsync(user));
|
||||
|
|
@ -995,11 +982,11 @@ namespace Microsoft.AspNet.Identity.Entity.Test
|
|||
}
|
||||
|
||||
private class AlwaysBadValidator : IUserValidator<EntityUser>, IRoleValidator<EntityRole>,
|
||||
IPasswordValidator
|
||||
IPasswordValidator<EntityUser>
|
||||
{
|
||||
public const string ErrorMessage = "I'm Bad.";
|
||||
|
||||
public Task<IdentityResult> ValidateAsync(string password, CancellationToken token)
|
||||
public Task<IdentityResult> ValidateAsync(string password, UserManager<EntityUser> manager,CancellationToken token)
|
||||
{
|
||||
return Task.FromResult(IdentityResult.Failed(ErrorMessage));
|
||||
}
|
||||
|
|
@ -1326,7 +1313,7 @@ namespace Microsoft.AspNet.Identity.Entity.Test
|
|||
{
|
||||
var manager = TestIdentityFactory.CreateManager();
|
||||
const string userName = "PhoneTest";
|
||||
var user = new EntityUser(userName) {PhoneNumber = "123-456-7890"};
|
||||
var user = new EntityUser(userName) { PhoneNumber = "123-456-7890" };
|
||||
IdentityResultAssert.IsSuccess(await manager.CreateAsync(user));
|
||||
var stamp = await manager.GetSecurityStampAsync(user);
|
||||
Assert.Equal(await manager.GetPhoneNumberAsync(user), "123-456-7890");
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
{
|
||||
"version": "0.1-alpha-*",
|
||||
"dependencies": {
|
||||
"Microsoft.Bcl.Immutable": "1.1.18-beta-*",
|
||||
"Microsoft.AspNet.DependencyInjection": "0.1-alpha-*",
|
||||
"Microsoft.AspNet.Abstractions": "0.1-alpha-*",
|
||||
"Microsoft.AspNet.ConfigurationModel": "0.1-alpha-*",
|
||||
"Microsoft.AspNet.DependencyInjection": "0.1-alpha-*",
|
||||
"Microsoft.AspNet.Identity": "",
|
||||
"Microsoft.AspNet.Identity.Entity": "",
|
||||
"Microsoft.AspNet.PipelineCore": "0.1-alpha-*",
|
||||
|
|
@ -11,9 +11,12 @@
|
|||
"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.Entity": "0.1-alpha-*",
|
||||
"Microsoft.Data.InMemory": "0.1-alpha-*",
|
||||
"Microsoft.Data.Migrations": "0.1-alpha-*",
|
||||
"Microsoft.Data.Relational": "0.1-alpha-*",
|
||||
"Microsoft.Data.SqlServer": "0.1-alpha-*",
|
||||
"Remotion.Linq": "1.15.13.0",
|
||||
"System.Security.Claims": "0.1-alpha-*",
|
||||
"Xunit.KRunner": "0.1-alpha-*",
|
||||
|
|
@ -22,9 +25,11 @@
|
|||
"xunit.core": "2.0.0-aspnet-*",
|
||||
"xunit.execution": "2.0.0-aspnet-*"
|
||||
},
|
||||
"code": "**\\*.cs;..\\Shared\\*.cs",
|
||||
"configurations": {
|
||||
"net45": {
|
||||
"dependencies": {
|
||||
"Moq" : "4.2.1312.1622",
|
||||
"System.Runtime": "",
|
||||
"System.Collections": "",
|
||||
"System.Data": ""
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
|
|
@ -23,6 +23,10 @@
|
|||
<ItemGroup>
|
||||
<Compile Include="IdentityResultAssert.cs" />
|
||||
<Compile Include="InMemoryStoreTest.cs" />
|
||||
<Compile Include="StartupTest.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Folder Include="Properties\" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VSToolsPath)\ProjectK\Microsoft.Web.ProjectK.targets" Condition="'$(VSToolsPath)' != ''" />
|
||||
</Project>
|
||||
|
|
@ -18,6 +18,7 @@
|
|||
using Microsoft.AspNet.Abstractions;
|
||||
using Microsoft.AspNet.DependencyInjection;
|
||||
using Microsoft.AspNet.DependencyInjection.Fallback;
|
||||
using Microsoft.AspNet.Identity.Test;
|
||||
using Microsoft.AspNet.PipelineCore;
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
|
|
@ -27,23 +28,78 @@ namespace Microsoft.AspNet.Identity.InMemory.Test
|
|||
{
|
||||
public class StartupTest
|
||||
{
|
||||
public class ApplicationUser : IdentityUser { }
|
||||
|
||||
public class ApplicationUserManager : UserManager<ApplicationUser>
|
||||
{
|
||||
public ApplicationUserManager(IServiceProvider services, IUserStore<ApplicationUser> store, IOptionsAccessor<IdentityOptions> options) : base(services, store, options) { }
|
||||
}
|
||||
|
||||
public class PasswordsNegativeLengthSetup : IOptionsSetup<IdentityOptions>
|
||||
{
|
||||
public int Order { get { return 0; } }
|
||||
public void Setup(IdentityOptions options)
|
||||
{
|
||||
options.Password.RequiredLength = -1;
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CanCustomizeIdentityOptions()
|
||||
{
|
||||
IBuilder builder = new Builder(new ServiceCollection().BuildServiceProvider());
|
||||
builder.UseServices(services => {
|
||||
services.AddIdentity<IdentityUser>(identityServices => { });
|
||||
services.AddSetup<PasswordsNegativeLengthSetup>();
|
||||
});
|
||||
|
||||
var setup = builder.ApplicationServices.GetService<IOptionsSetup<IdentityOptions>>();
|
||||
Assert.IsType(typeof(PasswordsNegativeLengthSetup), setup);
|
||||
var optionsGetter = builder.ApplicationServices.GetService<IOptionsAccessor<IdentityOptions>>();
|
||||
Assert.NotNull(optionsGetter);
|
||||
setup.Setup(optionsGetter.Options);
|
||||
|
||||
var myOptions = optionsGetter.Options;
|
||||
Assert.True(myOptions.Password.RequireLowercase);
|
||||
Assert.True(myOptions.Password.RequireDigit);
|
||||
Assert.True(myOptions.Password.RequireNonLetterOrDigit);
|
||||
Assert.True(myOptions.Password.RequireUppercase);
|
||||
Assert.Equal(-1, myOptions.Password.RequiredLength);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CanSetupIdentityOptions()
|
||||
{
|
||||
IBuilder app = new Builder(new ServiceCollection().BuildServiceProvider());
|
||||
app.UseServices(services => services.AddIdentity<IdentityUser>(identityServices => identityServices.SetupOptions(options => options.User.RequireUniqueEmail = true)));
|
||||
|
||||
var optionsGetter = app.ApplicationServices.GetService<IOptionsAccessor<IdentityOptions>>();
|
||||
Assert.NotNull(optionsGetter);
|
||||
|
||||
var myOptions = optionsGetter.Options;
|
||||
Assert.True(myOptions.User.RequireUniqueEmail);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task EnsureStartupUsageWorks()
|
||||
{
|
||||
IBuilder builder = new Builder(new ServiceCollection().BuildServiceProvider());
|
||||
|
||||
//builder.UseServices(services => services.AddIdentity<ApplicationUser>(s =>
|
||||
// s.AddEntity<ApplicationDbContext>()
|
||||
//{
|
||||
|
||||
builder.UseServices(services => services.AddIdentity<ApplicationUser>(s =>
|
||||
{
|
||||
s.UseUserStore(() => new InMemoryUserStore<ApplicationUser>());
|
||||
s.UseUserManager<ApplicationUserManager>();
|
||||
s.UseRoleStore(() => new InMemoryRoleStore<IdentityRole>());
|
||||
s.UseRoleManager<ApplicationRoleManager>();
|
||||
s.AddInMemory();
|
||||
s.AddUserManager<ApplicationUserManager>();
|
||||
s.AddRoleManager<ApplicationRoleManager>();
|
||||
}));
|
||||
|
||||
var userStore = builder.ApplicationServices.GetService<IUserStore<ApplicationUser>>();
|
||||
var roleStore = builder.ApplicationServices.GetService<IRoleStore<IdentityRole>>();
|
||||
var userManager = builder.ApplicationServices.GetService<ApplicationUserManager>();
|
||||
//TODO: var userManager = builder.ApplicationServices.GetService<UserManager<IdentityUser>();
|
||||
var roleManager = builder.ApplicationServices.GetService<ApplicationRoleManager>();
|
||||
|
||||
Assert.NotNull(userStore);
|
||||
|
|
@ -67,21 +123,5 @@ namespace Microsoft.AspNet.Identity.InMemory.Test
|
|||
IdentityResultAssert.IsSuccess(await roleManager.CreateAsync(new IdentityRole { Name = roleName }));
|
||||
IdentityResultAssert.IsSuccess(await userManager.AddToRoleAsync(user, roleName));
|
||||
}
|
||||
|
||||
|
||||
public class ApplicationUserManager : UserManager<ApplicationUser>
|
||||
{
|
||||
public ApplicationUserManager(IServiceProvider services) : base(services) { }
|
||||
}
|
||||
|
||||
public class ApplicationRoleManager : RoleManager<IdentityRole>
|
||||
{
|
||||
public ApplicationRoleManager(IServiceProvider services) : base(services) { }
|
||||
}
|
||||
|
||||
public class ApplicationUser : IdentityUser
|
||||
{
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -2,7 +2,7 @@
|
|||
"version": "0.1-alpha-*",
|
||||
"dependencies": {
|
||||
"Microsoft.AspNet.Abstractions" : "0.1-alpha-*",
|
||||
"Microsoft.AspNet.ConfigurationModel" : "0.1-alpha-*",
|
||||
"Microsoft.AspNet.ConfigurationModel": "0.1-alpha-*",
|
||||
"Microsoft.AspNet.DependencyInjection" : "0.1-alpha-*",
|
||||
"Microsoft.AspNet.Identity" : "0.1-alpha-*",
|
||||
"Microsoft.AspNet.Identity.InMemory" : "0.1-alpha-*",
|
||||
|
|
@ -15,9 +15,11 @@
|
|||
"xunit.core": "2.0.0-aspnet-*",
|
||||
"xunit.execution": "2.0.0-aspnet-*"
|
||||
},
|
||||
"code": "**\\*.cs;..\\Shared\\*.cs",
|
||||
"configurations": {
|
||||
"net45": {
|
||||
"dependencies": {
|
||||
"Moq" : "4.2.1312.1622",
|
||||
"System.Runtime": "",
|
||||
"System.Collections": ""
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,8 +21,12 @@
|
|||
<Content Include="Project.json" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="IdentityExtensionsTest.cs" />
|
||||
<Compile Include="SignInManagerTest.cs" />
|
||||
<Compile Include="TestUser.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Folder Include="Properties\" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VSToolsPath)\ProjectK\Microsoft.Web.ProjectK.targets" Condition="'$(VSToolsPath)' != ''" />
|
||||
</Project>
|
||||
|
|
@ -15,9 +15,18 @@
|
|||
// See the Apache 2 License for the specific language governing
|
||||
// permissions and limitations under the License.
|
||||
|
||||
using System;
|
||||
using System.Threading;
|
||||
using Microsoft.AspNet.Abstractions;
|
||||
using Microsoft.AspNet.Abstractions.Security;
|
||||
using Microsoft.AspNet.DependencyInjection.Fallback;
|
||||
using Microsoft.AspNet.Identity.InMemory;
|
||||
using Microsoft.AspNet.Identity.Test;
|
||||
using Microsoft.AspNet.DependencyInjection;
|
||||
using Microsoft.AspNet.Logging;
|
||||
using Microsoft.AspNet.PipelineCore;
|
||||
using Microsoft.AspNet.FeatureModel;
|
||||
using Microsoft.AspNet.Security.Cookies;
|
||||
using Moq;
|
||||
using System.Security.Claims;
|
||||
using System.Threading.Tasks;
|
||||
|
|
@ -27,16 +36,117 @@ namespace Microsoft.AspNet.Identity.Security.Test
|
|||
{
|
||||
public class SignInManagerTest
|
||||
{
|
||||
|
||||
#if NET45
|
||||
[Theory]
|
||||
[InlineData(true)]
|
||||
[InlineData(false)]
|
||||
public async Task VerifyAccountControllerSignIn(bool isPersistent)
|
||||
{
|
||||
IBuilder app = new Builder(new ServiceCollection().BuildServiceProvider());
|
||||
app.UseCookieAuthentication(new CookieAuthenticationOptions
|
||||
{
|
||||
AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie
|
||||
});
|
||||
|
||||
var context = new Mock<HttpContext>();
|
||||
var response = new Mock<HttpResponse>();
|
||||
context.Setup(c => c.Response).Returns(response.Object).Verifiable();
|
||||
response.Setup(r => r.SignIn(It.IsAny<ClaimsIdentity>(), It.Is<AuthenticationProperties>(v => v.IsPersistent == isPersistent))).Verifiable();
|
||||
var contextAccessor = new Mock<IContextAccessor<HttpContext>>();
|
||||
contextAccessor.Setup(a => a.Value).Returns(context.Object);
|
||||
app.UseServices(services =>
|
||||
{
|
||||
services.AddInstance(contextAccessor.Object);
|
||||
services.AddInstance<ILoggerFactory>(new NullLoggerFactory());
|
||||
services.AddIdentity<ApplicationUser, IdentityRole>(s =>
|
||||
{
|
||||
s.AddInMemory();
|
||||
s.AddUserManager<ApplicationUserManager>();
|
||||
s.AddRoleManager<ApplicationRoleManager>();
|
||||
});
|
||||
services.AddTransient<ApplicationSignInManager>();
|
||||
});
|
||||
|
||||
// Act
|
||||
var user = new ApplicationUser
|
||||
{
|
||||
UserName = "Yolo"
|
||||
};
|
||||
const string password = "Yol0Sw@g!";
|
||||
var userManager = app.ApplicationServices.GetService<ApplicationUserManager>();
|
||||
var signInManager = app.ApplicationServices.GetService<ApplicationSignInManager>();
|
||||
|
||||
IdentityResultAssert.IsSuccess(await userManager.CreateAsync(user, password));
|
||||
var result = await signInManager.PasswordSignInAsync(user.UserName, password, isPersistent, false);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(SignInStatus.Success, result);
|
||||
context.VerifyAll();
|
||||
response.VerifyAll();
|
||||
contextAccessor.VerifyAll();
|
||||
}
|
||||
|
||||
//[Theory]
|
||||
//[InlineData(true)]
|
||||
//[InlineData(false)]
|
||||
//public async Task VerifyAccountControllerSignInFunctional(bool isPersistent)
|
||||
//{
|
||||
// IBuilder app = new Builder(new ServiceCollection().BuildServiceProvider());
|
||||
// app.UseCookieAuthentication(new CookieAuthenticationOptions
|
||||
// {
|
||||
// AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie
|
||||
// });
|
||||
|
||||
// TODO: how to functionally test context?
|
||||
// var context = new DefaultHttpContext(new FeatureCollection());
|
||||
// var contextAccessor = new Mock<IContextAccessor<HttpContext>>();
|
||||
// contextAccessor.Setup(a => a.Value).Returns(context);
|
||||
// app.UseServices(services =>
|
||||
// {
|
||||
// services.AddInstance(contextAccessor.Object);
|
||||
// services.AddInstance<ILoggerFactory>(new NullLoggerFactory());
|
||||
// services.AddIdentity<ApplicationUser, IdentityRole>(s =>
|
||||
// {
|
||||
// s.AddUserStore(() => new InMemoryUserStore<ApplicationUser>());
|
||||
// s.AddUserManager<ApplicationUserManager>();
|
||||
// s.AddRoleStore(() => new InMemoryRoleStore<IdentityRole>());
|
||||
// s.AddRoleManager<ApplicationRoleManager>();
|
||||
// });
|
||||
// services.AddTransient<ApplicationSignInManager>();
|
||||
// });
|
||||
|
||||
// // Act
|
||||
// var user = new ApplicationUser
|
||||
// {
|
||||
// UserName = "Yolo"
|
||||
// };
|
||||
// const string password = "Yol0Sw@g!";
|
||||
// var userManager = app.ApplicationServices.GetService<ApplicationUserManager>();
|
||||
// var signInManager = app.ApplicationServices.GetService<ApplicationSignInManager>();
|
||||
|
||||
// IdentityResultAssert.IsSuccess(await userManager.CreateAsync(user, password));
|
||||
// var result = await signInManager.PasswordSignInAsync(user.UserName, password, isPersistent, false);
|
||||
|
||||
// // Assert
|
||||
// Assert.Equal(SignInStatus.Success, result);
|
||||
// contextAccessor.VerifyAll();
|
||||
//}
|
||||
|
||||
[Fact]
|
||||
public void ConstructorNullChecks()
|
||||
{
|
||||
Assert.Throws<ArgumentNullException>("userManager", () => new SignInManager<IdentityUser>(null, null));
|
||||
var userManager = MockHelpers.MockUserManager<IdentityUser>().Object;
|
||||
Assert.Throws<ArgumentNullException>("contextAccessor", () => new SignInManager<IdentityUser>(userManager, null));
|
||||
}
|
||||
|
||||
//TODO: Mock fails in K (this works fine in net45)
|
||||
[Fact]
|
||||
public async Task EnsureClaimsIdentityFactoryCreateIdentityCalled()
|
||||
{
|
||||
// Setup
|
||||
var store = new Mock<IUserStore<TestUser>>();
|
||||
var user = new TestUser { UserName = "Foo" };
|
||||
var userManager = new UserManager<TestUser>(store.Object);
|
||||
var userManager = MockHelpers.TestUserManager<TestUser>();
|
||||
var identityFactory = new Mock<IClaimsIdentityFactory<TestUser>>();
|
||||
const string authType = "Test";
|
||||
var testIdentity = new ClaimsIdentity(authType);
|
||||
|
|
@ -46,13 +156,21 @@ namespace Microsoft.AspNet.Identity.Security.Test
|
|||
var response = new Mock<HttpResponse>();
|
||||
context.Setup(c => c.Response).Returns(response.Object).Verifiable();
|
||||
response.Setup(r => r.SignIn(testIdentity, It.IsAny<AuthenticationProperties>())).Verifiable();
|
||||
var helper = new SignInManager<TestUser> { UserManager = userManager, AuthenticationType = authType, Context = context.Object };
|
||||
var contextAccessor = new Mock<IContextAccessor<HttpContext>>();
|
||||
contextAccessor.Setup(a => a.Value).Returns(context.Object);
|
||||
var helper = new SignInManager<TestUser>(userManager, contextAccessor.Object)
|
||||
{
|
||||
AuthenticationType = authType
|
||||
};
|
||||
|
||||
// Act
|
||||
await helper.SignInAsync(user, false, false);
|
||||
|
||||
// Assert
|
||||
identityFactory.VerifyAll();
|
||||
context.VerifyAll();
|
||||
contextAccessor.VerifyAll();
|
||||
response.VerifyAll();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
|
@ -60,10 +178,13 @@ namespace Microsoft.AspNet.Identity.Security.Test
|
|||
{
|
||||
// Setup
|
||||
var user = new TestUser { UserName = "Foo" };
|
||||
var manager = new Mock<UserManager<TestUser>>();
|
||||
var manager = MockHelpers.MockUserManager<TestUser>();
|
||||
manager.Setup(m => m.IsLockedOutAsync(user, CancellationToken.None)).ReturnsAsync(true).Verifiable();
|
||||
manager.Setup(m => m.FindByNameAsync(user.UserName, CancellationToken.None)).ReturnsAsync(user).Verifiable();
|
||||
var helper = new SignInManager<TestUser> { UserManager = manager.Object };
|
||||
var context = new Mock<HttpContext>();
|
||||
var contextAccessor = new Mock<IContextAccessor<HttpContext>>();
|
||||
contextAccessor.Setup(a => a.Value).Returns(context.Object);
|
||||
var helper = new SignInManager<TestUser>(manager.Object, contextAccessor.Object);
|
||||
|
||||
// Act
|
||||
var result = await helper.PasswordSignInAsync(user.UserName, "bogus", false, false);
|
||||
|
|
@ -72,13 +193,15 @@ namespace Microsoft.AspNet.Identity.Security.Test
|
|||
Assert.Equal(SignInStatus.LockedOut, result);
|
||||
manager.VerifyAll();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task CanPasswordSignIn()
|
||||
|
||||
[Theory]
|
||||
[InlineData(true)]
|
||||
[InlineData(false)]
|
||||
public async Task CanPasswordSignIn(bool isPersistent)
|
||||
{
|
||||
// Setup
|
||||
var user = new TestUser { UserName = "Foo" };
|
||||
var manager = new Mock<UserManager<TestUser>>();
|
||||
var manager = MockHelpers.MockUserManager<TestUser>();
|
||||
manager.Setup(m => m.IsLockedOutAsync(user, CancellationToken.None)).ReturnsAsync(false).Verifiable();
|
||||
manager.Setup(m => m.FindByNameAsync(user.UserName, CancellationToken.None)).ReturnsAsync(user).Verifiable();
|
||||
manager.Setup(m => m.CheckPasswordAsync(user, "password", CancellationToken.None)).ReturnsAsync(true).Verifiable();
|
||||
|
|
@ -86,28 +209,39 @@ namespace Microsoft.AspNet.Identity.Security.Test
|
|||
var context = new Mock<HttpContext>();
|
||||
var response = new Mock<HttpResponse>();
|
||||
context.Setup(c => c.Response).Returns(response.Object).Verifiable();
|
||||
response.Setup(r => r.SignIn(It.IsAny<ClaimsIdentity>(), It.IsAny<AuthenticationProperties>())).Verifiable();
|
||||
var helper = new SignInManager<TestUser> { UserManager = manager.Object, Context = context.Object };
|
||||
response.Setup(r => r.SignIn(It.IsAny<ClaimsIdentity>(), It.Is<AuthenticationProperties>(v => v.IsPersistent == isPersistent))).Verifiable();
|
||||
var contextAccessor = new Mock<IContextAccessor<HttpContext>>();
|
||||
contextAccessor.Setup(a => a.Value).Returns(context.Object);
|
||||
var helper = new SignInManager<TestUser>(manager.Object, contextAccessor.Object);
|
||||
|
||||
// Act
|
||||
var result = await helper.PasswordSignInAsync(user.UserName, "password", false, false);
|
||||
var result = await helper.PasswordSignInAsync(user.UserName, "password", isPersistent, false);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(SignInStatus.Success, result);
|
||||
manager.VerifyAll();
|
||||
context.VerifyAll();
|
||||
response.VerifyAll();
|
||||
contextAccessor.VerifyAll();
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(DefaultAuthenticationTypes.ApplicationCookie)]
|
||||
[InlineData("Microsoft.AspNet.Identity.Security.Application")]
|
||||
[InlineData("Foo")]
|
||||
public void SignOutCallsContextResponseSignOut(string authenticationType)
|
||||
{
|
||||
// Setup
|
||||
var manager = MockHelpers.MockUserManager<TestUser>();
|
||||
var context = new Mock<HttpContext>();
|
||||
var response = new Mock<HttpResponse>();
|
||||
context.Setup(c => c.Response).Returns(response.Object).Verifiable();
|
||||
response.Setup(r => r.SignOut(authenticationType)).Verifiable();
|
||||
var helper = new SignInManager<TestUser> { Context = context.Object, AuthenticationType = authenticationType };
|
||||
var contextAccessor = new Mock<IContextAccessor<HttpContext>>();
|
||||
contextAccessor.Setup(a => a.Value).Returns(context.Object);
|
||||
var helper = new SignInManager<TestUser>(manager.Object, contextAccessor.Object)
|
||||
{
|
||||
AuthenticationType = authenticationType
|
||||
};
|
||||
|
||||
// Act
|
||||
helper.SignOut();
|
||||
|
|
@ -122,12 +256,14 @@ namespace Microsoft.AspNet.Identity.Security.Test
|
|||
{
|
||||
// Setup
|
||||
var user = new TestUser { UserName = "Foo" };
|
||||
var manager = new Mock<UserManager<TestUser>>();
|
||||
var manager = MockHelpers.MockUserManager<TestUser>();
|
||||
manager.Setup(m => m.IsLockedOutAsync(user, CancellationToken.None)).ReturnsAsync(false).Verifiable();
|
||||
manager.Setup(m => m.FindByNameAsync(user.UserName, CancellationToken.None)).ReturnsAsync(user).Verifiable();
|
||||
manager.Setup(m => m.CheckPasswordAsync(user, "bogus", CancellationToken.None)).ReturnsAsync(false).Verifiable();
|
||||
var helper = new SignInManager<TestUser> { UserManager = manager.Object };
|
||||
|
||||
var context = new Mock<HttpContext>();
|
||||
var contextAccessor = new Mock<IContextAccessor<HttpContext>>();
|
||||
contextAccessor.Setup(a => a.Value).Returns(context.Object);
|
||||
var helper = new SignInManager<TestUser>(manager.Object, contextAccessor.Object);
|
||||
// Act
|
||||
var result = await helper.PasswordSignInAsync(user.UserName, "bogus", false, false);
|
||||
|
||||
|
|
@ -141,9 +277,12 @@ namespace Microsoft.AspNet.Identity.Security.Test
|
|||
public async Task PasswordSignInFailsWithUnknownUser()
|
||||
{
|
||||
// Setup
|
||||
var manager = new Mock<UserManager<TestUser>>();
|
||||
var manager = MockHelpers.MockUserManager<TestUser>();
|
||||
manager.Setup(m => m.FindByNameAsync("bogus", CancellationToken.None)).ReturnsAsync(null).Verifiable();
|
||||
var helper = new SignInManager<TestUser> { UserManager = manager.Object };
|
||||
var context = new Mock<HttpContext>();
|
||||
var contextAccessor = new Mock<IContextAccessor<HttpContext>>();
|
||||
contextAccessor.Setup(a => a.Value).Returns(context.Object);
|
||||
var helper = new SignInManager<TestUser>(manager.Object, contextAccessor.Object);
|
||||
|
||||
// Act
|
||||
var result = await helper.PasswordSignInAsync("bogus", "bogus", false, false);
|
||||
|
|
@ -153,60 +292,12 @@ namespace Microsoft.AspNet.Identity.Security.Test
|
|||
manager.VerifyAll();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task PasswordSignInFailsWithNoUserManager()
|
||||
{
|
||||
// Setup
|
||||
var helper = new SignInManager<TestUser>();
|
||||
|
||||
// Act
|
||||
var result = await helper.PasswordSignInAsync("bogus", "bogus", false, false);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(SignInStatus.Failure, result);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task SignInWithNoContextDoesNotBlowUp()
|
||||
{
|
||||
// Setup
|
||||
var helper = new SignInManager<TestUser>();
|
||||
|
||||
// Act
|
||||
await helper.SignInAsync(null, false, false);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SignOutWithNoContextDoesNotBlowUp()
|
||||
{
|
||||
// Setup
|
||||
var helper = new SignInManager<TestUser>();
|
||||
|
||||
// Act
|
||||
helper.SignOut();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task CreateUserIdentityReturnsNullNoUserManager()
|
||||
{
|
||||
// Setup
|
||||
var user = new TestUser();
|
||||
var helper = new SignInManager<TestUser>();
|
||||
|
||||
// Act
|
||||
var result = await helper.CreateUserIdentityAsync(user);
|
||||
|
||||
// Assert
|
||||
Assert.Null(result);
|
||||
}
|
||||
|
||||
|
||||
[Fact]
|
||||
public async Task PasswordSignInFailsWithWrongPasswordCanAccessFailedAndLockout()
|
||||
{
|
||||
// Setup
|
||||
var user = new TestUser { UserName = "Foo" };
|
||||
var manager = new Mock<UserManager<TestUser>>();
|
||||
var manager = MockHelpers.MockUserManager<TestUser>();
|
||||
var lockedout = false;
|
||||
manager.Setup(m => m.AccessFailedAsync(user, CancellationToken.None)).Returns(() =>
|
||||
{
|
||||
|
|
@ -216,7 +307,10 @@ namespace Microsoft.AspNet.Identity.Security.Test
|
|||
manager.Setup(m => m.IsLockedOutAsync(user, CancellationToken.None)).Returns(() => Task.FromResult(lockedout));
|
||||
manager.Setup(m => m.FindByNameAsync(user.UserName, CancellationToken.None)).ReturnsAsync(user).Verifiable();
|
||||
manager.Setup(m => m.CheckPasswordAsync(user, "bogus", CancellationToken.None)).ReturnsAsync(false).Verifiable();
|
||||
var helper = new SignInManager<TestUser> { UserManager = manager.Object };
|
||||
var context = new Mock<HttpContext>();
|
||||
var contextAccessor = new Mock<IContextAccessor<HttpContext>>();
|
||||
contextAccessor.Setup(a => a.Value).Returns(context.Object);
|
||||
var helper = new SignInManager<TestUser>(manager.Object, contextAccessor.Object);
|
||||
|
||||
// Act
|
||||
var result = await helper.PasswordSignInAsync(user.UserName, "bogus", false, true);
|
||||
|
|
@ -226,5 +320,30 @@ namespace Microsoft.AspNet.Identity.Security.Test
|
|||
manager.VerifyAll();
|
||||
}
|
||||
#endif
|
||||
public class ApplicationSignInManager : SignInManager<ApplicationUser>
|
||||
{
|
||||
public ApplicationSignInManager(ApplicationUserManager manager, IContextAccessor<HttpContext> contextAccessor)
|
||||
: base(manager, contextAccessor)
|
||||
{
|
||||
AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie;
|
||||
}
|
||||
}
|
||||
|
||||
public class NullLoggerFactory : ILoggerFactory
|
||||
{
|
||||
public ILogger Create(string name)
|
||||
{
|
||||
return new NullLogger();
|
||||
}
|
||||
}
|
||||
|
||||
public class NullLogger : ILogger
|
||||
{
|
||||
public bool WriteCore(TraceType eventType, int eventId, object state, Exception exception, Func<object, Exception, string> formatter)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -2,10 +2,18 @@
|
|||
"version": "0.1-alpha-*",
|
||||
"dependencies": {
|
||||
"Microsoft.AspNet.Abstractions" : "0.1-alpha-*",
|
||||
"Microsoft.AspNet.ConfigurationModel" : "0.1-alpha-*",
|
||||
"Microsoft.AspNet.ConfigurationModel": "0.1-alpha-*",
|
||||
"Microsoft.AspNet.DependencyInjection" : "0.1-alpha-*",
|
||||
"Microsoft.AspNet.Identity" : "",
|
||||
"Microsoft.AspNet.Identity.Security" : "",
|
||||
"Microsoft.AspNet.Identity" : "0.1-alpha-*",
|
||||
"Microsoft.AspNet.Identity.InMemory" : "0.1-alpha-*",
|
||||
"Microsoft.AspNet.Identity.Security" : "0.1-alpha-*",
|
||||
"Microsoft.AspNet.Logging" : "0.1-alpha-*",
|
||||
"Microsoft.AspNet.HttpFeature" : "0.1-alpha-*",
|
||||
"Microsoft.AspNet.FeatureModel" : "0.1-alpha-*",
|
||||
"Microsoft.AspNet.PipelineCore" : "0.1-alpha-*",
|
||||
"Microsoft.AspNet.RequestContainer" : "0.1-alpha-*",
|
||||
"Microsoft.AspNet.Security" : "0.1-alpha-*",
|
||||
"Microsoft.AspNet.Security.Cookies" : "0.1-alpha-*",
|
||||
"Microsoft.AspNet.Testing" : "0.1-alpha-*",
|
||||
"System.Security.Claims" : "0.1-alpha-*",
|
||||
"Xunit.KRunner": "0.1-alpha-*",
|
||||
|
|
@ -14,6 +22,7 @@
|
|||
"xunit.core": "2.0.0-aspnet-*",
|
||||
"xunit.execution": "2.0.0-aspnet-*"
|
||||
},
|
||||
"code": "**\\*.cs;..\\Shared\\*.cs",
|
||||
"configurations": {
|
||||
"net45": {
|
||||
"dependencies": {
|
||||
|
|
|
|||
|
|
@ -20,6 +20,8 @@ using System.Linq;
|
|||
using System.Security.Claims;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNet.DependencyInjection;
|
||||
using Microsoft.AspNet.DependencyInjection.Fallback;
|
||||
using Moq;
|
||||
using Xunit;
|
||||
|
||||
|
|
@ -31,7 +33,7 @@ namespace Microsoft.AspNet.Identity.Test
|
|||
public async Task CreateIdentityNullChecks()
|
||||
{
|
||||
var factory = new ClaimsIdentityFactory<TestUser>();
|
||||
var manager = new UserManager<TestUser>(new NoopUserStore());
|
||||
var manager = MockHelpers.MockUserManager<TestUser>().Object;
|
||||
await Assert.ThrowsAsync<ArgumentNullException>("manager",
|
||||
async () => await factory.CreateAsync(null, null, "whatever"));
|
||||
await Assert.ThrowsAsync<ArgumentNullException>("user",
|
||||
|
|
@ -50,7 +52,7 @@ namespace Microsoft.AspNet.Identity.Test
|
|||
public async Task EnsureClaimsIdentityHasExpectedClaims(bool supportRoles, bool supportClaims)
|
||||
{
|
||||
// Setup
|
||||
var userManager = new Mock<UserManager<TestUser>>();
|
||||
var userManager = MockHelpers.MockUserManager<TestUser>();
|
||||
var user = new TestUser { UserName = "Foo" };
|
||||
userManager.Setup(m => m.SupportsUserRole).Returns(supportRoles);
|
||||
userManager.Setup(m => m.SupportsUserClaim).Returns(supportClaims);
|
||||
|
|
@ -60,6 +62,7 @@ namespace Microsoft.AspNet.Identity.Test
|
|||
userManager.Setup(m => m.GetRolesAsync(user, CancellationToken.None)).ReturnsAsync(roleClaims);
|
||||
var userClaims = new[] { new Claim("Whatever", "Value"), new Claim("Whatever2", "Value2") };
|
||||
userManager.Setup(m => m.GetClaimsAsync(user, CancellationToken.None)).ReturnsAsync(userClaims);
|
||||
userManager.Object.Options = new IdentityOptions();
|
||||
|
||||
const string authType = "Microsoft.AspNet.Identity";
|
||||
var factory = new ClaimsIdentityFactory<TestUser>();
|
||||
|
|
@ -68,15 +71,16 @@ namespace Microsoft.AspNet.Identity.Test
|
|||
var identity = await factory.CreateAsync(userManager.Object, user, authType);
|
||||
|
||||
// Assert
|
||||
var manager = userManager.Object;
|
||||
Assert.NotNull(identity);
|
||||
Assert.Equal(authType, identity.AuthenticationType);
|
||||
var claims = identity.Claims.ToList();
|
||||
Assert.NotNull(claims);
|
||||
Assert.True(
|
||||
claims.Any(c => c.Type == factory.UserNameClaimType && c.Value == user.UserName));
|
||||
Assert.True(claims.Any(c => c.Type == factory.UserIdClaimType && c.Value == user.Id));
|
||||
Assert.Equal(supportRoles, claims.Any(c => c.Type == factory.RoleClaimType && c.Value == "Admin"));
|
||||
Assert.Equal(supportRoles, claims.Any(c => c.Type == factory.RoleClaimType && c.Value == "Local"));
|
||||
claims.Any(c => c.Type == manager.Options.ClaimType.UserName && c.Value == user.UserName));
|
||||
Assert.True(claims.Any(c => c.Type == manager.Options.ClaimType.UserId && c.Value == user.Id));
|
||||
Assert.Equal(supportRoles, claims.Any(c => c.Type == manager.Options.ClaimType.Role && c.Value == "Admin"));
|
||||
Assert.Equal(supportRoles, claims.Any(c => c.Type == manager.Options.ClaimType.Role && c.Value == "Local"));
|
||||
foreach (var cl in userClaims)
|
||||
{
|
||||
Assert.Equal(supportClaims, claims.Any(c => c.Type == cl.Type && c.Value == cl.Value));
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ namespace Microsoft.AspNet.Identity.Test
|
|||
{
|
||||
var services = new ServiceCollection();
|
||||
var validator = new UserValidator<IdentityUser>();
|
||||
services.AddIdentity<IdentityUser>(b => b.UseUserValidator(() => validator));
|
||||
services.AddIdentity<IdentityUser>(b => b.AddUserValidator(() => validator));
|
||||
Assert.Equal(validator, services.BuildServiceProvider().GetService<IUserValidator<IdentityUser>>());
|
||||
}
|
||||
|
||||
|
|
@ -37,69 +37,47 @@ namespace Microsoft.AspNet.Identity.Test
|
|||
public void CanSpecifyPasswordValidatorInstance()
|
||||
{
|
||||
var services = new ServiceCollection();
|
||||
var validator = new PasswordValidator();
|
||||
services.AddIdentity<IdentityUser>(b => b.UsePasswordValidator(() => validator));
|
||||
Assert.Equal(validator, services.BuildServiceProvider().GetService<IPasswordValidator>());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CanSpecifyLockoutPolicyInstance()
|
||||
{
|
||||
var services = new ServiceCollection();
|
||||
var policy = new LockoutPolicy();
|
||||
services.AddIdentity<IdentityUser>(b => b.UseLockoutPolicy(() => policy));
|
||||
Assert.Equal(policy, services.BuildServiceProvider().GetService<LockoutPolicy>());
|
||||
var validator = new PasswordValidator<IdentityUser>();
|
||||
services.AddIdentity<IdentityUser>(b => b.AddPasswordValidator(() => validator));
|
||||
Assert.Equal(validator, services.BuildServiceProvider().GetService<IPasswordValidator<IdentityUser>>());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CanSpecifyPasswordHasherInstance()
|
||||
{
|
||||
CanOverride<IPasswordHasher, PasswordHasher>();
|
||||
CanOverride<IPasswordHasher>(new PasswordHasher());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CanSpecifyClaimsIdentityFactoryInstance()
|
||||
{
|
||||
CanOverride<IClaimsIdentityFactory<IdentityUser>, ClaimsIdentityFactory<IdentityUser>>();
|
||||
CanOverride<IClaimsIdentityFactory<IdentityUser>>(new ClaimsIdentityFactory<IdentityUser>());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void EnsureDefaultServices()
|
||||
{
|
||||
var services = new ServiceCollection();
|
||||
var builder = new IdentityBuilder<IdentityUser, IdentityRole>(services);
|
||||
builder.UseIdentity();
|
||||
services.AddIdentity<IdentityUser>(identity => { });
|
||||
|
||||
var provider = services.BuildServiceProvider();
|
||||
var userValidator = provider.GetService<IUserValidator<IdentityUser>>() as UserValidator<IdentityUser>;
|
||||
Assert.NotNull(userValidator);
|
||||
Assert.True(userValidator.AllowOnlyAlphanumericUserNames);
|
||||
Assert.False(userValidator.RequireUniqueEmail);
|
||||
|
||||
var pwdValidator = provider.GetService<IPasswordValidator>() as PasswordValidator;
|
||||
Assert.NotNull(userValidator);
|
||||
Assert.True(pwdValidator.RequireDigit);
|
||||
Assert.True(pwdValidator.RequireLowercase);
|
||||
Assert.True(pwdValidator.RequireNonLetterOrDigit);
|
||||
Assert.True(pwdValidator.RequireUppercase);
|
||||
Assert.Equal(6, pwdValidator.RequiredLength);
|
||||
var pwdValidator = provider.GetService<IPasswordValidator<IdentityUser>>() as PasswordValidator<IdentityUser>;
|
||||
Assert.NotNull(pwdValidator);
|
||||
|
||||
var hasher = provider.GetService<IPasswordHasher>() as PasswordHasher;
|
||||
Assert.NotNull(hasher);
|
||||
|
||||
var claimsFactory = provider.GetService<IClaimsIdentityFactory<IdentityUser>>() as ClaimsIdentityFactory<IdentityUser>;
|
||||
Assert.NotNull(claimsFactory);
|
||||
Assert.Equal(ClaimTypes.Role, claimsFactory.RoleClaimType);
|
||||
Assert.Equal(ClaimsIdentityFactory<IdentityUser>.DefaultSecurityStampClaimType, claimsFactory.SecurityStampClaimType);
|
||||
Assert.Equal(ClaimTypes.Name, claimsFactory.UserNameClaimType);
|
||||
Assert.Equal(ClaimTypes.NameIdentifier, claimsFactory.UserIdClaimType);
|
||||
}
|
||||
|
||||
private static void CanOverride<TService, TImplementation>() where TImplementation : TService,new()
|
||||
private static void CanOverride<TService>(TService instance)
|
||||
{
|
||||
var services = new ServiceCollection();
|
||||
var instance = new TImplementation();
|
||||
services.AddIdentity<IdentityUser>(b => b.Use<TService>(() => instance));
|
||||
services.AddIdentity<IdentityUser>(b => b.AddInstance<TService>(() => instance));
|
||||
Assert.Equal(instance, services.BuildServiceProvider().GetService<TService>());
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,125 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Security.Claims;
|
||||
using Microsoft.AspNet.ConfigurationModel;
|
||||
using Microsoft.AspNet.ConfigurationModel.Sources;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.AspNet.Identity.Test
|
||||
{
|
||||
public class IdentityOptionsTest
|
||||
{
|
||||
[Fact]
|
||||
public void VerifyDefaultOptions()
|
||||
{
|
||||
var options = new IdentityOptions();
|
||||
Assert.False(options.Lockout.EnabledByDefault);
|
||||
Assert.Equal(TimeSpan.FromMinutes(5), options.Lockout.DefaultLockoutTimeSpan);
|
||||
Assert.Equal(5, options.Lockout.MaxFailedAccessAttempts);
|
||||
|
||||
Assert.True(options.Password.RequireDigit);
|
||||
Assert.True(options.Password.RequireLowercase);
|
||||
Assert.True(options.Password.RequireNonLetterOrDigit);
|
||||
Assert.True(options.Password.RequireUppercase);
|
||||
Assert.Equal(6, options.Password.RequiredLength);
|
||||
|
||||
Assert.True(options.User.AllowOnlyAlphanumericNames);
|
||||
Assert.False(options.User.RequireUniqueEmail);
|
||||
|
||||
Assert.Equal(ClaimTypes.Role, options.ClaimType.Role);
|
||||
Assert.Equal(ClaimTypes.Name, options.ClaimType.UserName);
|
||||
Assert.Equal(ClaimTypes.NameIdentifier, options.ClaimType.UserId);
|
||||
Assert.Equal(ClaimTypeOptions.DefaultSecurityStampClaimType, options.ClaimType.SecurityStamp);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CopyNullIsNoop()
|
||||
{
|
||||
var options = new IdentityOptions();
|
||||
options.Copy(null);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void IdentityOptionsFromConfig()
|
||||
{
|
||||
const string roleClaimType = "rolez";
|
||||
const string usernameClaimType = "namez";
|
||||
const string useridClaimType = "idz";
|
||||
const string securityStampClaimType = "stampz";
|
||||
|
||||
var dic = new Dictionary<string, string>
|
||||
{
|
||||
{"identity:claimtype:role", roleClaimType},
|
||||
{"identity:claimtype:username", usernameClaimType},
|
||||
{"identity:claimtype:userid", useridClaimType},
|
||||
{"identity:claimtype:securitystamp", securityStampClaimType},
|
||||
{"identity:user:requireUniqueEmail", "true"},
|
||||
{"identity:password:RequiredLength", "10"},
|
||||
{"identity:password:RequireNonLetterOrDigit", "false"},
|
||||
{"identity:password:RequireUpperCase", "false"},
|
||||
{"identity:password:RequireDigit", "false"},
|
||||
{"identity:password:RequireLowerCase", "false"}
|
||||
};
|
||||
var config = new ConfigurationModel.Configuration { new MemoryConfigurationSource(dic) };
|
||||
Assert.Equal(roleClaimType, config.Get("identity:claimtype:role"));
|
||||
var options = new IdentityOptions(config);
|
||||
Assert.Equal(roleClaimType, options.ClaimType.Role);
|
||||
Assert.Equal(useridClaimType, options.ClaimType.UserId);
|
||||
Assert.Equal(usernameClaimType, options.ClaimType.UserName);
|
||||
Assert.Equal(securityStampClaimType, options.ClaimType.SecurityStamp);
|
||||
Assert.True(options.User.RequireUniqueEmail);
|
||||
Assert.True(options.User.AllowOnlyAlphanumericNames);
|
||||
Assert.True(options.User.AllowOnlyAlphanumericNames);
|
||||
Assert.False(options.Password.RequireDigit);
|
||||
Assert.False(options.Password.RequireLowercase);
|
||||
Assert.False(options.Password.RequireNonLetterOrDigit);
|
||||
Assert.False(options.Password.RequireUppercase);
|
||||
Assert.Equal(10, options.Password.RequiredLength);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ClaimTypeOptionsFromConfig()
|
||||
{
|
||||
const string roleClaimType = "rolez";
|
||||
const string usernameClaimType = "namez";
|
||||
const string useridClaimType = "idz";
|
||||
const string securityStampClaimType = "stampz";
|
||||
|
||||
var dic = new Dictionary<string, string>
|
||||
{
|
||||
{"role", roleClaimType},
|
||||
{"username", usernameClaimType},
|
||||
{"userid", useridClaimType},
|
||||
{"securitystamp", securityStampClaimType}
|
||||
};
|
||||
var config = new ConfigurationModel.Configuration {new MemoryConfigurationSource(dic)};
|
||||
Assert.Equal(roleClaimType, config.Get("role"));
|
||||
var options = new ClaimTypeOptions(config);
|
||||
Assert.Equal(roleClaimType, options.Role);
|
||||
Assert.Equal(useridClaimType, options.UserId);
|
||||
Assert.Equal(usernameClaimType, options.UserName);
|
||||
Assert.Equal(securityStampClaimType, options.SecurityStamp);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void PasswordOptionsFromConfig()
|
||||
{
|
||||
var dic = new Dictionary<string, string>
|
||||
{
|
||||
{"RequiredLength", "10"},
|
||||
{"RequireNonLetterOrDigit", "false"},
|
||||
{"RequireUpperCase", "false"},
|
||||
{"RequireDigit", "false"},
|
||||
{"RequireLowerCase", "false"}
|
||||
};
|
||||
var config = new ConfigurationModel.Configuration { new MemoryConfigurationSource(dic) };
|
||||
var options = new PasswordOptions(config);
|
||||
Assert.False(options.RequireDigit);
|
||||
Assert.False(options.RequireLowercase);
|
||||
Assert.False(options.RequireNonLetterOrDigit);
|
||||
Assert.False(options.RequireUppercase);
|
||||
Assert.Equal(10, options.RequiredLength);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -22,6 +22,7 @@
|
|||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="ClaimsIdentityFactoryTest.cs" />
|
||||
<Compile Include="IdentityBuilderTest.cs" />
|
||||
<Compile Include="IdentityResultAssert.cs" />
|
||||
<Compile Include="IdentityResultTest.cs" />
|
||||
<Compile Include="NoopRoleStore.cs" />
|
||||
|
|
@ -30,10 +31,12 @@
|
|||
<Compile Include="RoleManagerTest.cs" />
|
||||
<Compile Include="RoleValidatorTest.cs" />
|
||||
<Compile Include="TestRole.cs" />
|
||||
<Compile Include="TestServices.cs" />
|
||||
<Compile Include="TestUser.cs" />
|
||||
<Compile Include="UserManagerTest.cs" />
|
||||
<Compile Include="UserValidatorTest.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Folder Include="Properties\" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VSToolsPath)\ProjectK\Microsoft.Web.ProjectK.targets" Condition="'$(VSToolsPath)' != ''" />
|
||||
</Project>
|
||||
|
|
@ -39,11 +39,12 @@ namespace Microsoft.AspNet.Identity.Test
|
|||
public async Task ValidateThrowsWithNullTest()
|
||||
{
|
||||
// Setup
|
||||
var validator = new PasswordValidator();
|
||||
var validator = new PasswordValidator<IdentityUser>();
|
||||
|
||||
// Act
|
||||
// Assert
|
||||
await Assert.ThrowsAsync<ArgumentNullException>(() => validator.ValidateAsync(null));
|
||||
await Assert.ThrowsAsync<ArgumentNullException>("password", () => validator.ValidateAsync(null, null));
|
||||
await Assert.ThrowsAsync<ArgumentNullException>("manager", () => validator.ValidateAsync("foo", null));
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -54,8 +55,13 @@ namespace Microsoft.AspNet.Identity.Test
|
|||
public async Task FailsIfTooShortTests(string input)
|
||||
{
|
||||
const string error = "Passwords must be at least 6 characters.";
|
||||
var valid = new PasswordValidator {RequiredLength = 6};
|
||||
IdentityResultAssert.IsFailure(await valid.ValidateAsync(input), error);
|
||||
var manager = MockHelpers.TestUserManager<IdentityUser>();
|
||||
var valid = new PasswordValidator<IdentityUser>();
|
||||
manager.Options.Password.RequireUppercase = false;
|
||||
manager.Options.Password.RequireNonLetterOrDigit = false;
|
||||
manager.Options.Password.RequireLowercase = false;
|
||||
manager.Options.Password.RequireDigit = false;
|
||||
IdentityResultAssert.IsFailure(await valid.ValidateAsync(input, manager), error);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
|
|
@ -63,8 +69,13 @@ namespace Microsoft.AspNet.Identity.Test
|
|||
[InlineData("aaaaaaaaaaa")]
|
||||
public async Task SuccessIfLongEnoughTests(string input)
|
||||
{
|
||||
var valid = new PasswordValidator {RequiredLength = 6};
|
||||
IdentityResultAssert.IsSuccess(await valid.ValidateAsync(input));
|
||||
var manager = MockHelpers.TestUserManager<IdentityUser>();
|
||||
var valid = new PasswordValidator<IdentityUser>();
|
||||
manager.Options.Password.RequireUppercase = false;
|
||||
manager.Options.Password.RequireNonLetterOrDigit = false;
|
||||
manager.Options.Password.RequireLowercase = false;
|
||||
manager.Options.Password.RequireDigit = false;
|
||||
IdentityResultAssert.IsSuccess(await valid.ValidateAsync(input, manager));
|
||||
}
|
||||
|
||||
[Theory]
|
||||
|
|
@ -72,8 +83,14 @@ namespace Microsoft.AspNet.Identity.Test
|
|||
[InlineData("aaaaaaaaaaa")]
|
||||
public async Task FailsWithoutRequiredNonAlphanumericTests(string input)
|
||||
{
|
||||
var valid = new PasswordValidator {RequireNonLetterOrDigit = true};
|
||||
IdentityResultAssert.IsFailure(await valid.ValidateAsync(input),
|
||||
var manager = MockHelpers.TestUserManager<IdentityUser>();
|
||||
var valid = new PasswordValidator<IdentityUser>();
|
||||
manager.Options.Password.RequireUppercase = false;
|
||||
manager.Options.Password.RequireNonLetterOrDigit = true;
|
||||
manager.Options.Password.RequireLowercase = false;
|
||||
manager.Options.Password.RequireDigit = false;
|
||||
manager.Options.Password.RequiredLength = 0;
|
||||
IdentityResultAssert.IsFailure(await valid.ValidateAsync(input, manager),
|
||||
"Passwords must have at least one non letter or digit character.");
|
||||
}
|
||||
|
||||
|
|
@ -83,8 +100,14 @@ namespace Microsoft.AspNet.Identity.Test
|
|||
[InlineData("!!!!!!")]
|
||||
public async Task SucceedsWithRequiredNonAlphanumericTests(string input)
|
||||
{
|
||||
var valid = new PasswordValidator {RequireNonLetterOrDigit = true};
|
||||
IdentityResultAssert.IsSuccess(await valid.ValidateAsync(input));
|
||||
var manager = MockHelpers.TestUserManager<IdentityUser>();
|
||||
var valid = new PasswordValidator<IdentityUser>();
|
||||
manager.Options.Password.RequireUppercase = false;
|
||||
manager.Options.Password.RequireNonLetterOrDigit = true;
|
||||
manager.Options.Password.RequireLowercase = false;
|
||||
manager.Options.Password.RequireDigit = false;
|
||||
manager.Options.Password.RequiredLength = 0;
|
||||
IdentityResultAssert.IsSuccess(await valid.ValidateAsync(input, manager));
|
||||
}
|
||||
|
||||
[Theory]
|
||||
|
|
@ -101,14 +124,8 @@ namespace Microsoft.AspNet.Identity.Test
|
|||
const string lowerError = "Passwords must have at least one lowercase ('a'-'z').";
|
||||
const string digitError = "Passwords must have at least one digit ('0'-'9').";
|
||||
const string lengthError = "Passwords must be at least 6 characters.";
|
||||
var valid = new PasswordValidator
|
||||
{
|
||||
RequireNonLetterOrDigit = true,
|
||||
RequireDigit = true,
|
||||
RequireLowercase = true,
|
||||
RequireUppercase = true,
|
||||
RequiredLength = 6
|
||||
};
|
||||
var manager = MockHelpers.TestUserManager<IdentityUser>();
|
||||
var valid = new PasswordValidator<IdentityUser>();
|
||||
var errors = new List<string>();
|
||||
if ((errorMask & Errors.Length) != Errors.None)
|
||||
{
|
||||
|
|
@ -132,11 +149,11 @@ namespace Microsoft.AspNet.Identity.Test
|
|||
}
|
||||
if (errors.Count == 0)
|
||||
{
|
||||
IdentityResultAssert.IsSuccess(await valid.ValidateAsync(input));
|
||||
IdentityResultAssert.IsSuccess(await valid.ValidateAsync(input, manager));
|
||||
}
|
||||
else
|
||||
{
|
||||
IdentityResultAssert.IsFailure(await valid.ValidateAsync(input), string.Join(" ", errors));
|
||||
IdentityResultAssert.IsFailure(await valid.ValidateAsync(input, manager), string.Join(" ", errors));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,22 +19,18 @@ using System;
|
|||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNet.DependencyInjection;
|
||||
using Microsoft.AspNet.DependencyInjection.Fallback;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.AspNet.Identity.Test
|
||||
{
|
||||
public class RoleManagerTest
|
||||
{
|
||||
[Fact]
|
||||
public void ConstructorThrowsWithNullStore()
|
||||
{
|
||||
Assert.Throws<ArgumentNullException>("store", () => new RoleManager<TestRole>((IRoleStore<TestRole>)null));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void RolesQueryableFailWhenStoreNotImplemented()
|
||||
{
|
||||
var manager = new RoleManager<TestRole>(new NoopRoleStore());
|
||||
var manager = new RoleManager<TestRole>(new ServiceCollection().BuildServiceProvider(), new NoopRoleStore());
|
||||
Assert.False(manager.SupportsQueryableRoles);
|
||||
Assert.Throws<NotSupportedException>(() => manager.Roles.Count());
|
||||
}
|
||||
|
|
@ -42,7 +38,7 @@ namespace Microsoft.AspNet.Identity.Test
|
|||
[Fact]
|
||||
public void DisposeAfterDisposeDoesNotThrow()
|
||||
{
|
||||
var manager = new RoleManager<TestRole>(new NoopRoleStore());
|
||||
var manager = new RoleManager<TestRole>(new ServiceCollection().BuildServiceProvider(), new NoopRoleStore());
|
||||
manager.Dispose();
|
||||
manager.Dispose();
|
||||
}
|
||||
|
|
@ -50,10 +46,12 @@ namespace Microsoft.AspNet.Identity.Test
|
|||
[Fact]
|
||||
public async Task RoleManagerPublicNullChecks()
|
||||
{
|
||||
var provider = new ServiceCollection().BuildServiceProvider();
|
||||
Assert.Throws<ArgumentNullException>("store",
|
||||
() => new RoleManager<TestRole>((IRoleStore<TestRole>)null));
|
||||
var manager = new RoleManager<TestRole>(new NotImplementedStore());
|
||||
Assert.Throws<ArgumentNullException>("services", () => manager.Initialize(null));
|
||||
() => new RoleManager<TestRole>(provider, null));
|
||||
Assert.Throws<ArgumentNullException>("services",
|
||||
() => new RoleManager<TestRole>(null, new NotImplementedStore()));
|
||||
var manager = new RoleManager<TestRole>(provider, new NotImplementedStore());
|
||||
await Assert.ThrowsAsync<ArgumentNullException>("role", async () => await manager.CreateAsync(null));
|
||||
await Assert.ThrowsAsync<ArgumentNullException>("role", async () => await manager.UpdateAsync(null));
|
||||
await Assert.ThrowsAsync<ArgumentNullException>("role", async () => await manager.DeleteAsync(null));
|
||||
|
|
@ -64,7 +62,7 @@ namespace Microsoft.AspNet.Identity.Test
|
|||
[Fact]
|
||||
public async Task RoleStoreMethodsThrowWhenDisposed()
|
||||
{
|
||||
var manager = new RoleManager<TestRole>(new NoopRoleStore());
|
||||
var manager = new RoleManager<TestRole>(new ServiceCollection().BuildServiceProvider(), new NoopRoleStore());
|
||||
manager.Dispose();
|
||||
await Assert.ThrowsAsync<ObjectDisposedException>(() => manager.FindByIdAsync(null));
|
||||
await Assert.ThrowsAsync<ObjectDisposedException>(() => manager.FindByNameAsync(null));
|
||||
|
|
|
|||
|
|
@ -17,6 +17,8 @@
|
|||
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNet.DependencyInjection;
|
||||
using Microsoft.AspNet.DependencyInjection.Fallback;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.AspNet.Identity.Test
|
||||
|
|
@ -27,7 +29,7 @@ namespace Microsoft.AspNet.Identity.Test
|
|||
public async Task ValidateThrowsWithNull()
|
||||
{
|
||||
// Setup
|
||||
var manager = new RoleManager<TestRole>(new NoopRoleStore());
|
||||
var manager = new RoleManager<TestRole>(new ServiceCollection().BuildServiceProvider(), new NoopRoleStore());
|
||||
var validator = new RoleValidator<TestRole>();
|
||||
|
||||
// Act
|
||||
|
|
@ -42,7 +44,7 @@ namespace Microsoft.AspNet.Identity.Test
|
|||
public async Task ValidateFailsWithTooShortRoleName(string input)
|
||||
{
|
||||
// Setup
|
||||
var manager = new RoleManager<TestRole>(new NoopRoleStore());
|
||||
var manager = new RoleManager<TestRole>(new ServiceCollection().BuildServiceProvider(), new NoopRoleStore());
|
||||
var validator = new RoleValidator<TestRole>();
|
||||
var user = new TestRole {Name = input};
|
||||
|
||||
|
|
|
|||
|
|
@ -34,23 +34,22 @@ namespace Microsoft.AspNet.Identity.Test
|
|||
{
|
||||
public IUserStore<TestUser> StorePublic { get { return Store; } }
|
||||
|
||||
public TestManager(IServiceProvider provider) : base(provider) { }
|
||||
public TestManager(IServiceProvider provider, IUserStore<TestUser> store, IOptionsAccessor<IdentityOptions> options) : base(provider, store, options) { }
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void EnsureDefaultServicesDefaultsWithStoreWorks()
|
||||
{
|
||||
var services = new ServiceCollection {IdentityServices.GetDefaultUserServices<TestUser>()};
|
||||
services.AddInstance<IUserStore<TestUser>>(new NoopUserStore());
|
||||
var manager = new TestManager(services.BuildServiceProvider());
|
||||
services.AddInstance<IOptionsAccessor<IdentityOptions>>(new OptionsAccessor<IdentityOptions>(null));
|
||||
services.AddTransient<IUserStore<TestUser>, NoopUserStore>();
|
||||
services.AddTransient<TestManager>();
|
||||
var manager = services.BuildServiceProvider().GetService<TestManager>();
|
||||
Assert.NotNull(manager.PasswordHasher);
|
||||
Assert.NotNull(manager.PasswordValidator);
|
||||
Assert.NotNull(manager.UserValidator);
|
||||
Assert.NotNull(manager.StorePublic);
|
||||
Assert.NotNull(manager.LockoutPolicy);
|
||||
Assert.Equal(TimeSpan.FromMinutes(5), manager.LockoutPolicy.DefaultAccountLockoutTimeSpan);
|
||||
Assert.Equal(5, manager.LockoutPolicy.MaxFailedAccessAttemptsBeforeLockout);
|
||||
Assert.False(manager.LockoutPolicy.UserLockoutEnabledByDefault);
|
||||
Assert.NotNull(manager.Options);
|
||||
}
|
||||
|
||||
#if NET45
|
||||
|
|
@ -61,11 +60,9 @@ namespace Microsoft.AspNet.Identity.Test
|
|||
// Setup
|
||||
var store = new Mock<IUserStore<TestUser>>();
|
||||
var user = new TestUser { UserName = "Foo" };
|
||||
var options = new OptionsAccessor<IdentityOptions>(null);
|
||||
store.Setup(s => s.CreateAsync(user, CancellationToken.None)).Returns(Task.FromResult(0)).Verifiable();
|
||||
var validator = new Mock<UserValidator<TestUser>>();
|
||||
var userManager = new UserManager<TestUser>(store.Object);
|
||||
validator.Setup(v => v.ValidateAsync(userManager, user, CancellationToken.None)).Returns(Task.FromResult(IdentityResult.Success)).Verifiable();
|
||||
userManager.UserValidator = validator.Object;
|
||||
var userManager = MockHelpers.TestUserManager<TestUser>(store.Object);
|
||||
|
||||
// Act
|
||||
var result = await userManager.CreateAsync(user);
|
||||
|
|
@ -81,8 +78,9 @@ namespace Microsoft.AspNet.Identity.Test
|
|||
// Setup
|
||||
var store = new Mock<IUserStore<TestUser>>();
|
||||
var user = new TestUser { UserName = "Foo" };
|
||||
var options = new OptionsAccessor<IdentityOptions>(null);
|
||||
store.Setup(s => s.DeleteAsync(user, CancellationToken.None)).Returns(Task.FromResult(0)).Verifiable();
|
||||
var userManager = new UserManager<TestUser>(store.Object);
|
||||
var userManager = new UserManager<TestUser>(new ServiceCollection().BuildServiceProvider(), store.Object, options);
|
||||
|
||||
// Act
|
||||
var result = await userManager.DeleteAsync(user);
|
||||
|
|
@ -99,10 +97,7 @@ namespace Microsoft.AspNet.Identity.Test
|
|||
var store = new Mock<IUserStore<TestUser>>();
|
||||
var user = new TestUser { UserName = "Foo" };
|
||||
store.Setup(s => s.UpdateAsync(user, CancellationToken.None)).Returns(Task.FromResult(0)).Verifiable();
|
||||
var validator = new Mock<UserValidator<TestUser>>();
|
||||
var userManager = new UserManager<TestUser>(store.Object);
|
||||
validator.Setup(v => v.ValidateAsync(userManager, user, CancellationToken.None)).Returns(Task.FromResult(IdentityResult.Success)).Verifiable();
|
||||
userManager.UserValidator = validator.Object;
|
||||
var userManager = MockHelpers.TestUserManager<TestUser>(store.Object);
|
||||
|
||||
// Act
|
||||
var result = await userManager.UpdateAsync(user);
|
||||
|
|
@ -119,10 +114,7 @@ namespace Microsoft.AspNet.Identity.Test
|
|||
var store = new Mock<IUserStore<TestUser>>();
|
||||
var user = new TestUser();
|
||||
store.Setup(s => s.SetUserNameAsync(user, It.IsAny<string>(), CancellationToken.None)).Returns(Task.FromResult(0)).Verifiable();
|
||||
var validator = new Mock<UserValidator<TestUser>>();
|
||||
var userManager = new UserManager<TestUser>(store.Object);
|
||||
validator.Setup(v => v.ValidateAsync(userManager, user, CancellationToken.None)).Returns(Task.FromResult(IdentityResult.Success)).Verifiable();
|
||||
userManager.UserValidator = validator.Object;
|
||||
var userManager = MockHelpers.TestUserManager<TestUser>(store.Object);
|
||||
|
||||
// Act
|
||||
var result = await userManager.SetUserNameAsync(user, "foo");
|
||||
|
|
@ -139,7 +131,7 @@ namespace Microsoft.AspNet.Identity.Test
|
|||
var store = new Mock<IUserStore<TestUser>>();
|
||||
var user = new TestUser { UserName = "Foo" };
|
||||
store.Setup(s => s.FindByIdAsync(user.Id, CancellationToken.None)).Returns(Task.FromResult(user)).Verifiable();
|
||||
var userManager = new UserManager<TestUser>(store.Object);
|
||||
var userManager = MockHelpers.TestUserManager<TestUser>(store.Object);
|
||||
|
||||
// Act
|
||||
var result = await userManager.FindByIdAsync(user.Id);
|
||||
|
|
@ -156,7 +148,7 @@ namespace Microsoft.AspNet.Identity.Test
|
|||
var store = new Mock<IUserStore<TestUser>>();
|
||||
var user = new TestUser {UserName="Foo"};
|
||||
store.Setup(s => s.FindByNameAsync(user.UserName, CancellationToken.None)).Returns(Task.FromResult(user)).Verifiable();
|
||||
var userManager = new UserManager<TestUser>(store.Object);
|
||||
var userManager = MockHelpers.TestUserManager<TestUser>(store.Object);
|
||||
|
||||
// Act
|
||||
var result = await userManager.FindByNameAsync(user.UserName);
|
||||
|
|
@ -184,7 +176,7 @@ namespace Microsoft.AspNet.Identity.Test
|
|||
.Verifiable();
|
||||
store.Setup(s => s.UpdateAsync(user, CancellationToken.None)).Returns(Task.FromResult(0)).Verifiable();
|
||||
store.Setup(s => s.GetRolesAsync(user, CancellationToken.None)).ReturnsAsync(new List<string>()).Verifiable();
|
||||
var userManager = new UserManager<TestUser>(store.Object) {UserValidator = null};
|
||||
var userManager = MockHelpers.TestUserManager<TestUser>(store.Object);
|
||||
|
||||
// Act
|
||||
var result = await userManager.AddToRolesAsync(user, roles);
|
||||
|
|
@ -200,12 +192,12 @@ namespace Microsoft.AspNet.Identity.Test
|
|||
// Setup
|
||||
var store = new Mock<IUserRoleStore<TestUser>>();
|
||||
var user = new TestUser { UserName = "Foo" };
|
||||
var roles = new string[] { "A", "B", "C" };
|
||||
var roles = new[] { "A", "B", "C" };
|
||||
store.Setup(s => s.AddToRoleAsync(user, "A", CancellationToken.None))
|
||||
.Returns(Task.FromResult(0))
|
||||
.Verifiable();
|
||||
store.Setup(s => s.GetRolesAsync(user, CancellationToken.None)).ReturnsAsync(new List<string> { "B" }).Verifiable();
|
||||
var userManager = new UserManager<TestUser>(store.Object) { UserValidator = null };
|
||||
var userManager = MockHelpers.TestUserManager<TestUser>(store.Object);
|
||||
|
||||
// Act
|
||||
var result = await userManager.AddToRolesAsync(user, roles);
|
||||
|
|
@ -221,7 +213,7 @@ namespace Microsoft.AspNet.Identity.Test
|
|||
// Setup
|
||||
var store = new Mock<IUserRoleStore<TestUser>>();
|
||||
var user = new TestUser { UserName = "Foo" };
|
||||
var roles = new string[] { "A", "B", "C" };
|
||||
var roles = new[] { "A", "B", "C" };
|
||||
store.Setup(s => s.RemoveFromRoleAsync(user, "A", CancellationToken.None))
|
||||
.Returns(Task.FromResult(0))
|
||||
.Verifiable();
|
||||
|
|
@ -241,7 +233,7 @@ namespace Microsoft.AspNet.Identity.Test
|
|||
store.Setup(s => s.IsInRoleAsync(user, "C", CancellationToken.None))
|
||||
.Returns(Task.FromResult(true))
|
||||
.Verifiable();
|
||||
var userManager = new UserManager<TestUser>(store.Object) { UserValidator = null };
|
||||
var userManager = MockHelpers.TestUserManager<TestUser>(store.Object);
|
||||
|
||||
// Act
|
||||
var result = await userManager.RemoveFromRolesAsync(user, roles);
|
||||
|
|
@ -267,7 +259,7 @@ namespace Microsoft.AspNet.Identity.Test
|
|||
store.Setup(s => s.IsInRoleAsync(user, "B", CancellationToken.None))
|
||||
.Returns(Task.FromResult(false))
|
||||
.Verifiable();
|
||||
var userManager = new UserManager<TestUser>(store.Object) { UserValidator = null };
|
||||
var userManager = MockHelpers.TestUserManager<TestUser>(store.Object);
|
||||
|
||||
// Act
|
||||
var result = await userManager.RemoveFromRolesAsync(user, roles);
|
||||
|
|
@ -282,21 +274,21 @@ namespace Microsoft.AspNet.Identity.Test
|
|||
[Fact]
|
||||
public async Task CheckPasswordWithNullUserReturnsFalse()
|
||||
{
|
||||
var manager = new UserManager<TestUser>(new EmptyStore());
|
||||
var manager = MockHelpers.TestUserManager(new EmptyStore());
|
||||
Assert.False(await manager.CheckPasswordAsync(null, "whatevs"));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task FindWithUnknownUserAndPasswordReturnsNull()
|
||||
{
|
||||
var manager = new UserManager<TestUser>(new EmptyStore());
|
||||
var manager = MockHelpers.TestUserManager(new EmptyStore());
|
||||
Assert.Null(await manager.FindByUserNamePasswordAsync("bogus", "whatevs"));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void UsersQueryableFailWhenStoreNotImplemented()
|
||||
{
|
||||
var manager = new UserManager<TestUser>(new NoopUserStore());
|
||||
var manager = MockHelpers.TestUserManager(new NoopUserStore());
|
||||
Assert.False(manager.SupportsQueryableUsers);
|
||||
Assert.Throws<NotSupportedException>(() => manager.Users.Count());
|
||||
}
|
||||
|
|
@ -304,7 +296,7 @@ namespace Microsoft.AspNet.Identity.Test
|
|||
[Fact]
|
||||
public async Task UsersEmailMethodsFailWhenStoreNotImplemented()
|
||||
{
|
||||
var manager = new UserManager<TestUser>(new NoopUserStore());
|
||||
var manager = MockHelpers.TestUserManager(new NoopUserStore());
|
||||
Assert.False(manager.SupportsUserEmail);
|
||||
await Assert.ThrowsAsync<NotSupportedException>(() => manager.FindByEmailAsync(null));
|
||||
await Assert.ThrowsAsync<NotSupportedException>(() => manager.SetEmailAsync(null, null));
|
||||
|
|
@ -316,7 +308,7 @@ namespace Microsoft.AspNet.Identity.Test
|
|||
[Fact]
|
||||
public async Task UsersPhoneNumberMethodsFailWhenStoreNotImplemented()
|
||||
{
|
||||
var manager = new UserManager<TestUser>(new NoopUserStore());
|
||||
var manager = MockHelpers.TestUserManager(new NoopUserStore());
|
||||
Assert.False(manager.SupportsUserPhoneNumber);
|
||||
await Assert.ThrowsAsync<NotSupportedException>(async () => await manager.SetPhoneNumberAsync(null, null));
|
||||
await Assert.ThrowsAsync<NotSupportedException>(async () => await manager.SetPhoneNumberAsync(null, null));
|
||||
|
|
@ -326,7 +318,7 @@ namespace Microsoft.AspNet.Identity.Test
|
|||
[Fact]
|
||||
public async Task TokenMethodsThrowWithNoTokenProvider()
|
||||
{
|
||||
var manager = new UserManager<TestUser>(new NoopUserStore());
|
||||
var manager = MockHelpers.TestUserManager(new NoopUserStore());
|
||||
await Assert.ThrowsAsync<NotSupportedException>(
|
||||
async () => await manager.GenerateUserTokenAsync(null, null));
|
||||
await Assert.ThrowsAsync<NotSupportedException>(
|
||||
|
|
@ -336,7 +328,7 @@ namespace Microsoft.AspNet.Identity.Test
|
|||
[Fact]
|
||||
public async Task PasswordMethodsFailWhenStoreNotImplemented()
|
||||
{
|
||||
var manager = new UserManager<TestUser>(new NoopUserStore());
|
||||
var manager = MockHelpers.TestUserManager(new NoopUserStore());
|
||||
Assert.False(manager.SupportsUserPassword);
|
||||
await Assert.ThrowsAsync<NotSupportedException>(() => manager.CreateAsync(null, null));
|
||||
await Assert.ThrowsAsync<NotSupportedException>(() => manager.ChangePasswordAsync(null, null, null));
|
||||
|
|
@ -349,7 +341,7 @@ namespace Microsoft.AspNet.Identity.Test
|
|||
[Fact]
|
||||
public async Task SecurityStampMethodsFailWhenStoreNotImplemented()
|
||||
{
|
||||
var manager = new UserManager<TestUser>(new NoopUserStore());
|
||||
var manager = MockHelpers.TestUserManager(new NoopUserStore());
|
||||
Assert.False(manager.SupportsUserSecurityStamp);
|
||||
await Assert.ThrowsAsync<NotSupportedException>(() => manager.UpdateSecurityStampAsync(null));
|
||||
await Assert.ThrowsAsync<NotSupportedException>(() => manager.GetSecurityStampAsync(null));
|
||||
|
|
@ -366,7 +358,7 @@ namespace Microsoft.AspNet.Identity.Test
|
|||
[Fact]
|
||||
public async Task LoginMethodsFailWhenStoreNotImplemented()
|
||||
{
|
||||
var manager = new UserManager<TestUser>(new NoopUserStore());
|
||||
var manager = MockHelpers.TestUserManager(new NoopUserStore());
|
||||
Assert.False(manager.SupportsUserLogin);
|
||||
await Assert.ThrowsAsync<NotSupportedException>(async () => await manager.AddLoginAsync(null, null));
|
||||
await Assert.ThrowsAsync<NotSupportedException>(async () => await manager.RemoveLoginAsync(null, null));
|
||||
|
|
@ -377,7 +369,7 @@ namespace Microsoft.AspNet.Identity.Test
|
|||
[Fact]
|
||||
public async Task ClaimMethodsFailWhenStoreNotImplemented()
|
||||
{
|
||||
var manager = new UserManager<TestUser>(new NoopUserStore());
|
||||
var manager = MockHelpers.TestUserManager(new NoopUserStore());
|
||||
Assert.False(manager.SupportsUserClaim);
|
||||
await Assert.ThrowsAsync<NotSupportedException>(async () => await manager.AddClaimAsync(null, null));
|
||||
await Assert.ThrowsAsync<NotSupportedException>(async () => await manager.RemoveClaimAsync(null, null));
|
||||
|
|
@ -387,7 +379,7 @@ namespace Microsoft.AspNet.Identity.Test
|
|||
[Fact]
|
||||
public async Task TwoFactorStoreMethodsFailWhenStoreNotImplemented()
|
||||
{
|
||||
var manager = new UserManager<TestUser>(new NoopUserStore());
|
||||
var manager = MockHelpers.TestUserManager(new NoopUserStore());
|
||||
Assert.False(manager.SupportsUserTwoFactor);
|
||||
await Assert.ThrowsAsync<NotSupportedException>(async () => await manager.GetTwoFactorEnabledAsync(null));
|
||||
await
|
||||
|
|
@ -397,7 +389,7 @@ namespace Microsoft.AspNet.Identity.Test
|
|||
[Fact]
|
||||
public async Task LockoutStoreMethodsFailWhenStoreNotImplemented()
|
||||
{
|
||||
var manager = new UserManager<TestUser>(new NoopUserStore());
|
||||
var manager = MockHelpers.TestUserManager(new NoopUserStore());
|
||||
Assert.False(manager.SupportsUserLockout);
|
||||
await Assert.ThrowsAsync<NotSupportedException>(async () => await manager.GetLockoutEnabledAsync(null));
|
||||
await Assert.ThrowsAsync<NotSupportedException>(async () => await manager.SetLockoutEnabledAsync(null, true));
|
||||
|
|
@ -410,7 +402,7 @@ namespace Microsoft.AspNet.Identity.Test
|
|||
[Fact]
|
||||
public async Task RoleMethodsFailWhenStoreNotImplemented()
|
||||
{
|
||||
var manager = new UserManager<TestUser>(new NoopUserStore());
|
||||
var manager = MockHelpers.TestUserManager(new NoopUserStore());
|
||||
Assert.False(manager.SupportsUserRole);
|
||||
await Assert.ThrowsAsync<NotSupportedException>(async () => await manager.AddToRoleAsync(null, "bogus"));
|
||||
await Assert.ThrowsAsync<NotSupportedException>(async () => await manager.AddToRolesAsync(null, null));
|
||||
|
|
@ -423,7 +415,7 @@ namespace Microsoft.AspNet.Identity.Test
|
|||
[Fact]
|
||||
public void DisposeAfterDisposeDoesNotThrow()
|
||||
{
|
||||
var manager = new UserManager<TestUser>(new NoopUserStore());
|
||||
var manager = MockHelpers.TestUserManager(new NoopUserStore());
|
||||
manager.Dispose();
|
||||
manager.Dispose();
|
||||
}
|
||||
|
|
@ -432,23 +424,26 @@ namespace Microsoft.AspNet.Identity.Test
|
|||
public async Task PasswordValidatorBlocksCreate()
|
||||
{
|
||||
// TODO: Can switch to Mock eventually
|
||||
var manager = new UserManager<TestUser>(new EmptyStore())
|
||||
{
|
||||
PasswordValidator = new BadPasswordValidtor()
|
||||
};
|
||||
var manager = MockHelpers.TestUserManager(new EmptyStore());
|
||||
manager.PasswordValidator = new BadPasswordValidator<TestUser>();
|
||||
IdentityResultAssert.IsFailure(await manager.CreateAsync(new TestUser(), "password"),
|
||||
BadPasswordValidtor.ErrorMessage);
|
||||
BadPasswordValidator<TestUser>.ErrorMessage);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ManagerPublicNullChecks()
|
||||
{
|
||||
var provider = new ServiceCollection().BuildServiceProvider();
|
||||
Assert.Throws<ArgumentNullException>("serviceProvider",
|
||||
() => new UserManager<TestUser>((IServiceProvider)null));
|
||||
var manager = new UserManager<TestUser>(new NotImplementedStore());
|
||||
Assert.Throws<ArgumentNullException>(() => manager.ClaimsIdentityFactory = null);
|
||||
Assert.Throws<ArgumentNullException>(() => manager.PasswordHasher = null);
|
||||
Assert.Throws<ArgumentNullException>("serviceProvider", () => manager.Initialize(null));
|
||||
() => new UserManager<TestUser>(null, null, null));
|
||||
Assert.Throws<ArgumentNullException>("store",
|
||||
() => new UserManager<TestUser>(provider, null, null));
|
||||
Assert.Throws<ArgumentNullException>("optionsAccessor",
|
||||
() => new UserManager<TestUser>(provider, new NotImplementedStore(), null));
|
||||
var manager = new UserManager<TestUser>(provider, new NotImplementedStore(), new OptionsAccessor<IdentityOptions>(null));
|
||||
Assert.Throws<ArgumentNullException>("value", () => manager.ClaimsIdentityFactory = null);
|
||||
Assert.Throws<ArgumentNullException>("value", () => manager.PasswordHasher = null);
|
||||
Assert.Throws<ArgumentNullException>("value", () => manager.Options = null);
|
||||
await
|
||||
Assert.ThrowsAsync<ArgumentNullException>("user",
|
||||
async () => await manager.CreateIdentityAsync(null, "whatever"));
|
||||
|
|
@ -476,10 +471,8 @@ namespace Microsoft.AspNet.Identity.Test
|
|||
[Fact]
|
||||
public async Task MethodsFailWithUnknownUserTest()
|
||||
{
|
||||
var manager = new UserManager<TestUser>(new EmptyStore())
|
||||
{
|
||||
UserTokenProvider = new NoOpTokenProvider()
|
||||
};
|
||||
var manager = MockHelpers.TestUserManager(new EmptyStore());
|
||||
manager.UserTokenProvider = new NoOpTokenProvider();
|
||||
await Assert.ThrowsAsync<ArgumentNullException>("user",
|
||||
async () => await manager.GetUserNameAsync(null));
|
||||
await Assert.ThrowsAsync<ArgumentNullException>("user",
|
||||
|
|
@ -583,7 +576,7 @@ namespace Microsoft.AspNet.Identity.Test
|
|||
[Fact]
|
||||
public async Task MethodsThrowWhenDisposedTest()
|
||||
{
|
||||
var manager = new UserManager<TestUser>(new NoopUserStore());
|
||||
var manager = MockHelpers.TestUserManager(new NoopUserStore());
|
||||
manager.Dispose();
|
||||
Assert.Throws<ObjectDisposedException>(() => manager.ClaimsIdentityFactory);
|
||||
await Assert.ThrowsAsync<ObjectDisposedException>(() => manager.AddClaimAsync(null, null));
|
||||
|
|
@ -620,11 +613,11 @@ namespace Microsoft.AspNet.Identity.Test
|
|||
await Assert.ThrowsAsync<ObjectDisposedException>(() => manager.ConfirmEmailAsync(null, null));
|
||||
}
|
||||
|
||||
private class BadPasswordValidtor : IPasswordValidator
|
||||
private class BadPasswordValidator<TUser> : IPasswordValidator<TUser> where TUser : class
|
||||
{
|
||||
public const string ErrorMessage = "I'm Bad.";
|
||||
|
||||
public Task<IdentityResult> ValidateAsync(string password, CancellationToken cancellationToken = default(CancellationToken))
|
||||
public Task<IdentityResult> ValidateAsync(string password, UserManager<TUser> manager, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
return Task.FromResult(IdentityResult.Failed(ErrorMessage));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,6 +17,8 @@
|
|||
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNet.DependencyInjection;
|
||||
using Microsoft.AspNet.DependencyInjection.Fallback;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.AspNet.Identity.Test
|
||||
|
|
@ -27,7 +29,7 @@ namespace Microsoft.AspNet.Identity.Test
|
|||
public async Task ValidateThrowsWithNull()
|
||||
{
|
||||
// Setup
|
||||
var manager = new UserManager<TestUser>(new NoopUserStore());
|
||||
var manager = MockHelpers.TestUserManager(new NoopUserStore());
|
||||
var validator = new UserValidator<TestUser>();
|
||||
|
||||
// Act
|
||||
|
|
@ -42,7 +44,7 @@ namespace Microsoft.AspNet.Identity.Test
|
|||
public async Task ValidateFailsWithTooShortUserNames(string input)
|
||||
{
|
||||
// Setup
|
||||
var manager = new UserManager<TestUser>(new NoopUserStore());
|
||||
var manager = MockHelpers.TestUserManager(new NoopUserStore());
|
||||
var validator = new UserValidator<TestUser>();
|
||||
var user = new TestUser {UserName = input};
|
||||
|
||||
|
|
@ -62,7 +64,7 @@ namespace Microsoft.AspNet.Identity.Test
|
|||
public async Task DefaultAlphaNumericOnlyUserNameValidation(string userName, bool expectSuccess)
|
||||
{
|
||||
// Setup
|
||||
var manager = new UserManager<TestUser>(new NoopUserStore());
|
||||
var manager = MockHelpers.TestUserManager(new NoopUserStore());
|
||||
var validator = new UserValidator<TestUser>();
|
||||
var user = new TestUser {UserName = userName};
|
||||
|
||||
|
|
@ -89,8 +91,9 @@ namespace Microsoft.AspNet.Identity.Test
|
|||
public async Task CanAllowNonAlphaNumericUserName(string userName, bool expectSuccess)
|
||||
{
|
||||
// Setup
|
||||
var manager = new UserManager<TestUser>(new NoopUserStore());
|
||||
var validator = new UserValidator<TestUser> {AllowOnlyAlphanumericUserNames = false};
|
||||
var manager = MockHelpers.TestUserManager(new NoopUserStore());
|
||||
manager.Options.User.AllowOnlyAlphanumericNames = false;
|
||||
var validator = new UserValidator<TestUser>();
|
||||
var user = new TestUser {UserName = userName};
|
||||
|
||||
// Act
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@
|
|||
"xunit.core": "2.0.0-aspnet-*",
|
||||
"xunit.execution": "2.0.0-aspnet-*"
|
||||
},
|
||||
"code": "**\\*.cs;..\\Shared\\*.cs",
|
||||
"configurations": {
|
||||
"net45": {
|
||||
"dependencies": {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,19 @@
|
|||
using System;
|
||||
using Microsoft.AspNet.DependencyInjection;
|
||||
|
||||
namespace Microsoft.AspNet.Identity.Test
|
||||
{
|
||||
public class ApplicationUserManager : UserManager<ApplicationUser>
|
||||
{
|
||||
public ApplicationUserManager(IServiceProvider services, IUserStore<ApplicationUser> store, IOptionsAccessor<IdentityOptions> options) : base(services, store, options) { }
|
||||
}
|
||||
|
||||
public class ApplicationRoleManager : RoleManager<IdentityRole>
|
||||
{
|
||||
public ApplicationRoleManager(IServiceProvider services, IRoleStore<IdentityRole> store) : base(services, store) { }
|
||||
}
|
||||
|
||||
public class ApplicationUser : IdentityUser
|
||||
{
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNet.DependencyInjection;
|
||||
using Microsoft.AspNet.DependencyInjection.Fallback;
|
||||
using Moq;
|
||||
|
||||
namespace Microsoft.AspNet.Identity.Test
|
||||
{
|
||||
public static class MockHelpers
|
||||
{
|
||||
public static Mock<UserManager<TUser>> MockUserManager<TUser>() where TUser : class
|
||||
{
|
||||
var store = new Mock<IUserStore<TUser>>();
|
||||
var options = new OptionsAccessor<IdentityOptions>(null);
|
||||
return new Mock<UserManager<TUser>>(new ServiceCollection().BuildServiceProvider(), store.Object, options);
|
||||
}
|
||||
|
||||
public static UserManager<TUser> TestUserManager<TUser>() where TUser : class
|
||||
{
|
||||
return TestUserManager(new Mock<IUserStore<TUser>>().Object);
|
||||
}
|
||||
|
||||
public static UserManager<TUser> TestUserManager<TUser>(IUserStore<TUser> store) where TUser : class
|
||||
{
|
||||
var options = new OptionsAccessor<IdentityOptions>(null);
|
||||
var validator = new Mock<UserValidator<TUser>>();
|
||||
var userManager = new UserManager<TUser>(new ServiceCollection().BuildServiceProvider(), store, options);
|
||||
validator.Setup(v => v.ValidateAsync(userManager, It.IsAny<TUser>(), CancellationToken.None)).Returns(Task.FromResult(IdentityResult.Success)).Verifiable();
|
||||
userManager.UserValidator = validator.Object;
|
||||
return userManager;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Microsoft.AspNet.Identity.Test
|
||||
{
|
||||
public class TestMessageService : IIdentityMessageService
|
||||
{
|
||||
public IdentityMessage Message { get; set; }
|
||||
|
||||
public Task SendAsync(IdentityMessage message, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
Message = message;
|
||||
return Task.FromResult(0);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -26,7 +26,7 @@ namespace Microsoft.AspNet.Identity.Test
|
|||
Id = Guid.NewGuid().ToString();
|
||||
}
|
||||
|
||||
public string Id { get; set; }
|
||||
public string Id { get; private set; }
|
||||
public string UserName { get; set; }
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue