Merge branch 'release' of github.com:aspnet/Identity into release
This commit is contained in:
commit
8080826e4a
|
|
@ -19,10 +19,10 @@ IF EXIST packages\KoreBuild goto run
|
|||
.nuget\NuGet.exe install KoreBuild -ExcludeVersion -o packages -nocache -pre
|
||||
.nuget\NuGet.exe install Sake -version 0.2 -o packages -ExcludeVersion
|
||||
|
||||
IF "%SKIP_KRE_INSTALL%"=="1" goto run
|
||||
CALL packages\KoreBuild\build\kvm upgrade -runtime CLR -x86
|
||||
CALL packages\KoreBuild\build\kvm install default -runtime CoreCLR -x86
|
||||
IF "%SKIP_DOTNET_INSTALL%"=="1" goto run
|
||||
CALL packages\KoreBuild\build\dotnetsdk upgrade -runtime CLR -x86
|
||||
CALL packages\KoreBuild\build\dotnetsdk install default -runtime CoreCLR -x86
|
||||
|
||||
:run
|
||||
CALL packages\KoreBuild\build\kvm use default -runtime CLR -x86
|
||||
CALL packages\KoreBuild\build\dotnetsdk use default -runtime CLR -x86
|
||||
packages\Sake\tools\Sake.exe -I packages\KoreBuild\build -f makefile.shade %*
|
||||
|
|
|
|||
4
build.sh
4
build.sh
|
|
@ -28,11 +28,11 @@ if test ! -d packages/KoreBuild; then
|
|||
fi
|
||||
|
||||
if ! type k > /dev/null 2>&1; then
|
||||
source packages/KoreBuild/build/kvm.sh
|
||||
source packages/KoreBuild/build/dotnetsdk.sh
|
||||
fi
|
||||
|
||||
if ! type k > /dev/null 2>&1; then
|
||||
kvm upgrade
|
||||
dotnetsdk upgrade
|
||||
fi
|
||||
|
||||
mono packages/Sake/tools/Sake.exe -I packages/KoreBuild/build -f makefile.shade "$@"
|
||||
|
|
|
|||
|
|
@ -1,11 +1,10 @@
|
|||
using Microsoft.AspNet.Http;
|
||||
using Microsoft.AspNet.Identity;
|
||||
using Microsoft.AspNet.Mvc;
|
||||
using Microsoft.AspNet.Mvc.Rendering;
|
||||
using System.Linq;
|
||||
using System.Linq;
|
||||
using System.Security.Claims;
|
||||
using System.Security.Principal;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNet.Identity;
|
||||
using Microsoft.AspNet.Mvc;
|
||||
using Microsoft.AspNet.Mvc.Rendering;
|
||||
|
||||
namespace IdentitySample.Models
|
||||
{
|
||||
|
|
@ -43,20 +42,23 @@ namespace IdentitySample.Models
|
|||
ViewBag.ReturnUrl = returnUrl;
|
||||
if (ModelState.IsValid)
|
||||
{
|
||||
var signInStatus = await SignInManager.PasswordSignInAsync(model.UserName, model.Password, model.RememberMe, shouldLockout: false);
|
||||
switch (signInStatus)
|
||||
var result = await SignInManager.PasswordSignInAsync(model.UserName, model.Password, model.RememberMe, shouldLockout: false);
|
||||
if (result.Succeeded)
|
||||
{
|
||||
case SignInStatus.Success:
|
||||
return RedirectToLocal(returnUrl);
|
||||
case SignInStatus.LockedOut:
|
||||
ModelState.AddModelError("", "User is locked out, try again later.");
|
||||
return View(model);
|
||||
case SignInStatus.RequiresVerification:
|
||||
return RedirectToAction("SendCode", new { ReturnUrl = returnUrl, RememberMe = model.RememberMe });
|
||||
case SignInStatus.Failure:
|
||||
default:
|
||||
ModelState.AddModelError("", "Invalid username or password.");
|
||||
return View(model);
|
||||
return RedirectToLocal(returnUrl);
|
||||
}
|
||||
if (result.RequiresTwoFactor)
|
||||
{
|
||||
return RedirectToAction("SendCode", new { ReturnUrl = returnUrl, RememberMe = model.RememberMe });
|
||||
}
|
||||
if (result.IsLockedOut)
|
||||
{
|
||||
return View("Lockout");
|
||||
}
|
||||
else
|
||||
{
|
||||
ModelState.AddModelError("", "Invalid username or password.");
|
||||
return View(model);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -143,22 +145,26 @@ namespace IdentitySample.Models
|
|||
// Sign in the user with this external login provider if the user already has a login
|
||||
var result = await SignInManager.ExternalLoginSignInAsync(info.LoginProvider, info.ProviderKey,
|
||||
isPersistent: false);
|
||||
switch (result)
|
||||
if (result.Succeeded)
|
||||
{
|
||||
case SignInStatus.Success:
|
||||
return RedirectToLocal(returnUrl);
|
||||
case SignInStatus.LockedOut:
|
||||
return View("Lockout");
|
||||
case SignInStatus.RequiresVerification:
|
||||
return RedirectToAction("SendCode", new { ReturnUrl = returnUrl });
|
||||
case SignInStatus.Failure:
|
||||
default:
|
||||
// If the user does not have an account, then prompt the user to create an account
|
||||
ViewBag.ReturnUrl = returnUrl;
|
||||
ViewBag.LoginProvider = info.LoginProvider;
|
||||
// REVIEW: handle case where email not in claims?
|
||||
var email = info.ExternalIdentity.FindFirstValue(ClaimTypes.Email);
|
||||
return View("ExternalLoginConfirmation", new ExternalLoginConfirmationViewModel { Email = email });
|
||||
return RedirectToLocal(returnUrl);
|
||||
}
|
||||
if (result.RequiresTwoFactor)
|
||||
{
|
||||
return RedirectToAction("SendCode", new { ReturnUrl = returnUrl });
|
||||
}
|
||||
if (result.IsLockedOut)
|
||||
{
|
||||
return View("Lockout");
|
||||
}
|
||||
else
|
||||
{
|
||||
// If the user does not have an account, then prompt the user to create an account
|
||||
ViewBag.ReturnUrl = returnUrl;
|
||||
ViewBag.LoginProvider = info.LoginProvider;
|
||||
// REVIEW: handle case where email not in claims?
|
||||
var email = info.ExternalIdentity.FindFirstValue(ClaimTypes.Email);
|
||||
return View("ExternalLoginConfirmation", new ExternalLoginConfirmationViewModel { Email = email });
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -380,15 +386,18 @@ namespace IdentitySample.Models
|
|||
}
|
||||
|
||||
var result = await SignInManager.TwoFactorSignInAsync(model.Provider, model.Code, model.RememberMe, model.RememberBrowser);
|
||||
switch (result)
|
||||
if (result.Succeeded)
|
||||
{
|
||||
case SignInStatus.Success:
|
||||
return RedirectToLocal(model.ReturnUrl);
|
||||
case SignInStatus.LockedOut:
|
||||
return View("Lockout");
|
||||
default:
|
||||
ModelState.AddModelError("", "Invalid code.");
|
||||
return View(model);
|
||||
return RedirectToLocal(model.ReturnUrl);
|
||||
}
|
||||
if (result.IsLockedOut)
|
||||
{
|
||||
return View("Lockout");
|
||||
}
|
||||
else
|
||||
{
|
||||
ModelState.AddModelError("", "Invalid code.");
|
||||
return View(model);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -398,7 +407,7 @@ namespace IdentitySample.Models
|
|||
{
|
||||
foreach (var error in result.Errors)
|
||||
{
|
||||
ModelState.AddModelError("", error);
|
||||
ModelState.AddModelError("", error.Description);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -346,7 +346,7 @@ namespace IdentitySample
|
|||
{
|
||||
foreach (var error in result.Errors)
|
||||
{
|
||||
ModelState.AddModelError("", error);
|
||||
ModelState.AddModelError("", error.Description);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">14.0</VisualStudioVersion>
|
||||
|
|
@ -12,6 +12,7 @@
|
|||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<SchemaVersion>2.0</SchemaVersion>
|
||||
<DevelopmentServerPort>5131</DevelopmentServerPort>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VSToolsPath)\AspNet\Microsoft.Web.AspNet.targets" Condition="'$(VSToolsPath)' != ''" />
|
||||
</Project>
|
||||
</Project>
|
||||
|
|
@ -3,7 +3,7 @@
|
|||
"DefaultAdminPassword": "YouShouldChangeThisPassword1!",
|
||||
"Data": {
|
||||
"IdentityConnection": {
|
||||
"Connectionstring": "Server=(localdb)\\mssqllocaldb;Database=IdentityMvc-11-24-14;Trusted_Connection=True;MultipleActiveResultSets=true"
|
||||
"Connectionstring": "Server=(localdb)\\mssqllocaldb;Database=IdentityMvc-1-7-15;Trusted_Connection=True;MultipleActiveResultSets=true"
|
||||
}
|
||||
},
|
||||
"Identity": {
|
||||
|
|
|
|||
|
|
@ -72,7 +72,7 @@
|
|||
<a href="http://www.windowsazure.com/en-us/documentation/articles/web-sites-dotnet-deploy-aspnet-mvc-app-membership-oauth-sql-database/">Add Social Logins</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="http://blogs.msdn.com/b/webdev/archive/2013/10/16/get-more-information-from-social-providers-used-in-the-vs-2013-project-templates.aspx">Get more data about the user when they login suing Facebook</a>
|
||||
<a href="http://blogs.msdn.com/b/webdev/archive/2013/10/16/get-more-information-from-social-providers-used-in-the-vs-2013-project-templates.aspx">Get more data about the user when they log in using Facebook</a>
|
||||
</li>
|
||||
</ul>
|
||||
</dd>
|
||||
|
|
@ -102,7 +102,7 @@
|
|||
<dt>Account Confirmation</dt>
|
||||
<dd>
|
||||
When you register a new account, you will be sent an email confirmation.
|
||||
You can use an email service such as <a href="http://www.windowsazure.com/en-us/documentation/articles/sendgrid-dotnet-how-to-send-email/">SendGrid</a> which integrate nicely with Windows Azure and requires no configuration or
|
||||
You can use an email service such as <a href="http://www.windowsazure.com/en-us/documentation/articles/sendgrid-dotnet-how-to-send-email/">SendGrid</a> which integrates nicely with Windows Azure and requires no configuration or
|
||||
set up an SMTP server to send email.
|
||||
You can send email using the EmailService which is registered in App_Start\IdentityConfig.cs
|
||||
</dd>
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@
|
|||
<appSettings>
|
||||
<!-- This will turn on detailed errors when deployed to remote servers -->
|
||||
<!-- This setting is not recommended for production -->
|
||||
<add key="K_DETAILED_ERRORS" value="true" />
|
||||
<add key="ASPNET_DETAILED_ERRORS" value="true" />
|
||||
</appSettings>
|
||||
|
||||
</configuration>
|
||||
|
|
@ -30,45 +30,30 @@ namespace Microsoft.AspNet.Identity.EntityFramework
|
|||
{
|
||||
b.Key(u => u.Id);
|
||||
b.ForRelational().Table("AspNetUsers");
|
||||
b.Property(u => u.ConcurrencyStamp).ConcurrencyToken();
|
||||
});
|
||||
|
||||
builder.Entity<TRole>(b =>
|
||||
{
|
||||
b.Key(r => r.Id);
|
||||
b.ForRelational().Table("AspNetRoles");
|
||||
b.Property(r => r.ConcurrencyStamp).ConcurrencyToken();
|
||||
});
|
||||
|
||||
builder.Entity<IdentityUserClaim<TKey>>(b =>
|
||||
{
|
||||
b.Key(uc => uc.Id);
|
||||
b.ManyToOne<TUser>().ForeignKey(uc => uc.UserId);
|
||||
b.HasOne<TUser>().WithMany().ForeignKey(uc => uc.UserId);
|
||||
b.ForRelational().Table("AspNetUserClaims");
|
||||
});
|
||||
|
||||
builder.Entity<IdentityRoleClaim<TKey>>(b =>
|
||||
{
|
||||
b.Key(rc => rc.Id);
|
||||
b.ManyToOne<TRole>().ForeignKey(rc => rc.RoleId);
|
||||
b.HasOne<TRole>().WithMany().ForeignKey(rc => rc.RoleId);
|
||||
b.ForRelational().Table("AspNetRoleClaims");
|
||||
});
|
||||
|
||||
var userType = builder.Model.GetEntityType(typeof(TUser));
|
||||
var roleType = builder.Model.GetEntityType(typeof(TRole));
|
||||
var userClaimType = builder.Model.GetEntityType(typeof(IdentityUserClaim<TKey>));
|
||||
var roleClaimType = builder.Model.GetEntityType(typeof(IdentityRoleClaim<TKey>));
|
||||
var userRoleType = builder.Model.GetEntityType(typeof(IdentityUserRole<TKey>));
|
||||
//var ucfk = userClaimType.GetOrAddForeignKey(userType.GetPrimaryKey(), new[] { userClaimType.GetProperty("UserId") });
|
||||
//userType.AddNavigation(new Navigation(ucfk, "Claims", false));
|
||||
//userClaimType.AddNavigation(new Navigation(ucfk, "User", true));
|
||||
//var urfk = userRoleType.GetOrAddForeignKey(userType.GetPrimaryKey(), new[] { userRoleType.GetProperty("UserId") });
|
||||
//userType.AddNavigation(new Navigation(urfk, "Roles", false));
|
||||
|
||||
//var urfk2 = userRoleType.GetOrAddForeignKey(roleType.GetPrimaryKey(), new[] { userRoleType.GetProperty("RoleId") });
|
||||
//roleType.AddNavigation(new Navigation(urfk2, "Users", false));
|
||||
|
||||
var rcfk = roleClaimType.GetOrAddForeignKey(new[] { roleClaimType.GetProperty("RoleId") }, roleType.GetPrimaryKey());
|
||||
roleType.AddNavigation("Claims", rcfk, false);
|
||||
|
||||
builder.Entity<IdentityUserRole<TKey>>(b =>
|
||||
{
|
||||
b.Key(r => new { r.UserId, r.RoleId });
|
||||
|
|
@ -81,7 +66,7 @@ namespace Microsoft.AspNet.Identity.EntityFramework
|
|||
builder.Entity<IdentityUserLogin<TKey>>(b =>
|
||||
{
|
||||
b.Key(l => new { l.LoginProvider, l.ProviderKey });
|
||||
b.ManyToOne<TUser>().ForeignKey(uc => uc.UserId);
|
||||
b.HasOne<TUser>().WithMany().ForeignKey(uc => uc.UserId);
|
||||
b.ForRelational().Table("AspNetUserLogins");
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,41 +4,42 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Linq.Expressions;
|
||||
using System.Security.Claims;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Data.Entity;
|
||||
using Microsoft.Data.Entity.Update;
|
||||
|
||||
namespace Microsoft.AspNet.Identity.EntityFramework
|
||||
{
|
||||
public class RoleStore<TRole> : RoleStore<TRole, DbContext, string>
|
||||
where TRole : IdentityRole
|
||||
{
|
||||
public RoleStore(DbContext context) : base(context) { }
|
||||
public RoleStore(DbContext context, IdentityErrorDescriber describer = null) : base(context, describer) { }
|
||||
}
|
||||
|
||||
public class RoleStore<TRole, TContext> : RoleStore<TRole, TContext, string>
|
||||
where TRole : IdentityRole
|
||||
where TContext : DbContext
|
||||
{
|
||||
public RoleStore(TContext context) : base(context) { }
|
||||
public RoleStore(TContext context, IdentityErrorDescriber describer = null) : base(context, describer) { }
|
||||
}
|
||||
|
||||
public class RoleStore<TRole, TContext, TKey> :
|
||||
IQueryableRoleStore<TRole>,
|
||||
public class RoleStore<TRole, TContext, TKey> :
|
||||
IQueryableRoleStore<TRole>,
|
||||
IRoleClaimStore<TRole>
|
||||
where TRole : IdentityRole<TKey>
|
||||
where TKey : IEquatable<TKey>
|
||||
where TContext : DbContext
|
||||
{
|
||||
public RoleStore(TContext context)
|
||||
public RoleStore(TContext context, IdentityErrorDescriber describer = null)
|
||||
{
|
||||
if (context == null)
|
||||
{
|
||||
throw new ArgumentNullException("context");
|
||||
}
|
||||
Context = context;
|
||||
ErrorDescriber = describer ?? new IdentityErrorDescriber();
|
||||
}
|
||||
|
||||
private bool _disposed;
|
||||
|
|
@ -46,6 +47,11 @@ namespace Microsoft.AspNet.Identity.EntityFramework
|
|||
|
||||
public TContext Context { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Used to generate public API error messages
|
||||
/// </summary>
|
||||
public IdentityErrorDescriber ErrorDescriber { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// If true will call SaveChanges after CreateAsync/UpdateAsync/DeleteAsync
|
||||
/// </summary>
|
||||
|
|
@ -59,12 +65,7 @@ namespace Microsoft.AspNet.Identity.EntityFramework
|
|||
}
|
||||
}
|
||||
|
||||
public virtual Task<TRole> GetRoleAggregate(Expression<Func<TRole, bool>> filter, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
return Roles.FirstOrDefaultAsync(filter);
|
||||
}
|
||||
|
||||
public async virtual Task CreateAsync(TRole role, CancellationToken cancellationToken = default(CancellationToken))
|
||||
public async virtual Task<IdentityResult> CreateAsync(TRole role, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
ThrowIfDisposed();
|
||||
|
|
@ -74,9 +75,10 @@ namespace Microsoft.AspNet.Identity.EntityFramework
|
|||
}
|
||||
await Context.AddAsync(role, cancellationToken);
|
||||
await SaveChanges(cancellationToken);
|
||||
return IdentityResult.Success;
|
||||
}
|
||||
|
||||
public async virtual Task UpdateAsync(TRole role, CancellationToken cancellationToken = default(CancellationToken))
|
||||
public async virtual Task<IdentityResult> UpdateAsync(TRole role, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
ThrowIfDisposed();
|
||||
|
|
@ -84,11 +86,21 @@ namespace Microsoft.AspNet.Identity.EntityFramework
|
|||
{
|
||||
throw new ArgumentNullException("role");
|
||||
}
|
||||
Context.Attach(role);
|
||||
role.ConcurrencyStamp = Guid.NewGuid().ToString();
|
||||
Context.Update(role);
|
||||
await SaveChanges(cancellationToken);
|
||||
try
|
||||
{
|
||||
await SaveChanges(cancellationToken);
|
||||
}
|
||||
catch (DbUpdateConcurrencyException)
|
||||
{
|
||||
return IdentityResult.Failed(ErrorDescriber.ConcurrencyFailure());
|
||||
}
|
||||
return IdentityResult.Success;
|
||||
}
|
||||
|
||||
public async virtual Task DeleteAsync(TRole role, CancellationToken cancellationToken = default(CancellationToken))
|
||||
public async virtual Task<IdentityResult> DeleteAsync(TRole role, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
ThrowIfDisposed();
|
||||
|
|
@ -97,7 +109,15 @@ namespace Microsoft.AspNet.Identity.EntityFramework
|
|||
throw new ArgumentNullException("role");
|
||||
}
|
||||
Context.Remove(role);
|
||||
await SaveChanges(cancellationToken);
|
||||
try
|
||||
{
|
||||
await SaveChanges(cancellationToken);
|
||||
}
|
||||
catch (DbUpdateConcurrencyException)
|
||||
{
|
||||
return IdentityResult.Failed(ErrorDescriber.ConcurrencyFailure());
|
||||
}
|
||||
return IdentityResult.Success;
|
||||
}
|
||||
|
||||
public Task<string> GetRoleIdAsync(TRole role, CancellationToken cancellationToken = default(CancellationToken))
|
||||
|
|
@ -163,20 +183,43 @@ namespace Microsoft.AspNet.Identity.EntityFramework
|
|||
cancellationToken.ThrowIfCancellationRequested();
|
||||
ThrowIfDisposed();
|
||||
var roleId = ConvertIdFromString(id);
|
||||
return GetRoleAggregate(u => u.Id.Equals(roleId), cancellationToken);
|
||||
return Roles.FirstOrDefaultAsync(u => u.Id.Equals(roleId), cancellationToken);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Find a role by name
|
||||
/// Find a role by normalized name
|
||||
/// </summary>
|
||||
/// <param name="name"></param>
|
||||
/// <param name="normalizedName"></param>
|
||||
/// <param name="cancellationToken"></param>
|
||||
/// <returns></returns>
|
||||
public virtual Task<TRole> FindByNameAsync(string name, CancellationToken cancellationToken = default(CancellationToken))
|
||||
public virtual Task<TRole> FindByNameAsync(string normalizedName, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
ThrowIfDisposed();
|
||||
return GetRoleAggregate(u => u.Name.ToUpper() == name.ToUpper(), cancellationToken);
|
||||
return Roles.FirstOrDefaultAsync(r => r.NormalizedName == normalizedName, cancellationToken);
|
||||
}
|
||||
|
||||
public virtual Task<string> GetNormalizedRoleNameAsync(TRole role, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
ThrowIfDisposed();
|
||||
if (role == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(role));
|
||||
}
|
||||
return Task.FromResult(role.NormalizedName);
|
||||
}
|
||||
|
||||
public virtual Task SetNormalizedRoleNameAsync(TRole role, string normalizedName, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
ThrowIfDisposed();
|
||||
if (role == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(role));
|
||||
}
|
||||
role.NormalizedName = normalizedName;
|
||||
return Task.FromResult(0);
|
||||
}
|
||||
|
||||
private void ThrowIfDisposed()
|
||||
|
|
@ -203,7 +246,7 @@ namespace Microsoft.AspNet.Identity.EntityFramework
|
|||
throw new ArgumentNullException("role");
|
||||
}
|
||||
|
||||
return await RoleClaims.Where(rc => rc.RoleId.Equals(role.Id)).Select(c => new Claim(c.ClaimType, c.ClaimValue)).ToListAsync();
|
||||
return await RoleClaims.Where(rc => rc.RoleId.Equals(role.Id)).Select(c => new Claim(c.ClaimType, c.ClaimValue)).ToListAsync(cancellationToken);
|
||||
}
|
||||
|
||||
public Task AddClaimAsync(TRole role, Claim claim, CancellationToken cancellationToken = default(CancellationToken))
|
||||
|
|
@ -218,7 +261,7 @@ namespace Microsoft.AspNet.Identity.EntityFramework
|
|||
throw new ArgumentNullException("claim");
|
||||
}
|
||||
|
||||
return RoleClaims.AddAsync(new IdentityRoleClaim<TKey> { RoleId = role.Id, ClaimType = claim.Type, ClaimValue = claim.Value });
|
||||
return RoleClaims.AddAsync(new IdentityRoleClaim<TKey> { RoleId = role.Id, ClaimType = claim.Type, ClaimValue = claim.Value }, cancellationToken);
|
||||
}
|
||||
|
||||
public async Task RemoveClaimAsync(TRole role, Claim claim, CancellationToken cancellationToken = default(CancellationToken))
|
||||
|
|
@ -232,7 +275,7 @@ namespace Microsoft.AspNet.Identity.EntityFramework
|
|||
{
|
||||
throw new ArgumentNullException("claim");
|
||||
}
|
||||
var claims = await RoleClaims.Where(uc => uc.ClaimValue == claim.Value && uc.ClaimType == claim.Type).ToListAsync();
|
||||
var claims = await RoleClaims.Where(uc => uc.ClaimValue == claim.Value && uc.ClaimType == claim.Type).ToListAsync(cancellationToken);
|
||||
foreach (var c in claims)
|
||||
{
|
||||
RoleClaims.Remove(c);
|
||||
|
|
|
|||
|
|
@ -5,23 +5,23 @@ using System;
|
|||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Linq.Expressions;
|
||||
using System.Security.Claims;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Data.Entity;
|
||||
using Microsoft.Data.Entity.Update;
|
||||
|
||||
namespace Microsoft.AspNet.Identity.EntityFramework
|
||||
{
|
||||
public class UserStore : UserStore<IdentityUser>
|
||||
{
|
||||
public UserStore(DbContext context) : base(context) { }
|
||||
public UserStore(DbContext context, IdentityErrorDescriber describer = null) : base(context, describer) { }
|
||||
}
|
||||
|
||||
public class UserStore<TUser> : UserStore<TUser, IdentityRole, DbContext>
|
||||
where TUser : IdentityUser, new()
|
||||
{
|
||||
public UserStore(DbContext context) : base(context) { }
|
||||
public UserStore(DbContext context, IdentityErrorDescriber describer = null) : base(context, describer) { }
|
||||
}
|
||||
|
||||
public class UserStore<TUser, TRole, TContext> : UserStore<TUser, TRole, TContext, string>
|
||||
|
|
@ -29,7 +29,7 @@ namespace Microsoft.AspNet.Identity.EntityFramework
|
|||
where TRole : IdentityRole, new()
|
||||
where TContext : DbContext
|
||||
{
|
||||
public UserStore(TContext context) : base(context) { }
|
||||
public UserStore(TContext context, IdentityErrorDescriber describer = null) : base(context, describer) { }
|
||||
}
|
||||
|
||||
public class UserStore<TUser, TRole, TContext, TKey> :
|
||||
|
|
@ -49,19 +49,25 @@ namespace Microsoft.AspNet.Identity.EntityFramework
|
|||
where TKey : IEquatable<TKey>
|
||||
{
|
||||
|
||||
public UserStore(TContext context)
|
||||
public UserStore(TContext context, IdentityErrorDescriber describer = null)
|
||||
{
|
||||
if (context == null)
|
||||
{
|
||||
throw new ArgumentNullException("context");
|
||||
}
|
||||
Context = context;
|
||||
ErrorDescriber = describer ?? new IdentityErrorDescriber();
|
||||
}
|
||||
|
||||
private bool _disposed;
|
||||
|
||||
public TContext Context { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Used to generate public API error messages
|
||||
/// </summary>
|
||||
public IdentityErrorDescriber ErrorDescriber { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// If true will call SaveChanges after CreateAsync/UpdateAsync/DeleteAsync
|
||||
/// </summary>
|
||||
|
|
@ -72,15 +78,7 @@ namespace Microsoft.AspNet.Identity.EntityFramework
|
|||
return AutoSaveChanges ? Context.SaveChangesAsync(cancellationToken) : Task.FromResult(0);
|
||||
}
|
||||
|
||||
protected virtual Task<TUser> GetUserAggregate(Expression<Func<TUser, bool>> filter, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
return Users.FirstOrDefaultAsync(filter, cancellationToken);
|
||||
// TODO: .Include(u => u.Roles)
|
||||
//.Include(u => u.Claims)
|
||||
//.Include(u => u.Logins);
|
||||
}
|
||||
|
||||
public Task<string> GetUserIdAsync(TUser user, CancellationToken cancellationToken = default(CancellationToken))
|
||||
public virtual Task<string> GetUserIdAsync(TUser user, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
ThrowIfDisposed();
|
||||
|
|
@ -91,7 +89,7 @@ namespace Microsoft.AspNet.Identity.EntityFramework
|
|||
return Task.FromResult(ConvertIdToString(user.Id));
|
||||
}
|
||||
|
||||
public Task<string> GetUserNameAsync(TUser user, CancellationToken cancellationToken = default(CancellationToken))
|
||||
public virtual Task<string> GetUserNameAsync(TUser user, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
ThrowIfDisposed();
|
||||
|
|
@ -102,7 +100,7 @@ namespace Microsoft.AspNet.Identity.EntityFramework
|
|||
return Task.FromResult(user.UserName);
|
||||
}
|
||||
|
||||
public Task SetUserNameAsync(TUser user, string userName, CancellationToken cancellationToken = default(CancellationToken))
|
||||
public virtual Task SetUserNameAsync(TUser user, string userName, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
ThrowIfDisposed();
|
||||
|
|
@ -114,7 +112,7 @@ namespace Microsoft.AspNet.Identity.EntityFramework
|
|||
return Task.FromResult(0);
|
||||
}
|
||||
|
||||
public Task<string> GetNormalizedUserNameAsync(TUser user, CancellationToken cancellationToken = default(CancellationToken))
|
||||
public virtual Task<string> GetNormalizedUserNameAsync(TUser user, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
ThrowIfDisposed();
|
||||
|
|
@ -125,7 +123,7 @@ namespace Microsoft.AspNet.Identity.EntityFramework
|
|||
return Task.FromResult(user.NormalizedUserName);
|
||||
}
|
||||
|
||||
public Task SetNormalizedUserNameAsync(TUser user, string normalizedName, CancellationToken cancellationToken = default(CancellationToken))
|
||||
public virtual Task SetNormalizedUserNameAsync(TUser user, string normalizedName, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
ThrowIfDisposed();
|
||||
|
|
@ -137,7 +135,7 @@ namespace Microsoft.AspNet.Identity.EntityFramework
|
|||
return Task.FromResult(0);
|
||||
}
|
||||
|
||||
public async virtual Task CreateAsync(TUser user, CancellationToken cancellationToken = default(CancellationToken))
|
||||
public async virtual Task<IdentityResult> CreateAsync(TUser user, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
ThrowIfDisposed();
|
||||
|
|
@ -147,9 +145,10 @@ namespace Microsoft.AspNet.Identity.EntityFramework
|
|||
}
|
||||
await Context.AddAsync(user, cancellationToken);
|
||||
await SaveChanges(cancellationToken);
|
||||
return IdentityResult.Success;
|
||||
}
|
||||
|
||||
public async virtual Task UpdateAsync(TUser user, CancellationToken cancellationToken = default(CancellationToken))
|
||||
public async virtual Task<IdentityResult> UpdateAsync(TUser user, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
ThrowIfDisposed();
|
||||
|
|
@ -157,11 +156,22 @@ namespace Microsoft.AspNet.Identity.EntityFramework
|
|||
{
|
||||
throw new ArgumentNullException("user");
|
||||
}
|
||||
|
||||
Context.Attach(user);
|
||||
user.ConcurrencyStamp = Guid.NewGuid().ToString();
|
||||
Context.Update(user);
|
||||
await SaveChanges(cancellationToken);
|
||||
try
|
||||
{
|
||||
await SaveChanges(cancellationToken);
|
||||
}
|
||||
catch (DbUpdateConcurrencyException)
|
||||
{
|
||||
return IdentityResult.Failed(ErrorDescriber.ConcurrencyFailure());
|
||||
}
|
||||
return IdentityResult.Success;
|
||||
}
|
||||
|
||||
public async virtual Task DeleteAsync(TUser user, CancellationToken cancellationToken = default(CancellationToken))
|
||||
public async virtual Task<IdentityResult> DeleteAsync(TUser user, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
ThrowIfDisposed();
|
||||
|
|
@ -169,8 +179,17 @@ namespace Microsoft.AspNet.Identity.EntityFramework
|
|||
{
|
||||
throw new ArgumentNullException("user");
|
||||
}
|
||||
|
||||
Context.Remove(user);
|
||||
await SaveChanges(cancellationToken);
|
||||
try
|
||||
{
|
||||
await SaveChanges(cancellationToken);
|
||||
}
|
||||
catch (DbUpdateConcurrencyException)
|
||||
{
|
||||
return IdentityResult.Failed(ErrorDescriber.ConcurrencyFailure());
|
||||
}
|
||||
return IdentityResult.Success;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -184,7 +203,7 @@ namespace Microsoft.AspNet.Identity.EntityFramework
|
|||
cancellationToken.ThrowIfCancellationRequested();
|
||||
ThrowIfDisposed();
|
||||
var id = ConvertIdFromString(userId);
|
||||
return GetUserAggregate(u => u.Id.Equals(id), cancellationToken);
|
||||
return Users.FirstOrDefaultAsync(u => u.Id.Equals(id), cancellationToken);
|
||||
}
|
||||
|
||||
public virtual TKey ConvertIdFromString(string id)
|
||||
|
|
@ -215,7 +234,7 @@ namespace Microsoft.AspNet.Identity.EntityFramework
|
|||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
ThrowIfDisposed();
|
||||
return GetUserAggregate(u => u.NormalizedUserName == normalizedUserName, cancellationToken);
|
||||
return Users.FirstOrDefaultAsync(u => u.NormalizedUserName == normalizedUserName, cancellationToken);
|
||||
}
|
||||
|
||||
public IQueryable<TUser> Users
|
||||
|
|
@ -290,16 +309,13 @@ namespace Microsoft.AspNet.Identity.EntityFramework
|
|||
{
|
||||
throw new ArgumentException(Resources.ValueCannotBeNullOrEmpty, "roleName");
|
||||
}
|
||||
var roleEntity = await Roles.SingleOrDefaultAsync(r => r.Name.ToUpper() == roleName.ToUpper());
|
||||
var roleEntity = await Roles.SingleOrDefaultAsync(r => r.Name.ToUpper() == roleName.ToUpper(), cancellationToken);
|
||||
if (roleEntity == null)
|
||||
{
|
||||
throw new InvalidOperationException(String.Format(CultureInfo.CurrentCulture, Resources.RoleNotFound, roleName));
|
||||
}
|
||||
var ur = new IdentityUserRole<TKey> { UserId = user.Id, RoleId = roleEntity.Id };
|
||||
// TODO: rely on fixup?
|
||||
await UserRoles.AddAsync(ur);
|
||||
user.Roles.Add(ur);
|
||||
roleEntity.Users.Add(ur);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -321,14 +337,13 @@ namespace Microsoft.AspNet.Identity.EntityFramework
|
|||
{
|
||||
throw new ArgumentException(Resources.ValueCannotBeNullOrEmpty, "roleName");
|
||||
}
|
||||
var roleEntity = await Roles.SingleOrDefaultAsync(r => r.Name.ToUpper() == roleName.ToUpper());
|
||||
var roleEntity = await Roles.SingleOrDefaultAsync(r => r.Name.ToUpper() == roleName.ToUpper(), cancellationToken);
|
||||
if (roleEntity != null)
|
||||
{
|
||||
var userRole = await UserRoles.FirstOrDefaultAsync(r => roleEntity.Id.Equals(r.RoleId) && r.UserId.Equals(user.Id));
|
||||
var userRole = await UserRoles.FirstOrDefaultAsync(r => roleEntity.Id.Equals(r.RoleId) && r.UserId.Equals(user.Id), cancellationToken);
|
||||
if (userRole != null)
|
||||
{
|
||||
UserRoles.Remove(userRole);
|
||||
user.Roles.Remove(userRole);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -339,7 +354,7 @@ namespace Microsoft.AspNet.Identity.EntityFramework
|
|||
/// <param name="user"></param>
|
||||
/// <param name="cancellationToken"></param>
|
||||
/// <returns></returns>
|
||||
public virtual Task<IList<string>> GetRolesAsync(TUser user, CancellationToken cancellationToken = default(CancellationToken))
|
||||
public virtual async Task<IList<string>> GetRolesAsync(TUser user, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
ThrowIfDisposed();
|
||||
|
|
@ -348,12 +363,11 @@ namespace Microsoft.AspNet.Identity.EntityFramework
|
|||
throw new ArgumentNullException("user");
|
||||
}
|
||||
var userId = user.Id;
|
||||
// TODO: var query = from userRole in UserRoles
|
||||
var query = from userRole in user.Roles
|
||||
var query = from userRole in UserRoles
|
||||
join role in Roles on userRole.RoleId equals role.Id
|
||||
where userRole.UserId.Equals(userId)
|
||||
select role.Name;
|
||||
//return await query.ToListAsync();
|
||||
return Task.FromResult<IList<string>>(query.ToList());
|
||||
return await query.ToListAsync();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -371,18 +385,16 @@ namespace Microsoft.AspNet.Identity.EntityFramework
|
|||
{
|
||||
throw new ArgumentNullException("user");
|
||||
}
|
||||
if (String.IsNullOrWhiteSpace(roleName))
|
||||
if (string.IsNullOrWhiteSpace(roleName))
|
||||
{
|
||||
throw new ArgumentException(Resources.ValueCannotBeNullOrEmpty, "roleName");
|
||||
}
|
||||
var role = await Roles.SingleOrDefaultAsync(r => r.Name.ToUpper() == roleName.ToUpper());
|
||||
var role = await Roles.SingleOrDefaultAsync(r => r.Name.ToUpper() == roleName.ToUpper(), cancellationToken);
|
||||
if (role != null)
|
||||
{
|
||||
var userId = user.Id;
|
||||
var roleId = role.Id;
|
||||
return user.Roles.Any(ur => ur.RoleId.Equals(roleId));
|
||||
//return await UserRoles.AnyAsync(ur => ur.RoleId.Equals(roleId) && ur.UserId.Equals(userId));
|
||||
//return UserRoles.Any(ur => ur.RoleId.Equals(roleId) && ur.UserId.Equals(userId));
|
||||
return await UserRoles.AnyAsync(ur => ur.RoleId.Equals(roleId) && ur.UserId.Equals(userId));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
|
@ -408,7 +420,7 @@ namespace Microsoft.AspNet.Identity.EntityFramework
|
|||
private DbSet<IdentityUserRole<TKey>> UserRoles { get { return Context.Set<IdentityUserRole<TKey>>(); } }
|
||||
private DbSet<IdentityUserLogin<TKey>> UserLogins { get { return Context.Set<IdentityUserLogin<TKey>>(); } }
|
||||
|
||||
public async Task<IList<Claim>> GetClaimsAsync(TUser user, CancellationToken cancellationToken = default(CancellationToken))
|
||||
public async virtual Task<IList<Claim>> GetClaimsAsync(TUser user, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
ThrowIfDisposed();
|
||||
if (user == null)
|
||||
|
|
@ -416,10 +428,10 @@ namespace Microsoft.AspNet.Identity.EntityFramework
|
|||
throw new ArgumentNullException("user");
|
||||
}
|
||||
|
||||
return await UserClaims.Where(uc => uc.UserId.Equals(user.Id)).Select(c => new Claim(c.ClaimType, c.ClaimValue)).ToListAsync();
|
||||
return await UserClaims.Where(uc => uc.UserId.Equals(user.Id)).Select(c => new Claim(c.ClaimType, c.ClaimValue)).ToListAsync(cancellationToken);
|
||||
}
|
||||
|
||||
public async Task AddClaimsAsync(TUser user, IEnumerable<Claim> claims, CancellationToken cancellationToken = default(CancellationToken))
|
||||
public async virtual Task AddClaimsAsync(TUser user, IEnumerable<Claim> claims, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
ThrowIfDisposed();
|
||||
if (user == null)
|
||||
|
|
@ -432,11 +444,11 @@ namespace Microsoft.AspNet.Identity.EntityFramework
|
|||
}
|
||||
foreach (var claim in claims)
|
||||
{
|
||||
await UserClaims.AddAsync(new IdentityUserClaim<TKey> { UserId = user.Id, ClaimType = claim.Type, ClaimValue = claim.Value });
|
||||
await UserClaims.AddAsync(new IdentityUserClaim<TKey> { UserId = user.Id, ClaimType = claim.Type, ClaimValue = claim.Value }, cancellationToken);
|
||||
}
|
||||
}
|
||||
|
||||
public async Task ReplaceClaimAsync(TUser user, Claim claim, Claim newClaim, CancellationToken cancellationToken = default(CancellationToken))
|
||||
public async virtual Task ReplaceClaimAsync(TUser user, Claim claim, Claim newClaim, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
ThrowIfDisposed();
|
||||
if (user == null)
|
||||
|
|
@ -452,15 +464,15 @@ namespace Microsoft.AspNet.Identity.EntityFramework
|
|||
throw new ArgumentNullException("newClaim");
|
||||
}
|
||||
|
||||
var matchedClaims = await UserClaims.Where(uc => uc.ClaimValue == claim.Value && uc.ClaimType == claim.Type).ToListAsync();
|
||||
foreach(var matchedClaim in matchedClaims)
|
||||
var matchedClaims = await UserClaims.Where(uc => uc.UserId.Equals(user.Id) && uc.ClaimValue == claim.Value && uc.ClaimType == claim.Type).ToListAsync(cancellationToken);
|
||||
foreach (var matchedClaim in matchedClaims)
|
||||
{
|
||||
matchedClaim.ClaimValue = newClaim.Value;
|
||||
matchedClaim.ClaimType = newClaim.Type;
|
||||
}
|
||||
}
|
||||
|
||||
public async Task RemoveClaimsAsync(TUser user, IEnumerable<Claim> claims, CancellationToken cancellationToken = default(CancellationToken))
|
||||
public async virtual Task RemoveClaimsAsync(TUser user, IEnumerable<Claim> claims, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
ThrowIfDisposed();
|
||||
if (user == null)
|
||||
|
|
@ -471,8 +483,9 @@ namespace Microsoft.AspNet.Identity.EntityFramework
|
|||
{
|
||||
throw new ArgumentNullException("claims");
|
||||
}
|
||||
foreach (var claim in claims) {
|
||||
var matchedClaims = await UserClaims.Where(uc => uc.ClaimValue == claim.Value && uc.ClaimType == claim.Type).ToListAsync();
|
||||
foreach (var claim in claims)
|
||||
{
|
||||
var matchedClaims = await UserClaims.Where(uc => uc.UserId.Equals(user.Id) && uc.ClaimValue == claim.Value && uc.ClaimType == claim.Type).ToListAsync(cancellationToken);
|
||||
foreach (var c in matchedClaims)
|
||||
{
|
||||
UserClaims.Remove(c);
|
||||
|
|
@ -502,7 +515,6 @@ namespace Microsoft.AspNet.Identity.EntityFramework
|
|||
};
|
||||
// TODO: fixup so we don't have to update both
|
||||
await UserLogins.AddAsync(l);
|
||||
user.Logins.Add(l);
|
||||
}
|
||||
|
||||
public virtual async Task RemoveLoginAsync(TUser user, string loginProvider, string providerKey,
|
||||
|
|
@ -515,12 +527,10 @@ namespace Microsoft.AspNet.Identity.EntityFramework
|
|||
throw new ArgumentNullException("user");
|
||||
}
|
||||
var userId = user.Id;
|
||||
// todo: ensure logins loaded
|
||||
var entry = await UserLogins.SingleOrDefaultAsync(l => l.UserId.Equals(userId) && l.LoginProvider == loginProvider && l.ProviderKey == providerKey);
|
||||
var entry = await UserLogins.SingleOrDefaultAsync(l => l.UserId.Equals(userId) && l.LoginProvider == loginProvider && l.ProviderKey == providerKey, cancellationToken);
|
||||
if (entry != null)
|
||||
{
|
||||
UserLogins.Remove(entry);
|
||||
user.Logins.Remove(entry);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -532,13 +542,9 @@ namespace Microsoft.AspNet.Identity.EntityFramework
|
|||
{
|
||||
throw new ArgumentNullException("user");
|
||||
}
|
||||
// todo: ensure logins loaded
|
||||
//IList<UserLoginInfo> result = user.Logins
|
||||
// .Select(l => new UserLoginInfo(l.LoginProvider, l.ProviderKey, l.ProviderDisplayName)).ToList();
|
||||
var userId = user.Id;
|
||||
|
||||
return await UserLogins.Where(l => l.UserId.Equals(userId))
|
||||
.Select(l => new UserLoginInfo(l.LoginProvider, l.ProviderKey, l.ProviderDisplayName)).ToListAsync();
|
||||
.Select(l => new UserLoginInfo(l.LoginProvider, l.ProviderKey, l.ProviderDisplayName)).ToListAsync(cancellationToken);
|
||||
}
|
||||
|
||||
public async virtual Task<TUser> FindByLoginAsync(string loginProvider, string providerKey,
|
||||
|
|
@ -546,12 +552,11 @@ namespace Microsoft.AspNet.Identity.EntityFramework
|
|||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
ThrowIfDisposed();
|
||||
// todo: ensure logins loaded
|
||||
var userLogin = await
|
||||
UserLogins.FirstOrDefaultAsync(l => l.LoginProvider == loginProvider && l.ProviderKey == providerKey);
|
||||
UserLogins.FirstOrDefaultAsync(l => l.LoginProvider == loginProvider && l.ProviderKey == providerKey, cancellationToken);
|
||||
if (userLogin != null)
|
||||
{
|
||||
return await GetUserAggregate(u => u.Id.Equals(userLogin.UserId), cancellationToken);
|
||||
return await Users.FirstOrDefaultAsync(u => u.Id.Equals(userLogin.UserId), cancellationToken);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
|
@ -628,19 +633,40 @@ namespace Microsoft.AspNet.Identity.EntityFramework
|
|||
return Task.FromResult(user.Email);
|
||||
}
|
||||
|
||||
public virtual Task<string> GetNormalizedEmailAsync(TUser user, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
ThrowIfDisposed();
|
||||
if (user == null)
|
||||
{
|
||||
throw new ArgumentNullException("user");
|
||||
}
|
||||
return Task.FromResult(user.NormalizedEmail);
|
||||
}
|
||||
|
||||
public virtual Task SetNormalizedEmailAsync(TUser user, string normalizedEmail, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
ThrowIfDisposed();
|
||||
if (user == null)
|
||||
{
|
||||
throw new ArgumentNullException("user");
|
||||
}
|
||||
user.NormalizedEmail = normalizedEmail;
|
||||
return Task.FromResult(0);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Find an user by email
|
||||
/// </summary>
|
||||
/// <param name="email"></param>
|
||||
/// <param name="cancellationToken"></param>
|
||||
/// <returns></returns>
|
||||
public virtual Task<TUser> FindByEmailAsync(string email, CancellationToken cancellationToken = default(CancellationToken))
|
||||
public virtual Task<TUser> FindByEmailAsync(string normalizedEmail, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
ThrowIfDisposed();
|
||||
return GetUserAggregate(u => u.Email == email, cancellationToken);
|
||||
// todo: ToUpper blows up with Null Ref
|
||||
//return GetUserAggregate(u => u.Email.ToUpper() == email.ToUpper(), cancellationToken);
|
||||
return Users.FirstOrDefaultAsync(u => u.NormalizedEmail == normalizedEmail, cancellationToken);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -913,5 +939,58 @@ namespace Microsoft.AspNet.Identity.EntityFramework
|
|||
}
|
||||
return Task.FromResult(user.TwoFactorEnabled);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get all users with given claim
|
||||
/// </summary>
|
||||
/// <param name="claim"></param>
|
||||
/// <param name="cancellationToken"></param>
|
||||
/// <returns></returns>
|
||||
public async virtual Task<IList<TUser>> GetUsersForClaimAsync(Claim claim, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
ThrowIfDisposed();
|
||||
if (claim == null)
|
||||
{
|
||||
throw new ArgumentNullException("claim");
|
||||
}
|
||||
|
||||
var query = from userclaims in UserClaims
|
||||
join user in Users on userclaims.UserId equals user.Id
|
||||
where userclaims.ClaimValue == claim.Value
|
||||
&& userclaims.ClaimType == claim.Type
|
||||
select user;
|
||||
|
||||
return await query.ToListAsync(cancellationToken);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get all users in given role
|
||||
/// </summary>
|
||||
/// <param name="roleName"></param>
|
||||
/// <param name="cancellationToken"></param>
|
||||
/// <returns></returns>
|
||||
public async virtual Task<IList<TUser>> GetUsersInRoleAsync(string roleName, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
ThrowIfDisposed();
|
||||
if (String.IsNullOrEmpty(roleName))
|
||||
{
|
||||
throw new ArgumentNullException("role");
|
||||
}
|
||||
|
||||
var role = await Roles.Where(x => x.Name.Equals(roleName)).FirstOrDefaultAsync(cancellationToken);
|
||||
|
||||
if (role != null)
|
||||
{
|
||||
var query = from userrole in UserRoles
|
||||
join user in Users on userrole.UserId equals user.Id
|
||||
where userrole.RoleId.Equals(role.Id)
|
||||
select user;
|
||||
|
||||
return await query.ToListAsync(cancellationToken);
|
||||
}
|
||||
return new List<TUser>();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -2,15 +2,21 @@
|
|||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
|
||||
using Microsoft.AspNet.Identity;
|
||||
|
||||
namespace Microsoft.AspNet.Builder
|
||||
{
|
||||
/// <summary>
|
||||
/// Startup extensions
|
||||
/// Identity extensions for <see cref="IApplicationBuilder"/>.
|
||||
/// </summary>
|
||||
public static class BuilderExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Enables the ASP.NET identity for the current application.
|
||||
/// </summary>
|
||||
/// <param name="app">The <see cref="IApplicationBuilder"/> instance this method extends.</param>
|
||||
/// <returns>The <see cref="IApplicationBuilder"/> instance this method extends.</returns>
|
||||
public static IApplicationBuilder UseIdentity(this IApplicationBuilder app)
|
||||
{
|
||||
if (app == null)
|
||||
|
|
|
|||
|
|
@ -6,15 +6,16 @@ using System.Security.Claims;
|
|||
namespace System.Security.Principal
|
||||
{
|
||||
/// <summary>
|
||||
/// Extensions making it easier to get the user name/user id claims off of an identity
|
||||
/// Claims related extensions for <see cref="IIdentity"/>.
|
||||
/// </summary>
|
||||
public static class ClaimsIdentityExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Return the user name using the UserNameClaimType
|
||||
/// Returns the Name claim value if present otherwise returns null.
|
||||
/// </summary>
|
||||
/// <param name="identity"></param>
|
||||
/// <returns></returns>
|
||||
/// <param name="identity">The <see cref="IIdentity"/> instance this method extends.</param>
|
||||
/// <returns>The Name claim value, or null if the claim is not present.</returns>
|
||||
/// <remarks>The name claim is identified by <see cref="ClaimsIdentity.DefaultNameClaimType"/>.</remarks>
|
||||
public static string GetUserName(this IIdentity identity)
|
||||
{
|
||||
if (identity == null)
|
||||
|
|
@ -26,10 +27,11 @@ namespace System.Security.Principal
|
|||
}
|
||||
|
||||
/// <summary>
|
||||
/// Return the user id using the UserIdClaimType
|
||||
/// Returns the User ID claim value if present otherwise returns null.
|
||||
/// </summary>
|
||||
/// <param name="identity"></param>
|
||||
/// <returns></returns>
|
||||
/// <param name="identity">The <see cref="IIdentity"/> instance this method extends.</param>
|
||||
/// <returns>The User ID claim value, or null if the claim is not present.</returns>
|
||||
/// <remarks>The name claim is identified by <see cref="ClaimTypes.NameIdentifier"/>.</remarks>
|
||||
public static string GetUserId(this IIdentity identity)
|
||||
{
|
||||
if (identity == null)
|
||||
|
|
@ -41,11 +43,11 @@ namespace System.Security.Principal
|
|||
}
|
||||
|
||||
/// <summary>
|
||||
/// Return the claim value for the first claim with the specified type if it exists, null otherwise
|
||||
/// Returns the value for the first claim of the specified type otherwise null the claim is not present.
|
||||
/// </summary>
|
||||
/// <param name="identity"></param>
|
||||
/// <param name="claimType"></param>
|
||||
/// <returns></returns>
|
||||
/// <param name="identity">The <see cref="IIdentity"/> instance this method extends.</param>
|
||||
/// <param name="claimType">The claim type whose first value should be returned.</param>
|
||||
/// <returns>The value of the first instance of the specifed claim type, or null if the claim is not present.</returns>
|
||||
public static string FindFirstValue(this ClaimsIdentity identity, string claimType)
|
||||
{
|
||||
if (identity == null)
|
||||
|
|
|
|||
|
|
@ -5,19 +5,29 @@ using System;
|
|||
using System.Security.Claims;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
using Microsoft.Framework.OptionsModel;
|
||||
|
||||
namespace Microsoft.AspNet.Identity
|
||||
{
|
||||
/// <summary>
|
||||
/// Creates a ClaimsIdentity from a User
|
||||
/// Provides methods to create a claims identity for a given user.
|
||||
/// </summary>
|
||||
/// <typeparam name="TUser"></typeparam>
|
||||
/// <typeparam name="TUser">The type used to represent a user.</typeparam>
|
||||
/// <typeparam name="TRole">The type used to represent a role.</typeparam>
|
||||
public class ClaimsIdentityFactory<TUser, TRole> : IClaimsIdentityFactory<TUser>
|
||||
where TUser : class
|
||||
where TRole : class
|
||||
{
|
||||
public ClaimsIdentityFactory(UserManager<TUser> userManager, RoleManager<TRole> roleManager,
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="ClaimsIdentityFactory"/> class.
|
||||
/// </summary>
|
||||
/// <param name="userManager">The <see cref="UserManager{TUser}"/> to retrieve user information from.</param>
|
||||
/// <param name="roleManager">The <see cref="RoleManager{TRole}"/> to retrieve a user's roles from.</param>
|
||||
/// <param name="optionsAccessor">The configured <see cref="IdentityOptions"/>.</param>
|
||||
public ClaimsIdentityFactory(
|
||||
UserManager<TUser> userManager,
|
||||
RoleManager<TRole> roleManager,
|
||||
IOptions<IdentityOptions> optionsAccessor)
|
||||
{
|
||||
if (userManager == null)
|
||||
|
|
@ -37,19 +47,38 @@ namespace Microsoft.AspNet.Identity
|
|||
Options = optionsAccessor.Options;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the <see cref="UserManager{TUser}"/> for this factory.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The current <see cref="UserManager{TUser}"/> for this factory instance.
|
||||
/// </value>
|
||||
public UserManager<TUser> UserManager { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the <see cref="RoleManager{TRole}"/> for this factory.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The current <see cref="RoleManager{TRole}"/> for this factory instance.
|
||||
/// </value>
|
||||
public RoleManager<TRole> RoleManager { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the <see cref="IdentityOptions"/> for this factory.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The current <see cref="IdentityOptions"/> for this factory instance.
|
||||
/// </value>
|
||||
public IdentityOptions Options { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// CreateAsync a ClaimsIdentity from a user
|
||||
/// Creates a populated <see cref="ClaimsIdentity"/> for the specified <paramref name="user"/>.
|
||||
/// </summary>
|
||||
/// <param name="manager"></param>
|
||||
/// <param name="user"></param>
|
||||
/// <param name="authenticationType"></param>
|
||||
/// <param name="cancellationToken"></param>
|
||||
/// <returns></returns>
|
||||
public virtual async Task<ClaimsIdentity> CreateAsync(TUser user,
|
||||
/// <param name="user">The user instance to create claims on.</param>
|
||||
/// <param name="cancellationToken">A <see cref="CancellationToken"/> to observe while waiting for the tasks to complete.</param>
|
||||
/// <returns>A <see cref="Task{TResult}"/> that represents the started task.</returns>
|
||||
public virtual async Task<ClaimsIdentity> CreateAsync(
|
||||
TUser user,
|
||||
CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
if (user == null)
|
||||
|
|
|
|||
|
|
@ -5,28 +5,41 @@ using System.Security.Claims;
|
|||
|
||||
namespace Microsoft.AspNet.Identity
|
||||
{
|
||||
/// <summary>
|
||||
/// Options for ClaimType names.
|
||||
/// </summary>
|
||||
public class ClaimsIdentityOptions
|
||||
{
|
||||
public static readonly string DefaultSecurityStampClaimType = "AspNet.Identity.SecurityStamp";
|
||||
|
||||
/// <summary>
|
||||
/// Claim type used for role claims
|
||||
/// Gets the ClaimType used for a Role claim.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This defaults to <see cref="ClaimTypes.Role"/>.
|
||||
/// </remarks>
|
||||
public string RoleClaimType { get; set; } = ClaimTypes.Role;
|
||||
|
||||
/// <summary>
|
||||
/// Claim type used for the user name
|
||||
/// Gets the ClaimType used for the user name claim.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This defaults to <see cref="ClaimTypes.Name"/>.
|
||||
/// </remarks>
|
||||
public string UserNameClaimType { get; set; } = ClaimTypes.Name;
|
||||
|
||||
/// <summary>
|
||||
/// Claim type used for the user id
|
||||
/// Gets the ClaimType used for the user identifier claim.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This defaults to <see cref="ClaimTypes.NameIdentifier"/>.
|
||||
/// </remarks>
|
||||
public string UserIdClaimType { get; set; } = ClaimTypes.NameIdentifier;
|
||||
|
||||
/// <summary>
|
||||
/// Claim type used for the user security stamp
|
||||
/// Gets the ClaimType used for the security stamp claim..
|
||||
/// </summary>
|
||||
public string SecurityStampClaimType { get; set; } = DefaultSecurityStampClaimType;
|
||||
/// <remarks>
|
||||
/// This defaults to "AspNet.Identity.SecurityStamp".
|
||||
/// </remarks>
|
||||
public string SecurityStampClaimType { get; set; } = "AspNet.Identity.SecurityStamp";
|
||||
}
|
||||
}
|
||||
|
|
@ -1,51 +1,71 @@
|
|||
using Microsoft.AspNet.Security.DataProtection;
|
||||
using Microsoft.Framework.OptionsModel;
|
||||
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
using Microsoft.AspNet.Security.DataProtection;
|
||||
using Microsoft.Framework.OptionsModel;
|
||||
|
||||
namespace Microsoft.AspNet.Identity
|
||||
{
|
||||
public class DataProtectionTokenProviderOptions
|
||||
{
|
||||
public string Name { get; set; } = "DataProtection";
|
||||
public TimeSpan TokenLifespan { get; set; } = TimeSpan.FromDays(1);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Token provider that uses an IDataProtector to generate encrypted tokens based off of the security stamp
|
||||
/// Provides protection and validation of identity tokens.
|
||||
/// </summary>
|
||||
/// <typeparam name="TUser">The type used to represent a user.</typeparam>
|
||||
public class DataProtectorTokenProvider<TUser> : IUserTokenProvider<TUser> where TUser : class
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="DataProtectorTokenProvider{TUser}"/> class.
|
||||
/// </summary>
|
||||
/// <param name="dataProtectionProvider">The system data protection provider.</param>
|
||||
/// <param name="options">The configured <see cref="DataProtectionTokenProviderOptions"/>.</param>
|
||||
public DataProtectorTokenProvider(IDataProtectionProvider dataProtectionProvider, IOptions<DataProtectionTokenProviderOptions> options)
|
||||
{
|
||||
if (options == null || options.Options == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(options));
|
||||
}
|
||||
if (dataProtectionProvider == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(dataProtectionProvider));
|
||||
}
|
||||
Options = options.Options;
|
||||
Options = options?.Options ?? new DataProtectionTokenProviderOptions();
|
||||
// Use the Name as the purpose which should usually be distinct from others
|
||||
Protector = dataProtectionProvider.CreateProtector(Name ?? "DataProtectorTokenProvider");
|
||||
}
|
||||
|
||||
public DataProtectionTokenProviderOptions Options { get; private set; }
|
||||
public IDataProtector Protector { get; private set; }
|
||||
/// <summary>
|
||||
/// Gets the <see cref="DataProtectionTokenProviderOptions"/> for this instance.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The <see cref="DataProtectionTokenProviderOptions"/> for this instance.
|
||||
/// </value>
|
||||
protected DataProtectionTokenProviderOptions Options { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the <see cref="IDataProtector"/> for this instance.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The <see cref="IDataProtector"/> for this instance.
|
||||
/// </value>
|
||||
protected IDataProtector Protector { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the name of this instance.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The name of this instance.
|
||||
/// </value>
|
||||
public string Name { get { return Options.Name; } }
|
||||
|
||||
/// <summary>
|
||||
/// Generate a protected string for a user
|
||||
/// Generates a protected token for the specified <paramref name="User"/>.
|
||||
/// </summary>
|
||||
/// <param name="purpose"></param>
|
||||
/// <param name="manager"></param>
|
||||
/// <param name="user"></param>
|
||||
/// <returns></returns>
|
||||
/// <param name="purpose">The purpose the token will be used for.</param>
|
||||
/// <param name="manager">The <see cref="UserManager{TUser}"/> to retrieve user properties from.</param>
|
||||
/// <param name="user">The <see cref="TUser"/> the token will be generated from.</param>
|
||||
/// <param name="cancellationToken">A <see cref="CancellationToken"/> to observe while waiting for the tasks to complete.</param>
|
||||
/// <returns>A <see cref="Task{TResult}"/> that contains the protected token.</returns>
|
||||
public async Task<string> GenerateAsync(string purpose, UserManager<TUser> manager, TUser user,
|
||||
CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
|
|
@ -72,13 +92,14 @@ namespace Microsoft.AspNet.Identity
|
|||
}
|
||||
|
||||
/// <summary>
|
||||
/// Return false if the token is not valid
|
||||
/// Validates the protected <paramref name="token"/> for the specified <paramref name="user"/> and <paramref name="purpose"/>.
|
||||
/// </summary>
|
||||
/// <param name="purpose"></param>
|
||||
/// <param name="token"></param>
|
||||
/// <param name="manager"></param>
|
||||
/// <param name="user"></param>
|
||||
/// <returns></returns>
|
||||
/// <param name="purpose">The purpose the token was be used for.</param>
|
||||
/// <param name="token">The token to validate.</param>
|
||||
/// <param name="manager">The <see cref="UserManager{TUser}"/> to retrieve user properties from.</param>
|
||||
/// <param name="user">The <see cref="TUser"/> the token was generated for.</param>
|
||||
/// <param name="cancellationToken">A <see cref="CancellationToken"/> to observe while waiting for the tasks to complete.</param>
|
||||
/// <returns>A <see cref="Task{TResult}"/> that is true if the token is valid, otherwise false.</returns>
|
||||
public async Task<bool> ValidateAsync(string purpose, string token, UserManager<TUser> manager, TUser user,
|
||||
CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
|
|
@ -128,11 +149,13 @@ namespace Microsoft.AspNet.Identity
|
|||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns false because tokens are two long to be used for two factor
|
||||
/// Returns a <see cref="boolean"/> indicating whether a token generated by this instance
|
||||
/// can be used as a Two Factor Authentication token.
|
||||
/// </summary>
|
||||
/// <param name="manager"></param>
|
||||
/// <param name="user"></param>
|
||||
/// <returns></returns>
|
||||
/// <param name="manager">The <see cref="UserManager{TUser}"/> to retrieve user properties from.</param>
|
||||
/// <param name="user">The <see cref="TUser"/> the token was generated for.</param>
|
||||
/// <returns>True if a token generated by this instance can be used as a Two Factor Authentication token, otherwise false.</returns>
|
||||
/// <remarks>This method will always return false for instances of <see cref="DataProtectorTokenProvider{TUser}"/>.</remarks>
|
||||
public Task<bool> CanGenerateTwoFactorTokenAsync(UserManager<TUser> manager, TUser user,
|
||||
CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
|
|
@ -140,12 +163,13 @@ namespace Microsoft.AspNet.Identity
|
|||
}
|
||||
|
||||
/// <summary>
|
||||
/// This provider no-ops by default when asked to notify a user
|
||||
/// Creates a notification task for A <paramref name="user"/> based on the supplied <paramref name="token"/>.
|
||||
/// </summary>
|
||||
/// <param name="token"></param>
|
||||
/// <param name="manager"></param>
|
||||
/// <param name="user"></param>
|
||||
/// <returns></returns>
|
||||
/// <param name="token">The token to generate notifications for..</param>
|
||||
/// <param name="manager">The <see cref="UserManager{TUser}"/> to retrieve user properties from.</param>
|
||||
/// <param name="user">The <see cref="TUser"/> the token was generated for.</param>
|
||||
/// <param name="cancellationToken">A <see cref="CancellationToken"/> to observe while waiting for the tasks to complete.</param>
|
||||
/// <returns>A <see cref="Task{TResult}"/> that represents the started task.</returns>
|
||||
public Task NotifyAsync(string token, UserManager<TUser> manager, TUser user,
|
||||
CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
|
|
@ -153,7 +177,9 @@ namespace Microsoft.AspNet.Identity
|
|||
}
|
||||
}
|
||||
|
||||
// Based on Levi's authentication sample
|
||||
/// <summary>
|
||||
/// Utility extensions to streams
|
||||
/// </summary>
|
||||
internal static class StreamExtensions
|
||||
{
|
||||
internal static readonly Encoding DefaultEncoding = new UTF8Encoding(false, true);
|
||||
|
|
|
|||
|
|
@ -0,0 +1,29 @@
|
|||
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
|
||||
namespace Microsoft.AspNet.Identity
|
||||
{
|
||||
/// <summary>
|
||||
/// Contains options for the <see cref="DataProtectorTokenProvider{TUser}"/>.
|
||||
/// </summary>
|
||||
public class DataProtectionTokenProviderOptions
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the name of the <see cref="DataProtectorTokenProvider{TUser}"/>.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The name of the <see cref="DataProtectorTokenProvider{TUser}"/>.
|
||||
/// </value>
|
||||
public string Name { get; set; } = "DataProtectorTokenProvider";
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the amount of time a generated token remains valid.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The amount of time a generated token remains valid.
|
||||
/// </value>
|
||||
public TimeSpan TokenLifespan { get; set; } = TimeSpan.FromDays(1);
|
||||
}
|
||||
}
|
||||
|
|
@ -4,15 +4,15 @@
|
|||
namespace Microsoft.AspNet.Identity
|
||||
{
|
||||
/// <summary>
|
||||
/// Used to normalize a user name
|
||||
/// Used to normalize keys for consistent lookups
|
||||
/// </summary>
|
||||
public interface IUserNameNormalizer
|
||||
public interface ILookupNormalizer
|
||||
{
|
||||
/// <summary>
|
||||
/// Returns the normalized user name
|
||||
/// Returns the normalized key
|
||||
/// </summary>
|
||||
/// <param name="userName"></param>
|
||||
/// <param name="key"></param>
|
||||
/// <returns></returns>
|
||||
string Normalize(string userName);
|
||||
string Normalize(string key);
|
||||
}
|
||||
}
|
||||
|
|
@ -19,7 +19,7 @@ namespace Microsoft.AspNet.Identity
|
|||
/// <param name="role"></param>
|
||||
/// <param name="cancellationToken"></param>
|
||||
/// <returns></returns>
|
||||
Task CreateAsync(TRole role, CancellationToken cancellationToken = default(CancellationToken));
|
||||
Task<IdentityResult> CreateAsync(TRole role, CancellationToken cancellationToken = default(CancellationToken));
|
||||
|
||||
/// <summary>
|
||||
/// Update a role
|
||||
|
|
@ -27,7 +27,7 @@ namespace Microsoft.AspNet.Identity
|
|||
/// <param name="role"></param>
|
||||
/// <param name="cancellationToken"></param>
|
||||
/// <returns></returns>
|
||||
Task UpdateAsync(TRole role, CancellationToken cancellationToken = default(CancellationToken));
|
||||
Task<IdentityResult> UpdateAsync(TRole role, CancellationToken cancellationToken = default(CancellationToken));
|
||||
|
||||
/// <summary>
|
||||
/// DeleteAsync a role
|
||||
|
|
@ -35,7 +35,7 @@ namespace Microsoft.AspNet.Identity
|
|||
/// <param name="role"></param>
|
||||
/// <param name="cancellationToken"></param>
|
||||
/// <returns></returns>
|
||||
Task DeleteAsync(TRole role, CancellationToken cancellationToken = default(CancellationToken));
|
||||
Task<IdentityResult> DeleteAsync(TRole role, CancellationToken cancellationToken = default(CancellationToken));
|
||||
|
||||
/// <summary>
|
||||
/// Returns a role's id
|
||||
|
|
@ -63,6 +63,26 @@ namespace Microsoft.AspNet.Identity
|
|||
Task SetRoleNameAsync(TRole role, string roleName,
|
||||
CancellationToken cancellationToken = default(CancellationToken));
|
||||
|
||||
/// <summary>
|
||||
/// Get a role's normalized name
|
||||
/// </summary>
|
||||
/// <param name="role"></param>
|
||||
/// <param name="cancellationToken"></param>
|
||||
/// <returns></returns>
|
||||
Task<string> GetNormalizedRoleNameAsync(TRole role,
|
||||
CancellationToken cancellationToken = default(CancellationToken));
|
||||
|
||||
/// <summary>
|
||||
/// Set a role's normalized name
|
||||
/// </summary>
|
||||
/// <param name="role"></param>
|
||||
/// <param name="normalizedName"></param>
|
||||
/// <param name="cancellationToken"></param>
|
||||
/// <returns></returns>
|
||||
Task SetNormalizedRoleNameAsync(TRole role, string normalizedName,
|
||||
CancellationToken cancellationToken = default(CancellationToken));
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Finds a role by id
|
||||
/// </summary>
|
||||
|
|
@ -72,11 +92,11 @@ namespace Microsoft.AspNet.Identity
|
|||
Task<TRole> FindByIdAsync(string roleId, CancellationToken cancellationToken = default(CancellationToken));
|
||||
|
||||
/// <summary>
|
||||
/// Find a role by name
|
||||
/// Find a role by normalized name
|
||||
/// </summary>
|
||||
/// <param name="roleName"></param>
|
||||
/// <param name="normalizedRoleName"></param>
|
||||
/// <param name="cancellationToken"></param>
|
||||
/// <returns></returns>
|
||||
Task<TRole> FindByNameAsync(string roleName, CancellationToken cancellationToken = default(CancellationToken));
|
||||
Task<TRole> FindByNameAsync(string normalizedRoleName, CancellationToken cancellationToken = default(CancellationToken));
|
||||
}
|
||||
}
|
||||
|
|
@ -51,5 +51,13 @@ namespace Microsoft.AspNet.Identity
|
|||
/// <returns></returns>
|
||||
Task RemoveClaimsAsync(TUser user, IEnumerable<Claim> claims,
|
||||
CancellationToken cancellationToken = default(CancellationToken));
|
||||
|
||||
/// <summary>
|
||||
/// Get users having a specific claim
|
||||
/// </summary>
|
||||
/// <param name="claim">Claim to look up</param>
|
||||
/// <param name="cancellationToken"></param>
|
||||
/// <returns></returns>
|
||||
Task<IList<TUser>> GetUsersForClaimAsync(Claim claim, CancellationToken cancellationToken = default(CancellationToken));
|
||||
}
|
||||
}
|
||||
|
|
@ -51,9 +51,28 @@ namespace Microsoft.AspNet.Identity
|
|||
/// <summary>
|
||||
/// Returns the user associated with this email
|
||||
/// </summary>
|
||||
/// <param name="email"></param>
|
||||
/// <param name="normalizedEmail"></param>
|
||||
/// <param name="cancellationToken"></param>
|
||||
/// <returns></returns>
|
||||
Task<TUser> FindByEmailAsync(string email, CancellationToken cancellationToken = default(CancellationToken));
|
||||
Task<TUser> FindByEmailAsync(string normalizedEmail, CancellationToken cancellationToken = default(CancellationToken));
|
||||
|
||||
/// <summary>
|
||||
/// Returns the normalized email
|
||||
/// </summary>
|
||||
/// <param name="user"></param>
|
||||
/// <param name="cancellationToken"></param>
|
||||
/// <returns></returns>
|
||||
Task<string> GetNormalizedEmailAsync(TUser user, CancellationToken cancellationToken = default(CancellationToken));
|
||||
|
||||
/// <summary>
|
||||
/// Set the normalized email
|
||||
/// </summary>
|
||||
/// <param name="user"></param>
|
||||
/// <param name="normalizedEmail"></param>
|
||||
/// <param name="cancellationToken"></param>
|
||||
/// <returns></returns>
|
||||
Task SetNormalizedEmailAsync(TUser user, string normalizedEmail,
|
||||
CancellationToken cancellationToken = default(CancellationToken));
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -51,5 +51,13 @@ namespace Microsoft.AspNet.Identity
|
|||
/// <returns></returns>
|
||||
Task<bool> IsInRoleAsync(TUser user, string roleName,
|
||||
CancellationToken cancellationToken = default(CancellationToken));
|
||||
|
||||
/// <summary>
|
||||
/// Returns all users in given role
|
||||
/// </summary>
|
||||
/// <param name="roleName"></param>
|
||||
/// <param name="cancellationToken"></param>
|
||||
/// <returns></returns>
|
||||
Task<IList<TUser>> GetUsersInRoleAsync(string roleName, CancellationToken cancellationToken = default(CancellationToken));
|
||||
}
|
||||
}
|
||||
|
|
@ -63,7 +63,7 @@ namespace Microsoft.AspNet.Identity
|
|||
/// <param name="user"></param>
|
||||
/// <param name="cancellationToken"></param>
|
||||
/// <returns></returns>
|
||||
Task CreateAsync(TUser user, CancellationToken cancellationToken = default(CancellationToken));
|
||||
Task<IdentityResult> CreateAsync(TUser user, CancellationToken cancellationToken = default(CancellationToken));
|
||||
|
||||
/// <summary>
|
||||
/// UpdateAsync a user
|
||||
|
|
@ -71,7 +71,7 @@ namespace Microsoft.AspNet.Identity
|
|||
/// <param name="user"></param>
|
||||
/// <param name="cancellationToken"></param>
|
||||
/// <returns></returns>
|
||||
Task UpdateAsync(TUser user, CancellationToken cancellationToken = default(CancellationToken));
|
||||
Task<IdentityResult> UpdateAsync(TUser user, CancellationToken cancellationToken = default(CancellationToken));
|
||||
|
||||
/// <summary>
|
||||
/// DeleteAsync a user
|
||||
|
|
@ -79,7 +79,7 @@ namespace Microsoft.AspNet.Identity
|
|||
/// <param name="user"></param>
|
||||
/// <param name="cancellationToken"></param>
|
||||
/// <returns></returns>
|
||||
Task DeleteAsync(TUser user, CancellationToken cancellationToken = default(CancellationToken));
|
||||
Task<IdentityResult> DeleteAsync(TUser user, CancellationToken cancellationToken = default(CancellationToken));
|
||||
|
||||
/// <summary>
|
||||
/// Finds a user
|
||||
|
|
|
|||
|
|
@ -35,6 +35,12 @@ namespace Microsoft.AspNet.Identity
|
|||
return AddScoped(typeof(IRoleValidator<>).MakeGenericType(RoleType), typeof(T));
|
||||
}
|
||||
|
||||
public IdentityBuilder AddErrorDescriber<TDescriber>() where TDescriber : IdentityErrorDescriber
|
||||
{
|
||||
Services.AddScoped<IdentityErrorDescriber, TDescriber>();
|
||||
return this;
|
||||
}
|
||||
|
||||
public IdentityBuilder AddPasswordValidator<T>() where T : class
|
||||
{
|
||||
return AddScoped(typeof(IPasswordValidator<>).MakeGenericType(UserType), typeof(T));
|
||||
|
|
@ -76,5 +82,15 @@ namespace Microsoft.AspNet.Identity
|
|||
.AddTokenProvider(typeof(PhoneNumberTokenProvider<>).MakeGenericType(UserType))
|
||||
.AddTokenProvider(typeof(EmailTokenProvider<>).MakeGenericType(UserType));
|
||||
}
|
||||
|
||||
public IdentityBuilder AddUserManager<TUserManager>() where TUserManager : class
|
||||
{
|
||||
return AddScoped(typeof(UserManager<>).MakeGenericType(UserType), typeof(TUserManager));
|
||||
}
|
||||
|
||||
public IdentityBuilder AddRoleManager<TRoleManager>() where TRoleManager : class
|
||||
{
|
||||
return AddScoped(typeof(RoleManager<>).MakeGenericType(RoleType), typeof(TRoleManager));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -3,12 +3,9 @@
|
|||
|
||||
namespace Microsoft.AspNet.Identity
|
||||
{
|
||||
public enum SignInStatus
|
||||
public class IdentityError
|
||||
{
|
||||
Success,
|
||||
LockedOut,
|
||||
RequiresVerification,
|
||||
NotAllowed,
|
||||
Failure
|
||||
public string Code { get; set; }
|
||||
public string Description { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,189 @@
|
|||
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
namespace Microsoft.AspNet.Identity
|
||||
{
|
||||
public class IdentityErrorDescriber
|
||||
{
|
||||
public static IdentityErrorDescriber Default = new IdentityErrorDescriber();
|
||||
|
||||
public virtual IdentityError DefaultError()
|
||||
{
|
||||
return new IdentityError
|
||||
{
|
||||
Code = nameof(DefaultError),
|
||||
Description = Resources.DefaultError
|
||||
};
|
||||
}
|
||||
public virtual IdentityError ConcurrencyFailure()
|
||||
{
|
||||
return new IdentityError
|
||||
{
|
||||
Code = nameof(ConcurrencyFailure),
|
||||
Description = Resources.ConcurrencyFailure
|
||||
};
|
||||
}
|
||||
|
||||
public virtual IdentityError PasswordMismatch()
|
||||
{
|
||||
return new IdentityError
|
||||
{
|
||||
Code = nameof(PasswordMismatch),
|
||||
Description = Resources.PasswordMismatch
|
||||
};
|
||||
}
|
||||
|
||||
public virtual IdentityError InvalidToken()
|
||||
{
|
||||
return new IdentityError
|
||||
{
|
||||
Code = nameof(InvalidToken),
|
||||
Description = Resources.InvalidToken
|
||||
};
|
||||
}
|
||||
|
||||
public virtual IdentityError LoginAlreadyAssociated()
|
||||
{
|
||||
return new IdentityError
|
||||
{
|
||||
Code = nameof(LoginAlreadyAssociated),
|
||||
Description = Resources.LoginAlreadyAssociated
|
||||
};
|
||||
}
|
||||
|
||||
public virtual IdentityError InvalidUserName(string name)
|
||||
{
|
||||
return new IdentityError
|
||||
{
|
||||
Code = nameof(InvalidUserName),
|
||||
Description = Resources.FormatInvalidUserName(name)
|
||||
};
|
||||
}
|
||||
|
||||
public virtual IdentityError InvalidEmail(string email)
|
||||
{
|
||||
return new IdentityError
|
||||
{
|
||||
Code = nameof(InvalidEmail),
|
||||
Description = Resources.FormatInvalidEmail(email)
|
||||
};
|
||||
}
|
||||
|
||||
public virtual IdentityError DuplicateUserName(string name)
|
||||
{
|
||||
return new IdentityError
|
||||
{
|
||||
Code = nameof(DuplicateUserName),
|
||||
Description = Resources.FormatDuplicateUserName(name)
|
||||
};
|
||||
}
|
||||
|
||||
public virtual IdentityError DuplicateEmail(string email)
|
||||
{
|
||||
return new IdentityError
|
||||
{
|
||||
Code = nameof(DuplicateEmail),
|
||||
Description = Resources.FormatDuplicateEmail(email)
|
||||
};
|
||||
}
|
||||
|
||||
public virtual IdentityError InvalidRoleName(string name)
|
||||
{
|
||||
return new IdentityError
|
||||
{
|
||||
Code = nameof(InvalidRoleName),
|
||||
Description = Resources.FormatInvalidRoleName(name)
|
||||
};
|
||||
}
|
||||
|
||||
public virtual IdentityError DuplicateRoleName(string name)
|
||||
{
|
||||
return new IdentityError
|
||||
{
|
||||
Code = nameof(DuplicateRoleName),
|
||||
Description = Resources.FormatDuplicateRoleName(name)
|
||||
};
|
||||
}
|
||||
|
||||
public virtual IdentityError UserAlreadyHasPassword()
|
||||
{
|
||||
return new IdentityError
|
||||
{
|
||||
Code = nameof(UserAlreadyHasPassword),
|
||||
Description = Resources.UserAlreadyHasPassword
|
||||
};
|
||||
}
|
||||
|
||||
public virtual IdentityError UserLockoutNotEnabled()
|
||||
{
|
||||
return new IdentityError
|
||||
{
|
||||
Code = nameof(UserLockoutNotEnabled),
|
||||
Description = Resources.UserLockoutNotEnabled
|
||||
};
|
||||
}
|
||||
|
||||
public virtual IdentityError UserAlreadyInRole(string role)
|
||||
{
|
||||
return new IdentityError
|
||||
{
|
||||
Code = nameof(UserAlreadyInRole),
|
||||
Description = Resources.FormatUserAlreadyInRole(role)
|
||||
};
|
||||
}
|
||||
|
||||
public virtual IdentityError UserNotInRole(string role)
|
||||
{
|
||||
return new IdentityError
|
||||
{
|
||||
Code = nameof(UserNotInRole),
|
||||
Description = Resources.FormatUserNotInRole(role)
|
||||
};
|
||||
}
|
||||
|
||||
public virtual IdentityError PasswordTooShort(int length)
|
||||
{
|
||||
return new IdentityError
|
||||
{
|
||||
Code = nameof(PasswordTooShort),
|
||||
Description = Resources.FormatPasswordTooShort(length)
|
||||
};
|
||||
}
|
||||
|
||||
public virtual IdentityError PasswordRequiresNonLetterAndDigit()
|
||||
{
|
||||
return new IdentityError
|
||||
{
|
||||
Code = nameof(PasswordRequiresNonLetterAndDigit),
|
||||
Description = Resources.PasswordRequiresNonLetterAndDigit
|
||||
};
|
||||
}
|
||||
|
||||
public virtual IdentityError PasswordRequiresDigit()
|
||||
{
|
||||
return new IdentityError
|
||||
{
|
||||
Code = nameof(PasswordRequiresDigit),
|
||||
Description = Resources.PasswordRequiresDigit
|
||||
};
|
||||
}
|
||||
|
||||
public virtual IdentityError PasswordRequiresLower()
|
||||
{
|
||||
return new IdentityError
|
||||
{
|
||||
Code = nameof(PasswordRequiresLower),
|
||||
Description = Resources.PasswordRequiresLower
|
||||
};
|
||||
}
|
||||
|
||||
public virtual IdentityError PasswordRequiresUpper()
|
||||
{
|
||||
return new IdentityError
|
||||
{
|
||||
Code = nameof(PasswordRequiresUpper),
|
||||
Description = Resources.PasswordRequiresUpper
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -3,6 +3,7 @@
|
|||
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Microsoft.Framework.Logging;
|
||||
|
||||
namespace Microsoft.AspNet.Identity
|
||||
{
|
||||
|
|
@ -11,45 +12,19 @@ namespace Microsoft.AspNet.Identity
|
|||
/// </summary>
|
||||
public class IdentityResult
|
||||
{
|
||||
private static readonly IdentityResult _success = new IdentityResult(true);
|
||||
private static readonly IdentityResult _success = new IdentityResult { Succeeded = true };
|
||||
|
||||
/// <summary>
|
||||
/// Failure constructor that takes error messages
|
||||
/// </summary>
|
||||
/// <param name="errors"></param>
|
||||
public IdentityResult(params string[] errors) : this((IEnumerable<string>)errors)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Failure constructor that takes error messages
|
||||
/// </summary>
|
||||
/// <param name="errors"></param>
|
||||
public IdentityResult(IEnumerable<string> errors)
|
||||
{
|
||||
if (errors == null || !errors.Any())
|
||||
{
|
||||
errors = new[] { Resources.DefaultError };
|
||||
}
|
||||
Succeeded = false;
|
||||
Errors = errors;
|
||||
}
|
||||
|
||||
protected IdentityResult(bool success)
|
||||
{
|
||||
Succeeded = success;
|
||||
Errors = new string[0];
|
||||
}
|
||||
private List<IdentityError> _errors = new List<IdentityError>();
|
||||
|
||||
/// <summary>
|
||||
/// True if the operation was successful
|
||||
/// </summary>
|
||||
public bool Succeeded { get; private set; }
|
||||
public bool Succeeded { get; protected set; }
|
||||
|
||||
/// <summary>
|
||||
/// List of errors
|
||||
/// </summary>
|
||||
public IEnumerable<string> Errors { get; private set; }
|
||||
public IEnumerable<IdentityError> Errors { get { return _errors; } }
|
||||
|
||||
/// <summary>
|
||||
/// Static success result
|
||||
|
|
@ -65,9 +40,32 @@ namespace Microsoft.AspNet.Identity
|
|||
/// </summary>
|
||||
/// <param name="errors"></param>
|
||||
/// <returns></returns>
|
||||
public static IdentityResult Failed(params string[] errors)
|
||||
public static IdentityResult Failed(params IdentityError[] errors)
|
||||
{
|
||||
return new IdentityResult(errors);
|
||||
var result = new IdentityResult { Succeeded = false };
|
||||
if (errors != null)
|
||||
{
|
||||
result._errors.AddRange(errors);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Log Identity result
|
||||
/// </summary>
|
||||
/// <param name="logger"></param>
|
||||
/// <param name="message"></param>
|
||||
public virtual void Log(ILogger logger, string message)
|
||||
{
|
||||
// TODO: Take logging level as a parameter
|
||||
if (Succeeded)
|
||||
{
|
||||
logger.WriteInformation(Resources.FormatLogIdentityResultSuccess(message));
|
||||
}
|
||||
else
|
||||
{
|
||||
logger.WriteWarning(Resources.FormatLogIdentityResultFailure(message, string.Join(",", Errors.Select(x => x.Code).ToList())));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -65,5 +65,11 @@ namespace Microsoft.AspNet.Identity
|
|||
/// Role name
|
||||
/// </summary>
|
||||
public virtual string Name { get; set; }
|
||||
public virtual string NormalizedName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// A random value that should change whenever a role is persisted to the store
|
||||
/// </summary>
|
||||
public virtual string ConcurrencyStamp { get; set; } = Guid.NewGuid().ToString();
|
||||
}
|
||||
}
|
||||
|
|
@ -57,8 +57,10 @@ namespace Microsoft.Framework.DependencyInjection
|
|||
services.TryAdd(describe.Transient<IUserValidator<TUser>, UserValidator<TUser>>());
|
||||
services.TryAdd(describe.Transient<IPasswordValidator<TUser>, PasswordValidator<TUser>>());
|
||||
services.TryAdd(describe.Transient<IPasswordHasher<TUser>, PasswordHasher<TUser>>());
|
||||
services.TryAdd(describe.Transient<IUserNameNormalizer, UpperInvariantUserNameNormalizer>());
|
||||
services.TryAdd(describe.Transient<ILookupNormalizer, UpperInvariantLookupNormalizer>());
|
||||
services.TryAdd(describe.Transient<IRoleValidator<TRole>, RoleValidator<TRole>>());
|
||||
// No interface for the error describer so we can add errors without rev'ing the interface
|
||||
services.TryAdd(describe.Transient<IdentityErrorDescriber, IdentityErrorDescriber>());
|
||||
services.TryAdd(describe.Scoped<ISecurityStampValidator, SecurityStampValidator<TUser>>());
|
||||
services.TryAdd(describe.Scoped<IClaimsIdentityFactory<TUser>, ClaimsIdentityFactory<TUser, TRole>>());
|
||||
services.TryAdd(describe.Scoped<UserManager<TUser>, UserManager<TUser>>());
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@
|
|||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Microsoft.AspNet.Identity
|
||||
{
|
||||
|
|
@ -37,6 +36,8 @@ namespace Microsoft.AspNet.Identity
|
|||
/// </summary>
|
||||
public virtual string Email { get; set; }
|
||||
|
||||
public virtual string NormalizedEmail { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// True if the email is confirmed, default is false
|
||||
/// </summary>
|
||||
|
|
@ -52,6 +53,11 @@ namespace Microsoft.AspNet.Identity
|
|||
/// </summary>
|
||||
public virtual string SecurityStamp { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// A random value that should change whenever a user is persisted to the store
|
||||
/// </summary>
|
||||
public virtual string ConcurrencyStamp { get; set; } = Guid.NewGuid().ToString();
|
||||
|
||||
/// <summary>
|
||||
/// PhoneNumber for the user
|
||||
/// </summary>
|
||||
|
|
@ -81,20 +87,5 @@ namespace Microsoft.AspNet.Identity
|
|||
/// Used to record failures for the purposes of lockout
|
||||
/// </summary>
|
||||
public virtual int AccessFailedCount { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Roles for the user
|
||||
/// </summary>
|
||||
public virtual ICollection<IdentityUserRole<TKey>> Roles { get; } = new List<IdentityUserRole<TKey>>();
|
||||
|
||||
/// <summary>
|
||||
/// Claims for the user
|
||||
/// </summary>
|
||||
public virtual ICollection<IdentityUserClaim<TKey>> Claims { get; } = new List<IdentityUserClaim<TKey>>();
|
||||
|
||||
/// <summary>
|
||||
/// Associated logins for the user
|
||||
/// </summary>
|
||||
public virtual ICollection<IdentityUserLogin<TKey>> Logins { get; } = new List<IdentityUserLogin<TKey>>();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">14.0</VisualStudioVersion>
|
||||
|
|
@ -13,5 +13,13 @@
|
|||
<PropertyGroup>
|
||||
<SchemaVersion>2.0</SchemaVersion>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
|
||||
<ProduceOutputsOnBuild>False</ProduceOutputsOnBuild>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VSToolsPath)\AspNet\Microsoft.Web.AspNet.targets" Condition="'$(VSToolsPath)' != ''" />
|
||||
</Project>
|
||||
<ProjectExtensions>
|
||||
<VisualStudio>
|
||||
<UserProperties project_1json__JSONSchema="http://www.asp.net/media/4878834/project.json" />
|
||||
</VisualStudio>
|
||||
</ProjectExtensions>
|
||||
</Project>
|
||||
|
|
@ -37,14 +37,11 @@ namespace Microsoft.AspNet.Identity
|
|||
/// Constructs a PasswordHasher using the specified options
|
||||
/// </summary>
|
||||
/// <param name="options"></param>
|
||||
public PasswordHasher(IOptions<PasswordHasherOptions> options)
|
||||
public PasswordHasher(IOptions<PasswordHasherOptions> optionsAccessor = null)
|
||||
{
|
||||
if (options == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(options));
|
||||
}
|
||||
var options = optionsAccessor?.Options ?? new PasswordHasherOptions();
|
||||
|
||||
_compatibilityMode = options.Options.CompatibilityMode;
|
||||
_compatibilityMode = options.CompatibilityMode;
|
||||
switch (_compatibilityMode)
|
||||
{
|
||||
case PasswordHasherCompatibilityMode.IdentityV2:
|
||||
|
|
@ -52,7 +49,7 @@ namespace Microsoft.AspNet.Identity
|
|||
break;
|
||||
|
||||
case PasswordHasherCompatibilityMode.IdentityV3:
|
||||
_iterCount = options.Options.IterationCount;
|
||||
_iterCount = options.IterationCount;
|
||||
if (_iterCount < 1)
|
||||
{
|
||||
throw new InvalidOperationException(Resources.InvalidPasswordHasherIterationCount);
|
||||
|
|
@ -63,7 +60,7 @@ namespace Microsoft.AspNet.Identity
|
|||
throw new InvalidOperationException(Resources.InvalidPasswordHasherCompatibilityMode);
|
||||
}
|
||||
|
||||
_rng = options.Options.Rng;
|
||||
_rng = options.Rng;
|
||||
}
|
||||
|
||||
// Compares two byte arrays for equality. The method is specifically written so that the loop is not optimized.
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@
|
|||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System.Security.Cryptography;
|
||||
using Microsoft.AspNet.Security.DataProtection;
|
||||
|
||||
namespace Microsoft.AspNet.Identity
|
||||
{
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@
|
|||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
|
@ -15,6 +14,13 @@ namespace Microsoft.AspNet.Identity
|
|||
/// </summary>
|
||||
public class PasswordValidator<TUser> : IPasswordValidator<TUser> where TUser : class
|
||||
{
|
||||
public PasswordValidator(IdentityErrorDescriber errors = null)
|
||||
{
|
||||
Describer = errors ?? new IdentityErrorDescriber();
|
||||
}
|
||||
|
||||
public IdentityErrorDescriber Describer { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Ensures that the password is of the required length and meets the configured requirements
|
||||
/// </summary>
|
||||
|
|
@ -33,33 +39,32 @@ namespace Microsoft.AspNet.Identity
|
|||
{
|
||||
throw new ArgumentNullException("manager");
|
||||
}
|
||||
var errors = new List<string>();
|
||||
var errors = new List<IdentityError>();
|
||||
var options = manager.Options.Password;
|
||||
if (string.IsNullOrWhiteSpace(password) || password.Length < options.RequiredLength)
|
||||
{
|
||||
errors.Add(String.Format(CultureInfo.CurrentCulture, Resources.PasswordTooShort,
|
||||
options.RequiredLength));
|
||||
errors.Add(Describer.PasswordTooShort(options.RequiredLength));
|
||||
}
|
||||
if (options.RequireNonLetterOrDigit && password.All(IsLetterOrDigit))
|
||||
{
|
||||
errors.Add(Resources.PasswordRequireNonLetterOrDigit);
|
||||
errors.Add(Describer.PasswordRequiresNonLetterAndDigit());
|
||||
}
|
||||
if (options.RequireDigit && !password.Any(IsDigit))
|
||||
{
|
||||
errors.Add(Resources.PasswordRequireDigit);
|
||||
errors.Add(Describer.PasswordRequiresDigit());
|
||||
}
|
||||
if (options.RequireLowercase && !password.Any(IsLower))
|
||||
{
|
||||
errors.Add(Resources.PasswordRequireLower);
|
||||
errors.Add(Describer.PasswordRequiresLower());
|
||||
}
|
||||
if (options.RequireUppercase && !password.Any(IsUpper))
|
||||
{
|
||||
errors.Add(Resources.PasswordRequireUpper);
|
||||
errors.Add(Describer.PasswordRequiresUpper());
|
||||
}
|
||||
return
|
||||
Task.FromResult(errors.Count == 0
|
||||
? IdentityResult.Success
|
||||
: IdentityResult.Failed(String.Join(" ", errors)));
|
||||
: IdentityResult.Failed(errors.ToArray()));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
|
|||
|
|
@ -10,6 +10,22 @@ namespace Microsoft.AspNet.Identity
|
|||
private static readonly ResourceManager _resourceManager
|
||||
= new ResourceManager("Microsoft.AspNet.Identity.Resources", typeof(Resources).GetTypeInfo().Assembly);
|
||||
|
||||
/// <summary>
|
||||
/// Optimistic concurrency failure, object has been modified.
|
||||
/// </summary>
|
||||
internal static string ConcurrencyFailure
|
||||
{
|
||||
get { return GetString("ConcurrencyFailure"); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Optimistic concurrency failure, object has been modified.
|
||||
/// </summary>
|
||||
internal static string FormatConcurrencyFailure()
|
||||
{
|
||||
return GetString("ConcurrencyFailure");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Your security code is: {0}
|
||||
/// </summary>
|
||||
|
|
@ -43,7 +59,7 @@ namespace Microsoft.AspNet.Identity
|
|||
}
|
||||
|
||||
/// <summary>
|
||||
/// Security Code
|
||||
/// Security code
|
||||
/// </summary>
|
||||
internal static string DefaultEmailTokenProviderSubject
|
||||
{
|
||||
|
|
@ -51,7 +67,7 @@ namespace Microsoft.AspNet.Identity
|
|||
}
|
||||
|
||||
/// <summary>
|
||||
/// Security Code
|
||||
/// Security code
|
||||
/// </summary>
|
||||
internal static string FormatDefaultEmailTokenProviderSubject()
|
||||
{
|
||||
|
|
@ -107,7 +123,7 @@ namespace Microsoft.AspNet.Identity
|
|||
}
|
||||
|
||||
/// <summary>
|
||||
/// DefaultTokenProvider
|
||||
/// Default Token Provider
|
||||
/// </summary>
|
||||
internal static string DefaultTokenProvider
|
||||
{
|
||||
|
|
@ -115,7 +131,7 @@ namespace Microsoft.AspNet.Identity
|
|||
}
|
||||
|
||||
/// <summary>
|
||||
/// DefaultTokenProvider
|
||||
/// Default Token Provider
|
||||
/// </summary>
|
||||
internal static string FormatDefaultTokenProvider()
|
||||
{
|
||||
|
|
@ -139,35 +155,35 @@ namespace Microsoft.AspNet.Identity
|
|||
}
|
||||
|
||||
/// <summary>
|
||||
/// Name {0} is already taken.
|
||||
/// Role name '{0}' is already taken.
|
||||
/// </summary>
|
||||
internal static string DuplicateName
|
||||
internal static string DuplicateRoleName
|
||||
{
|
||||
get { return GetString("DuplicateName"); }
|
||||
get { return GetString("DuplicateRoleName"); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Name {0} is already taken.
|
||||
/// Role name '{0}' is already taken.
|
||||
/// </summary>
|
||||
internal static string FormatDuplicateName(object p0)
|
||||
internal static string FormatDuplicateRoleName(object p0)
|
||||
{
|
||||
return string.Format(CultureInfo.CurrentCulture, GetString("DuplicateName"), p0);
|
||||
return string.Format(CultureInfo.CurrentCulture, GetString("DuplicateRoleName"), p0);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A user with that external login already exists.
|
||||
/// User name '{0}' is already taken.
|
||||
/// </summary>
|
||||
internal static string ExternalLoginExists
|
||||
internal static string DuplicateUserName
|
||||
{
|
||||
get { return GetString("ExternalLoginExists"); }
|
||||
get { return GetString("DuplicateUserName"); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A user with that external login already exists.
|
||||
/// User name '{0}' is already taken.
|
||||
/// </summary>
|
||||
internal static string FormatExternalLoginExists()
|
||||
internal static string FormatDuplicateUserName(object p0)
|
||||
{
|
||||
return GetString("ExternalLoginExists");
|
||||
return string.Format(CultureInfo.CurrentCulture, GetString("DuplicateUserName"), p0);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -218,6 +234,22 @@ namespace Microsoft.AspNet.Identity
|
|||
return GetString("InvalidPasswordHasherIterationCount");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Role name '{0}' is invalid.
|
||||
/// </summary>
|
||||
internal static string InvalidRoleName
|
||||
{
|
||||
get { return GetString("InvalidRoleName"); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Role name '{0}' is invalid.
|
||||
/// </summary>
|
||||
internal static string FormatInvalidRoleName(object p0)
|
||||
{
|
||||
return string.Format(CultureInfo.CurrentCulture, GetString("InvalidRoleName"), p0);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Invalid token.
|
||||
/// </summary>
|
||||
|
|
@ -235,7 +267,7 @@ namespace Microsoft.AspNet.Identity
|
|||
}
|
||||
|
||||
/// <summary>
|
||||
/// User name {0} is invalid, can only contain letters or digits.
|
||||
/// User name '{0}' is invalid, can only contain letters or digits.
|
||||
/// </summary>
|
||||
internal static string InvalidUserName
|
||||
{
|
||||
|
|
@ -243,7 +275,7 @@ namespace Microsoft.AspNet.Identity
|
|||
}
|
||||
|
||||
/// <summary>
|
||||
/// User name {0} is invalid, can only contain letters or digits.
|
||||
/// User name '{0}' is invalid, can only contain letters or digits.
|
||||
/// </summary>
|
||||
internal static string FormatInvalidUserName(object p0)
|
||||
{
|
||||
|
|
@ -251,19 +283,19 @@ namespace Microsoft.AspNet.Identity
|
|||
}
|
||||
|
||||
/// <summary>
|
||||
/// Lockout is not enabled for this user.
|
||||
/// A user with this login already exists.
|
||||
/// </summary>
|
||||
internal static string LockoutNotEnabled
|
||||
internal static string LoginAlreadyAssociated
|
||||
{
|
||||
get { return GetString("LockoutNotEnabled"); }
|
||||
get { return GetString("LoginAlreadyAssociated"); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Lockout is not enabled for this user.
|
||||
/// A user with this login already exists.
|
||||
/// </summary>
|
||||
internal static string FormatLockoutNotEnabled()
|
||||
internal static string FormatLoginAlreadyAssociated()
|
||||
{
|
||||
return GetString("LockoutNotEnabled");
|
||||
return GetString("LoginAlreadyAssociated");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -317,65 +349,65 @@ namespace Microsoft.AspNet.Identity
|
|||
/// <summary>
|
||||
/// Passwords must have at least one digit ('0'-'9').
|
||||
/// </summary>
|
||||
internal static string PasswordRequireDigit
|
||||
internal static string PasswordRequiresDigit
|
||||
{
|
||||
get { return GetString("PasswordRequireDigit"); }
|
||||
get { return GetString("PasswordRequiresDigit"); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Passwords must have at least one digit ('0'-'9').
|
||||
/// </summary>
|
||||
internal static string FormatPasswordRequireDigit()
|
||||
internal static string FormatPasswordRequiresDigit()
|
||||
{
|
||||
return GetString("PasswordRequireDigit");
|
||||
return GetString("PasswordRequiresDigit");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Passwords must have at least one lowercase ('a'-'z').
|
||||
/// </summary>
|
||||
internal static string PasswordRequireLower
|
||||
internal static string PasswordRequiresLower
|
||||
{
|
||||
get { return GetString("PasswordRequireLower"); }
|
||||
get { return GetString("PasswordRequiresLower"); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Passwords must have at least one lowercase ('a'-'z').
|
||||
/// </summary>
|
||||
internal static string FormatPasswordRequireLower()
|
||||
internal static string FormatPasswordRequiresLower()
|
||||
{
|
||||
return GetString("PasswordRequireLower");
|
||||
return GetString("PasswordRequiresLower");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Passwords must have at least one non letter and non digit character.
|
||||
/// </summary>
|
||||
internal static string PasswordRequireNonLetterOrDigit
|
||||
internal static string PasswordRequiresNonLetterAndDigit
|
||||
{
|
||||
get { return GetString("PasswordRequireNonLetterOrDigit"); }
|
||||
get { return GetString("PasswordRequiresNonLetterAndDigit"); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Passwords must have at least one non letter and non digit character.
|
||||
/// </summary>
|
||||
internal static string FormatPasswordRequireNonLetterOrDigit()
|
||||
internal static string FormatPasswordRequiresNonLetterAndDigit()
|
||||
{
|
||||
return GetString("PasswordRequireNonLetterOrDigit");
|
||||
return GetString("PasswordRequiresNonLetterAndDigit");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Passwords must have at least one uppercase ('A'-'Z').
|
||||
/// </summary>
|
||||
internal static string PasswordRequireUpper
|
||||
internal static string PasswordRequiresUpper
|
||||
{
|
||||
get { return GetString("PasswordRequireUpper"); }
|
||||
get { return GetString("PasswordRequiresUpper"); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Passwords must have at least one uppercase ('A'-'Z').
|
||||
/// </summary>
|
||||
internal static string FormatPasswordRequireUpper()
|
||||
internal static string FormatPasswordRequiresUpper()
|
||||
{
|
||||
return GetString("PasswordRequireUpper");
|
||||
return GetString("PasswordRequiresUpper");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -394,22 +426,6 @@ namespace Microsoft.AspNet.Identity
|
|||
return string.Format(CultureInfo.CurrentCulture, GetString("PasswordTooShort"), p0);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// {0} cannot be null or empty.
|
||||
/// </summary>
|
||||
internal static string PropertyTooShort
|
||||
{
|
||||
get { return GetString("PropertyTooShort"); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// {0} cannot be null or empty.
|
||||
/// </summary>
|
||||
internal static string FormatPropertyTooShort(object p0)
|
||||
{
|
||||
return string.Format(CultureInfo.CurrentCulture, GetString("PropertyTooShort"), p0);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Role {0} does not exist.
|
||||
/// </summary>
|
||||
|
|
@ -651,7 +667,7 @@ namespace Microsoft.AspNet.Identity
|
|||
}
|
||||
|
||||
/// <summary>
|
||||
/// User already in role.
|
||||
/// User already in role '{0}'.
|
||||
/// </summary>
|
||||
internal static string UserAlreadyInRole
|
||||
{
|
||||
|
|
@ -659,11 +675,43 @@ namespace Microsoft.AspNet.Identity
|
|||
}
|
||||
|
||||
/// <summary>
|
||||
/// User already in role.
|
||||
/// User already in role '{0}'.
|
||||
/// </summary>
|
||||
internal static string FormatUserAlreadyInRole()
|
||||
internal static string FormatUserAlreadyInRole(object p0)
|
||||
{
|
||||
return GetString("UserAlreadyInRole");
|
||||
return string.Format(CultureInfo.CurrentCulture, GetString("UserAlreadyInRole"), p0);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// User is locked out.
|
||||
/// </summary>
|
||||
internal static string UserLockedOut
|
||||
{
|
||||
get { return GetString("UserLockedOut"); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// User is locked out.
|
||||
/// </summary>
|
||||
internal static string FormatUserLockedOut()
|
||||
{
|
||||
return GetString("UserLockedOut");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Lockout is not enabled for this user.
|
||||
/// </summary>
|
||||
internal static string UserLockoutNotEnabled
|
||||
{
|
||||
get { return GetString("UserLockoutNotEnabled"); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Lockout is not enabled for this user.
|
||||
/// </summary>
|
||||
internal static string FormatUserLockoutNotEnabled()
|
||||
{
|
||||
return GetString("UserLockoutNotEnabled");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -683,7 +731,7 @@ namespace Microsoft.AspNet.Identity
|
|||
}
|
||||
|
||||
/// <summary>
|
||||
/// User is not in role.
|
||||
/// User is not in role '{0}'.
|
||||
/// </summary>
|
||||
internal static string UserNotInRole
|
||||
{
|
||||
|
|
@ -691,11 +739,91 @@ namespace Microsoft.AspNet.Identity
|
|||
}
|
||||
|
||||
/// <summary>
|
||||
/// User is not in role.
|
||||
/// User is not in role '{0}'.
|
||||
/// </summary>
|
||||
internal static string FormatUserNotInRole()
|
||||
internal static string FormatUserNotInRole(object p0)
|
||||
{
|
||||
return GetString("UserNotInRole");
|
||||
return string.Format(CultureInfo.CurrentCulture, GetString("UserNotInRole"), p0);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// {0} : Failed : {1}
|
||||
/// </summary>
|
||||
internal static string LogIdentityResultFailure
|
||||
{
|
||||
get { return GetString("LogIdentityResultFailure"); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// {0} : Failed : {1}
|
||||
/// </summary>
|
||||
internal static string FormatLogIdentityResultFailure(object p0, object p1)
|
||||
{
|
||||
return string.Format(CultureInfo.CurrentCulture, GetString("LogIdentityResultFailure"), p0, p1);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// {0} : Success
|
||||
/// </summary>
|
||||
internal static string LogIdentityResultSuccess
|
||||
{
|
||||
get { return GetString("LogIdentityResultSuccess"); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// {0} : Success
|
||||
/// </summary>
|
||||
internal static string FormatLogIdentityResultSuccess(object p0)
|
||||
{
|
||||
return string.Format(CultureInfo.CurrentCulture, GetString("LogIdentityResultSuccess"), p0);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// {0} : Result : {1}
|
||||
/// </summary>
|
||||
internal static string LoggingSigninResult
|
||||
{
|
||||
get { return GetString("LoggingSigninResult"); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// {0} : Result : {1}
|
||||
/// </summary>
|
||||
internal static string FormatLoggingSigninResult(object p0, object p1)
|
||||
{
|
||||
return string.Format(CultureInfo.CurrentCulture, GetString("LoggingSigninResult"), p0, p1);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// {0} for user: {1}
|
||||
/// </summary>
|
||||
internal static string LoggingResultMessage
|
||||
{
|
||||
get { return GetString("LoggingResultMessage"); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// {0} for user: {1}
|
||||
/// </summary>
|
||||
internal static string FormatLoggingResultMessage(object p0, object p1)
|
||||
{
|
||||
return string.Format(CultureInfo.CurrentCulture, GetString("LoggingResultMessage"), p0, p1);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// {0} for role: {1}
|
||||
/// </summary>
|
||||
internal static string LoggingResultMessageForRole
|
||||
{
|
||||
get { return GetString("LoggingResultMessageForRole"); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// {0} for role: {1}
|
||||
/// </summary>
|
||||
internal static string FormatLoggingResultMessageForRole(object p0, object p1)
|
||||
{
|
||||
return string.Format(CultureInfo.CurrentCulture, GetString("LoggingResultMessageForRole"), p0, p1);
|
||||
}
|
||||
|
||||
private static string GetString(string name, params string[] formatterNames)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,3 @@
|
|||
{
|
||||
"Profiles": []
|
||||
}
|
||||
|
|
@ -117,6 +117,10 @@
|
|||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<data name="ConcurrencyFailure" xml:space="preserve">
|
||||
<value>Optimistic concurrency failure, object has been modified.</value>
|
||||
<comment>Error when optimistic concurrency fails</comment>
|
||||
</data>
|
||||
<data name="DefaultEmailTokenProviderBodyFormat" xml:space="preserve">
|
||||
<value>Your security code is: {0}</value>
|
||||
<comment>Default body format for the email</comment>
|
||||
|
|
@ -126,7 +130,7 @@
|
|||
<comment>Default name for the email token provider</comment>
|
||||
</data>
|
||||
<data name="DefaultEmailTokenProviderSubject" xml:space="preserve">
|
||||
<value>Security Code</value>
|
||||
<value>Security code</value>
|
||||
<comment>Default subject for the email</comment>
|
||||
</data>
|
||||
<data name="DefaultError" xml:space="preserve">
|
||||
|
|
@ -142,24 +146,24 @@
|
|||
<comment>Default name for the phone number token provider</comment>
|
||||
</data>
|
||||
<data name="DefaultTokenProvider" xml:space="preserve">
|
||||
<value>DefaultTokenProvider</value>
|
||||
<value>Default Token Provider</value>
|
||||
<comment>Name of the default token provider</comment>
|
||||
</data>
|
||||
<data name="DuplicateEmail" xml:space="preserve">
|
||||
<value>Email '{0}' is already taken.</value>
|
||||
<comment>error for duplicate emails</comment>
|
||||
<comment>Error for duplicate emails</comment>
|
||||
</data>
|
||||
<data name="DuplicateName" xml:space="preserve">
|
||||
<value>Name {0} is already taken.</value>
|
||||
<comment>error for duplicate usernames</comment>
|
||||
<data name="DuplicateRoleName" xml:space="preserve">
|
||||
<value>Role name '{0}' is already taken.</value>
|
||||
<comment>Error for duplicate user names</comment>
|
||||
</data>
|
||||
<data name="ExternalLoginExists" xml:space="preserve">
|
||||
<value>A user with that external login already exists.</value>
|
||||
<comment>Error when a login already linked</comment>
|
||||
<data name="DuplicateUserName" xml:space="preserve">
|
||||
<value>User name '{0}' is already taken.</value>
|
||||
<comment>Error for duplicate user names</comment>
|
||||
</data>
|
||||
<data name="InvalidEmail" xml:space="preserve">
|
||||
<value>Email '{0}' is invalid.</value>
|
||||
<comment>invalid email</comment>
|
||||
<comment>Invalid email</comment>
|
||||
</data>
|
||||
<data name="InvalidPasswordHasherCompatibilityMode" xml:space="preserve">
|
||||
<value>The provided PasswordHasherCompatibilityMode is invalid.</value>
|
||||
|
|
@ -169,17 +173,21 @@
|
|||
<value>The iteration count must be a positive integer.</value>
|
||||
<comment>Error when the iteration count is < 1.</comment>
|
||||
</data>
|
||||
<data name="InvalidRoleName" xml:space="preserve">
|
||||
<value>Role name '{0}' is invalid.</value>
|
||||
<comment>Error for invalid role names</comment>
|
||||
</data>
|
||||
<data name="InvalidToken" xml:space="preserve">
|
||||
<value>Invalid token.</value>
|
||||
<comment>Error when a token is not recognized</comment>
|
||||
</data>
|
||||
<data name="InvalidUserName" xml:space="preserve">
|
||||
<value>User name {0} is invalid, can only contain letters or digits.</value>
|
||||
<comment>usernames can only contain letters or digits</comment>
|
||||
<value>User name '{0}' is invalid, can only contain letters or digits.</value>
|
||||
<comment>User names can only contain letters or digits</comment>
|
||||
</data>
|
||||
<data name="LockoutNotEnabled" xml:space="preserve">
|
||||
<value>Lockout is not enabled for this user.</value>
|
||||
<comment>error when lockout is not enabled</comment>
|
||||
<data name="LoginAlreadyAssociated" xml:space="preserve">
|
||||
<value>A user with this login already exists.</value>
|
||||
<comment>Error when a login already linked</comment>
|
||||
</data>
|
||||
<data name="NoMessageProvider" xml:space="preserve">
|
||||
<value>No IUserMessageProvider named '{0}' is registered.</value>
|
||||
|
|
@ -193,19 +201,19 @@
|
|||
<value>Incorrect password.</value>
|
||||
<comment>Error when a password doesn't match</comment>
|
||||
</data>
|
||||
<data name="PasswordRequireDigit" xml:space="preserve">
|
||||
<data name="PasswordRequiresDigit" xml:space="preserve">
|
||||
<value>Passwords must have at least one digit ('0'-'9').</value>
|
||||
<comment>Error when passwords do not have a digit</comment>
|
||||
</data>
|
||||
<data name="PasswordRequireLower" xml:space="preserve">
|
||||
<data name="PasswordRequiresLower" xml:space="preserve">
|
||||
<value>Passwords must have at least one lowercase ('a'-'z').</value>
|
||||
<comment>Error when passwords do not have a lowercase letter</comment>
|
||||
</data>
|
||||
<data name="PasswordRequireNonLetterOrDigit" xml:space="preserve">
|
||||
<data name="PasswordRequiresNonLetterAndDigit" xml:space="preserve">
|
||||
<value>Passwords must have at least one non letter and non digit character.</value>
|
||||
<comment>Error when password does not have enough letter or digit characters</comment>
|
||||
</data>
|
||||
<data name="PasswordRequireUpper" xml:space="preserve">
|
||||
<data name="PasswordRequiresUpper" xml:space="preserve">
|
||||
<value>Passwords must have at least one uppercase ('A'-'Z').</value>
|
||||
<comment>Error when passwords do not have an uppercase letter</comment>
|
||||
</data>
|
||||
|
|
@ -213,80 +221,104 @@
|
|||
<value>Passwords must be at least {0} characters.</value>
|
||||
<comment>Error message for passwords that are too short</comment>
|
||||
</data>
|
||||
<data name="PropertyTooShort" xml:space="preserve">
|
||||
<value>{0} cannot be null or empty.</value>
|
||||
<comment>error for empty or null usernames</comment>
|
||||
</data>
|
||||
<data name="RoleNotFound" xml:space="preserve">
|
||||
<value>Role {0} does not exist.</value>
|
||||
<comment>error when a role does not exist</comment>
|
||||
<comment>Error when a role does not exist</comment>
|
||||
</data>
|
||||
<data name="StoreNotIQueryableRoleStore" xml:space="preserve">
|
||||
<value>Store does not implement IQueryableRoleStore<TRole>.</value>
|
||||
<comment>error when the store does not implement this interface</comment>
|
||||
<comment>Error when the store does not implement this interface</comment>
|
||||
</data>
|
||||
<data name="StoreNotIQueryableUserStore" xml:space="preserve">
|
||||
<value>Store does not implement IQueryableUserStore<TUser>.</value>
|
||||
<comment>error when the store does not implement this interface</comment>
|
||||
<comment>Error when the store does not implement this interface</comment>
|
||||
</data>
|
||||
<data name="StoreNotIRoleClaimStore" xml:space="preserve">
|
||||
<value>Store does not implement IRoleClaimStore<TRole>.</value>
|
||||
<comment>error when the store does not implement this interface</comment>
|
||||
<comment>Error when the store does not implement this interface</comment>
|
||||
</data>
|
||||
<data name="StoreNotIUserClaimStore" xml:space="preserve">
|
||||
<value>Store does not implement IUserClaimStore<TUser>.</value>
|
||||
<comment>error when the store does not implement this interface</comment>
|
||||
<comment>Error when the store does not implement this interface</comment>
|
||||
</data>
|
||||
<data name="StoreNotIUserConfirmationStore" xml:space="preserve">
|
||||
<value>Store does not implement IUserConfirmationStore<TUser>.</value>
|
||||
<comment>error when the store does not implement this interface</comment>
|
||||
<comment>Error when the store does not implement this interface</comment>
|
||||
</data>
|
||||
<data name="StoreNotIUserEmailStore" xml:space="preserve">
|
||||
<value>Store does not implement IUserEmailStore<TUser>.</value>
|
||||
<comment>error when the store does not implement this interface</comment>
|
||||
<comment>Error when the store does not implement this interface</comment>
|
||||
</data>
|
||||
<data name="StoreNotIUserLockoutStore" xml:space="preserve">
|
||||
<value>Store does not implement IUserLockoutStore<TUser>.</value>
|
||||
<comment>error when the store does not implement this interface</comment>
|
||||
<comment>Error when the store does not implement this interface</comment>
|
||||
</data>
|
||||
<data name="StoreNotIUserLoginStore" xml:space="preserve">
|
||||
<value>Store does not implement IUserLoginStore<TUser>.</value>
|
||||
<comment>error when the store does not implement this interface</comment>
|
||||
<comment>Error when the store does not implement this interface</comment>
|
||||
</data>
|
||||
<data name="StoreNotIUserPasswordStore" xml:space="preserve">
|
||||
<value>Store does not implement IUserPasswordStore<TUser>.</value>
|
||||
<comment>error when the store does not implement this interface</comment>
|
||||
<comment>Error when the store does not implement this interface</comment>
|
||||
</data>
|
||||
<data name="StoreNotIUserPhoneNumberStore" xml:space="preserve">
|
||||
<value>Store does not implement IUserPhoneNumberStore<TUser>.</value>
|
||||
<comment>error when the store does not implement this interface</comment>
|
||||
<comment>Error when the store does not implement this interface</comment>
|
||||
</data>
|
||||
<data name="StoreNotIUserRoleStore" xml:space="preserve">
|
||||
<value>Store does not implement IUserRoleStore<TUser>.</value>
|
||||
<comment>error when the store does not implement this interface</comment>
|
||||
<comment>Error when the store does not implement this interface</comment>
|
||||
</data>
|
||||
<data name="StoreNotIUserSecurityStampStore" xml:space="preserve">
|
||||
<value>Store does not implement IUserSecurityStampStore<TUser>.</value>
|
||||
<comment>error when the store does not implement this interface</comment>
|
||||
<comment>Error when the store does not implement this interface</comment>
|
||||
</data>
|
||||
<data name="StoreNotIUserTwoFactorStore" xml:space="preserve">
|
||||
<value>Store does not implement IUserTwoFactorStore<TUser>.</value>
|
||||
<comment>error when the store does not implement this interface</comment>
|
||||
<comment>Error when the store does not implement this interface</comment>
|
||||
</data>
|
||||
<data name="UserAlreadyHasPassword" xml:space="preserve">
|
||||
<value>User already has a password set.</value>
|
||||
<comment>error when AddPasswordAsync called when a user already has a password</comment>
|
||||
<comment>Error when AddPasswordAsync called when a user already has a password</comment>
|
||||
</data>
|
||||
<data name="UserAlreadyInRole" xml:space="preserve">
|
||||
<value>User already in role.</value>
|
||||
<value>User already in role '{0}'.</value>
|
||||
<comment>Error when a user is already in a role</comment>
|
||||
</data>
|
||||
<data name="UserLockedOut" xml:space="preserve">
|
||||
<value>User is locked out.</value>
|
||||
<comment>Error when a user is locked out</comment>
|
||||
</data>
|
||||
<data name="UserLockoutNotEnabled" xml:space="preserve">
|
||||
<value>Lockout is not enabled for this user.</value>
|
||||
<comment>Error when lockout is not enabled</comment>
|
||||
</data>
|
||||
<data name="UserNameNotFound" xml:space="preserve">
|
||||
<value>User {0} does not exist.</value>
|
||||
<comment>error when a user does not exist</comment>
|
||||
<comment>Error when a user does not exist</comment>
|
||||
</data>
|
||||
<data name="UserNotInRole" xml:space="preserve">
|
||||
<value>User is not in role.</value>
|
||||
<value>User is not in role '{0}'.</value>
|
||||
<comment>Error when a user is not in the role</comment>
|
||||
</data>
|
||||
<data name="LogIdentityResultFailure" xml:space="preserve">
|
||||
<value>{0} : Failed : {1}</value>
|
||||
<comment>Logging method execution failure</comment>
|
||||
</data>
|
||||
<data name="LogIdentityResultSuccess" xml:space="preserve">
|
||||
<value>{0} : Success</value>
|
||||
<comment>Logging method execution success</comment>
|
||||
</data>
|
||||
<data name="LoggingSigninResult" xml:space="preserve">
|
||||
<value>{0} : Result : {1}</value>
|
||||
<comment>Logging statement for SignInManager</comment>
|
||||
</data>
|
||||
<data name="LoggingResultMessage" xml:space="preserve">
|
||||
<value>{0} for user: {1}</value>
|
||||
<comment>Message prefix for Identity result</comment>
|
||||
</data>
|
||||
<data name="LoggingResultMessageForRole" xml:space="preserve">
|
||||
<value>{0} for role: {1}</value>
|
||||
<comment>Message prefix for Identity result for role operation</comment>
|
||||
</data>
|
||||
</root>
|
||||
|
|
@ -7,7 +7,7 @@ using System.Linq;
|
|||
using System.Security.Claims;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Framework.DependencyInjection;
|
||||
using Microsoft.Framework.Logging;
|
||||
|
||||
namespace Microsoft.AspNet.Identity
|
||||
{
|
||||
|
|
@ -24,13 +24,19 @@ namespace Microsoft.AspNet.Identity
|
|||
/// </summary>
|
||||
/// <param name="store">The IRoleStore commits changes via the UpdateAsync/CreateAsync methods</param>
|
||||
/// <param name="roleValidator"></param>
|
||||
public RoleManager(IRoleStore<TRole> store, IEnumerable<IRoleValidator<TRole>> roleValidators)
|
||||
public RoleManager(IRoleStore<TRole> store,
|
||||
IEnumerable<IRoleValidator<TRole>> roleValidators = null,
|
||||
ILookupNormalizer keyNormalizer = null,
|
||||
IdentityErrorDescriber errors = null,
|
||||
ILoggerFactory loggerFactory = null)
|
||||
{
|
||||
if (store == null)
|
||||
{
|
||||
throw new ArgumentNullException("store");
|
||||
}
|
||||
Store = store;
|
||||
KeyNormalizer = keyNormalizer ?? new UpperInvariantLookupNormalizer();
|
||||
ErrorDescriber = errors ?? new IdentityErrorDescriber();
|
||||
|
||||
if (roleValidators != null)
|
||||
{
|
||||
|
|
@ -39,6 +45,9 @@ namespace Microsoft.AspNet.Identity
|
|||
RoleValidators.Add(v);
|
||||
}
|
||||
}
|
||||
|
||||
loggerFactory = loggerFactory ?? new LoggerFactory();
|
||||
Logger = loggerFactory.Create(nameof(RoleManager<TRole>));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -51,6 +60,21 @@ namespace Microsoft.AspNet.Identity
|
|||
/// </summary>
|
||||
public IList<IRoleValidator<TRole>> RoleValidators { get; } = new List<IRoleValidator<TRole>>();
|
||||
|
||||
/// <summary>
|
||||
/// Used to generate public API error messages
|
||||
/// </summary>
|
||||
public IdentityErrorDescriber ErrorDescriber { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Used to log results
|
||||
/// </summary>
|
||||
public ILogger Logger { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Used to normalize user names, role names, emails for uniqueness
|
||||
/// </summary>
|
||||
public ILookupNormalizer KeyNormalizer { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Returns an IQueryable of roles if the store is an IQueryableRoleStore
|
||||
/// </summary>
|
||||
|
|
@ -102,7 +126,7 @@ namespace Microsoft.AspNet.Identity
|
|||
|
||||
private async Task<IdentityResult> ValidateRoleInternal(TRole role, CancellationToken cancellationToken)
|
||||
{
|
||||
var errors = new List<string>();
|
||||
var errors = new List<IdentityError>();
|
||||
foreach (var v in RoleValidators)
|
||||
{
|
||||
var result = await v.ValidateAsync(this, role, cancellationToken);
|
||||
|
|
@ -120,7 +144,7 @@ namespace Microsoft.AspNet.Identity
|
|||
/// <param name="role"></param>
|
||||
/// <param name="cancellationToken"></param>
|
||||
/// <returns></returns>
|
||||
public virtual async Task<IdentityResult> CreateAsync(TRole role,
|
||||
public virtual async Task<IdentityResult> CreateAsync(TRole role,
|
||||
CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
ThrowIfDisposed();
|
||||
|
|
@ -134,17 +158,31 @@ namespace Microsoft.AspNet.Identity
|
|||
{
|
||||
return result;
|
||||
}
|
||||
await Store.CreateAsync(role, cancellationToken);
|
||||
return IdentityResult.Success;
|
||||
await UpdateNormalizedRoleNameAsync(role, cancellationToken);
|
||||
return await LogResultAsync(await Store.CreateAsync(role, cancellationToken), role);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Update the user's normalized user name
|
||||
/// </summary>
|
||||
/// <param name="user"></param>
|
||||
/// <param name="cancellationToken"></param>
|
||||
/// <returns></returns>
|
||||
public virtual async Task UpdateNormalizedRoleNameAsync(TRole role,
|
||||
CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
var name = await GetRoleNameAsync(role, cancellationToken);
|
||||
await Store.SetNormalizedRoleNameAsync(role, NormalizeKey(name), cancellationToken);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// UpdateAsync an existing role
|
||||
/// </summary>
|
||||
/// <param name="role"></param>
|
||||
/// <param name="cancellationToken"></param>
|
||||
/// <returns></returns>
|
||||
public virtual async Task<IdentityResult> UpdateAsync(TRole role,
|
||||
public virtual async Task<IdentityResult> UpdateAsync(TRole role,
|
||||
CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
ThrowIfDisposed();
|
||||
|
|
@ -153,13 +191,19 @@ namespace Microsoft.AspNet.Identity
|
|||
throw new ArgumentNullException("role");
|
||||
}
|
||||
|
||||
return await LogResultAsync(await UpdateRoleAsync(role, cancellationToken), role);
|
||||
}
|
||||
|
||||
private async Task<IdentityResult> UpdateRoleAsync(TRole role,
|
||||
CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
var result = await ValidateRoleInternal(role, cancellationToken);
|
||||
if (!result.Succeeded)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
await Store.UpdateAsync(role, cancellationToken);
|
||||
return IdentityResult.Success;
|
||||
await UpdateNormalizedRoleNameAsync(role, cancellationToken);
|
||||
return await Store.UpdateAsync(role, cancellationToken);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -168,7 +212,7 @@ namespace Microsoft.AspNet.Identity
|
|||
/// <param name="role"></param>
|
||||
/// <param name="cancellationToken"></param>
|
||||
/// <returns></returns>
|
||||
public virtual async Task<IdentityResult> DeleteAsync(TRole role,
|
||||
public virtual async Task<IdentityResult> DeleteAsync(TRole role,
|
||||
CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
ThrowIfDisposed();
|
||||
|
|
@ -176,9 +220,7 @@ namespace Microsoft.AspNet.Identity
|
|||
{
|
||||
throw new ArgumentNullException("role");
|
||||
}
|
||||
|
||||
await Store.DeleteAsync(role, cancellationToken);
|
||||
return IdentityResult.Success;
|
||||
return await LogResultAsync(await Store.DeleteAsync(role, cancellationToken), role);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -187,7 +229,7 @@ namespace Microsoft.AspNet.Identity
|
|||
/// <param name="roleName"></param>
|
||||
/// <param name="cancellationToken"></param>
|
||||
/// <returns></returns>
|
||||
public virtual async Task<bool> RoleExistsAsync(string roleName,
|
||||
public virtual async Task<bool> RoleExistsAsync(string roleName,
|
||||
CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
ThrowIfDisposed();
|
||||
|
|
@ -196,16 +238,27 @@ namespace Microsoft.AspNet.Identity
|
|||
throw new ArgumentNullException("roleName");
|
||||
}
|
||||
|
||||
return await FindByNameAsync(roleName, cancellationToken) != null;
|
||||
return await FindByNameAsync(NormalizeKey(roleName), cancellationToken) != null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Normalize a key (role name) for uniqueness comparisons
|
||||
/// </summary>
|
||||
/// <param name="key"></param>
|
||||
/// <returns></returns>
|
||||
public virtual string NormalizeKey(string key)
|
||||
{
|
||||
return (KeyNormalizer == null) ? key : KeyNormalizer.Normalize(key);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// FindByLoginAsync a role by id
|
||||
/// </summary>
|
||||
/// <param name="roleId"></param>
|
||||
/// <param name="cancellationToken"></param>
|
||||
/// <returns></returns>
|
||||
public virtual async Task<TRole> FindByIdAsync(string roleId,
|
||||
public virtual async Task<TRole> FindByIdAsync(string roleId,
|
||||
CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
ThrowIfDisposed();
|
||||
|
|
@ -218,7 +271,7 @@ namespace Microsoft.AspNet.Identity
|
|||
/// <param name="role"></param>
|
||||
/// <param name="cancellationToken"></param>
|
||||
/// <returns></returns>
|
||||
public virtual async Task<string> GetRoleNameAsync(TRole role,
|
||||
public virtual async Task<string> GetRoleNameAsync(TRole role,
|
||||
CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
ThrowIfDisposed();
|
||||
|
|
@ -232,12 +285,13 @@ namespace Microsoft.AspNet.Identity
|
|||
/// <param name="name"></param>
|
||||
/// <param name="cancellationToken"></param>
|
||||
/// <returns></returns>
|
||||
public virtual async Task<IdentityResult> SetRoleNameAsync(TRole role, string name,
|
||||
public virtual async Task<IdentityResult> SetRoleNameAsync(TRole role, string name,
|
||||
CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
ThrowIfDisposed();
|
||||
await Store.SetRoleNameAsync(role, name, cancellationToken);
|
||||
return IdentityResult.Success;
|
||||
await UpdateNormalizedRoleNameAsync(role, cancellationToken);
|
||||
return await LogResultAsync(IdentityResult.Success, role);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -246,7 +300,7 @@ namespace Microsoft.AspNet.Identity
|
|||
/// <param name="role"></param>
|
||||
/// <param name="cancellationToken"></param>
|
||||
/// <returns></returns>
|
||||
public virtual async Task<string> GetRoleIdAsync(TRole role,
|
||||
public virtual async Task<string> GetRoleIdAsync(TRole role,
|
||||
CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
ThrowIfDisposed();
|
||||
|
|
@ -259,7 +313,7 @@ namespace Microsoft.AspNet.Identity
|
|||
/// <param name="roleName"></param>
|
||||
/// <param name="cancellationToken"></param>
|
||||
/// <returns></returns>
|
||||
public virtual async Task<TRole> FindByNameAsync(string roleName,
|
||||
public virtual async Task<TRole> FindByNameAsync(string roleName,
|
||||
CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
ThrowIfDisposed();
|
||||
|
|
@ -268,7 +322,7 @@ namespace Microsoft.AspNet.Identity
|
|||
throw new ArgumentNullException("roleName");
|
||||
}
|
||||
|
||||
return await Store.FindByNameAsync(roleName, cancellationToken);
|
||||
return await Store.FindByNameAsync(NormalizeKey(roleName), cancellationToken);
|
||||
}
|
||||
|
||||
// IRoleClaimStore methods
|
||||
|
|
@ -289,7 +343,7 @@ namespace Microsoft.AspNet.Identity
|
|||
/// <param name="claim"></param>
|
||||
/// <param name="cancellationToken"></param>
|
||||
/// <returns></returns>
|
||||
public virtual async Task<IdentityResult> AddClaimAsync(TRole role, Claim claim,
|
||||
public virtual async Task<IdentityResult> AddClaimAsync(TRole role, Claim claim,
|
||||
CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
ThrowIfDisposed();
|
||||
|
|
@ -303,7 +357,7 @@ namespace Microsoft.AspNet.Identity
|
|||
throw new ArgumentNullException("role");
|
||||
}
|
||||
await claimStore.AddClaimAsync(role, claim, cancellationToken);
|
||||
return await UpdateAsync(role, cancellationToken);
|
||||
return await LogResultAsync(await UpdateRoleAsync(role, cancellationToken), role);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -313,7 +367,7 @@ namespace Microsoft.AspNet.Identity
|
|||
/// <param name="claim"></param>
|
||||
/// <param name="cancellationToken"></param>
|
||||
/// <returns></returns>
|
||||
public virtual async Task<IdentityResult> RemoveClaimAsync(TRole role, Claim claim,
|
||||
public virtual async Task<IdentityResult> RemoveClaimAsync(TRole role, Claim claim,
|
||||
CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
ThrowIfDisposed();
|
||||
|
|
@ -323,7 +377,7 @@ namespace Microsoft.AspNet.Identity
|
|||
throw new ArgumentNullException("role");
|
||||
}
|
||||
await claimStore.RemoveClaimAsync(role, claim, cancellationToken);
|
||||
return await UpdateAsync(role, cancellationToken);
|
||||
return await LogResultAsync(await UpdateRoleAsync(role, cancellationToken), role);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -332,7 +386,7 @@ namespace Microsoft.AspNet.Identity
|
|||
/// <param name="role"></param>
|
||||
/// <param name="cancellationToken"></param>
|
||||
/// <returns></returns>
|
||||
public virtual async Task<IList<Claim>> GetClaimsAsync(TRole role,
|
||||
public virtual async Task<IList<Claim>> GetClaimsAsync(TRole role,
|
||||
CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
ThrowIfDisposed();
|
||||
|
|
@ -344,6 +398,21 @@ namespace Microsoft.AspNet.Identity
|
|||
return await claimStore.GetClaimsAsync(role, cancellationToken);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Logs the current Identity Result and returns result object
|
||||
/// </summary>
|
||||
/// <param name="result"></param>
|
||||
/// <param name="user"></param>
|
||||
/// <param name="methodName"></param>
|
||||
/// <returns></returns>
|
||||
protected async Task<IdentityResult> LogResultAsync(IdentityResult result,
|
||||
TRole role, [System.Runtime.CompilerServices.CallerMemberName] string methodName = "")
|
||||
{
|
||||
result.Log(Logger, Resources.FormatLoggingResultMessageForRole(methodName, await GetRoleIdAsync(role)));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private void ThrowIfDisposed()
|
||||
{
|
||||
if (_disposed)
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@
|
|||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
|
|
@ -15,6 +14,13 @@ namespace Microsoft.AspNet.Identity
|
|||
/// <typeparam name="TRole"></typeparam>
|
||||
public class RoleValidator<TRole> : IRoleValidator<TRole> where TRole : class
|
||||
{
|
||||
public RoleValidator(IdentityErrorDescriber errors = null)
|
||||
{
|
||||
Describer = errors ?? new IdentityErrorDescriber();
|
||||
}
|
||||
|
||||
private IdentityErrorDescriber Describer { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Validates a role before saving
|
||||
/// </summary>
|
||||
|
|
@ -33,7 +39,7 @@ namespace Microsoft.AspNet.Identity
|
|||
{
|
||||
throw new ArgumentNullException("role");
|
||||
}
|
||||
var errors = new List<string>();
|
||||
var errors = new List<IdentityError>();
|
||||
await ValidateRoleName(manager, role, errors);
|
||||
if (errors.Count > 0)
|
||||
{
|
||||
|
|
@ -42,13 +48,13 @@ namespace Microsoft.AspNet.Identity
|
|||
return IdentityResult.Success;
|
||||
}
|
||||
|
||||
private static async Task ValidateRoleName(RoleManager<TRole> manager, TRole role,
|
||||
ICollection<string> errors)
|
||||
private async Task ValidateRoleName(RoleManager<TRole> manager, TRole role,
|
||||
ICollection<IdentityError> errors)
|
||||
{
|
||||
var roleName = await manager.GetRoleNameAsync(role);
|
||||
if (string.IsNullOrWhiteSpace(roleName))
|
||||
{
|
||||
errors.Add(String.Format(CultureInfo.CurrentCulture, Resources.PropertyTooShort, "Name"));
|
||||
errors.Add(Describer.InvalidRoleName(roleName));
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -56,7 +62,7 @@ namespace Microsoft.AspNet.Identity
|
|||
if (owner != null &&
|
||||
!string.Equals(await manager.GetRoleIdAsync(owner), await manager.GetRoleIdAsync(role)))
|
||||
{
|
||||
errors.Add(String.Format(CultureInfo.CurrentCulture, Resources.DuplicateName, roleName));
|
||||
errors.Add(Describer.DuplicateRoleName(roleName));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,9 +8,10 @@ using System.Security.Claims;
|
|||
using System.Security.Principal;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNet.Hosting;
|
||||
using Microsoft.AspNet.Http;
|
||||
using Microsoft.AspNet.Http.Security;
|
||||
using Microsoft.Framework.DependencyInjection;
|
||||
using Microsoft.Framework.Logging;
|
||||
using Microsoft.Framework.OptionsModel;
|
||||
|
||||
namespace Microsoft.AspNet.Identity
|
||||
|
|
@ -21,8 +22,11 @@ namespace Microsoft.AspNet.Identity
|
|||
/// <typeparam name="TUser"></typeparam>
|
||||
public class SignInManager<TUser> where TUser : class
|
||||
{
|
||||
public SignInManager(UserManager<TUser> userManager, IContextAccessor<HttpContext> contextAccessor,
|
||||
IClaimsIdentityFactory<TUser> claimsFactory, IOptions<IdentityOptions> optionsAccessor)
|
||||
public SignInManager(UserManager<TUser> userManager,
|
||||
IHttpContextAccessor contextAccessor,
|
||||
IClaimsIdentityFactory<TUser> claimsFactory,
|
||||
IOptions<IdentityOptions> optionsAccessor = null,
|
||||
ILoggerFactory loggerFactory = null)
|
||||
{
|
||||
if (userManager == null)
|
||||
{
|
||||
|
|
@ -36,20 +40,21 @@ namespace Microsoft.AspNet.Identity
|
|||
{
|
||||
throw new ArgumentNullException(nameof(claimsFactory));
|
||||
}
|
||||
if (optionsAccessor == null || optionsAccessor.Options == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(optionsAccessor));
|
||||
}
|
||||
|
||||
UserManager = userManager;
|
||||
Context = contextAccessor.Value;
|
||||
ClaimsFactory = claimsFactory;
|
||||
Options = optionsAccessor.Options;
|
||||
Options = optionsAccessor?.Options ?? new IdentityOptions();
|
||||
|
||||
loggerFactory = loggerFactory ?? new LoggerFactory();
|
||||
Logger = loggerFactory.Create(nameof(SignInManager<TUser>));
|
||||
}
|
||||
|
||||
public UserManager<TUser> UserManager { get; private set; }
|
||||
public HttpContext Context { get; private set; }
|
||||
public IClaimsIdentityFactory<TUser> ClaimsFactory { get; private set; }
|
||||
public IdentityOptions Options { get; private set; }
|
||||
public ILogger Logger { get; set; }
|
||||
|
||||
// Should this be a func?
|
||||
public virtual async Task<ClaimsIdentity> CreateUserIdentityAsync(TUser user,
|
||||
|
|
@ -63,13 +68,13 @@ namespace Microsoft.AspNet.Identity
|
|||
{
|
||||
if (Options.SignIn.RequireConfirmedEmail && !(await UserManager.IsEmailConfirmedAsync(user, cancellationToken)))
|
||||
{
|
||||
return false;
|
||||
return await LogResultAsync(false, user);
|
||||
}
|
||||
if (Options.SignIn.RequireConfirmedPhoneNumber && !(await UserManager.IsPhoneNumberConfirmedAsync(user, cancellationToken)))
|
||||
{
|
||||
return false;
|
||||
return await LogResultAsync(false, user);
|
||||
}
|
||||
return true;
|
||||
return await LogResultAsync(true, user);
|
||||
}
|
||||
|
||||
public virtual async Task SignInAsync(TUser user, bool isPersistent, string authenticationMethod = null,
|
||||
|
|
@ -96,15 +101,15 @@ namespace Microsoft.AspNet.Identity
|
|||
return UserManager.SupportsUserLockout && await UserManager.IsLockedOutAsync(user, token);
|
||||
}
|
||||
|
||||
private async Task<SignInStatus?> PreSignInCheck(TUser user, CancellationToken token)
|
||||
private async Task<SignInResult> PreSignInCheck(TUser user, CancellationToken token)
|
||||
{
|
||||
if (!await CanSignInAsync(user, token))
|
||||
{
|
||||
return SignInStatus.NotAllowed;
|
||||
return SignInResult.NotAllowed;
|
||||
}
|
||||
if (await IsLockedOut(user, token))
|
||||
{
|
||||
return SignInStatus.LockedOut;
|
||||
return SignInResult.LockedOut;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
|
@ -141,18 +146,26 @@ namespace Microsoft.AspNet.Identity
|
|||
return null;
|
||||
}
|
||||
|
||||
public virtual async Task<SignInStatus> PasswordSignInAsync(TUser user, string password,
|
||||
public virtual async Task<SignInResult> PasswordSignInAsync(TUser user, string password,
|
||||
bool isPersistent, bool shouldLockout, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
if (user == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(user));
|
||||
}
|
||||
var error = await PreSignInCheck(user, cancellationToken);
|
||||
if (error != null)
|
||||
{
|
||||
return error.Value;
|
||||
return await LogResultAsync(error, user);
|
||||
}
|
||||
if (await IsLockedOut(user, cancellationToken))
|
||||
{
|
||||
return await LogResultAsync(SignInResult.LockedOut, user);
|
||||
}
|
||||
if (await UserManager.CheckPasswordAsync(user, password, cancellationToken))
|
||||
{
|
||||
await ResetLockout(user, cancellationToken);
|
||||
return await SignInOrTwoFactorAsync(user, isPersistent, cancellationToken);
|
||||
return await LogResultAsync(await SignInOrTwoFactorAsync(user, isPersistent, cancellationToken), user);
|
||||
}
|
||||
if (UserManager.SupportsUserLockout && shouldLockout)
|
||||
{
|
||||
|
|
@ -160,19 +173,20 @@ namespace Microsoft.AspNet.Identity
|
|||
await UserManager.AccessFailedAsync(user, cancellationToken);
|
||||
if (await UserManager.IsLockedOutAsync(user, cancellationToken))
|
||||
{
|
||||
return SignInStatus.LockedOut;
|
||||
|
||||
return await LogResultAsync(SignInResult.LockedOut, user);
|
||||
}
|
||||
}
|
||||
return SignInStatus.Failure;
|
||||
return await LogResultAsync(SignInResult.Failed, user);
|
||||
}
|
||||
|
||||
public virtual async Task<SignInStatus> PasswordSignInAsync(string userName, string password,
|
||||
public virtual async Task<SignInResult> PasswordSignInAsync(string userName, string password,
|
||||
bool isPersistent, bool shouldLockout, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
var user = await UserManager.FindByNameAsync(userName, cancellationToken);
|
||||
if (user == null)
|
||||
{
|
||||
return SignInStatus.Failure;
|
||||
return SignInResult.Failed;
|
||||
}
|
||||
return await PasswordSignInAsync(user, password, isPersistent, shouldLockout, cancellationToken);
|
||||
}
|
||||
|
|
@ -207,9 +221,8 @@ namespace Microsoft.AspNet.Identity
|
|||
return false;
|
||||
}
|
||||
var token = await UserManager.GenerateTwoFactorTokenAsync(user, provider, cancellationToken);
|
||||
// See IdentityConfig.cs to plug in Email/SMS services to actually send the code
|
||||
await UserManager.NotifyTwoFactorTokenAsync(user, provider, token, cancellationToken);
|
||||
return true;
|
||||
return await LogResultAsync(true, user);
|
||||
}
|
||||
|
||||
public async Task<bool> IsTwoFactorClientRememberedAsync(TUser user,
|
||||
|
|
@ -236,23 +249,23 @@ namespace Microsoft.AspNet.Identity
|
|||
return Task.FromResult(0);
|
||||
}
|
||||
|
||||
public virtual async Task<SignInStatus> TwoFactorSignInAsync(string provider, string code, bool isPersistent,
|
||||
public virtual async Task<SignInResult> TwoFactorSignInAsync(string provider, string code, bool isPersistent,
|
||||
bool rememberClient, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
var twoFactorInfo = await RetrieveTwoFactorInfoAsync(cancellationToken);
|
||||
if (twoFactorInfo == null || twoFactorInfo.UserId == null)
|
||||
{
|
||||
return SignInStatus.Failure;
|
||||
return SignInResult.Failed;
|
||||
}
|
||||
var user = await UserManager.FindByIdAsync(twoFactorInfo.UserId, cancellationToken);
|
||||
if (user == null)
|
||||
{
|
||||
return SignInStatus.Failure;
|
||||
return SignInResult.Failed;
|
||||
}
|
||||
var error = await PreSignInCheck(user, cancellationToken);
|
||||
if (error != null)
|
||||
{
|
||||
return error.Value;
|
||||
return await LogResultAsync(error, user);
|
||||
}
|
||||
if (await UserManager.VerifyTwoFactorTokenAsync(user, provider, code, cancellationToken))
|
||||
{
|
||||
|
|
@ -268,11 +281,13 @@ namespace Microsoft.AspNet.Identity
|
|||
{
|
||||
await RememberTwoFactorClientAsync(user, cancellationToken);
|
||||
}
|
||||
return SignInStatus.Success;
|
||||
await UserManager.ResetAccessFailedCountAsync(user, cancellationToken);
|
||||
await SignInAsync(user, isPersistent);
|
||||
return await LogResultAsync(SignInResult.Success, user);
|
||||
}
|
||||
// If the token is incorrect, record the failure which also may cause the user to be locked out
|
||||
await UserManager.AccessFailedAsync(user, cancellationToken);
|
||||
return SignInStatus.Failure;
|
||||
return await LogResultAsync(SignInResult.Failed, user);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -292,20 +307,20 @@ namespace Microsoft.AspNet.Identity
|
|||
return await UserManager.FindByIdAsync(info.UserId, cancellationToken);
|
||||
}
|
||||
|
||||
public virtual async Task<SignInStatus> ExternalLoginSignInAsync(string loginProvider, string providerKey, bool isPersistent,
|
||||
public async Task<SignInResult> ExternalLoginSignInAsync(string loginProvider, string providerKey, bool isPersistent,
|
||||
CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
var user = await UserManager.FindByLoginAsync(loginProvider, providerKey, cancellationToken);
|
||||
if (user == null)
|
||||
{
|
||||
return SignInStatus.Failure;
|
||||
return SignInResult.Failed;
|
||||
}
|
||||
var error = await PreSignInCheck(user, cancellationToken);
|
||||
if (error != null)
|
||||
{
|
||||
return error.Value;
|
||||
return await LogResultAsync(error, user);
|
||||
}
|
||||
return await SignInOrTwoFactorAsync(user, isPersistent, cancellationToken, loginProvider);
|
||||
return await LogResultAsync(await SignInOrTwoFactorAsync(user, isPersistent, cancellationToken, loginProvider), user);
|
||||
}
|
||||
|
||||
private const string LoginProviderKey = "LoginProvider";
|
||||
|
|
@ -316,7 +331,7 @@ namespace Microsoft.AspNet.Identity
|
|||
return Context.GetAuthenticationTypes().Where(d => !string.IsNullOrEmpty(d.Caption));
|
||||
}
|
||||
|
||||
public virtual async Task<ExternalLoginInfo> GetExternalLoginInfoAsync(string expectedXsrf = null,
|
||||
public virtual async Task<ExternalLoginInfo> GetExternalLoginInfoAsync(string expectedXsrf = null,
|
||||
CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
var auth = await Context.AuthenticateAsync(IdentityOptions.ExternalCookieAuthenticationType);
|
||||
|
|
@ -358,10 +373,10 @@ namespace Microsoft.AspNet.Identity
|
|||
return properties;
|
||||
}
|
||||
|
||||
private async Task<SignInStatus> SignInOrTwoFactorAsync(TUser user, bool isPersistent,
|
||||
private async Task<SignInResult> SignInOrTwoFactorAsync(TUser user, bool isPersistent,
|
||||
CancellationToken cancellationToken, string loginProvider = null)
|
||||
{
|
||||
if (UserManager.SupportsUserTwoFactor &&
|
||||
if (UserManager.SupportsUserTwoFactor &&
|
||||
await UserManager.GetTwoFactorEnabledAsync(user, cancellationToken) &&
|
||||
(await UserManager.GetValidTwoFactorProvidersAsync(user, cancellationToken)).Count > 0)
|
||||
{
|
||||
|
|
@ -370,7 +385,7 @@ namespace Microsoft.AspNet.Identity
|
|||
// Store the userId for use after two factor check
|
||||
var userId = await UserManager.GetUserIdAsync(user, cancellationToken);
|
||||
Context.Response.SignIn(StoreTwoFactorInfo(userId, loginProvider));
|
||||
return SignInStatus.RequiresVerification;
|
||||
return SignInResult.TwoFactorRequired;
|
||||
}
|
||||
}
|
||||
// Cleanup external cookie
|
||||
|
|
@ -379,7 +394,7 @@ namespace Microsoft.AspNet.Identity
|
|||
Context.Response.SignOut(IdentityOptions.ExternalCookieAuthenticationType);
|
||||
}
|
||||
await SignInAsync(user, isPersistent, loginProvider, cancellationToken);
|
||||
return SignInStatus.Success;
|
||||
return SignInResult.Success;
|
||||
}
|
||||
|
||||
private async Task<TwoFactorAuthenticationInfo> RetrieveTwoFactorInfoAsync(CancellationToken cancellationToken)
|
||||
|
|
@ -396,6 +411,35 @@ namespace Microsoft.AspNet.Identity
|
|||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Log boolean result for user and return result
|
||||
/// </summary>
|
||||
/// <param name="result"></param>
|
||||
/// <param name="user"></param>
|
||||
/// <param name="methodName"></param>
|
||||
/// <returns></returns>
|
||||
protected async virtual Task<bool> LogResultAsync(bool result, TUser user, [System.Runtime.CompilerServices.CallerMemberName] string methodName = "")
|
||||
{
|
||||
Logger.WriteInformation(Resources.FormatLoggingSigninResult(Resources.FormatLoggingResultMessage(methodName,
|
||||
await UserManager.GetUserIdAsync(user)), result));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Log SignInStatus for user and return SignInStatus
|
||||
/// </summary>
|
||||
/// <param name="status"></param>
|
||||
/// <param name="user"></param>
|
||||
/// <param name="methodName"></param>
|
||||
/// <returns></returns>
|
||||
protected async virtual Task<SignInResult> LogResultAsync(SignInResult status, TUser user, [System.Runtime.CompilerServices.CallerMemberName] string methodName = "")
|
||||
{
|
||||
status.Log(Logger, Resources.FormatLoggingResultMessage(methodName, await UserManager.GetUserIdAsync(user)));
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
internal static ClaimsIdentity StoreTwoFactorInfo(string userId, string loginProvider)
|
||||
{
|
||||
var identity = new ClaimsIdentity(IdentityOptions.TwoFactorUserIdCookieAuthenticationType);
|
||||
|
|
|
|||
|
|
@ -0,0 +1,113 @@
|
|||
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using Microsoft.Framework.Logging;
|
||||
|
||||
namespace Microsoft.AspNet.Identity
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents the result of an sign in operation
|
||||
/// </summary>
|
||||
public class SignInResult
|
||||
{
|
||||
private static readonly SignInResult _success = new SignInResult { Succeeded = true };
|
||||
private static readonly SignInResult _failed = new SignInResult();
|
||||
private static readonly SignInResult _lockedOut = new SignInResult { IsLockedOut = true };
|
||||
private static readonly SignInResult _notAllowed = new SignInResult { IsNotAllowed = true };
|
||||
private static readonly SignInResult _twoFactorRequired = new SignInResult { RequiresTwoFactor = true };
|
||||
|
||||
/// <summary>
|
||||
/// True if the operation was successful
|
||||
/// </summary>
|
||||
public bool Succeeded { get; protected set; }
|
||||
|
||||
/// <summary>
|
||||
/// True if the user is locked out
|
||||
/// </summary>
|
||||
public bool IsLockedOut { get; protected set; }
|
||||
|
||||
/// <summary>
|
||||
/// True if the user is not allowed to sign in
|
||||
/// </summary>
|
||||
public bool IsNotAllowed { get; protected set; }
|
||||
|
||||
/// <summary>
|
||||
/// True if the sign in requires two factor
|
||||
/// </summary>
|
||||
public bool RequiresTwoFactor { get; protected set; }
|
||||
|
||||
/// <summary>
|
||||
/// Static success result
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public static SignInResult Success
|
||||
{
|
||||
get { return _success; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Static failure result
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public static SignInResult Failed
|
||||
{
|
||||
get { return _failed; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Static locked out result
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public static SignInResult LockedOut
|
||||
{
|
||||
get { return _lockedOut; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Static not allowed result
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public static SignInResult NotAllowed
|
||||
{
|
||||
get { return _notAllowed; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Static two factor required result
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public static SignInResult TwoFactorRequired
|
||||
{
|
||||
get { return _twoFactorRequired; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Log result based on properties
|
||||
/// </summary>
|
||||
/// <param name="logger"></param>
|
||||
/// <param name="message"></param>
|
||||
public virtual void Log(ILogger logger, string message)
|
||||
{
|
||||
if (IsLockedOut)
|
||||
{
|
||||
logger.WriteInformation(Resources.FormatLoggingSigninResult(message, "Lockedout"));
|
||||
}
|
||||
else if (IsNotAllowed)
|
||||
{
|
||||
logger.WriteInformation(Resources.FormatLoggingSigninResult(message, "NotAllowed"));
|
||||
}
|
||||
else if (RequiresTwoFactor)
|
||||
{
|
||||
logger.WriteInformation(Resources.FormatLoggingSigninResult(message, "RequiresTwoFactor"));
|
||||
}
|
||||
else if (Succeeded)
|
||||
{
|
||||
logger.WriteInformation(Resources.FormatLoggingSigninResult(message, "Succeeded"));
|
||||
}
|
||||
else
|
||||
{
|
||||
logger.WriteInformation(Resources.FormatLoggingSigninResult(message, "Failed"));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -6,22 +6,22 @@ using System;
|
|||
namespace Microsoft.AspNet.Identity
|
||||
{
|
||||
/// <summary>
|
||||
/// Normalizes user names via ToUpperInvariant()
|
||||
/// Normalizes via ToUpperInvariant()
|
||||
/// </summary>
|
||||
public class UpperInvariantUserNameNormalizer : IUserNameNormalizer
|
||||
public class UpperInvariantLookupNormalizer : ILookupNormalizer
|
||||
{
|
||||
/// <summary>
|
||||
/// Normalizes user names via ToUpperInvariant()
|
||||
/// Normalizes via ToUpperInvariant()
|
||||
/// </summary>
|
||||
/// <param name="userName"></param>
|
||||
/// <param name="key"></param>
|
||||
/// <returns></returns>
|
||||
public string Normalize(string userName)
|
||||
public string Normalize(string key)
|
||||
{
|
||||
if (userName == null)
|
||||
if (key == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
return userName.Normalize().ToUpperInvariant();
|
||||
return key.Normalize().ToUpperInvariant();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -9,6 +9,7 @@ using System.Security.Claims;
|
|||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Framework.Logging;
|
||||
using Microsoft.Framework.OptionsModel;
|
||||
|
||||
namespace Microsoft.AspNet.Identity
|
||||
|
|
@ -30,39 +31,39 @@ namespace Microsoft.AspNet.Identity
|
|||
private IdentityOptions _options;
|
||||
|
||||
/// <summary>
|
||||
/// Constructor which takes a service provider and user store
|
||||
/// Constructor
|
||||
/// </summary>
|
||||
/// <param name="store"></param>
|
||||
/// <param name="optionsAccessor"></param>
|
||||
/// <param name="passwordHasher"></param>
|
||||
/// <param name="userValidator"></param>
|
||||
/// <param name="passwordValidator"></param>
|
||||
/// <param name="claimsIdentityFactory"></param>
|
||||
public UserManager(IUserStore<TUser> store,
|
||||
IOptions<IdentityOptions> optionsAccessor,
|
||||
IPasswordHasher<TUser> passwordHasher,
|
||||
IEnumerable<IUserValidator<TUser>> userValidators,
|
||||
IEnumerable<IPasswordValidator<TUser>> passwordValidators,
|
||||
IUserNameNormalizer userNameNormalizer,
|
||||
IEnumerable<IUserTokenProvider<TUser>> tokenProviders,
|
||||
IEnumerable<IIdentityMessageProvider> msgProviders)
|
||||
/// <param name="userValidators"></param>
|
||||
/// <param name="passwordValidators"></param>
|
||||
/// <param name="keyNormalizer"></param>
|
||||
/// <param name="errors"></param>
|
||||
/// <param name="tokenProviders"></param>
|
||||
/// <param name="msgProviders"></param>
|
||||
/// <param name="loggerFactory"></param>
|
||||
public UserManager(IUserStore<TUser> store,
|
||||
IOptions<IdentityOptions> optionsAccessor = null,
|
||||
IPasswordHasher<TUser> passwordHasher = null,
|
||||
IEnumerable<IUserValidator<TUser>> userValidators = null,
|
||||
IEnumerable<IPasswordValidator<TUser>> passwordValidators = null,
|
||||
ILookupNormalizer keyNormalizer = null,
|
||||
IdentityErrorDescriber errors = null,
|
||||
IEnumerable<IUserTokenProvider<TUser>> tokenProviders = null,
|
||||
IEnumerable<IIdentityMessageProvider> msgProviders = null,
|
||||
ILoggerFactory loggerFactory = null)
|
||||
{
|
||||
if (store == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(store));
|
||||
}
|
||||
if (optionsAccessor == null || optionsAccessor.Options == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(optionsAccessor));
|
||||
}
|
||||
if (passwordHasher == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(passwordHasher));
|
||||
}
|
||||
Store = store;
|
||||
Options = optionsAccessor.Options;
|
||||
PasswordHasher = passwordHasher;
|
||||
UserNameNormalizer = userNameNormalizer;
|
||||
Options = optionsAccessor?.Options ?? new IdentityOptions();
|
||||
PasswordHasher = passwordHasher ?? new PasswordHasher<TUser>();
|
||||
KeyNormalizer = keyNormalizer ?? new UpperInvariantLookupNormalizer();
|
||||
ErrorDescriber = errors ?? new IdentityErrorDescriber();
|
||||
|
||||
if (userValidators != null)
|
||||
{
|
||||
foreach (var v in userValidators)
|
||||
|
|
@ -77,6 +78,10 @@ namespace Microsoft.AspNet.Identity
|
|||
PasswordValidators.Add(v);
|
||||
}
|
||||
}
|
||||
|
||||
loggerFactory = loggerFactory ?? new LoggerFactory();
|
||||
Logger = loggerFactory.Create(nameof(UserManager<TUser>));
|
||||
|
||||
if (tokenProviders != null)
|
||||
{
|
||||
foreach (var tokenProvider in tokenProviders)
|
||||
|
|
@ -132,9 +137,19 @@ namespace Microsoft.AspNet.Identity
|
|||
public IList<IPasswordValidator<TUser>> PasswordValidators { get; } = new List<IPasswordValidator<TUser>>();
|
||||
|
||||
/// <summary>
|
||||
/// Used to normalize user names for uniqueness
|
||||
/// Used to normalize user names and emails for uniqueness
|
||||
/// </summary>
|
||||
public IUserNameNormalizer UserNameNormalizer { get; set; }
|
||||
public ILookupNormalizer KeyNormalizer { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Used to generate public API error messages
|
||||
/// </summary>
|
||||
public IdentityErrorDescriber ErrorDescriber { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Used to log IdentityResult
|
||||
/// </summary>
|
||||
public ILogger Logger { get; set; }
|
||||
|
||||
public IdentityOptions Options
|
||||
{
|
||||
|
|
@ -301,7 +316,7 @@ namespace Microsoft.AspNet.Identity
|
|||
|
||||
private async Task<IdentityResult> ValidateUserInternal(TUser user, CancellationToken cancellationToken)
|
||||
{
|
||||
var errors = new List<string>();
|
||||
var errors = new List<IdentityError>();
|
||||
foreach (var v in UserValidators)
|
||||
{
|
||||
var result = await v.ValidateAsync(this, user, cancellationToken);
|
||||
|
|
@ -315,7 +330,7 @@ namespace Microsoft.AspNet.Identity
|
|||
|
||||
private async Task<IdentityResult> ValidatePasswordInternal(TUser user, string password, CancellationToken cancellationToken)
|
||||
{
|
||||
var errors = new List<string>();
|
||||
var errors = new List<IdentityError>();
|
||||
foreach (var v in PasswordValidators)
|
||||
{
|
||||
var result = await v.ValidateAsync(this, user, password, cancellationToken);
|
||||
|
|
@ -327,6 +342,31 @@ namespace Microsoft.AspNet.Identity
|
|||
return errors.Count > 0 ? IdentityResult.Failed(errors.ToArray()) : IdentityResult.Success;
|
||||
}
|
||||
|
||||
public virtual Task<string> GenerateConcurrencyStampAsync(TUser user,
|
||||
CancellationToken token = default(CancellationToken))
|
||||
{
|
||||
return Task.FromResult(Guid.NewGuid().ToString());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Validate user and update. Called by other UserManager methods
|
||||
/// </summary>
|
||||
/// <param name="user"></param>
|
||||
/// <param name="cancellationToken"></param>
|
||||
/// <returns></returns>
|
||||
private async Task<IdentityResult> UpdateUserAsync(TUser user,
|
||||
CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
var result = await ValidateUserInternal(user, cancellationToken);
|
||||
if (!result.Succeeded)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
await UpdateNormalizedUserNameAsync(user, cancellationToken);
|
||||
await UpdateNormalizedEmailAsync(user, cancellationToken);
|
||||
return await Store.UpdateAsync(user, cancellationToken);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create a user with no password
|
||||
/// </summary>
|
||||
|
|
@ -348,8 +388,8 @@ namespace Microsoft.AspNet.Identity
|
|||
await GetUserLockoutStore().SetLockoutEnabledAsync(user, true, cancellationToken);
|
||||
}
|
||||
await UpdateNormalizedUserNameAsync(user, cancellationToken);
|
||||
await Store.CreateAsync(user, cancellationToken);
|
||||
return IdentityResult.Success;
|
||||
await UpdateNormalizedEmailAsync(user, cancellationToken);
|
||||
return await LogResultAsync(await Store.CreateAsync(user, cancellationToken), user);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -366,14 +406,7 @@ namespace Microsoft.AspNet.Identity
|
|||
{
|
||||
throw new ArgumentNullException("user");
|
||||
}
|
||||
var result = await ValidateUserInternal(user, cancellationToken);
|
||||
if (!result.Succeeded)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
await UpdateNormalizedUserNameAsync(user, cancellationToken);
|
||||
await Store.UpdateAsync(user, cancellationToken);
|
||||
return IdentityResult.Success;
|
||||
return await LogResultAsync(await UpdateUserAsync(user, cancellationToken), user);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -390,8 +423,7 @@ namespace Microsoft.AspNet.Identity
|
|||
{
|
||||
throw new ArgumentNullException("user");
|
||||
}
|
||||
await Store.DeleteAsync(user, cancellationToken);
|
||||
return IdentityResult.Success;
|
||||
return await LogResultAsync(await Store.DeleteAsync(user, cancellationToken), user);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -421,7 +453,7 @@ namespace Microsoft.AspNet.Identity
|
|||
{
|
||||
throw new ArgumentNullException("userName");
|
||||
}
|
||||
userName = NormalizeUserName(userName);
|
||||
userName = NormalizeKey(userName);
|
||||
return Store.FindByNameAsync(userName, cancellationToken);
|
||||
}
|
||||
|
||||
|
|
@ -456,7 +488,7 @@ namespace Microsoft.AspNet.Identity
|
|||
{
|
||||
throw new ArgumentNullException("password");
|
||||
}
|
||||
var result = await UpdatePasswordInternal(passwordStore, user, password, cancellationToken);
|
||||
var result = await UpdatePasswordHash(passwordStore, user, password, cancellationToken);
|
||||
if (!result.Succeeded)
|
||||
{
|
||||
return result;
|
||||
|
|
@ -465,13 +497,13 @@ namespace Microsoft.AspNet.Identity
|
|||
}
|
||||
|
||||
/// <summary>
|
||||
/// Normalize a user name for uniqueness comparisons
|
||||
/// Normalize a key (user name, email) for uniqueness comparisons
|
||||
/// </summary>
|
||||
/// <param name="userName"></param>
|
||||
/// <returns></returns>
|
||||
public virtual string NormalizeUserName(string userName)
|
||||
public virtual string NormalizeKey(string key)
|
||||
{
|
||||
return (UserNameNormalizer == null) ? userName : UserNameNormalizer.Normalize(userName);
|
||||
return (KeyNormalizer == null) ? key : KeyNormalizer.Normalize(key);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -483,8 +515,8 @@ namespace Microsoft.AspNet.Identity
|
|||
public virtual async Task UpdateNormalizedUserNameAsync(TUser user,
|
||||
CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
var userName = await GetUserNameAsync(user, cancellationToken);
|
||||
await Store.SetNormalizedUserNameAsync(user, NormalizeUserName(userName), cancellationToken);
|
||||
var normalizedName = NormalizeKey(await GetUserNameAsync(user, cancellationToken));
|
||||
await Store.SetNormalizedUserNameAsync(user, normalizedName, cancellationToken);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -520,7 +552,7 @@ namespace Microsoft.AspNet.Identity
|
|||
throw new ArgumentNullException("user");
|
||||
}
|
||||
await UpdateUserName(user, userName, cancellationToken);
|
||||
return await UpdateAsync(user, cancellationToken);
|
||||
return await LogResultAsync(await UpdateUserAsync(user, cancellationToken), user);
|
||||
}
|
||||
|
||||
private async Task UpdateUserName(TUser user, string userName, CancellationToken cancellationToken)
|
||||
|
|
@ -558,7 +590,14 @@ namespace Microsoft.AspNet.Identity
|
|||
{
|
||||
return false;
|
||||
}
|
||||
return await VerifyPasswordAsync(passwordStore, user, password, cancellationToken);
|
||||
var result = await VerifyPasswordAsync(passwordStore, user, password, cancellationToken);
|
||||
if (result == PasswordVerificationResult.SuccessRehashNeeded)
|
||||
{
|
||||
await UpdatePasswordHash(passwordStore, user, password, cancellationToken, validatePassword: false);
|
||||
await UpdateUserAsync(user, cancellationToken);
|
||||
}
|
||||
|
||||
return await LogResultAsync(result != PasswordVerificationResult.Failed, user);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -576,7 +615,7 @@ namespace Microsoft.AspNet.Identity
|
|||
{
|
||||
throw new ArgumentNullException("user");
|
||||
}
|
||||
return await passwordStore.HasPasswordAsync(user, cancellationToken);
|
||||
return await LogResultAsync(await passwordStore.HasPasswordAsync(user, cancellationToken), user);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -598,14 +637,14 @@ namespace Microsoft.AspNet.Identity
|
|||
var hash = await passwordStore.GetPasswordHashAsync(user, cancellationToken);
|
||||
if (hash != null)
|
||||
{
|
||||
return new IdentityResult(Resources.UserAlreadyHasPassword);
|
||||
return await LogResultAsync(IdentityResult.Failed(ErrorDescriber.UserAlreadyHasPassword()), user);
|
||||
}
|
||||
var result = await UpdatePasswordInternal(passwordStore, user, password, cancellationToken);
|
||||
var result = await UpdatePasswordHash(passwordStore, user, password, cancellationToken);
|
||||
if (!result.Succeeded)
|
||||
{
|
||||
return result;
|
||||
return await LogResultAsync(result, user);
|
||||
}
|
||||
return await UpdateAsync(user, cancellationToken);
|
||||
return await LogResultAsync(await UpdateUserAsync(user, cancellationToken), user);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -625,16 +664,16 @@ namespace Microsoft.AspNet.Identity
|
|||
{
|
||||
throw new ArgumentNullException("user");
|
||||
}
|
||||
if (await VerifyPasswordAsync(passwordStore, user, currentPassword, cancellationToken))
|
||||
if (await VerifyPasswordAsync(passwordStore, user, currentPassword, cancellationToken) != PasswordVerificationResult.Failed)
|
||||
{
|
||||
var result = await UpdatePasswordInternal(passwordStore, user, newPassword, cancellationToken);
|
||||
var result = await UpdatePasswordHash(passwordStore, user, newPassword, cancellationToken);
|
||||
if (!result.Succeeded)
|
||||
{
|
||||
return result;
|
||||
return await LogResultAsync(result, user);
|
||||
}
|
||||
return await UpdateAsync(user, cancellationToken);
|
||||
return await LogResultAsync(await UpdateUserAsync(user, cancellationToken), user);
|
||||
}
|
||||
return IdentityResult.Failed(Resources.PasswordMismatch);
|
||||
return await LogResultAsync(IdentityResult.Failed(ErrorDescriber.PasswordMismatch()), user);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -652,21 +691,24 @@ namespace Microsoft.AspNet.Identity
|
|||
{
|
||||
throw new ArgumentNullException("user");
|
||||
}
|
||||
await passwordStore.SetPasswordHashAsync(user, null, cancellationToken);
|
||||
await UpdateSecurityStampInternal(user, cancellationToken);
|
||||
return await UpdateAsync(user, cancellationToken);
|
||||
await UpdatePasswordHash(passwordStore, user, null, cancellationToken, validatePassword: false);
|
||||
return await LogResultAsync(await UpdateUserAsync(user, cancellationToken), user);
|
||||
}
|
||||
|
||||
internal async Task<IdentityResult> UpdatePasswordInternal(IUserPasswordStore<TUser> passwordStore,
|
||||
TUser user, string newPassword, CancellationToken cancellationToken)
|
||||
internal async Task<IdentityResult> UpdatePasswordHash(IUserPasswordStore<TUser> passwordStore,
|
||||
TUser user, string newPassword, CancellationToken cancellationToken, bool validatePassword = true)
|
||||
{
|
||||
var validate = await ValidatePasswordInternal(user, newPassword, cancellationToken);
|
||||
if (!validate.Succeeded)
|
||||
if (validatePassword)
|
||||
{
|
||||
return validate;
|
||||
var validate = await ValidatePasswordInternal(user, newPassword, cancellationToken);
|
||||
if (!validate.Succeeded)
|
||||
{
|
||||
return validate;
|
||||
}
|
||||
}
|
||||
var hash = newPassword != null ? PasswordHasher.HashPassword(user, newPassword) : null;
|
||||
await
|
||||
passwordStore.SetPasswordHashAsync(user, PasswordHasher.HashPassword(user, newPassword), cancellationToken);
|
||||
passwordStore.SetPasswordHashAsync(user, hash, cancellationToken);
|
||||
await UpdateSecurityStampInternal(user, cancellationToken);
|
||||
return IdentityResult.Success;
|
||||
}
|
||||
|
|
@ -679,11 +721,11 @@ namespace Microsoft.AspNet.Identity
|
|||
/// <param name="password"></param>
|
||||
/// <param name="cancellationToken"></param>
|
||||
/// <returns></returns>
|
||||
protected virtual async Task<bool> VerifyPasswordAsync(IUserPasswordStore<TUser> store, TUser user,
|
||||
protected virtual async Task<PasswordVerificationResult> VerifyPasswordAsync(IUserPasswordStore<TUser> store, TUser user,
|
||||
string password, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
var hash = await store.GetPasswordHashAsync(user, cancellationToken);
|
||||
return PasswordHasher.VerifyHashedPassword(user, hash, password) != PasswordVerificationResult.Failed;
|
||||
return PasswordHasher.VerifyHashedPassword(user, hash, password);
|
||||
}
|
||||
|
||||
// IUserSecurityStampStore methods
|
||||
|
|
@ -731,7 +773,7 @@ namespace Microsoft.AspNet.Identity
|
|||
throw new ArgumentNullException("user");
|
||||
}
|
||||
await UpdateSecurityStampInternal(user, cancellationToken);
|
||||
return await UpdateAsync(user, cancellationToken);
|
||||
return await LogResultAsync(await UpdateUserAsync(user, cancellationToken), user);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -744,7 +786,10 @@ namespace Microsoft.AspNet.Identity
|
|||
CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
ThrowIfDisposed();
|
||||
return await GenerateUserTokenAsync(user, Options.PasswordResetTokenProvider, "ResetPassword", cancellationToken);
|
||||
var token = await GenerateUserTokenAsync(user, Options.PasswordResetTokenProvider, "ResetPassword", cancellationToken);
|
||||
await LogResultAsync(IdentityResult.Success, user);
|
||||
|
||||
return token;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -766,15 +811,15 @@ namespace Microsoft.AspNet.Identity
|
|||
// Make sure the token is valid and the stamp matches
|
||||
if (!await VerifyUserTokenAsync(user, Options.PasswordResetTokenProvider, "ResetPassword", token, cancellationToken))
|
||||
{
|
||||
return IdentityResult.Failed(Resources.InvalidToken);
|
||||
return await LogResultAsync(IdentityResult.Failed(ErrorDescriber.InvalidToken()), user);
|
||||
}
|
||||
var passwordStore = GetPasswordStore();
|
||||
var result = await UpdatePasswordInternal(passwordStore, user, newPassword, cancellationToken);
|
||||
var result = await UpdatePasswordHash(passwordStore, user, newPassword, cancellationToken);
|
||||
if (!result.Succeeded)
|
||||
{
|
||||
return result;
|
||||
return await LogResultAsync(result, user);
|
||||
}
|
||||
return await UpdateAsync(user, cancellationToken);
|
||||
return await LogResultAsync(await UpdateUserAsync(user, cancellationToken), user);
|
||||
}
|
||||
|
||||
// Update the security stamp if the store supports it
|
||||
|
|
@ -851,7 +896,7 @@ namespace Microsoft.AspNet.Identity
|
|||
}
|
||||
await loginStore.RemoveLoginAsync(user, loginProvider, providerKey, cancellationToken);
|
||||
await UpdateSecurityStampInternal(user, cancellationToken);
|
||||
return await UpdateAsync(user, cancellationToken);
|
||||
return await LogResultAsync(await UpdateUserAsync(user, cancellationToken), user);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -877,10 +922,10 @@ namespace Microsoft.AspNet.Identity
|
|||
var existingUser = await FindByLoginAsync(login.LoginProvider, login.ProviderKey, cancellationToken);
|
||||
if (existingUser != null)
|
||||
{
|
||||
return IdentityResult.Failed(Resources.ExternalLoginExists);
|
||||
return await LogResultAsync(IdentityResult.Failed(ErrorDescriber.LoginAlreadyAssociated()), user);
|
||||
}
|
||||
await loginStore.AddLoginAsync(user, login, cancellationToken);
|
||||
return await UpdateAsync(user, cancellationToken);
|
||||
return await LogResultAsync(await UpdateUserAsync(user, cancellationToken), user);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -956,7 +1001,7 @@ namespace Microsoft.AspNet.Identity
|
|||
throw new ArgumentNullException("user");
|
||||
}
|
||||
await claimStore.AddClaimsAsync(user, claims, cancellationToken);
|
||||
return await UpdateAsync(user, cancellationToken);
|
||||
return await LogResultAsync(await UpdateUserAsync(user, cancellationToken), user);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -985,7 +1030,7 @@ namespace Microsoft.AspNet.Identity
|
|||
throw new ArgumentNullException("user");
|
||||
}
|
||||
await claimStore.ReplaceClaimAsync(user, claim, newClaim, cancellationToken);
|
||||
return await UpdateAsync(user, cancellationToken);
|
||||
return await LogResultAsync(await UpdateUserAsync(user, cancellationToken), user);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -1032,7 +1077,7 @@ namespace Microsoft.AspNet.Identity
|
|||
throw new ArgumentNullException("claims");
|
||||
}
|
||||
await claimStore.RemoveClaimsAsync(user, claims, cancellationToken);
|
||||
return await UpdateAsync(user, cancellationToken);
|
||||
return await LogResultAsync(await UpdateUserAsync(user, cancellationToken), user);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -1082,10 +1127,10 @@ namespace Microsoft.AspNet.Identity
|
|||
var userRoles = await userRoleStore.GetRolesAsync(user, cancellationToken);
|
||||
if (userRoles.Contains(role))
|
||||
{
|
||||
return new IdentityResult(Resources.UserAlreadyInRole);
|
||||
return await LogResultAsync(IdentityResult.Failed(ErrorDescriber.UserAlreadyInRole(role)), user);
|
||||
}
|
||||
await userRoleStore.AddToRoleAsync(user, role, cancellationToken);
|
||||
return await UpdateAsync(user, cancellationToken);
|
||||
return await LogResultAsync(await UpdateUserAsync(user, cancellationToken), user);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -1113,11 +1158,11 @@ namespace Microsoft.AspNet.Identity
|
|||
{
|
||||
if (userRoles.Contains(role))
|
||||
{
|
||||
return new IdentityResult(Resources.UserAlreadyInRole);
|
||||
return await LogResultAsync(IdentityResult.Failed(ErrorDescriber.UserAlreadyInRole(role)), user);
|
||||
}
|
||||
await userRoleStore.AddToRoleAsync(user, role, cancellationToken);
|
||||
}
|
||||
return await UpdateAsync(user, cancellationToken);
|
||||
return await LogResultAsync(await UpdateUserAsync(user, cancellationToken), user);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -1138,10 +1183,10 @@ namespace Microsoft.AspNet.Identity
|
|||
}
|
||||
if (!await userRoleStore.IsInRoleAsync(user, role, cancellationToken))
|
||||
{
|
||||
return new IdentityResult(Resources.UserNotInRole);
|
||||
return await LogResultAsync(IdentityResult.Failed(ErrorDescriber.UserNotInRole(role)), user);
|
||||
}
|
||||
await userRoleStore.RemoveFromRoleAsync(user, role, cancellationToken);
|
||||
return await UpdateAsync(user, cancellationToken);
|
||||
return await LogResultAsync(await UpdateUserAsync(user, cancellationToken), user);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -1168,11 +1213,11 @@ namespace Microsoft.AspNet.Identity
|
|||
{
|
||||
if (!await userRoleStore.IsInRoleAsync(user, role, cancellationToken))
|
||||
{
|
||||
return new IdentityResult(Resources.UserNotInRole);
|
||||
return await LogResultAsync(IdentityResult.Failed(ErrorDescriber.UserNotInRole(role)), user);
|
||||
}
|
||||
await userRoleStore.RemoveFromRoleAsync(user, role, cancellationToken);
|
||||
}
|
||||
return await UpdateAsync(user, cancellationToken);
|
||||
return await LogResultAsync(await UpdateUserAsync(user, cancellationToken), user);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -1213,10 +1258,10 @@ namespace Microsoft.AspNet.Identity
|
|||
}
|
||||
|
||||
// IUserEmailStore methods
|
||||
internal IUserEmailStore<TUser> GetEmailStore()
|
||||
internal IUserEmailStore<TUser> GetEmailStore(bool throwOnFail = true)
|
||||
{
|
||||
var cast = Store as IUserEmailStore<TUser>;
|
||||
if (cast == null)
|
||||
if (throwOnFail && cast == null)
|
||||
{
|
||||
throw new NotSupportedException(Resources.StoreNotIUserEmailStore);
|
||||
}
|
||||
|
|
@ -1261,7 +1306,7 @@ namespace Microsoft.AspNet.Identity
|
|||
await store.SetEmailAsync(user, email, cancellationToken);
|
||||
await store.SetEmailConfirmedAsync(user, false, cancellationToken);
|
||||
await UpdateSecurityStampInternal(user, cancellationToken);
|
||||
return await UpdateAsync(user, cancellationToken);
|
||||
return await LogResultAsync(await UpdateUserAsync(user, cancellationToken), user);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -1279,20 +1324,41 @@ namespace Microsoft.AspNet.Identity
|
|||
{
|
||||
throw new ArgumentNullException("email");
|
||||
}
|
||||
return store.FindByEmailAsync(email, cancellationToken);
|
||||
return store.FindByEmailAsync(NormalizeKey(email), cancellationToken);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Update the user's normalized email
|
||||
/// </summary>
|
||||
/// <param name="user"></param>
|
||||
/// <param name="cancellationToken"></param>
|
||||
/// <returns></returns>
|
||||
public virtual async Task UpdateNormalizedEmailAsync(TUser user,
|
||||
CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
var store = GetEmailStore(throwOnFail: false);
|
||||
if (store != null)
|
||||
{
|
||||
var email = await GetEmailAsync(user, cancellationToken);
|
||||
await store.SetNormalizedEmailAsync(user, NormalizeKey(email), cancellationToken);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Get the confirmation token for the user
|
||||
/// </summary>
|
||||
/// <param name="user"></param>
|
||||
/// <param name="cancellationToken"></param>
|
||||
/// <returns></returns>
|
||||
public virtual Task<string> GenerateEmailConfirmationTokenAsync(TUser user,
|
||||
public async virtual Task<string> GenerateEmailConfirmationTokenAsync(TUser user,
|
||||
CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
ThrowIfDisposed();
|
||||
return GenerateUserTokenAsync(user, Options.EmailConfirmationTokenProvider, "Confirmation", cancellationToken);
|
||||
var token = await GenerateUserTokenAsync(user, Options.EmailConfirmationTokenProvider, "Confirmation", cancellationToken);
|
||||
await LogResultAsync(IdentityResult.Success, user);
|
||||
|
||||
return token;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -1313,10 +1379,10 @@ namespace Microsoft.AspNet.Identity
|
|||
}
|
||||
if (!await VerifyUserTokenAsync(user, Options.EmailConfirmationTokenProvider, "Confirmation", token, cancellationToken))
|
||||
{
|
||||
return IdentityResult.Failed(Resources.InvalidToken);
|
||||
return await LogResultAsync(IdentityResult.Failed(ErrorDescriber.InvalidToken()), user);
|
||||
}
|
||||
await store.SetEmailConfirmedAsync(user, true, cancellationToken);
|
||||
return await UpdateAsync(user, cancellationToken);
|
||||
return await LogResultAsync(await UpdateUserAsync(user, cancellationToken), user);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -1352,7 +1418,10 @@ namespace Microsoft.AspNet.Identity
|
|||
CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
ThrowIfDisposed();
|
||||
return await GenerateUserTokenAsync(user, Options.ChangeEmailTokenProvider, GetChangeEmailPurpose(newEmail), cancellationToken);
|
||||
var token = await GenerateUserTokenAsync(user, Options.ChangeEmailTokenProvider, GetChangeEmailPurpose(newEmail), cancellationToken);
|
||||
await LogResultAsync(IdentityResult.Success, user);
|
||||
|
||||
return token;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -1374,13 +1443,13 @@ namespace Microsoft.AspNet.Identity
|
|||
// Make sure the token is valid and the stamp matches
|
||||
if (!await VerifyUserTokenAsync(user, Options.ChangeEmailTokenProvider, GetChangeEmailPurpose(newEmail), token, cancellationToken))
|
||||
{
|
||||
return IdentityResult.Failed(Resources.InvalidToken);
|
||||
return await LogResultAsync(IdentityResult.Failed(ErrorDescriber.InvalidToken()), user);
|
||||
}
|
||||
var store = GetEmailStore();
|
||||
await store.SetEmailAsync(user, newEmail, cancellationToken);
|
||||
await store.SetEmailConfirmedAsync(user, true, cancellationToken);
|
||||
await UpdateSecurityStampInternal(user, cancellationToken);
|
||||
return await UpdateAsync(user, cancellationToken);
|
||||
return await LogResultAsync(await UpdateUserAsync(user, cancellationToken), user);
|
||||
}
|
||||
|
||||
// IUserPhoneNumberStore methods
|
||||
|
|
@ -1431,7 +1500,7 @@ namespace Microsoft.AspNet.Identity
|
|||
await store.SetPhoneNumberAsync(user, phoneNumber, cancellationToken);
|
||||
await store.SetPhoneNumberConfirmedAsync(user, false, cancellationToken);
|
||||
await UpdateSecurityStampInternal(user, cancellationToken);
|
||||
return await UpdateAsync(user, cancellationToken);
|
||||
return await LogResultAsync(await UpdateUserAsync(user, cancellationToken), user);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -1453,12 +1522,12 @@ namespace Microsoft.AspNet.Identity
|
|||
}
|
||||
if (!await VerifyChangePhoneNumberTokenAsync(user, token, phoneNumber, cancellationToken))
|
||||
{
|
||||
return IdentityResult.Failed(Resources.InvalidToken);
|
||||
return await LogResultAsync(IdentityResult.Failed(ErrorDescriber.InvalidToken()), user);
|
||||
}
|
||||
await store.SetPhoneNumberAsync(user, phoneNumber, cancellationToken);
|
||||
await store.SetPhoneNumberConfirmedAsync(user, true, cancellationToken);
|
||||
await UpdateSecurityStampInternal(user, cancellationToken);
|
||||
return await UpdateAsync(user, cancellationToken);
|
||||
return await LogResultAsync(await UpdateUserAsync(user, cancellationToken), user);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -1497,9 +1566,12 @@ namespace Microsoft.AspNet.Identity
|
|||
CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
ThrowIfDisposed();
|
||||
return Rfc6238AuthenticationService.GenerateCode(
|
||||
var token = Rfc6238AuthenticationService.GenerateCode(
|
||||
await CreateSecurityTokenAsync(user, cancellationToken), phoneNumber)
|
||||
.ToString(CultureInfo.InvariantCulture);
|
||||
|
||||
await LogResultAsync(IdentityResult.Success, user);
|
||||
return token;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -1517,8 +1589,13 @@ namespace Microsoft.AspNet.Identity
|
|||
int code;
|
||||
if (securityToken != null && Int32.TryParse(token, out code))
|
||||
{
|
||||
return Rfc6238AuthenticationService.ValidateCode(securityToken, code, phoneNumber);
|
||||
if (Rfc6238AuthenticationService.ValidateCode(securityToken, code, phoneNumber))
|
||||
{
|
||||
await LogResultAsync(IdentityResult.Success, user);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
await LogResultAsync(IdentityResult.Failed(ErrorDescriber.InvalidToken()), user);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -1547,7 +1624,18 @@ namespace Microsoft.AspNet.Identity
|
|||
throw new NotSupportedException(string.Format(CultureInfo.CurrentCulture, Resources.NoTokenProvider, tokenProvider));
|
||||
}
|
||||
// Make sure the token is valid
|
||||
return await _tokenProviders[tokenProvider].ValidateAsync(purpose, token, this, user, cancellationToken);
|
||||
var result = await _tokenProviders[tokenProvider].ValidateAsync(purpose, token, this, user, cancellationToken);
|
||||
|
||||
if (result)
|
||||
{
|
||||
await LogResultAsync(IdentityResult.Success, user);
|
||||
}
|
||||
else
|
||||
{
|
||||
await LogResultAsync(IdentityResult.Failed(ErrorDescriber.InvalidToken()), user);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -1573,7 +1661,11 @@ namespace Microsoft.AspNet.Identity
|
|||
{
|
||||
throw new NotSupportedException(string.Format(CultureInfo.CurrentCulture, Resources.NoTokenProvider, tokenProvider));
|
||||
}
|
||||
return await _tokenProviders[tokenProvider].GenerateAsync(purpose, this, user, cancellationToken);
|
||||
|
||||
var token = await _tokenProviders[tokenProvider].GenerateAsync(purpose, this, user, cancellationToken);
|
||||
await LogResultAsync(IdentityResult.Success, user);
|
||||
|
||||
return token;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -1651,7 +1743,18 @@ namespace Microsoft.AspNet.Identity
|
|||
Resources.NoTokenProvider, tokenProvider));
|
||||
}
|
||||
// Make sure the token is valid
|
||||
return await _tokenProviders[tokenProvider].ValidateAsync("TwoFactor", token, this, user, cancellationToken);
|
||||
var result = await _tokenProviders[tokenProvider].ValidateAsync("TwoFactor", token, this, user, cancellationToken);
|
||||
|
||||
if (result)
|
||||
{
|
||||
await LogResultAsync(IdentityResult.Success, user);
|
||||
}
|
||||
else
|
||||
{
|
||||
await LogResultAsync(IdentityResult.Failed(ErrorDescriber.InvalidToken()), user);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -1674,7 +1777,10 @@ namespace Microsoft.AspNet.Identity
|
|||
throw new NotSupportedException(String.Format(CultureInfo.CurrentCulture,
|
||||
Resources.NoTokenProvider, tokenProvider));
|
||||
}
|
||||
return await _tokenProviders[tokenProvider].GenerateAsync("TwoFactor", this, user, cancellationToken);
|
||||
var token = await _tokenProviders[tokenProvider].GenerateAsync("TwoFactor", this, user, cancellationToken);
|
||||
await LogResultAsync(IdentityResult.Success, user);
|
||||
|
||||
return token;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -1703,7 +1809,7 @@ namespace Microsoft.AspNet.Identity
|
|||
Resources.NoTokenProvider, tokenProvider));
|
||||
}
|
||||
await _tokenProviders[tokenProvider].NotifyAsync(token, this, user, cancellationToken);
|
||||
return IdentityResult.Success;
|
||||
return await LogResultAsync(IdentityResult.Success, user);
|
||||
}
|
||||
|
||||
// IUserFactorStore methods
|
||||
|
|
@ -1753,7 +1859,7 @@ namespace Microsoft.AspNet.Identity
|
|||
}
|
||||
await store.SetTwoFactorEnabledAsync(user, enabled, cancellationToken);
|
||||
await UpdateSecurityStampInternal(user, cancellationToken);
|
||||
return await UpdateAsync(user, cancellationToken);
|
||||
return await LogResultAsync(await UpdateUserAsync(user, cancellationToken), user);
|
||||
}
|
||||
|
||||
// Messaging methods
|
||||
|
|
@ -1765,7 +1871,7 @@ namespace Microsoft.AspNet.Identity
|
|||
/// <param name="message"></param>
|
||||
/// <param name="cancellationToken"></param>
|
||||
/// <returns></returns>
|
||||
public virtual async Task<IdentityResult> SendMessageAsync(string messageProvider, IdentityMessage message,
|
||||
public virtual async Task<IdentityResult> SendMessageAsync(string messageProvider, IdentityMessage message,
|
||||
CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
ThrowIfDisposed();
|
||||
|
|
@ -1833,7 +1939,7 @@ namespace Microsoft.AspNet.Identity
|
|||
throw new ArgumentNullException("user");
|
||||
}
|
||||
await store.SetLockoutEnabledAsync(user, enabled, cancellationToken);
|
||||
return await UpdateAsync(user, cancellationToken);
|
||||
return await LogResultAsync(await UpdateUserAsync(user, cancellationToken), user);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -1890,10 +1996,10 @@ namespace Microsoft.AspNet.Identity
|
|||
}
|
||||
if (!await store.GetLockoutEnabledAsync(user, cancellationToken).ConfigureAwait((false)))
|
||||
{
|
||||
return IdentityResult.Failed(Resources.LockoutNotEnabled);
|
||||
return await LogResultAsync(IdentityResult.Failed(ErrorDescriber.UserLockoutNotEnabled()), user);
|
||||
}
|
||||
await store.SetLockoutEndDateAsync(user, lockoutEnd, cancellationToken);
|
||||
return await UpdateAsync(user, cancellationToken);
|
||||
return await LogResultAsync(await UpdateUserAsync(user, cancellationToken), user);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -1917,12 +2023,12 @@ namespace Microsoft.AspNet.Identity
|
|||
var count = await store.IncrementAccessFailedCountAsync(user, cancellationToken);
|
||||
if (count < Options.Lockout.MaxFailedAccessAttempts)
|
||||
{
|
||||
return await UpdateAsync(user, cancellationToken);
|
||||
return await LogResultAsync(await UpdateUserAsync(user, cancellationToken), user);
|
||||
}
|
||||
await store.SetLockoutEndDateAsync(user, DateTimeOffset.UtcNow.Add(Options.Lockout.DefaultLockoutTimeSpan),
|
||||
cancellationToken);
|
||||
await store.ResetAccessFailedCountAsync(user, cancellationToken);
|
||||
return await UpdateAsync(user, cancellationToken);
|
||||
return await LogResultAsync(await UpdateUserAsync(user, cancellationToken), user);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -1941,7 +2047,7 @@ namespace Microsoft.AspNet.Identity
|
|||
throw new ArgumentNullException("user");
|
||||
}
|
||||
await store.ResetAccessFailedCountAsync(user, cancellationToken);
|
||||
return await UpdateAsync(user, cancellationToken);
|
||||
return await LogResultAsync(await UpdateUserAsync(user, cancellationToken), user);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -1962,6 +2068,75 @@ namespace Microsoft.AspNet.Identity
|
|||
return await store.GetAccessFailedCountAsync(user, cancellationToken);
|
||||
}
|
||||
|
||||
public virtual Task<IList<TUser>> GetUsersForClaimAsync(Claim claim,
|
||||
CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
ThrowIfDisposed();
|
||||
var store = GetClaimStore();
|
||||
if (claim == null)
|
||||
{
|
||||
throw new ArgumentNullException("claim");
|
||||
}
|
||||
return store.GetUsersForClaimAsync(claim, cancellationToken);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get all the users in a role
|
||||
/// </summary>
|
||||
/// <param name="role"></param>
|
||||
/// <param name="cancellationToken"></param>
|
||||
/// <returns></returns>
|
||||
public virtual Task<IList<TUser>> GetUsersInRoleAsync(string roleName,
|
||||
CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
ThrowIfDisposed();
|
||||
var store = GetUserRoleStore();
|
||||
if (roleName == null)
|
||||
{
|
||||
throw new ArgumentNullException("role");
|
||||
}
|
||||
|
||||
return store.GetUsersInRoleAsync(roleName, cancellationToken);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Logs the current Identity Result and returns result object
|
||||
/// </summary>
|
||||
/// <param name="result"></param>
|
||||
/// <param name="user"></param>
|
||||
/// <param name="methodName"></param>
|
||||
/// <returns></returns>
|
||||
protected async Task<IdentityResult> LogResultAsync(IdentityResult result,
|
||||
TUser user, [System.Runtime.CompilerServices.CallerMemberName] string methodName = "")
|
||||
{
|
||||
result.Log(Logger, Resources.FormatLoggingResultMessage(methodName, await GetUserIdAsync(user)));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Logs result of operation being true/false
|
||||
/// </summary>
|
||||
/// <param name="result"></param>
|
||||
/// <param name="user"></param>
|
||||
/// <param name="methodName"></param>
|
||||
/// <returns>result</returns>
|
||||
protected async Task<bool> LogResultAsync(bool result,
|
||||
TUser user, [System.Runtime.CompilerServices.CallerMemberName] string methodName = "")
|
||||
{
|
||||
var baseMessage = Resources.FormatLoggingResultMessage(methodName, await GetUserIdAsync(user));
|
||||
if (result)
|
||||
{
|
||||
Logger.WriteInformation(string.Format("{0} : {1}", baseMessage, result.ToString()));
|
||||
}
|
||||
else
|
||||
{
|
||||
Logger.WriteWarning(string.Format("{0} : {1}", baseMessage, result.ToString()));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private void ThrowIfDisposed()
|
||||
{
|
||||
if (_disposed)
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@
|
|||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
#if ASPNET50
|
||||
using System.Net.Mail;
|
||||
#endif
|
||||
|
|
@ -19,6 +18,13 @@ namespace Microsoft.AspNet.Identity
|
|||
/// <typeparam name="TUser"></typeparam>
|
||||
public class UserValidator<TUser> : IUserValidator<TUser> where TUser : class
|
||||
{
|
||||
public UserValidator(IdentityErrorDescriber errors = null)
|
||||
{
|
||||
Describer = errors ?? new IdentityErrorDescriber();
|
||||
}
|
||||
|
||||
public IdentityErrorDescriber Describer { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Validates a user before saving
|
||||
/// </summary>
|
||||
|
|
@ -37,7 +43,7 @@ namespace Microsoft.AspNet.Identity
|
|||
{
|
||||
throw new ArgumentNullException("user");
|
||||
}
|
||||
var errors = new List<string>();
|
||||
var errors = new List<IdentityError>();
|
||||
await ValidateUserName(manager, user, errors);
|
||||
if (manager.Options.User.RequireUniqueEmail)
|
||||
{
|
||||
|
|
@ -46,16 +52,16 @@ namespace Microsoft.AspNet.Identity
|
|||
return errors.Count > 0 ? IdentityResult.Failed(errors.ToArray()) : IdentityResult.Success;
|
||||
}
|
||||
|
||||
private async Task ValidateUserName(UserManager<TUser> manager, TUser user, ICollection<string> errors)
|
||||
private async Task ValidateUserName(UserManager<TUser> manager, TUser user, ICollection<IdentityError> errors)
|
||||
{
|
||||
var userName = await manager.GetUserNameAsync(user);
|
||||
if (string.IsNullOrWhiteSpace(userName))
|
||||
{
|
||||
errors.Add(String.Format(CultureInfo.CurrentCulture, Resources.PropertyTooShort, "UserName"));
|
||||
errors.Add(Describer.InvalidUserName(userName));
|
||||
}
|
||||
else if (manager.Options.User.UserNameValidationRegex != null && !Regex.IsMatch(userName, manager.Options.User.UserNameValidationRegex))
|
||||
{
|
||||
errors.Add(String.Format(CultureInfo.CurrentCulture, Resources.InvalidUserName, userName));
|
||||
errors.Add(Describer.InvalidUserName(userName));
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -63,18 +69,18 @@ namespace Microsoft.AspNet.Identity
|
|||
if (owner != null &&
|
||||
!string.Equals(await manager.GetUserIdAsync(owner), await manager.GetUserIdAsync(user)))
|
||||
{
|
||||
errors.Add(String.Format(CultureInfo.CurrentCulture, Resources.DuplicateName, userName));
|
||||
errors.Add(Describer.DuplicateUserName(userName));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// make sure email is not empty, valid, and unique
|
||||
private static async Task ValidateEmail(UserManager<TUser> manager, TUser user, List<string> errors)
|
||||
private async Task ValidateEmail(UserManager<TUser> manager, TUser user, List<IdentityError> errors)
|
||||
{
|
||||
var email = await manager.GetEmailAsync(user);
|
||||
if (string.IsNullOrWhiteSpace(email))
|
||||
{
|
||||
errors.Add(String.Format(CultureInfo.CurrentCulture, Resources.PropertyTooShort, "Email"));
|
||||
errors.Add(Describer.InvalidEmail(email));
|
||||
return;
|
||||
}
|
||||
#if ASPNET50
|
||||
|
|
@ -84,7 +90,7 @@ namespace Microsoft.AspNet.Identity
|
|||
}
|
||||
catch (FormatException)
|
||||
{
|
||||
errors.Add(String.Format(CultureInfo.CurrentCulture, Resources.InvalidEmail, email));
|
||||
errors.Add(Describer.InvalidEmail(email));
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
|
@ -92,7 +98,7 @@ namespace Microsoft.AspNet.Identity
|
|||
if (owner != null &&
|
||||
!string.Equals(await manager.GetUserIdAsync(owner), await manager.GetUserIdAsync(user)))
|
||||
{
|
||||
errors.Add(String.Format(CultureInfo.CurrentCulture, Resources.DuplicateEmail, email));
|
||||
errors.Add(Describer.DuplicateEmail(email));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,7 +7,8 @@
|
|||
"Microsoft.AspNet.Security.DataProtection": "1.0.0-*",
|
||||
"Microsoft.Framework.ConfigurationModel": "1.0.0-*",
|
||||
"Microsoft.Framework.DependencyInjection" : "1.0.0-*",
|
||||
"Microsoft.Framework.OptionsModel": "1.0.0-*"
|
||||
"Microsoft.Framework.OptionsModel": "1.0.0-*",
|
||||
"Microsoft.Framework.Logging": "1.0.0-*"
|
||||
},
|
||||
"frameworks": {
|
||||
"aspnet50": {},
|
||||
|
|
|
|||
|
|
@ -1,31 +0,0 @@
|
|||
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using Microsoft.AspNet.Identity.EntityFramework;
|
||||
using Microsoft.AspNet.Identity.EntityFramework.InMemory.Test;
|
||||
using Microsoft.Data.Entity;
|
||||
using Microsoft.Framework.DependencyInjection;
|
||||
|
||||
namespace Microsoft.AspNet.Identity
|
||||
{
|
||||
public static class EntityInMemoryTestServiceCollectionExtensions
|
||||
{
|
||||
public static IdentityBuilder AddIdentityInMemory(this ServiceCollection services, InMemoryContext context)
|
||||
{
|
||||
return services.AddIdentityInMemory<IdentityUser, IdentityRole, InMemoryContext>(context);
|
||||
}
|
||||
|
||||
public static IdentityBuilder AddIdentityInMemory<TUser, TRole, TDbContext>(this ServiceCollection services, TDbContext context)
|
||||
where TUser : IdentityUser
|
||||
where TRole : IdentityRole
|
||||
where TDbContext : DbContext
|
||||
{
|
||||
var builder = services.AddIdentity<TUser, TRole>();
|
||||
builder.AddDefaultTokenProviders();
|
||||
services.AddInstance<IUserStore<TUser>>(new InMemoryUserStore<TUser, TDbContext>(context));
|
||||
var store = new RoleStore<TRole, TDbContext>(context);
|
||||
services.AddInstance<IRoleStore<TRole>>(store);
|
||||
return builder;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -3,41 +3,25 @@
|
|||
|
||||
using System;
|
||||
using Microsoft.Data.Entity;
|
||||
using Microsoft.Data.Entity.Metadata;
|
||||
|
||||
namespace Microsoft.AspNet.Identity.EntityFramework.InMemory.Test
|
||||
{
|
||||
public class InMemoryContext :
|
||||
InMemoryContext<IdentityUser, IdentityRole, string, IdentityUserLogin, IdentityUserRole, IdentityUserClaim>
|
||||
InMemoryContext<IdentityUser, IdentityRole, string>
|
||||
{
|
||||
public InMemoryContext() { }
|
||||
public InMemoryContext(IServiceProvider serviceProvider) : base(serviceProvider) { }
|
||||
}
|
||||
|
||||
public class InMemoryContext<TUser> :
|
||||
InMemoryContext<TUser, IdentityRole, string, IdentityUserLogin, IdentityUserRole, IdentityUserClaim>
|
||||
InMemoryContext<TUser, IdentityRole, string>
|
||||
where TUser : IdentityUser
|
||||
{
|
||||
public InMemoryContext() { }
|
||||
public InMemoryContext(IServiceProvider serviceProvider) : base(serviceProvider) { }
|
||||
}
|
||||
|
||||
public class InMemoryContext<TUser, TRole, TKey, TUserLogin, TUserRole, TUserClaim> : DbContext
|
||||
public class InMemoryContext<TUser, TRole, TKey> : IdentityDbContext<TUser,TRole,TKey>
|
||||
where TUser : IdentityUser<TKey>
|
||||
where TRole : IdentityRole<TKey>
|
||||
where TUserLogin : IdentityUserLogin<TKey>
|
||||
where TUserRole : IdentityUserRole<TKey>
|
||||
where TUserClaim : IdentityUserClaim<TKey>
|
||||
where TKey : IEquatable<TKey>
|
||||
{
|
||||
|
||||
public DbSet<TUser> Users { get; set; }
|
||||
public DbSet<TRole> Roles { get; set; }
|
||||
public DbSet<IdentityRoleClaim> RoleClaims { get; set; }
|
||||
|
||||
public InMemoryContext(IServiceProvider serviceProvider)
|
||||
: base(serviceProvider) { }
|
||||
|
||||
public InMemoryContext() { }
|
||||
|
||||
protected override void OnConfiguring(DbContextOptions builder)
|
||||
|
|
@ -45,50 +29,5 @@ namespace Microsoft.AspNet.Identity.EntityFramework.InMemory.Test
|
|||
// Want fresh in memory store for tests always for now
|
||||
builder.UseInMemoryStore(persist: false);
|
||||
}
|
||||
|
||||
protected override void OnModelCreating(ModelBuilder builder)
|
||||
{
|
||||
builder.Entity<TUser>(b =>
|
||||
{
|
||||
b.Key(u => u.Id);
|
||||
b.Property(u => u.UserName);
|
||||
b.ForRelational().Table("AspNetUsers");
|
||||
});
|
||||
|
||||
builder.Entity<TRole>(b =>
|
||||
{
|
||||
b.Key(r => r.Id);
|
||||
b.ForRelational().Table("AspNetRoles");
|
||||
});
|
||||
|
||||
builder.Entity<TUserRole>(b =>
|
||||
{
|
||||
b.Key(r => new { r.UserId, r.RoleId });
|
||||
b.ForeignKey<TUser>(f => f.UserId);
|
||||
b.ForeignKey<TRole>(f => f.RoleId);
|
||||
b.ForRelational().Table("AspNetUserRoles");
|
||||
});
|
||||
|
||||
builder.Entity<TUserLogin>(b =>
|
||||
{
|
||||
b.Key(l => new { l.LoginProvider, l.ProviderKey, l.UserId });
|
||||
b.ForeignKey<TUser>(f => f.UserId);
|
||||
b.ForRelational().Table("AspNetUserLogins");
|
||||
});
|
||||
|
||||
builder.Entity<TUserClaim>(b =>
|
||||
{
|
||||
b.Key(c => c.Id);
|
||||
b.ForeignKey<TUser>(f => f.UserId);
|
||||
b.ForRelational().Table("AspNetUserClaims");
|
||||
});
|
||||
|
||||
builder.Entity<IdentityRoleClaim<TKey>>(b =>
|
||||
{
|
||||
b.Key(c => c.Id);
|
||||
b.ForeignKey<TRole>(f => f.RoleId);
|
||||
b.ForRelational().Table("AspNetRoleClaims");
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,6 +1,7 @@
|
|||
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using Microsoft.AspNet.Identity.Test;
|
||||
using Microsoft.Framework.DependencyInjection;
|
||||
|
||||
|
|
@ -15,7 +16,7 @@ namespace Microsoft.AspNet.Identity.EntityFramework.InMemory.Test
|
|||
|
||||
protected override void AddUserStore(IServiceCollection services, object context = null)
|
||||
{
|
||||
services.AddInstance<IUserStore<IdentityUser>>(new InMemoryUserStore<IdentityUser, InMemoryContext>((InMemoryContext)context));
|
||||
services.AddInstance<IUserStore<IdentityUser>>(new UserStore<IdentityUser>((InMemoryContext)context));
|
||||
}
|
||||
|
||||
protected override void AddRoleStore(IServiceCollection services, object context = null)
|
||||
|
|
|
|||
|
|
@ -1,929 +0,0 @@
|
|||
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Linq.Expressions;
|
||||
using System.Security.Claims;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Data.Entity;
|
||||
|
||||
namespace Microsoft.AspNet.Identity.EntityFramework.InMemory.Test
|
||||
{
|
||||
public class InMemoryUserStore : InMemoryUserStore<IdentityUser, InMemoryContext>
|
||||
{
|
||||
public InMemoryUserStore(InMemoryContext context) : base(context) { }
|
||||
}
|
||||
|
||||
public class InMemoryUserStore<TUser> : InMemoryUserStore<TUser, InMemoryContext>
|
||||
where TUser : IdentityUser
|
||||
{
|
||||
public InMemoryUserStore(InMemoryContext context) : base(context) { }
|
||||
}
|
||||
|
||||
public class InMemoryUserStore<TUser, TContext> : InMemoryUserStore<TUser, IdentityRole, string, IdentityUserLogin, IdentityUserRole, IdentityUserClaim, TContext>
|
||||
where TUser:IdentityUser
|
||||
where TContext : DbContext
|
||||
{
|
||||
public InMemoryUserStore(TContext context) : base(context) { }
|
||||
}
|
||||
|
||||
public class InMemoryUserStore<TUser, TRole, TKey, TUserLogin, TUserRole, TUserClaim, TContext> :
|
||||
IUserLoginStore<TUser>,
|
||||
IUserClaimStore<TUser>,
|
||||
IUserRoleStore<TUser>,
|
||||
IUserPasswordStore<TUser>,
|
||||
IUserSecurityStampStore<TUser>,
|
||||
IQueryableUserStore<TUser>,
|
||||
IUserEmailStore<TUser>,
|
||||
IUserPhoneNumberStore<TUser>,
|
||||
IUserTwoFactorStore<TUser>,
|
||||
IUserLockoutStore<TUser>
|
||||
where TKey : IEquatable<TKey>
|
||||
where TUser : IdentityUser<TKey>
|
||||
where TRole : IdentityRole<TKey>
|
||||
where TUserLogin : IdentityUserLogin<TKey>, new()
|
||||
where TUserRole : IdentityUserRole<TKey>, new()
|
||||
where TUserClaim : IdentityUserClaim<TKey>, new()
|
||||
where TContext : DbContext
|
||||
{
|
||||
private bool _disposed;
|
||||
|
||||
public InMemoryUserStore(TContext context)
|
||||
{
|
||||
if (context == null)
|
||||
{
|
||||
throw new ArgumentNullException("context");
|
||||
}
|
||||
Context = context;
|
||||
AutoSaveChanges = true;
|
||||
}
|
||||
|
||||
public TContext Context { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// If true will call SaveChanges after CreateAsync/UpdateAsync/DeleteAsync
|
||||
/// </summary>
|
||||
public bool AutoSaveChanges { get; set; }
|
||||
|
||||
private Task SaveChanges(CancellationToken cancellationToken)
|
||||
{
|
||||
return AutoSaveChanges ? Context.SaveChangesAsync(cancellationToken) : Task.FromResult(0);
|
||||
}
|
||||
|
||||
protected virtual Task<TUser> GetUserAggregate(Expression<Func<TUser, bool>> filter, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
return Task.FromResult(Users.SingleOrDefault(filter));
|
||||
// TODO: return Users.SingleOrDefaultAsync(filter, cancellationToken);
|
||||
//Include(u => u.Roles)
|
||||
//.Include(u => u.Claims)
|
||||
//.Include(u => u.Logins)
|
||||
}
|
||||
|
||||
public Task<string> GetUserIdAsync(TUser user, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
ThrowIfDisposed();
|
||||
if (user == null)
|
||||
{
|
||||
throw new ArgumentNullException("user");
|
||||
}
|
||||
return Task.FromResult(Convert.ToString(user.Id, CultureInfo.InvariantCulture));
|
||||
}
|
||||
|
||||
public Task<string> GetUserNameAsync(TUser user, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
ThrowIfDisposed();
|
||||
if (user == null)
|
||||
{
|
||||
throw new ArgumentNullException("user");
|
||||
}
|
||||
return Task.FromResult(user.UserName);
|
||||
}
|
||||
|
||||
public Task SetUserNameAsync(TUser user, string userName, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
ThrowIfDisposed();
|
||||
if (user == null)
|
||||
{
|
||||
throw new ArgumentNullException("user");
|
||||
}
|
||||
user.UserName = userName;
|
||||
return Task.FromResult(0);
|
||||
}
|
||||
|
||||
public Task<string> GetNormalizedUserNameAsync(TUser user, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
ThrowIfDisposed();
|
||||
if (user == null)
|
||||
{
|
||||
throw new ArgumentNullException("user");
|
||||
}
|
||||
return Task.FromResult(user.NormalizedUserName);
|
||||
}
|
||||
|
||||
public Task SetNormalizedUserNameAsync(TUser user, string userName, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
ThrowIfDisposed();
|
||||
if (user == null)
|
||||
{
|
||||
throw new ArgumentNullException("user");
|
||||
}
|
||||
user.NormalizedUserName = userName;
|
||||
return Task.FromResult(0);
|
||||
}
|
||||
|
||||
public async virtual Task CreateAsync(TUser user, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
ThrowIfDisposed();
|
||||
if (user == null)
|
||||
{
|
||||
throw new ArgumentNullException("user");
|
||||
}
|
||||
await Context.AddAsync(user, cancellationToken);
|
||||
await SaveChanges(cancellationToken);
|
||||
}
|
||||
|
||||
public async virtual Task UpdateAsync(TUser user, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
ThrowIfDisposed();
|
||||
if (user == null)
|
||||
{
|
||||
throw new ArgumentNullException("user");
|
||||
}
|
||||
Context.Update(user);
|
||||
await SaveChanges(cancellationToken);
|
||||
}
|
||||
|
||||
public async virtual Task DeleteAsync(TUser user, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
ThrowIfDisposed();
|
||||
if (user == null)
|
||||
{
|
||||
throw new ArgumentNullException("user");
|
||||
}
|
||||
Context.Remove(user);
|
||||
await SaveChanges(cancellationToken);
|
||||
}
|
||||
|
||||
public virtual TKey ConvertUserId(string userId)
|
||||
{
|
||||
return (TKey)Convert.ChangeType(userId, typeof(TKey));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Find a user by id
|
||||
/// </summary>
|
||||
/// <param name="userId"></param>
|
||||
/// <param name="cancellationToken"></param>
|
||||
/// <returns></returns>
|
||||
public virtual Task<TUser> FindByIdAsync(string userId, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
ThrowIfDisposed();
|
||||
var id = ConvertUserId(userId);
|
||||
return GetUserAggregate(u => u.Id.Equals(id), cancellationToken);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Find a user by name
|
||||
/// </summary>
|
||||
/// <param name="userName"></param>
|
||||
/// <param name="cancellationToken"></param>
|
||||
/// <returns></returns>
|
||||
public virtual Task<TUser> FindByNameAsync(string userName, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
ThrowIfDisposed();
|
||||
return GetUserAggregate(u => u.UserName.ToUpper() == userName.ToUpper(), cancellationToken);
|
||||
}
|
||||
|
||||
public IQueryable<TUser> Users
|
||||
{
|
||||
get { return Context.Set<TUser>(); }
|
||||
}
|
||||
|
||||
public async virtual Task AddLoginAsync(TUser user, UserLoginInfo login,
|
||||
CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
ThrowIfDisposed();
|
||||
if (user == null)
|
||||
{
|
||||
throw new ArgumentNullException("user");
|
||||
}
|
||||
var l = new TUserLogin
|
||||
{
|
||||
UserId = user.Id,
|
||||
ProviderKey = login.ProviderKey,
|
||||
LoginProvider = login.LoginProvider,
|
||||
ProviderDisplayName = login.ProviderDisplayName
|
||||
};
|
||||
await Context.Set<TUserLogin>().AddAsync(l, cancellationToken);
|
||||
user.Logins.Add(l);
|
||||
}
|
||||
|
||||
public virtual Task RemoveLoginAsync(TUser user, string loginProvider, string providerKey,
|
||||
CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
ThrowIfDisposed();
|
||||
if (user == null)
|
||||
{
|
||||
throw new ArgumentNullException("user");
|
||||
}
|
||||
var entry = user.Logins.SingleOrDefault(l => l.LoginProvider == loginProvider && l.ProviderKey == providerKey);
|
||||
if (entry != null)
|
||||
{
|
||||
user.Logins.Remove(entry);
|
||||
Context.Set<IdentityUserLogin<TKey>>().Remove(entry);
|
||||
}
|
||||
return Task.FromResult(0);
|
||||
}
|
||||
|
||||
public virtual Task<IList<UserLoginInfo>> GetLoginsAsync(TUser user, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
ThrowIfDisposed();
|
||||
if (user == null)
|
||||
{
|
||||
throw new ArgumentNullException("user");
|
||||
}
|
||||
IList<UserLoginInfo> result = user.Logins.Select(
|
||||
l => new UserLoginInfo(l.LoginProvider, l.ProviderKey, l.ProviderDisplayName))
|
||||
.ToList();
|
||||
return Task.FromResult(result);
|
||||
}
|
||||
|
||||
public async virtual Task<TUser> FindByLoginAsync(string loginProvider, string providerKey, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
ThrowIfDisposed();
|
||||
var userLogin = await Context.Set<TUserLogin>()
|
||||
.FirstOrDefaultAsync(l => l.LoginProvider == loginProvider && l.ProviderKey == providerKey);
|
||||
if (userLogin != null)
|
||||
{
|
||||
return await GetUserAggregate(u => u.Id.Equals(userLogin.UserId), cancellationToken);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set the password hash for a user
|
||||
/// </summary>
|
||||
/// <param name="user"></param>
|
||||
/// <param name="passwordHash"></param>
|
||||
/// <param name="cancellationToken"></param>
|
||||
/// <returns></returns>
|
||||
public virtual Task SetPasswordHashAsync(TUser user, string passwordHash, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
ThrowIfDisposed();
|
||||
if (user == null)
|
||||
{
|
||||
throw new ArgumentNullException("user");
|
||||
}
|
||||
user.PasswordHash = passwordHash;
|
||||
return Task.FromResult(0);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the password hash for a user
|
||||
/// </summary>
|
||||
/// <param name="user"></param>
|
||||
/// <param name="cancellationToken"></param>
|
||||
/// <returns></returns>
|
||||
public virtual Task<string> GetPasswordHashAsync(TUser user, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
ThrowIfDisposed();
|
||||
if (user == null)
|
||||
{
|
||||
throw new ArgumentNullException("user");
|
||||
}
|
||||
return Task.FromResult(user.PasswordHash);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if the user has a password set
|
||||
/// </summary>
|
||||
/// <param name="user"></param>
|
||||
/// <param name="cancellationToken"></param>
|
||||
/// <returns></returns>
|
||||
public virtual Task<bool> HasPasswordAsync(TUser user, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
return Task.FromResult(user.PasswordHash != null);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Return the claims for a user
|
||||
/// </summary>
|
||||
/// <param name="user"></param>
|
||||
/// <param name="cancellationToken"></param>
|
||||
/// <returns></returns>
|
||||
public virtual Task<IList<Claim>> GetClaimsAsync(TUser user, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
ThrowIfDisposed();
|
||||
if (user == null)
|
||||
{
|
||||
throw new ArgumentNullException("user");
|
||||
}
|
||||
IList<Claim> result = user.Claims.Select(c => new Claim(c.ClaimType, c.ClaimValue)).ToList();
|
||||
return Task.FromResult(result);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Add claims to a user
|
||||
/// </summary>
|
||||
/// <param name="user"></param>
|
||||
/// <param name="claims"></param>
|
||||
/// <param name="cancellationToken"></param>
|
||||
/// <returns></returns>
|
||||
public virtual Task AddClaimsAsync(TUser user, IEnumerable<Claim> claims, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
ThrowIfDisposed();
|
||||
if (user == null)
|
||||
{
|
||||
throw new ArgumentNullException("user");
|
||||
}
|
||||
if (claims == null)
|
||||
{
|
||||
throw new ArgumentNullException("claims");
|
||||
}
|
||||
foreach (var claim in claims)
|
||||
{
|
||||
user.Claims.Add(new TUserClaim { UserId = user.Id, ClaimType = claim.Type, ClaimValue = claim.Value });
|
||||
}
|
||||
return Task.FromResult(0);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Updates the give claim with the new one.
|
||||
/// </summary>
|
||||
/// <param name="user"></param>
|
||||
/// <param name="claim"></param>
|
||||
/// <param name="newClaim"></param>
|
||||
/// <param name="cancellationToken"></param>
|
||||
/// <returns></returns>
|
||||
public Task ReplaceClaimAsync(TUser user, Claim claim, Claim newClaim, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
ThrowIfDisposed();
|
||||
if (user == null)
|
||||
{
|
||||
throw new ArgumentNullException("user");
|
||||
}
|
||||
if (claim == null)
|
||||
{
|
||||
throw new ArgumentNullException("claim");
|
||||
}
|
||||
if (newClaim == null)
|
||||
{
|
||||
throw new ArgumentNullException("newClaim");
|
||||
}
|
||||
|
||||
var matchedClaim = user.Claims.FirstOrDefault(uc => uc.ClaimValue == claim.Value && uc.ClaimType == claim.Type);
|
||||
if(matchedClaim != null)
|
||||
{
|
||||
matchedClaim.ClaimValue = newClaim.Value;
|
||||
matchedClaim.ClaimType = newClaim.Type;
|
||||
}
|
||||
return Task.FromResult(0);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Remove claims from a user
|
||||
/// </summary>
|
||||
/// <param name="user"></param>
|
||||
/// <param name="claims"></param>
|
||||
/// <param name="cancellationToken"></param>
|
||||
/// <returns></returns>
|
||||
public virtual Task RemoveClaimsAsync(TUser user, IEnumerable<Claim> claims, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
ThrowIfDisposed();
|
||||
if (user == null)
|
||||
{
|
||||
throw new ArgumentNullException("user");
|
||||
}
|
||||
if (claims == null)
|
||||
{
|
||||
throw new ArgumentNullException("claims");
|
||||
}
|
||||
foreach (var claim in claims)
|
||||
{
|
||||
var matchingClaims =
|
||||
user.Claims.Where(uc => uc.ClaimValue == claim.Value && uc.ClaimType == claim.Type).ToList();
|
||||
foreach (var c in matchingClaims)
|
||||
{
|
||||
user.Claims.Remove(c);
|
||||
}
|
||||
}
|
||||
// TODO:these claims might not exist in the dbset
|
||||
//var query =
|
||||
// _userClaims.Where(
|
||||
// uc => uc.UserId.Equals(user.Id) && uc.ClaimValue == claim.Value && uc.ClaimType == claim.Type);
|
||||
//foreach (var c in query)
|
||||
//{
|
||||
// _userClaims.Remove(c);
|
||||
//}
|
||||
return Task.FromResult(0);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns whether the user email is confirmed
|
||||
/// </summary>
|
||||
/// <param name="user"></param>
|
||||
/// <param name="cancellationToken"></param>
|
||||
/// <returns></returns>
|
||||
public virtual Task<bool> GetEmailConfirmedAsync(TUser user, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
ThrowIfDisposed();
|
||||
if (user == null)
|
||||
{
|
||||
throw new ArgumentNullException("user");
|
||||
}
|
||||
return Task.FromResult(user.EmailConfirmed);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set IsConfirmed on the user
|
||||
/// </summary>
|
||||
/// <param name="user"></param>
|
||||
/// <param name="confirmed"></param>
|
||||
/// <param name="cancellationToken"></param>
|
||||
/// <returns></returns>
|
||||
public virtual Task SetEmailConfirmedAsync(TUser user, bool confirmed, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
ThrowIfDisposed();
|
||||
if (user == null)
|
||||
{
|
||||
throw new ArgumentNullException("user");
|
||||
}
|
||||
user.EmailConfirmed = confirmed;
|
||||
return Task.FromResult(0);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set the user email
|
||||
/// </summary>
|
||||
/// <param name="user"></param>
|
||||
/// <param name="email"></param>
|
||||
/// <param name="cancellationToken"></param>
|
||||
/// <returns></returns>
|
||||
public virtual Task SetEmailAsync(TUser user, string email, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
ThrowIfDisposed();
|
||||
if (user == null)
|
||||
{
|
||||
throw new ArgumentNullException("user");
|
||||
}
|
||||
user.Email = email;
|
||||
return Task.FromResult(0);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the user's email
|
||||
/// </summary>
|
||||
/// <param name="user"></param>
|
||||
/// <param name="cancellationToken"></param>
|
||||
/// <returns></returns>
|
||||
public virtual Task<string> GetEmailAsync(TUser user, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
ThrowIfDisposed();
|
||||
if (user == null)
|
||||
{
|
||||
throw new ArgumentNullException("user");
|
||||
}
|
||||
return Task.FromResult(user.Email);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// FindByLoginAsync a user by email
|
||||
/// </summary>
|
||||
/// <param name="email"></param>
|
||||
/// <param name="cancellationToken"></param>
|
||||
/// <returns></returns>
|
||||
public virtual Task<TUser> FindByEmailAsync(string email, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
ThrowIfDisposed();
|
||||
return Task.FromResult(Users.SingleOrDefault(u => u.Email.ToUpper() == email.ToUpper()));
|
||||
//return GetUserAggregate(u => u.Email.ToUpper() == email.ToUpper(), cancellationToken);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the DateTimeOffset that represents the end of a user's lockout, any time in the past should be considered
|
||||
/// not locked out.
|
||||
/// </summary>
|
||||
/// <param name="user"></param>
|
||||
/// <param name="cancellationToken"></param>
|
||||
/// <returns></returns>
|
||||
public virtual Task<DateTimeOffset?> GetLockoutEndDateAsync(TUser user, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
ThrowIfDisposed();
|
||||
if (user == null)
|
||||
{
|
||||
throw new ArgumentNullException("user");
|
||||
}
|
||||
return Task.FromResult(user.LockoutEnd);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Locks a user out until the specified end date (set to a past date, to unlock a user)
|
||||
/// </summary>
|
||||
/// <param name="user"></param>
|
||||
/// <param name="lockoutEnd"></param>
|
||||
/// <param name="cancellationToken"></param>
|
||||
/// <returns></returns>
|
||||
public virtual Task SetLockoutEndDateAsync(TUser user, DateTimeOffset? lockoutEnd, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
ThrowIfDisposed();
|
||||
if (user == null)
|
||||
{
|
||||
throw new ArgumentNullException("user");
|
||||
}
|
||||
user.LockoutEnd = lockoutEnd;
|
||||
return Task.FromResult(0);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Used to record when an attempt to access the user has failed
|
||||
/// </summary>
|
||||
/// <param name="user"></param>
|
||||
/// <param name="cancellationToken"></param>
|
||||
/// <returns></returns>
|
||||
public virtual Task<int> IncrementAccessFailedCountAsync(TUser user, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
ThrowIfDisposed();
|
||||
if (user == null)
|
||||
{
|
||||
throw new ArgumentNullException("user");
|
||||
}
|
||||
user.AccessFailedCount++;
|
||||
return Task.FromResult(user.AccessFailedCount);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Used to reset the account access count, typically after the account is successfully accessed
|
||||
/// </summary>
|
||||
/// <param name="user"></param>
|
||||
/// <param name="cancellationToken"></param>
|
||||
/// <returns></returns>
|
||||
public virtual Task ResetAccessFailedCountAsync(TUser user, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
ThrowIfDisposed();
|
||||
if (user == null)
|
||||
{
|
||||
throw new ArgumentNullException("user");
|
||||
}
|
||||
user.AccessFailedCount = 0;
|
||||
return Task.FromResult(0);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the current number of failed access attempts. This number usually will be reset whenever the password is
|
||||
/// verified or the account is locked out.
|
||||
/// </summary>
|
||||
/// <param name="user"></param>
|
||||
/// <param name="cancellationToken"></param>
|
||||
/// <returns></returns>
|
||||
public virtual Task<int> GetAccessFailedCountAsync(TUser user, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
ThrowIfDisposed();
|
||||
if (user == null)
|
||||
{
|
||||
throw new ArgumentNullException("user");
|
||||
}
|
||||
return Task.FromResult(user.AccessFailedCount);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns whether the user can be locked out.
|
||||
/// </summary>
|
||||
/// <param name="user"></param>
|
||||
/// <param name="cancellationToken"></param>
|
||||
/// <returns></returns>
|
||||
public virtual Task<bool> GetLockoutEnabledAsync(TUser user, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
ThrowIfDisposed();
|
||||
if (user == null)
|
||||
{
|
||||
throw new ArgumentNullException("user");
|
||||
}
|
||||
return Task.FromResult(user.LockoutEnabled);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets whether the user can be locked out.
|
||||
/// </summary>
|
||||
/// <param name="user"></param>
|
||||
/// <param name="enabled"></param>
|
||||
/// <param name="cancellationToken"></param>
|
||||
/// <returns></returns>
|
||||
public virtual Task SetLockoutEnabledAsync(TUser user, bool enabled, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
ThrowIfDisposed();
|
||||
if (user == null)
|
||||
{
|
||||
throw new ArgumentNullException("user");
|
||||
}
|
||||
user.LockoutEnabled = enabled;
|
||||
return Task.FromResult(0);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set the user's phone number
|
||||
/// </summary>
|
||||
/// <param name="user"></param>
|
||||
/// <param name="phoneNumber"></param>
|
||||
/// <param name="cancellationToken"></param>
|
||||
/// <returns></returns>
|
||||
public virtual Task SetPhoneNumberAsync(TUser user, string phoneNumber, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
ThrowIfDisposed();
|
||||
if (user == null)
|
||||
{
|
||||
throw new ArgumentNullException("user");
|
||||
}
|
||||
user.PhoneNumber = phoneNumber;
|
||||
return Task.FromResult(0);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get a user's phone number
|
||||
/// </summary>
|
||||
/// <param name="user"></param>
|
||||
/// <param name="cancellationToken"></param>
|
||||
/// <returns></returns>
|
||||
public virtual Task<string> GetPhoneNumberAsync(TUser user, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
ThrowIfDisposed();
|
||||
if (user == null)
|
||||
{
|
||||
throw new ArgumentNullException("user");
|
||||
}
|
||||
return Task.FromResult(user.PhoneNumber);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns whether the user phoneNumber is confirmed
|
||||
/// </summary>
|
||||
/// <param name="user"></param>
|
||||
/// <param name="cancellationToken"></param>
|
||||
/// <returns></returns>
|
||||
public virtual Task<bool> GetPhoneNumberConfirmedAsync(TUser user, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
ThrowIfDisposed();
|
||||
if (user == null)
|
||||
{
|
||||
throw new ArgumentNullException("user");
|
||||
}
|
||||
return Task.FromResult(user.PhoneNumberConfirmed);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set PhoneNumberConfirmed on the user
|
||||
/// </summary>
|
||||
/// <param name="user"></param>
|
||||
/// <param name="confirmed"></param>
|
||||
/// <param name="cancellationToken"></param>
|
||||
/// <returns></returns>
|
||||
public virtual Task SetPhoneNumberConfirmedAsync(TUser user, bool confirmed, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
ThrowIfDisposed();
|
||||
if (user == null)
|
||||
{
|
||||
throw new ArgumentNullException("user");
|
||||
}
|
||||
user.PhoneNumberConfirmed = confirmed;
|
||||
return Task.FromResult(0);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Add a user to a role
|
||||
/// </summary>
|
||||
/// <param name="user"></param>
|
||||
/// <param name="roleName"></param>
|
||||
/// <param name="cancellationToken"></param>
|
||||
/// <returns></returns>
|
||||
public virtual Task AddToRoleAsync(TUser user, string roleName, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
ThrowIfDisposed();
|
||||
if (user == null)
|
||||
{
|
||||
throw new ArgumentNullException("user");
|
||||
}
|
||||
// TODO:
|
||||
//if (String.IsNullOrWhiteSpace(roleName))
|
||||
//{
|
||||
// throw new ArgumentException(IdentityResources.ValueCannotBeNullOrEmpty, "roleName");
|
||||
//}
|
||||
var roleEntity = Context.Set<TRole>().SingleOrDefault(r => r.Name.ToUpper() == roleName.ToUpper());
|
||||
if (roleEntity == null)
|
||||
{
|
||||
throw new InvalidOperationException("Role Not Found");
|
||||
//TODO: String.Format(CultureInfo.CurrentCulture, IdentityResources.RoleNotFound, roleName));
|
||||
}
|
||||
var ur = new TUserRole { UserId = user.Id, RoleId = roleEntity.Id };
|
||||
user.Roles.Add(ur);
|
||||
roleEntity.Users.Add(ur);
|
||||
return Task.FromResult(0);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Remove a user from a role
|
||||
/// </summary>
|
||||
/// <param name="user"></param>
|
||||
/// <param name="roleName"></param>
|
||||
/// <param name="cancellationToken"></param>
|
||||
/// <returns></returns>
|
||||
public virtual Task RemoveFromRoleAsync(TUser user, string roleName, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
ThrowIfDisposed();
|
||||
if (user == null)
|
||||
{
|
||||
throw new ArgumentNullException("user");
|
||||
}
|
||||
//if (String.IsNullOrWhiteSpace(roleName))
|
||||
//{
|
||||
// throw new ArgumentException(IdentityResources.ValueCannotBeNullOrEmpty, "roleName");
|
||||
//}
|
||||
var roleEntity = Context.Set<TRole>().SingleOrDefault(r => r.Name.ToUpper() == roleName.ToUpper());
|
||||
if (roleEntity != null)
|
||||
{
|
||||
var userRole = user.Roles.FirstOrDefault(r => roleEntity.Id.Equals(r.RoleId));
|
||||
if (userRole != null)
|
||||
{
|
||||
user.Roles.Remove(userRole);
|
||||
roleEntity.Users.Remove(userRole);
|
||||
}
|
||||
}
|
||||
return Task.FromResult(0);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the names of the roles a user is a member of
|
||||
/// </summary>
|
||||
/// <param name="user"></param>
|
||||
/// <param name="cancellationToken"></param>
|
||||
/// <returns></returns>
|
||||
public virtual Task<IList<string>> GetRolesAsync(TUser user, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
ThrowIfDisposed();
|
||||
if (user == null)
|
||||
{
|
||||
throw new ArgumentNullException("user");
|
||||
}
|
||||
var query = from userRoles in user.Roles
|
||||
join roles in Context.Set<TRole>()
|
||||
on userRoles.RoleId equals roles.Id
|
||||
select roles.Name;
|
||||
return Task.FromResult<IList<string>>(query.ToList());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if the user is in the named role
|
||||
/// </summary>
|
||||
/// <param name="user"></param>
|
||||
/// <param name="roleName"></param>
|
||||
/// <param name="cancellationToken"></param>
|
||||
/// <returns></returns>
|
||||
public virtual Task<bool> IsInRoleAsync(TUser user, string roleName, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
ThrowIfDisposed();
|
||||
if (user == null)
|
||||
{
|
||||
throw new ArgumentNullException("user");
|
||||
}
|
||||
//if (String.IsNullOrWhiteSpace(roleName))
|
||||
//{
|
||||
// throw new ArgumentException(IdentityResources.ValueCannotBeNullOrEmpty, "roleName");
|
||||
//}
|
||||
var any =
|
||||
Context.Set<TRole>().Where(r => r.Name.ToUpper() == roleName.ToUpper())
|
||||
.Where(r => r.Users.Any(ur => ur.UserId.Equals(user.Id)))
|
||||
.Count() > 0;
|
||||
return Task.FromResult(any);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set the security stamp for the user
|
||||
/// </summary>
|
||||
/// <param name="user"></param>
|
||||
/// <param name="stamp"></param>
|
||||
/// <param name="cancellationToken"></param>
|
||||
/// <returns></returns>
|
||||
public virtual Task SetSecurityStampAsync(TUser user, string stamp, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
ThrowIfDisposed();
|
||||
if (user == null)
|
||||
{
|
||||
throw new ArgumentNullException("user");
|
||||
}
|
||||
user.SecurityStamp = stamp;
|
||||
return Task.FromResult(0);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the security stamp for a user
|
||||
/// </summary>
|
||||
/// <param name="user"></param>
|
||||
/// <param name="cancellationToken"></param>
|
||||
/// <returns></returns>
|
||||
public virtual Task<string> GetSecurityStampAsync(TUser user, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
ThrowIfDisposed();
|
||||
if (user == null)
|
||||
{
|
||||
throw new ArgumentNullException("user");
|
||||
}
|
||||
return Task.FromResult(user.SecurityStamp);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set whether two factor authentication is enabled for the user
|
||||
/// </summary>
|
||||
/// <param name="user"></param>
|
||||
/// <param name="enabled"></param>
|
||||
/// <param name="cancellationToken"></param>
|
||||
/// <returns></returns>
|
||||
public virtual Task SetTwoFactorEnabledAsync(TUser user, bool enabled, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
ThrowIfDisposed();
|
||||
if (user == null)
|
||||
{
|
||||
throw new ArgumentNullException("user");
|
||||
}
|
||||
user.TwoFactorEnabled = enabled;
|
||||
return Task.FromResult(0);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets whether two factor authentication is enabled for the user
|
||||
/// </summary>
|
||||
/// <param name="user"></param>
|
||||
/// <param name="cancellationToken"></param>
|
||||
/// <returns></returns>
|
||||
public virtual Task<bool> GetTwoFactorEnabledAsync(TUser user, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
ThrowIfDisposed();
|
||||
if (user == null)
|
||||
{
|
||||
throw new ArgumentNullException("user");
|
||||
}
|
||||
return Task.FromResult(user.TwoFactorEnabled);
|
||||
}
|
||||
|
||||
private void ThrowIfDisposed()
|
||||
{
|
||||
if (_disposed)
|
||||
{
|
||||
throw new ObjectDisposedException(GetType().Name);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Dispose the store
|
||||
/// </summary>
|
||||
public void Dispose()
|
||||
{
|
||||
_disposed = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -76,23 +76,10 @@ namespace Microsoft.AspNet.Identity.EntityFramework.InMemory.Test
|
|||
var role = new IdentityRole("UpdateRoleName");
|
||||
IdentityResultAssert.IsSuccess(await manager.CreateAsync(role));
|
||||
Assert.Null(await manager.FindByNameAsync("New"));
|
||||
role.Name = "New";
|
||||
IdentityResultAssert.IsSuccess(await manager.SetRoleNameAsync(role, "New"));
|
||||
IdentityResultAssert.IsSuccess(await manager.UpdateAsync(role));
|
||||
Assert.NotNull(await manager.FindByNameAsync("New"));
|
||||
Assert.Null(await manager.FindByNameAsync("UpdateAsync"));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task CanSetUserName()
|
||||
{
|
||||
var manager = TestIdentityFactory.CreateRoleManager();
|
||||
var role = new IdentityRole("UpdateRoleName");
|
||||
IdentityResultAssert.IsSuccess(await manager.CreateAsync(role));
|
||||
Assert.Null(await manager.FindByNameAsync("New"));
|
||||
IdentityResultAssert.IsSuccess(await manager.SetRoleNameAsync(role, "New"));
|
||||
Assert.NotNull(await manager.FindByNameAsync("New"));
|
||||
Assert.Null(await manager.FindByNameAsync("UpdateAsync"));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ namespace Microsoft.AspNet.Identity.EntityFramework.InMemory.Test
|
|||
services.AddEntityFramework().AddInMemoryStore();
|
||||
var serviceProvider = services.BuildServiceProvider();
|
||||
|
||||
var db = new InMemoryContext(serviceProvider);
|
||||
var db = new InMemoryContext();
|
||||
db.Database.EnsureCreated();
|
||||
|
||||
return db;
|
||||
|
|
|
|||
|
|
@ -4,14 +4,13 @@
|
|||
"Microsoft.AspNet.Http": "1.0.0-*",
|
||||
"Microsoft.AspNet.Identity": "3.0.0-*",
|
||||
"Microsoft.AspNet.Identity.EntityFramework": "3.0.0-*",
|
||||
"Microsoft.AspNet.PipelineCore": "1.0.0-*",
|
||||
"Microsoft.AspNet.RequestContainer": "1.0.0-*",
|
||||
"Microsoft.AspNet.Security.DataProtection": "1.0.0-*",
|
||||
"Microsoft.AspNet.Testing": "1.0.0-*",
|
||||
"EntityFramework.InMemory": "7.0.0-*",
|
||||
"Microsoft.Framework.OptionsModel" : "1.0.0-*",
|
||||
"System.Security.Claims": "1.0.0-*",
|
||||
"Xunit.KRunner": "1.0.0-*"
|
||||
"xunit.runner.kre": "1.0.0-*"
|
||||
},
|
||||
"code": "**\\*.cs;..\\Shared\\*.cs",
|
||||
"frameworks": {
|
||||
|
|
@ -22,6 +21,6 @@
|
|||
}
|
||||
},
|
||||
"commands": {
|
||||
"test": "Xunit.KRunner"
|
||||
"test": "xunit.runner.kre"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,10 +7,7 @@ using System.Security.Claims;
|
|||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNet.Builder;
|
||||
using Microsoft.AspNet.Identity.Test;
|
||||
using Microsoft.Data.Entity;
|
||||
using Microsoft.Framework.DependencyInjection;
|
||||
using Microsoft.Framework.DependencyInjection.Fallback;
|
||||
using Microsoft.Framework.OptionsModel;
|
||||
using Microsoft.Framework.Runtime.Infrastructure;
|
||||
using Xunit;
|
||||
|
||||
|
|
@ -156,16 +153,90 @@ namespace Microsoft.AspNet.Identity.EntityFramework.Test
|
|||
IdentityResultAssert.IsSuccess(await manager.DeleteAsync(user));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task EnsureRoleClaimNavigationProperty()
|
||||
private async Task LazyLoadTestSetup(TestDbContext db, TUser user)
|
||||
{
|
||||
var context = CreateContext();
|
||||
var roleManager = CreateRoleManager(context);
|
||||
var r = CreateRole();
|
||||
IdentityResultAssert.IsSuccess(await roleManager.CreateAsync(r));
|
||||
var c = new Claim("a", "b");
|
||||
IdentityResultAssert.IsSuccess(await roleManager.AddClaimAsync(r, c));
|
||||
Assert.NotNull(r.Claims.Single(cl => cl.ClaimValue == c.Value && cl.ClaimType == c.Type));
|
||||
var manager = CreateManager(context);
|
||||
var role = CreateRoleManager(context);
|
||||
var admin = CreateRole("Admin");
|
||||
var local = CreateRole("Local");
|
||||
IdentityResultAssert.IsSuccess(await manager.CreateAsync(user));
|
||||
IdentityResultAssert.IsSuccess(await manager.AddLoginAsync(user, new UserLoginInfo("provider", user.Id.ToString(), "display")));
|
||||
IdentityResultAssert.IsSuccess(await role.CreateAsync(admin));
|
||||
IdentityResultAssert.IsSuccess(await role.CreateAsync(local));
|
||||
IdentityResultAssert.IsSuccess(await manager.AddToRoleAsync(user, admin.Name));
|
||||
IdentityResultAssert.IsSuccess(await manager.AddToRoleAsync(user, local.Name));
|
||||
Claim[] userClaims =
|
||||
{
|
||||
new Claim("Whatever", "Value"),
|
||||
new Claim("Whatever2", "Value2")
|
||||
};
|
||||
foreach (var c in userClaims)
|
||||
{
|
||||
IdentityResultAssert.IsSuccess(await manager.AddClaimAsync(user, c));
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task LoadFromDbFindByIdTest()
|
||||
{
|
||||
var db = CreateContext();
|
||||
var user = CreateTestUser();
|
||||
await LazyLoadTestSetup(db, user);
|
||||
|
||||
db = CreateContext();
|
||||
var manager = CreateManager(db);
|
||||
|
||||
var userById = await manager.FindByIdAsync(user.Id.ToString());
|
||||
Assert.Equal(2, (await manager.GetClaimsAsync(userById)).Count);
|
||||
Assert.Equal(1, (await manager.GetLoginsAsync(userById)).Count);
|
||||
Assert.Equal(2, (await manager.GetRolesAsync(userById)).Count);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task LoadFromDbFindByNameTest()
|
||||
{
|
||||
var db = CreateContext();
|
||||
var user = CreateTestUser();
|
||||
await LazyLoadTestSetup(db, user);
|
||||
|
||||
db = CreateContext();
|
||||
var manager = CreateManager(db);
|
||||
var userByName = await manager.FindByNameAsync(user.UserName);
|
||||
Assert.Equal(2, (await manager.GetClaimsAsync(userByName)).Count);
|
||||
Assert.Equal(1, (await manager.GetLoginsAsync(userByName)).Count);
|
||||
Assert.Equal(2, (await manager.GetRolesAsync(userByName)).Count);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task LoadFromDbFindByLoginTest()
|
||||
{
|
||||
var db = CreateContext();
|
||||
var user = CreateTestUser();
|
||||
await LazyLoadTestSetup(db, user);
|
||||
|
||||
db = CreateContext();
|
||||
var manager = CreateManager(db);
|
||||
var userByLogin = await manager.FindByLoginAsync("provider", user.Id.ToString());
|
||||
Assert.Equal(2, (await manager.GetClaimsAsync(userByLogin)).Count);
|
||||
Assert.Equal(1, (await manager.GetLoginsAsync(userByLogin)).Count);
|
||||
Assert.Equal(2, (await manager.GetRolesAsync(userByLogin)).Count);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task LoadFromDbFindByEmailTest()
|
||||
{
|
||||
var db = CreateContext();
|
||||
var user = CreateTestUser();
|
||||
user.Email = "fooz@fizzy.pop";
|
||||
await LazyLoadTestSetup(db, user);
|
||||
|
||||
db = CreateContext();
|
||||
var manager = CreateManager(db);
|
||||
var userByEmail = await manager.FindByEmailAsync(user.Email);
|
||||
Assert.Equal(2, (await manager.GetClaimsAsync(userByEmail)).Count);
|
||||
Assert.Equal(1, (await manager.GetLoginsAsync(userByEmail)).Count);
|
||||
Assert.Equal(2, (await manager.GetRolesAsync(userByEmail)).Count);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -265,18 +265,6 @@ namespace Microsoft.AspNet.Identity.EntityFramework.Test
|
|||
IdentityResultAssert.IsSuccess(await manager.DeleteAsync(user));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task EnsureRoleClaimNavigationProperty()
|
||||
{
|
||||
var context = CreateContext();
|
||||
var roleManager = CreateRoleManager(context);
|
||||
var r = new IdentityRole("EnsureRoleClaimNavigationProperty");
|
||||
IdentityResultAssert.IsSuccess(await roleManager.CreateAsync(r));
|
||||
var c = new Claim("a", "b");
|
||||
IdentityResultAssert.IsSuccess(await roleManager.AddClaimAsync(r, c));
|
||||
Assert.NotNull(r.Claims.Single(cl => cl.ClaimValue == c.Value && cl.ClaimType == c.Type));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task AddUserToUnknownRoleFails()
|
||||
{
|
||||
|
|
@ -287,6 +275,157 @@ namespace Microsoft.AspNet.Identity.EntityFramework.Test
|
|||
async () => await manager.AddToRoleAsync(u, "bogus"));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ConcurrentUpdatesWillFail()
|
||||
{
|
||||
var user = CreateTestUser();
|
||||
using (var db = CreateContext())
|
||||
{
|
||||
var manager = CreateManager(db);
|
||||
IdentityResultAssert.IsSuccess(await manager.CreateAsync(user));
|
||||
}
|
||||
using (var db = CreateContext())
|
||||
using (var db2 = CreateContext())
|
||||
{
|
||||
var manager1 = CreateManager(db);
|
||||
var manager2 = CreateManager(db2);
|
||||
var user1 = await manager1.FindByIdAsync(user.Id);
|
||||
var user2 = await manager2.FindByIdAsync(user.Id);
|
||||
Assert.NotNull(user1);
|
||||
Assert.NotNull(user2);
|
||||
Assert.NotSame(user1, user2);
|
||||
user1.UserName = Guid.NewGuid().ToString();
|
||||
user2.UserName = Guid.NewGuid().ToString();
|
||||
IdentityResultAssert.IsSuccess(await manager1.UpdateAsync(user1));
|
||||
IdentityResultAssert.IsFailure(await manager2.UpdateAsync(user2), IdentityErrorDescriber.Default.ConcurrencyFailure());
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ConcurrentUpdatesWillFailWithDetachedUser()
|
||||
{
|
||||
var user = CreateTestUser();
|
||||
using (var db = CreateContext())
|
||||
{
|
||||
var manager = CreateManager(db);
|
||||
IdentityResultAssert.IsSuccess(await manager.CreateAsync(user));
|
||||
}
|
||||
using (var db = CreateContext())
|
||||
using (var db2 = CreateContext())
|
||||
{
|
||||
var manager1 = CreateManager(db);
|
||||
var manager2 = CreateManager(db2);
|
||||
var user2 = await manager2.FindByIdAsync(user.Id);
|
||||
Assert.NotNull(user2);
|
||||
Assert.NotSame(user, user2);
|
||||
user.UserName = Guid.NewGuid().ToString();
|
||||
user2.UserName = Guid.NewGuid().ToString();
|
||||
IdentityResultAssert.IsSuccess(await manager1.UpdateAsync(user));
|
||||
IdentityResultAssert.IsFailure(await manager2.UpdateAsync(user2), IdentityErrorDescriber.Default.ConcurrencyFailure());
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task DeleteAModifiedUserWillFail()
|
||||
{
|
||||
var user = CreateTestUser();
|
||||
using (var db = CreateContext())
|
||||
{
|
||||
var manager = CreateManager(db);
|
||||
IdentityResultAssert.IsSuccess(await manager.CreateAsync(user));
|
||||
}
|
||||
using (var db = CreateContext())
|
||||
using (var db2 = CreateContext())
|
||||
{
|
||||
var manager1 = CreateManager(db);
|
||||
var manager2 = CreateManager(db2);
|
||||
var user1 = await manager1.FindByIdAsync(user.Id);
|
||||
var user2 = await manager2.FindByIdAsync(user.Id);
|
||||
Assert.NotNull(user1);
|
||||
Assert.NotNull(user2);
|
||||
Assert.NotSame(user1, user2);
|
||||
user1.UserName = Guid.NewGuid().ToString();
|
||||
IdentityResultAssert.IsSuccess(await manager1.UpdateAsync(user1));
|
||||
IdentityResultAssert.IsFailure(await manager2.DeleteAsync(user2), IdentityErrorDescriber.Default.ConcurrencyFailure());
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ConcurrentRoleUpdatesWillFail()
|
||||
{
|
||||
var role = new IdentityRole(Guid.NewGuid().ToString());
|
||||
using (var db = CreateContext())
|
||||
{
|
||||
var manager = CreateRoleManager(db);
|
||||
IdentityResultAssert.IsSuccess(await manager.CreateAsync(role));
|
||||
}
|
||||
using (var db = CreateContext())
|
||||
using (var db2 = CreateContext())
|
||||
{
|
||||
var manager1 = CreateRoleManager(db);
|
||||
var manager2 = CreateRoleManager(db2);
|
||||
var role1 = await manager1.FindByIdAsync(role.Id);
|
||||
var role2 = await manager2.FindByIdAsync(role.Id);
|
||||
Assert.NotNull(role1);
|
||||
Assert.NotNull(role2);
|
||||
Assert.NotSame(role1, role2);
|
||||
role1.Name = Guid.NewGuid().ToString();
|
||||
role2.Name = Guid.NewGuid().ToString();
|
||||
IdentityResultAssert.IsSuccess(await manager1.UpdateAsync(role1));
|
||||
IdentityResultAssert.IsFailure(await manager2.UpdateAsync(role2), IdentityErrorDescriber.Default.ConcurrencyFailure());
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ConcurrentRoleUpdatesWillFailWithDetachedRole()
|
||||
{
|
||||
var role = new IdentityRole(Guid.NewGuid().ToString());
|
||||
using (var db = CreateContext())
|
||||
{
|
||||
var manager = CreateRoleManager(db);
|
||||
IdentityResultAssert.IsSuccess(await manager.CreateAsync(role));
|
||||
}
|
||||
using (var db = CreateContext())
|
||||
using (var db2 = CreateContext())
|
||||
{
|
||||
var manager1 = CreateRoleManager(db);
|
||||
var manager2 = CreateRoleManager(db2);
|
||||
var role2 = await manager2.FindByIdAsync(role.Id);
|
||||
Assert.NotNull(role);
|
||||
Assert.NotNull(role2);
|
||||
Assert.NotSame(role, role2);
|
||||
role.Name = Guid.NewGuid().ToString();
|
||||
role2.Name = Guid.NewGuid().ToString();
|
||||
IdentityResultAssert.IsSuccess(await manager1.UpdateAsync(role));
|
||||
IdentityResultAssert.IsFailure(await manager2.UpdateAsync(role2), IdentityErrorDescriber.Default.ConcurrencyFailure());
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task DeleteAModifiedRoleWillFail()
|
||||
{
|
||||
var role = new IdentityRole(Guid.NewGuid().ToString());
|
||||
using (var db = CreateContext())
|
||||
{
|
||||
var manager = CreateRoleManager(db);
|
||||
IdentityResultAssert.IsSuccess(await manager.CreateAsync(role));
|
||||
}
|
||||
using (var db = CreateContext())
|
||||
using (var db2 = CreateContext())
|
||||
{
|
||||
var manager1 = CreateRoleManager(db);
|
||||
var manager2 = CreateRoleManager(db2);
|
||||
var role1 = await manager1.FindByIdAsync(role.Id);
|
||||
var role2 = await manager2.FindByIdAsync(role.Id);
|
||||
Assert.NotNull(role1);
|
||||
Assert.NotNull(role2);
|
||||
Assert.NotSame(role1, role2);
|
||||
role1.Name = Guid.NewGuid().ToString();
|
||||
IdentityResultAssert.IsSuccess(await manager1.UpdateAsync(role1));
|
||||
IdentityResultAssert.IsFailure(await manager2.DeleteAsync(role2), IdentityErrorDescriber.Default.ConcurrencyFailure());
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: can we move these to UserManagerTestBase?
|
||||
[Fact]
|
||||
public async Task DeleteRoleNonEmptySucceedsTest()
|
||||
|
|
|
|||
|
|
@ -4,7 +4,6 @@
|
|||
"Microsoft.AspNet.Http": "1.0.0-*",
|
||||
"Microsoft.AspNet.Identity": "3.0.0-*",
|
||||
"Microsoft.AspNet.Identity.EntityFramework": "1.0.0-*",
|
||||
"Microsoft.AspNet.PipelineCore": "1.0.0-*",
|
||||
"Microsoft.AspNet.RequestContainer": "1.0.0-*",
|
||||
"Microsoft.AspNet.Security.DataProtection": "1.0.0-*",
|
||||
"Microsoft.AspNet.Testing": "1.0.0-*",
|
||||
|
|
@ -12,7 +11,7 @@
|
|||
"EntityFramework.SqlServer": "7.0.0-*",
|
||||
"Microsoft.Framework.OptionsModel" : "1.0.0-*",
|
||||
"System.Security.Claims": "1.0.0-*",
|
||||
"Xunit.KRunner": "1.0.0-*"
|
||||
"xunit.runner.kre": "1.0.0-*"
|
||||
},
|
||||
"code": "**\\*.cs;..\\Shared\\*.cs",
|
||||
"frameworks": {
|
||||
|
|
@ -23,6 +22,6 @@
|
|||
}
|
||||
},
|
||||
"commands": {
|
||||
"test": "Xunit.KRunner"
|
||||
"test": "xunit.runner.kre"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@
|
|||
using System.Security.Claims;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNet.Builder;
|
||||
using Microsoft.AspNet.Hosting;
|
||||
using Microsoft.AspNet.Http;
|
||||
using Microsoft.AspNet.Http.Security;
|
||||
using Microsoft.AspNet.Identity.Test;
|
||||
|
|
@ -14,7 +15,7 @@ using Xunit;
|
|||
|
||||
namespace Microsoft.AspNet.Identity.InMemory.Test
|
||||
{
|
||||
public class ApplicationUser : IdentityUser { }
|
||||
public class ApplicationUser : InMemoryUser { }
|
||||
|
||||
public class HttpSignInTest
|
||||
{
|
||||
|
|
@ -30,7 +31,7 @@ namespace Microsoft.AspNet.Identity.InMemory.Test
|
|||
var response = new Mock<HttpResponse>();
|
||||
context.Setup(c => c.Response).Returns(response.Object).Verifiable();
|
||||
response.Setup(r => r.SignIn(It.Is<AuthenticationProperties>(v => v.IsPersistent == isPersistent), It.IsAny<ClaimsIdentity>())).Verifiable();
|
||||
var contextAccessor = new Mock<IContextAccessor<HttpContext>>();
|
||||
var contextAccessor = new Mock<IHttpContextAccessor>();
|
||||
contextAccessor.Setup(a => a.Value).Returns(context.Object);
|
||||
app.UseServices(services =>
|
||||
{
|
||||
|
|
@ -50,10 +51,10 @@ namespace Microsoft.AspNet.Identity.InMemory.Test
|
|||
var signInManager = app.ApplicationServices.GetRequiredService<SignInManager<ApplicationUser>>();
|
||||
|
||||
IdentityResultAssert.IsSuccess(await userManager.CreateAsync(user, password));
|
||||
var result = await signInManager.PasswordSignInAsync(user.UserName, password, isPersistent, false);
|
||||
var result = await signInManager.PasswordSignInAsync(user, password, isPersistent, false);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(SignInStatus.Success, result);
|
||||
Assert.True(result.Succeeded);
|
||||
context.VerifyAll();
|
||||
response.VerifyAll();
|
||||
contextAccessor.VerifyAll();
|
||||
|
|
|
|||
|
|
@ -15,20 +15,20 @@ namespace Microsoft.AspNet.Identity.InMemory
|
|||
{
|
||||
private readonly Dictionary<string, TRole> _roles = new Dictionary<string, TRole>();
|
||||
|
||||
public Task CreateAsync(TRole role, CancellationToken cancellationToken = default(CancellationToken))
|
||||
public Task<IdentityResult> CreateAsync(TRole role, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
_roles[role.Id] = role;
|
||||
return Task.FromResult(0);
|
||||
return Task.FromResult(IdentityResult.Success);
|
||||
}
|
||||
|
||||
public Task DeleteAsync(TRole role, CancellationToken cancellationToken = default(CancellationToken))
|
||||
public Task<IdentityResult> DeleteAsync(TRole role, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
if (role == null || !_roles.ContainsKey(role.Id))
|
||||
{
|
||||
throw new InvalidOperationException("Unknown role");
|
||||
}
|
||||
_roles.Remove(role.Id);
|
||||
return Task.FromResult(0);
|
||||
return Task.FromResult(IdentityResult.Success);
|
||||
}
|
||||
|
||||
public Task<string> GetRoleIdAsync(TRole role, CancellationToken cancellationToken = default(CancellationToken))
|
||||
|
|
@ -47,10 +47,10 @@ namespace Microsoft.AspNet.Identity.InMemory
|
|||
return Task.FromResult(0);
|
||||
}
|
||||
|
||||
public Task UpdateAsync(TRole role, CancellationToken cancellationToken = default(CancellationToken))
|
||||
public Task<IdentityResult> UpdateAsync(TRole role, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
_roles[role.Id] = role;
|
||||
return Task.FromResult(0);
|
||||
return Task.FromResult(IdentityResult.Success);
|
||||
}
|
||||
|
||||
public Task<TRole> FindByIdAsync(string roleId, CancellationToken cancellationToken = default(CancellationToken))
|
||||
|
|
@ -97,6 +97,17 @@ namespace Microsoft.AspNet.Identity.InMemory
|
|||
return Task.FromResult(0);
|
||||
}
|
||||
|
||||
public Task<string> GetNormalizedRoleNameAsync(TRole role, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
return Task.FromResult(role.NormalizedName);
|
||||
}
|
||||
|
||||
public Task SetNormalizedRoleNameAsync(TRole role, string normalizedName, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
role.NormalizedName = normalizedName;
|
||||
return Task.FromResult(0);
|
||||
}
|
||||
|
||||
public IQueryable<TRole> Roles
|
||||
{
|
||||
get { return _roles.Values.AsQueryable(); }
|
||||
|
|
|
|||
|
|
@ -1,12 +1,13 @@
|
|||
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using Microsoft.AspNet.Identity.Test;
|
||||
using Microsoft.Framework.DependencyInjection;
|
||||
|
||||
namespace Microsoft.AspNet.Identity.InMemory.Test
|
||||
{
|
||||
public class InMemoryStoreTest : UserManagerTestBase<IdentityUser, IdentityRole>
|
||||
public class InMemoryStoreTest : UserManagerTestBase<InMemoryUser, IdentityRole>
|
||||
{
|
||||
protected override object CreateTestContext()
|
||||
{
|
||||
|
|
@ -15,7 +16,7 @@ namespace Microsoft.AspNet.Identity.InMemory.Test
|
|||
|
||||
protected override void AddUserStore(IServiceCollection services, object context = null)
|
||||
{
|
||||
services.AddSingleton<IUserStore<IdentityUser>, InMemoryUserStore<IdentityUser>>();
|
||||
services.AddSingleton<IUserStore<InMemoryUser>, InMemoryUserStore<InMemoryUser>>();
|
||||
}
|
||||
|
||||
protected override void AddRoleStore(IServiceCollection services, object context = null)
|
||||
|
|
|
|||
|
|
@ -10,6 +10,30 @@ using System.Threading.Tasks;
|
|||
|
||||
namespace Microsoft.AspNet.Identity.InMemory
|
||||
{
|
||||
public class InMemoryUser : IdentityUser
|
||||
{
|
||||
public InMemoryUser() { }
|
||||
|
||||
public InMemoryUser(string userName) : base(userName) { }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Roles for the user
|
||||
/// </summary>
|
||||
public virtual ICollection<IdentityUserRole> Roles { get; } = new List<IdentityUserRole>();
|
||||
|
||||
/// <summary>
|
||||
/// Claims for the user
|
||||
/// </summary>
|
||||
public virtual ICollection<IdentityUserClaim> Claims { get; } = new List<IdentityUserClaim>();
|
||||
|
||||
/// <summary>
|
||||
/// Associated logins for the user
|
||||
/// </summary>
|
||||
public virtual ICollection<IdentityUserLogin> Logins { get; } = new List<IdentityUserLogin>();
|
||||
|
||||
}
|
||||
|
||||
public class InMemoryUserStore<TUser> :
|
||||
IUserLoginStore<TUser>,
|
||||
IUserRoleStore<TUser>,
|
||||
|
|
@ -21,7 +45,7 @@ namespace Microsoft.AspNet.Identity.InMemory
|
|||
IUserPhoneNumberStore<TUser>,
|
||||
IQueryableUserStore<TUser>,
|
||||
IUserTwoFactorStore<TUser>
|
||||
where TUser : IdentityUser
|
||||
where TUser : InMemoryUser
|
||||
{
|
||||
private readonly Dictionary<string, TUser> _logins = new Dictionary<string, TUser>();
|
||||
|
||||
|
|
@ -42,7 +66,7 @@ namespace Microsoft.AspNet.Identity.InMemory
|
|||
{
|
||||
foreach (var claim in claims)
|
||||
{
|
||||
user.Claims.Add(new IdentityUserClaim<string> { ClaimType = claim.Type, ClaimValue = claim.Value, UserId = user.Id });
|
||||
user.Claims.Add(new IdentityUserClaim { ClaimType = claim.Type, ClaimValue = claim.Value, UserId = user.Id });
|
||||
}
|
||||
return Task.FromResult(0);
|
||||
}
|
||||
|
|
@ -50,7 +74,7 @@ namespace Microsoft.AspNet.Identity.InMemory
|
|||
public Task ReplaceClaimAsync(TUser user, Claim claim, Claim newClaim, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
var matchedClaims = user.Claims.Where(uc => uc.ClaimValue == claim.Value && uc.ClaimType == claim.Type).ToList();
|
||||
foreach(var matchedClaim in matchedClaims)
|
||||
foreach (var matchedClaim in matchedClaims)
|
||||
{
|
||||
matchedClaim.ClaimValue = newClaim.Value;
|
||||
matchedClaim.ClaimType = newClaim.Type;
|
||||
|
|
@ -84,6 +108,18 @@ namespace Microsoft.AspNet.Identity.InMemory
|
|||
return Task.FromResult(user.Email);
|
||||
}
|
||||
|
||||
public Task<string> GetNormalizedEmailAsync(TUser user, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
return Task.FromResult(user.NormalizedEmail);
|
||||
}
|
||||
|
||||
public Task SetNormalizedEmailAsync(TUser user, string normalizedEmail, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
user.NormalizedEmail = normalizedEmail;
|
||||
return Task.FromResult(0);
|
||||
}
|
||||
|
||||
|
||||
public Task<bool> GetEmailConfirmedAsync(TUser user, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
return Task.FromResult(user.EmailConfirmed);
|
||||
|
|
@ -99,7 +135,7 @@ namespace Microsoft.AspNet.Identity.InMemory
|
|||
{
|
||||
return
|
||||
Task.FromResult(
|
||||
Users.FirstOrDefault(u => String.Equals(u.Email, email, StringComparison.OrdinalIgnoreCase)));
|
||||
Users.FirstOrDefault(u => u.NormalizedEmail == email));
|
||||
}
|
||||
|
||||
public Task<DateTimeOffset?> GetLockoutEndDateAsync(TUser user, CancellationToken cancellationToken = default(CancellationToken))
|
||||
|
|
@ -149,7 +185,7 @@ namespace Microsoft.AspNet.Identity.InMemory
|
|||
public virtual Task AddLoginAsync(TUser user, UserLoginInfo login,
|
||||
CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
user.Logins.Add(new IdentityUserLogin<string>
|
||||
user.Logins.Add(new IdentityUserLogin
|
||||
{
|
||||
UserId = user.Id,
|
||||
ProviderKey = login.ProviderKey,
|
||||
|
|
@ -209,16 +245,16 @@ namespace Microsoft.AspNet.Identity.InMemory
|
|||
return Task.FromResult(0);
|
||||
}
|
||||
|
||||
public Task CreateAsync(TUser user, CancellationToken cancellationToken = default(CancellationToken))
|
||||
public Task<IdentityResult> CreateAsync(TUser user, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
_users[user.Id] = user;
|
||||
return Task.FromResult(0);
|
||||
return Task.FromResult(IdentityResult.Success);
|
||||
}
|
||||
|
||||
public Task UpdateAsync(TUser user, CancellationToken cancellationToken = default(CancellationToken))
|
||||
public Task<IdentityResult> UpdateAsync(TUser user, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
_users[user.Id] = user;
|
||||
return Task.FromResult(0);
|
||||
return Task.FromResult(IdentityResult.Success);
|
||||
}
|
||||
|
||||
public Task<TUser> FindByIdAsync(string userId, CancellationToken cancellationToken = default(CancellationToken))
|
||||
|
|
@ -238,17 +274,17 @@ namespace Microsoft.AspNet.Identity.InMemory
|
|||
{
|
||||
return
|
||||
Task.FromResult(
|
||||
Users.FirstOrDefault(u => String.Equals(u.UserName, userName, StringComparison.OrdinalIgnoreCase)));
|
||||
Users.FirstOrDefault(u => u.NormalizedUserName == userName));
|
||||
}
|
||||
|
||||
public Task DeleteAsync(TUser user, CancellationToken cancellationToken = default(CancellationToken))
|
||||
public Task<IdentityResult> DeleteAsync(TUser user, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
if (user == null || !_users.ContainsKey(user.Id))
|
||||
{
|
||||
throw new InvalidOperationException("Unknown user");
|
||||
}
|
||||
_users.Remove(user.Id);
|
||||
return Task.FromResult(0);
|
||||
return Task.FromResult(IdentityResult.Success);
|
||||
}
|
||||
|
||||
public Task SetPasswordHashAsync(TUser user, string passwordHash, CancellationToken cancellationToken = default(CancellationToken))
|
||||
|
|
@ -292,7 +328,7 @@ namespace Microsoft.AspNet.Identity.InMemory
|
|||
// RoleId == roleName for InMemory
|
||||
public Task AddToRoleAsync(TUser user, string role, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
user.Roles.Add(new IdentityUserRole<string> { RoleId = role, UserId = user.Id });
|
||||
user.Roles.Add(new IdentityUserRole { RoleId = role, UserId = user.Id });
|
||||
return Task.FromResult(0);
|
||||
}
|
||||
|
||||
|
|
@ -349,5 +385,30 @@ namespace Microsoft.AspNet.Identity.InMemory
|
|||
user.NormalizedUserName = userName;
|
||||
return Task.FromResult(0);
|
||||
}
|
||||
|
||||
// RoleId == rolename for inmemory store tests
|
||||
public Task<IList<TUser>> GetUsersInRoleAsync(string roleName, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
if (String.IsNullOrEmpty(roleName))
|
||||
{
|
||||
throw new ArgumentNullException("role");
|
||||
}
|
||||
|
||||
return Task.FromResult<IList<TUser>>(Users.Where(u => (u.Roles.Where(x => x.RoleId == roleName).Count() > 0)).Select(x => x).ToList());
|
||||
}
|
||||
|
||||
public Task<IList<TUser>> GetUsersForClaimAsync(Claim claim, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
if (claim == null)
|
||||
{
|
||||
throw new ArgumentNullException("claim");
|
||||
}
|
||||
|
||||
var query = from user in Users
|
||||
where user.Claims.Where(x => x.ClaimType == claim.Type && x.ClaimValue == claim.Value).FirstOrDefault() != null
|
||||
select user;
|
||||
|
||||
return Task.FromResult<IList<TUser>>(query.ToList());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -3,7 +3,6 @@
|
|||
"Microsoft.AspNet.Hosting": "1.0.0-*",
|
||||
"Microsoft.AspNet.Http" : "1.0.0-*",
|
||||
"Microsoft.AspNet.Identity" : "3.0.0-*",
|
||||
"Microsoft.AspNet.PipelineCore" : "1.0.0-*",
|
||||
"Microsoft.AspNet.RequestContainer" : "1.0.0-*",
|
||||
"Microsoft.AspNet.Security" : "1.0.0-*",
|
||||
"Microsoft.AspNet.Security.Cookies" : "1.0.0-*",
|
||||
|
|
@ -11,7 +10,7 @@
|
|||
"Microsoft.Framework.ConfigurationModel": "1.0.0-*",
|
||||
"Microsoft.Framework.DependencyInjection" : "1.0.0-*",
|
||||
"Microsoft.Framework.OptionsModel" : "1.0.0-*",
|
||||
"Xunit.KRunner": "1.0.0-*"
|
||||
"xunit.runner.kre": "1.0.0-*"
|
||||
},
|
||||
"code": "**\\*.cs;..\\Shared\\*.cs",
|
||||
"frameworks": {
|
||||
|
|
@ -22,6 +21,6 @@
|
|||
}
|
||||
},
|
||||
"commands": {
|
||||
"test": "Xunit.KRunner"
|
||||
"test": "xunit.runner.kre"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,6 @@
|
|||
namespace Microsoft.AspNet.Identity.Test
|
||||
{
|
||||
internal interface IHttpContextAccessor<T>
|
||||
{
|
||||
}
|
||||
}
|
||||
|
|
@ -10,7 +10,7 @@ using System;
|
|||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using System.Linq;
|
||||
using Microsoft.AspNet.Security.DataProtection;
|
||||
using Microsoft.Framework.Logging;
|
||||
|
||||
namespace Microsoft.AspNet.Identity.Test
|
||||
{
|
||||
|
|
@ -62,6 +62,28 @@ namespace Microsoft.AspNet.Identity.Test
|
|||
Assert.NotNull(thingy);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CanOverrideUserManager()
|
||||
{
|
||||
var services = new ServiceCollection();
|
||||
services.AddIdentity<TestUser, TestRole>()
|
||||
.AddUserStore<NoopUserStore>()
|
||||
.AddUserManager<MyUserManager>();
|
||||
var myUserManager = services.BuildServiceProvider().GetRequiredService(typeof(UserManager<TestUser>)) as MyUserManager;
|
||||
Assert.NotNull(myUserManager);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CanOverrideRoleManager()
|
||||
{
|
||||
var services = new ServiceCollection();
|
||||
services.AddIdentity<TestUser, TestRole>()
|
||||
.AddRoleStore<NoopRoleStore>()
|
||||
.AddRoleManager<MyRoleManager>();
|
||||
var myRoleManager = services.BuildServiceProvider().GetRequiredService<RoleManager<TestRole>>() as MyRoleManager;
|
||||
Assert.NotNull(myRoleManager);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void EnsureDefaultServices()
|
||||
{
|
||||
|
|
@ -92,22 +114,22 @@ namespace Microsoft.AspNet.Identity.Test
|
|||
|
||||
private class MyUberThingy : IUserValidator<IdentityUser>, IPasswordValidator<IdentityUser>, IRoleValidator<IdentityRole>, IUserStore<IdentityUser>, IRoleStore<IdentityRole>
|
||||
{
|
||||
public Task CreateAsync(IdentityRole role, CancellationToken cancellationToken = default(CancellationToken))
|
||||
public Task<IdentityResult> CreateAsync(IdentityRole role, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task CreateAsync(IdentityUser user, CancellationToken cancellationToken = default(CancellationToken))
|
||||
public Task<IdentityResult> CreateAsync(IdentityUser user, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task DeleteAsync(IdentityRole role, CancellationToken cancellationToken = default(CancellationToken))
|
||||
public Task<IdentityResult> DeleteAsync(IdentityRole role, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task DeleteAsync(IdentityUser user, CancellationToken cancellationToken = default(CancellationToken))
|
||||
public Task<IdentityResult> DeleteAsync(IdentityUser user, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
|
@ -127,6 +149,11 @@ namespace Microsoft.AspNet.Identity.Test
|
|||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task<string> GetNormalizedRoleNameAsync(IdentityRole role, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task<string> GetNormalizedUserNameAsync(IdentityUser user, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
|
|
@ -152,6 +179,11 @@ namespace Microsoft.AspNet.Identity.Test
|
|||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task SetNormalizedRoleNameAsync(IdentityRole role, string normalizedName, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task SetNormalizedUserNameAsync(IdentityUser user, string normalizedName, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
|
|
@ -167,12 +199,12 @@ namespace Microsoft.AspNet.Identity.Test
|
|||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task UpdateAsync(IdentityRole role, CancellationToken cancellationToken = default(CancellationToken))
|
||||
public Task<IdentityResult> UpdateAsync(IdentityRole role, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task UpdateAsync(IdentityUser user, CancellationToken cancellationToken = default(CancellationToken))
|
||||
public Task<IdentityResult> UpdateAsync(IdentityUser user, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
|
@ -203,5 +235,18 @@ namespace Microsoft.AspNet.Identity.Test
|
|||
}
|
||||
}
|
||||
|
||||
private class MyUserManager : UserManager<TestUser>
|
||||
{
|
||||
public MyUserManager(IUserStore<TestUser> store) : base(store) { }
|
||||
}
|
||||
|
||||
private class MyRoleManager : RoleManager<TestRole>
|
||||
{
|
||||
public MyRoleManager(IRoleStore<TestRole> store,
|
||||
IEnumerable<IRoleValidator<TestRole>> roleValidators) : base(store)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -36,7 +36,7 @@ namespace Microsoft.AspNet.Identity.Test
|
|||
Assert.Equal(ClaimTypes.Role, options.ClaimsIdentity.RoleClaimType);
|
||||
Assert.Equal(ClaimTypes.Name, options.ClaimsIdentity.UserNameClaimType);
|
||||
Assert.Equal(ClaimTypes.NameIdentifier, options.ClaimsIdentity.UserIdClaimType);
|
||||
Assert.Equal(ClaimsIdentityOptions.DefaultSecurityStampClaimType, options.ClaimsIdentity.SecurityStampClaimType);
|
||||
Assert.Equal("AspNet.Identity.SecurityStamp", options.ClaimsIdentity.SecurityStampClaimType);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.AspNet.Identity.Test
|
||||
|
|
@ -13,17 +14,39 @@ namespace Microsoft.AspNet.Identity.Test
|
|||
{
|
||||
var result = new IdentityResult();
|
||||
Assert.False(result.Succeeded);
|
||||
Assert.Equal(1, result.Errors.Count());
|
||||
Assert.Equal("An unknown failure has occured.", result.Errors.First());
|
||||
Assert.Equal(0, result.Errors.Count());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void NullErrorListUsesDefaultError()
|
||||
public void NullFailedUsesEmptyErrors()
|
||||
{
|
||||
var result = new IdentityResult(null);
|
||||
var result = IdentityResult.Failed();
|
||||
Assert.False(result.Succeeded);
|
||||
Assert.Equal(1, result.Errors.Count());
|
||||
Assert.Equal("An unknown failure has occured.", result.Errors.First());
|
||||
Assert.Equal(0, result.Errors.Count());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void VerifySuccessResultLog()
|
||||
{
|
||||
var result = IdentityResult.Success;
|
||||
var logMessage = new StringBuilder();
|
||||
var logger = MockHelpers.MockILogger(logMessage);
|
||||
|
||||
result.Log(logger.Object, "Operation");
|
||||
|
||||
Assert.Equal("Operation : Success", logMessage.ToString());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void VerifyFailureResultLog()
|
||||
{
|
||||
var result = IdentityResult.Failed(new IdentityError() { Code = "Foo" }, new IdentityError() { Code = "Bar" });
|
||||
var logMessage = new StringBuilder();
|
||||
var logger = MockHelpers.MockILogger(logMessage);
|
||||
|
||||
result.Log(logger.Object, "Operation");
|
||||
|
||||
Assert.Equal("Operation : Failed : Foo,Bar", logMessage.ToString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">14.0</VisualStudioVersion>
|
||||
|
|
@ -14,4 +14,9 @@
|
|||
<SchemaVersion>2.0</SchemaVersion>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VSToolsPath)\AspNet\Microsoft.Web.AspNet.targets" Condition="'$(VSToolsPath)' != ''" />
|
||||
</Project>
|
||||
<ProjectExtensions>
|
||||
<VisualStudio>
|
||||
<UserProperties project_1json__JSONSchema="http://www.asp.net/media/4878834/project.json" />
|
||||
</VisualStudio>
|
||||
</ProjectExtensions>
|
||||
</Project>
|
||||
|
|
@ -8,14 +8,14 @@ namespace Microsoft.AspNet.Identity.Test
|
|||
{
|
||||
public class NoopRoleStore : IRoleStore<TestRole>
|
||||
{
|
||||
public Task CreateAsync(TestRole user, CancellationToken cancellationToken = default(CancellationToken))
|
||||
public Task<IdentityResult> CreateAsync(TestRole user, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
return Task.FromResult(0);
|
||||
return Task.FromResult(IdentityResult.Success);
|
||||
}
|
||||
|
||||
public Task UpdateAsync(TestRole user, CancellationToken cancellationToken = default(CancellationToken))
|
||||
public Task<IdentityResult> UpdateAsync(TestRole user, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
return Task.FromResult(0);
|
||||
return Task.FromResult(IdentityResult.Success);
|
||||
}
|
||||
|
||||
public Task<string> GetRoleNameAsync(TestRole role, CancellationToken cancellationToken = default(CancellationToken))
|
||||
|
|
@ -42,14 +42,24 @@ namespace Microsoft.AspNet.Identity.Test
|
|||
{
|
||||
}
|
||||
|
||||
public Task DeleteAsync(TestRole user, CancellationToken cancellationToken = default(CancellationToken))
|
||||
public Task<IdentityResult> DeleteAsync(TestRole user, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
return Task.FromResult(0);
|
||||
return Task.FromResult(IdentityResult.Success);
|
||||
}
|
||||
|
||||
public Task<string> GetRoleIdAsync(TestRole role, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
return Task.FromResult<string>(null);
|
||||
}
|
||||
|
||||
public Task<string> GetNormalizedRoleNameAsync(TestRole role, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
return Task.FromResult<string>(null);
|
||||
}
|
||||
|
||||
public Task SetNormalizedRoleNameAsync(TestRole role, string normalizedName, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
return Task.FromResult(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -24,14 +24,14 @@ namespace Microsoft.AspNet.Identity.Test
|
|||
return Task.FromResult(0);
|
||||
}
|
||||
|
||||
public Task CreateAsync(TestUser user, CancellationToken cancellationToken = default(CancellationToken))
|
||||
public Task<IdentityResult> CreateAsync(TestUser user, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
return Task.FromResult(0);
|
||||
return Task.FromResult(IdentityResult.Success);
|
||||
}
|
||||
|
||||
public Task UpdateAsync(TestUser user, CancellationToken cancellationToken = default(CancellationToken))
|
||||
public Task<IdentityResult> UpdateAsync(TestUser user, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
return Task.FromResult(0);
|
||||
return Task.FromResult(IdentityResult.Success);
|
||||
}
|
||||
|
||||
public Task<TestUser> FindByIdAsync(string userId, CancellationToken cancellationToken = default(CancellationToken))
|
||||
|
|
@ -48,9 +48,9 @@ namespace Microsoft.AspNet.Identity.Test
|
|||
{
|
||||
}
|
||||
|
||||
public Task DeleteAsync(TestUser user, CancellationToken cancellationToken = default(CancellationToken))
|
||||
public Task<IdentityResult> DeleteAsync(TestUser user, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
return Task.FromResult(0);
|
||||
return Task.FromResult(IdentityResult.Success);
|
||||
}
|
||||
|
||||
public Task<string> GetNormalizedUserNameAsync(TestUser user, CancellationToken cancellationToken = default(CancellationToken))
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Xunit;
|
||||
|
||||
|
|
@ -133,13 +134,18 @@ namespace Microsoft.AspNet.Identity.Test
|
|||
{
|
||||
errors.Add(upperError);
|
||||
}
|
||||
var result = await valid.ValidateAsync(manager, null, input);
|
||||
if (errors.Count == 0)
|
||||
{
|
||||
IdentityResultAssert.IsSuccess(await valid.ValidateAsync(manager, null, input));
|
||||
IdentityResultAssert.IsSuccess(result);
|
||||
}
|
||||
else
|
||||
{
|
||||
IdentityResultAssert.IsFailure(await valid.ValidateAsync(manager, null, input), string.Join(" ", errors));
|
||||
IdentityResultAssert.IsFailure(result);
|
||||
foreach (var error in errors)
|
||||
{
|
||||
Assert.True(result.Errors.Any(e => e.Description == error));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,12 +6,51 @@ using System.Collections.Generic;
|
|||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Moq;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.AspNet.Identity.Test
|
||||
{
|
||||
public class RoleManagerTest
|
||||
{
|
||||
[Fact]
|
||||
public async Task CreateCallsStore()
|
||||
{
|
||||
// Setup
|
||||
var store = new Mock<IRoleStore<TestRole>>();
|
||||
var role = new TestRole { Name = "Foo" };
|
||||
store.Setup(s => s.CreateAsync(role, CancellationToken.None)).ReturnsAsync(IdentityResult.Success).Verifiable();
|
||||
store.Setup(s => s.GetRoleNameAsync(role, CancellationToken.None)).Returns(Task.FromResult(role.Name)).Verifiable();
|
||||
store.Setup(s => s.SetNormalizedRoleNameAsync(role, role.Name.ToUpperInvariant(), CancellationToken.None)).Returns(Task.FromResult(0)).Verifiable();
|
||||
var roleManager = MockHelpers.TestRoleManager(store.Object);
|
||||
|
||||
// Act
|
||||
var result = await roleManager.CreateAsync(role);
|
||||
|
||||
// Assert
|
||||
Assert.True(result.Succeeded);
|
||||
store.VerifyAll();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task UpdateCallsStore()
|
||||
{
|
||||
// Setup
|
||||
var store = new Mock<IRoleStore<TestRole>>();
|
||||
var role = new TestRole { Name = "Foo" };
|
||||
store.Setup(s => s.UpdateAsync(role, CancellationToken.None)).ReturnsAsync(IdentityResult.Success).Verifiable();
|
||||
store.Setup(s => s.GetRoleNameAsync(role, CancellationToken.None)).Returns(Task.FromResult(role.Name)).Verifiable();
|
||||
store.Setup(s => s.SetNormalizedRoleNameAsync(role, role.Name.ToUpperInvariant(), CancellationToken.None)).Returns(Task.FromResult(0)).Verifiable();
|
||||
var roleManager = MockHelpers.TestRoleManager(store.Object);
|
||||
|
||||
// Act
|
||||
var result = await roleManager.UpdateAsync(role);
|
||||
|
||||
// Assert
|
||||
Assert.True(result.Succeeded);
|
||||
store.VerifyAll();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void RolesQueryableFailWhenStoreNotImplemented()
|
||||
{
|
||||
|
|
@ -20,6 +59,59 @@ namespace Microsoft.AspNet.Identity.Test
|
|||
Assert.Throws<NotSupportedException>(() => manager.Roles.Count());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task FindByNameCallsStoreWithNormalizedName()
|
||||
{
|
||||
// Setup
|
||||
var store = new Mock<IRoleStore<TestRole>>();
|
||||
var role = new TestRole { Name = "Foo" };
|
||||
store.Setup(s => s.FindByNameAsync("FOO", CancellationToken.None)).Returns(Task.FromResult(role)).Verifiable();
|
||||
var manager = MockHelpers.TestRoleManager(store.Object);
|
||||
|
||||
// Act
|
||||
var result = await manager.FindByNameAsync(role.Name);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(role, result);
|
||||
store.VerifyAll();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task CanFindByNameCallsStoreWithoutNormalizedName()
|
||||
{
|
||||
// Setup
|
||||
var store = new Mock<IRoleStore<TestRole>>();
|
||||
var role = new TestRole { Name = "Foo" };
|
||||
store.Setup(s => s.FindByNameAsync(role.Name, CancellationToken.None)).Returns(Task.FromResult(role)).Verifiable();
|
||||
var manager = MockHelpers.TestRoleManager(store.Object);
|
||||
manager.KeyNormalizer = null;
|
||||
|
||||
// Act
|
||||
var result = await manager.FindByNameAsync(role.Name);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(role, result);
|
||||
store.VerifyAll();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task RoleExistsCallsStoreWithNormalizedName()
|
||||
{
|
||||
// Setup
|
||||
var store = new Mock<IRoleStore<TestRole>>();
|
||||
var role = new TestRole { Name = "Foo" };
|
||||
store.Setup(s => s.FindByNameAsync("FOO", CancellationToken.None)).Returns(Task.FromResult(role)).Verifiable();
|
||||
var manager = MockHelpers.TestRoleManager(store.Object);
|
||||
|
||||
// Act
|
||||
var result = await manager.RoleExistsAsync(role.Name);
|
||||
|
||||
// Assert
|
||||
Assert.True(result);
|
||||
store.VerifyAll();
|
||||
}
|
||||
|
||||
|
||||
[Fact]
|
||||
public void DisposeAfterDisposeDoesNotThrow()
|
||||
{
|
||||
|
|
@ -32,7 +124,7 @@ namespace Microsoft.AspNet.Identity.Test
|
|||
public async Task RoleManagerPublicNullChecks()
|
||||
{
|
||||
Assert.Throws<ArgumentNullException>("store",
|
||||
() => new RoleManager<TestRole>(null, null));
|
||||
() => new RoleManager<TestRole>(null, null, null));
|
||||
var manager = CreateRoleManager(new NotImplementedStore());
|
||||
await Assert.ThrowsAsync<ArgumentNullException>("role", async () => await manager.CreateAsync(null));
|
||||
await Assert.ThrowsAsync<ArgumentNullException>("role", async () => await manager.UpdateAsync(null));
|
||||
|
|
@ -58,22 +150,22 @@ namespace Microsoft.AspNet.Identity.Test
|
|||
{
|
||||
var v = new List<IRoleValidator<TestRole>>();
|
||||
v.Add(new RoleValidator<TestRole>());
|
||||
return new RoleManager<TestRole>(roleStore, v);
|
||||
return new RoleManager<TestRole>(roleStore);
|
||||
}
|
||||
|
||||
private class NotImplementedStore : IRoleStore<TestRole>
|
||||
{
|
||||
public Task CreateAsync(TestRole role, CancellationToken cancellationToken = default(CancellationToken))
|
||||
public Task<IdentityResult> CreateAsync(TestRole role, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task UpdateAsync(TestRole role, CancellationToken cancellationToken = default(CancellationToken))
|
||||
public Task<IdentityResult> UpdateAsync(TestRole role, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task DeleteAsync(TestRole role, CancellationToken cancellationToken = default(CancellationToken))
|
||||
public Task<IdentityResult> DeleteAsync(TestRole role, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
|
@ -107,6 +199,16 @@ namespace Microsoft.AspNet.Identity.Test
|
|||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task<string> GetNormalizedRoleNameAsync(TestRole role, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task SetNormalizedRoleNameAsync(TestRole role, string normalizedName, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -14,7 +14,7 @@ namespace Microsoft.AspNet.Identity.Test
|
|||
{
|
||||
// Setup
|
||||
var validator = new RoleValidator<TestRole>();
|
||||
var manager = new RoleManager<TestRole>(new NoopRoleStore(), null);
|
||||
var manager = new RoleManager<TestRole>(new NoopRoleStore());
|
||||
|
||||
// Act
|
||||
// Assert
|
||||
|
|
@ -29,14 +29,14 @@ namespace Microsoft.AspNet.Identity.Test
|
|||
{
|
||||
// Setup
|
||||
var validator = new RoleValidator<TestRole>();
|
||||
var manager = new RoleManager<TestRole>(new NoopRoleStore(), null);
|
||||
var manager = new RoleManager<TestRole>(new NoopRoleStore());
|
||||
var user = new TestRole {Name = input};
|
||||
|
||||
// Act
|
||||
var result = await validator.ValidateAsync(manager, user);
|
||||
|
||||
// Assert
|
||||
IdentityResultAssert.IsFailure(result, "Name cannot be null or empty.");
|
||||
IdentityResultAssert.IsFailure(result, IdentityErrorDescriber.Default.InvalidRoleName(input));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -5,6 +5,7 @@ using System;
|
|||
using System.Security.Claims;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNet.Hosting;
|
||||
using Microsoft.AspNet.Http;
|
||||
using Microsoft.AspNet.Http.Security;
|
||||
using Microsoft.AspNet.Security;
|
||||
|
|
@ -43,10 +44,10 @@ namespace Microsoft.AspNet.Identity.Test
|
|||
var options = new Mock<IOptions<IdentityOptions>>();
|
||||
options.Setup(a => a.Options).Returns(identityOptions);
|
||||
var httpContext = new Mock<HttpContext>();
|
||||
var contextAccessor = new Mock<IContextAccessor<HttpContext>>();
|
||||
var contextAccessor = new Mock<IHttpContextAccessor>();
|
||||
contextAccessor.Setup(a => a.Value).Returns(httpContext.Object);
|
||||
var signInManager = new Mock<SignInManager<IdentityUser>>(userManager.Object,
|
||||
contextAccessor.Object, claimsManager.Object, options.Object);
|
||||
contextAccessor.Object, claimsManager.Object, options.Object, null);
|
||||
signInManager.Setup(s => s.ValidateSecurityStampAsync(It.IsAny<ClaimsIdentity>(), user.Id, CancellationToken.None)).ReturnsAsync(user).Verifiable();
|
||||
signInManager.Setup(s => s.SignInAsync(user, isPersistent, null, CancellationToken.None)).Returns(Task.FromResult(0)).Verifiable();
|
||||
var services = new ServiceCollection();
|
||||
|
|
@ -78,10 +79,10 @@ namespace Microsoft.AspNet.Identity.Test
|
|||
var options = new Mock<IOptions<IdentityOptions>>();
|
||||
options.Setup(a => a.Options).Returns(identityOptions);
|
||||
var httpContext = new Mock<HttpContext>();
|
||||
var contextAccessor = new Mock<IContextAccessor<HttpContext>>();
|
||||
var contextAccessor = new Mock<IHttpContextAccessor>();
|
||||
contextAccessor.Setup(a => a.Value).Returns(httpContext.Object);
|
||||
var signInManager = new Mock<SignInManager<IdentityUser>>(userManager.Object,
|
||||
contextAccessor.Object, claimsManager.Object, options.Object);
|
||||
contextAccessor.Object, claimsManager.Object, options.Object, null);
|
||||
signInManager.Setup(s => s.ValidateSecurityStampAsync(It.IsAny<ClaimsIdentity>(), user.Id, CancellationToken.None)).ReturnsAsync(null).Verifiable();
|
||||
var services = new ServiceCollection();
|
||||
services.AddInstance(options.Object);
|
||||
|
|
@ -112,10 +113,10 @@ namespace Microsoft.AspNet.Identity.Test
|
|||
var identityOptions = new IdentityOptions { SecurityStampValidationInterval = TimeSpan.Zero };
|
||||
var options = new Mock<IOptions<IdentityOptions>>();
|
||||
options.Setup(a => a.Options).Returns(identityOptions);
|
||||
var contextAccessor = new Mock<IContextAccessor<HttpContext>>();
|
||||
var contextAccessor = new Mock<IHttpContextAccessor>();
|
||||
contextAccessor.Setup(a => a.Value).Returns(httpContext.Object);
|
||||
var signInManager = new Mock<SignInManager<IdentityUser>>(userManager.Object,
|
||||
contextAccessor.Object, claimsManager.Object, options.Object);
|
||||
contextAccessor.Object, claimsManager.Object, options.Object, null);
|
||||
signInManager.Setup(s => s.ValidateSecurityStampAsync(It.IsAny<ClaimsIdentity>(), user.Id, CancellationToken.None)).ReturnsAsync(null).Verifiable();
|
||||
var services = new ServiceCollection();
|
||||
services.AddInstance(options.Object);
|
||||
|
|
@ -146,10 +147,10 @@ namespace Microsoft.AspNet.Identity.Test
|
|||
var identityOptions = new IdentityOptions { SecurityStampValidationInterval = TimeSpan.FromDays(1) };
|
||||
var options = new Mock<IOptions<IdentityOptions>>();
|
||||
options.Setup(a => a.Options).Returns(identityOptions);
|
||||
var contextAccessor = new Mock<IContextAccessor<HttpContext>>();
|
||||
var contextAccessor = new Mock<IHttpContextAccessor>();
|
||||
contextAccessor.Setup(a => a.Value).Returns(httpContext.Object);
|
||||
var signInManager = new Mock<SignInManager<IdentityUser>>(userManager.Object,
|
||||
contextAccessor.Object, claimsManager.Object, options.Object);
|
||||
contextAccessor.Object, claimsManager.Object, options.Object, null);
|
||||
signInManager.Setup(s => s.ValidateSecurityStampAsync(It.IsAny<ClaimsIdentity>(), user.Id, CancellationToken.None)).Throws(new Exception("Shouldn't be called"));
|
||||
signInManager.Setup(s => s.SignInAsync(user, false, null, CancellationToken.None)).Throws(new Exception("Shouldn't be called"));
|
||||
var services = new ServiceCollection();
|
||||
|
|
|
|||
|
|
@ -1,17 +1,19 @@
|
|||
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Security.Claims;
|
||||
using System.Security.Principal;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNet.Hosting;
|
||||
using Microsoft.AspNet.Http;
|
||||
using Microsoft.AspNet.Http.Security;
|
||||
using Microsoft.Framework.DependencyInjection;
|
||||
using Microsoft.Framework.OptionsModel;
|
||||
using Moq;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Security.Claims;
|
||||
using System.Security.Principal;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.AspNet.Identity.Test
|
||||
|
|
@ -31,7 +33,7 @@ namespace Microsoft.AspNet.Identity.Test
|
|||
|
||||
// TODO: how to functionally test context?
|
||||
// var context = new DefaultHttpContext(new FeatureCollection());
|
||||
// var contextAccessor = new Mock<IContextAccessor<HttpContext>>();
|
||||
// var contextAccessor = new Mock<IHttpContextAccessor>();
|
||||
// contextAccessor.Setup(a => a.Value).Returns(context);
|
||||
// app.UseServices(services =>
|
||||
// {
|
||||
|
|
@ -67,16 +69,14 @@ namespace Microsoft.AspNet.Identity.Test
|
|||
[Fact]
|
||||
public void ConstructorNullChecks()
|
||||
{
|
||||
Assert.Throws<ArgumentNullException>("userManager", () => new SignInManager<IdentityUser>(null, null, null, null));
|
||||
Assert.Throws<ArgumentNullException>("userManager", () => new SignInManager<IdentityUser>(null, null, null, null, null));
|
||||
var userManager = MockHelpers.MockUserManager<IdentityUser>().Object;
|
||||
Assert.Throws<ArgumentNullException>("contextAccessor", () => new SignInManager<IdentityUser>(userManager, null, null, null));
|
||||
var contextAccessor = new Mock<IContextAccessor<HttpContext>>();
|
||||
var contextAccessor = new Mock<IHttpContextAccessor>();
|
||||
Assert.Throws<ArgumentNullException>("contextAccessor", () => new SignInManager<IdentityUser>(userManager, contextAccessor.Object, null, null));
|
||||
var context = new Mock<HttpContext>();
|
||||
contextAccessor.Setup(a => a.Value).Returns(context.Object);
|
||||
Assert.Throws<ArgumentNullException>("claimsFactory", () => new SignInManager<IdentityUser>(userManager, contextAccessor.Object, null, null));
|
||||
var claimsFactory = new Mock<IClaimsIdentityFactory<IdentityUser>>().Object;
|
||||
Assert.Throws<ArgumentNullException>("optionsAccessor", () => new SignInManager<IdentityUser>(userManager, contextAccessor.Object, claimsFactory, null));
|
||||
}
|
||||
|
||||
//TODO: Mock fails in K (this works fine in net45)
|
||||
|
|
@ -95,7 +95,7 @@ namespace Microsoft.AspNet.Identity.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 contextAccessor = new Mock<IContextAccessor<HttpContext>>();
|
||||
// var contextAccessor = new Mock<IHttpContextAccessor>();
|
||||
// contextAccessor.Setup(a => a.Value).Returns(context.Object);
|
||||
// var helper = new HttpAuthenticationManager(contextAccessor.Object);
|
||||
|
||||
|
|
@ -118,24 +118,31 @@ namespace Microsoft.AspNet.Identity.Test
|
|||
manager.Setup(m => m.SupportsUserLockout).Returns(true).Verifiable();
|
||||
manager.Setup(m => m.IsLockedOutAsync(user, CancellationToken.None)).ReturnsAsync(true).Verifiable();
|
||||
manager.Setup(m => m.FindByNameAsync(user.UserName, CancellationToken.None)).ReturnsAsync(user).Verifiable();
|
||||
manager.Setup(m => m.GetUserIdAsync(user, CancellationToken.None)).ReturnsAsync(user.Id.ToString()).Verifiable();
|
||||
|
||||
var context = new Mock<HttpContext>();
|
||||
var contextAccessor = new Mock<IContextAccessor<HttpContext>>();
|
||||
var contextAccessor = new Mock<IHttpContextAccessor>();
|
||||
contextAccessor.Setup(a => a.Value).Returns(context.Object);
|
||||
var roleManager = MockHelpers.MockRoleManager<TestRole>();
|
||||
var identityOptions = new IdentityOptions();
|
||||
var options = new Mock<IOptions<IdentityOptions>>();
|
||||
options.Setup(a => a.Options).Returns(identityOptions);
|
||||
var claimsFactory = new Mock<ClaimsIdentityFactory<TestUser, TestRole>>(manager.Object, roleManager.Object, options.Object);
|
||||
var helper = new SignInManager<TestUser>(manager.Object, contextAccessor.Object, claimsFactory.Object, options.Object);
|
||||
var logStore = new StringBuilder();
|
||||
var loggerFactory = MockHelpers.MockILoggerFactory(MockHelpers.MockILogger(logStore).Object);
|
||||
var helper = new SignInManager<TestUser>(manager.Object, contextAccessor.Object, claimsFactory.Object, options.Object, loggerFactory.Object);
|
||||
string expected = string.Format("{0} for user: {1} : Result : {2}", "PasswordSignInAsync", user.Id, "Lockedout");
|
||||
|
||||
// Act
|
||||
var result = await helper.PasswordSignInAsync(user.UserName, "bogus", false, false);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(SignInStatus.LockedOut, result);
|
||||
Assert.False(result.Succeeded);
|
||||
Assert.True(result.IsLockedOut);
|
||||
Assert.NotEqual(-1, logStore.ToString().IndexOf(expected));
|
||||
manager.VerifyAll();
|
||||
}
|
||||
|
||||
|
||||
[Theory]
|
||||
[InlineData(true)]
|
||||
[InlineData(false)]
|
||||
|
|
@ -149,11 +156,13 @@ namespace Microsoft.AspNet.Identity.Test
|
|||
manager.Setup(m => m.FindByNameAsync(user.UserName, CancellationToken.None)).ReturnsAsync(user).Verifiable();
|
||||
manager.Setup(m => m.CheckPasswordAsync(user, "password", CancellationToken.None)).ReturnsAsync(true).Verifiable();
|
||||
manager.Setup(m => m.ResetAccessFailedCountAsync(user, CancellationToken.None)).ReturnsAsync(IdentityResult.Success).Verifiable();
|
||||
manager.Setup(m => m.GetUserIdAsync(user, CancellationToken.None)).ReturnsAsync(user.Id.ToString()).Verifiable();
|
||||
|
||||
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.Is<AuthenticationProperties>(v => v.IsPersistent == isPersistent), It.IsAny<ClaimsIdentity>())).Verifiable();
|
||||
var contextAccessor = new Mock<IContextAccessor<HttpContext>>();
|
||||
var contextAccessor = new Mock<IHttpContextAccessor>();
|
||||
contextAccessor.Setup(a => a.Value).Returns(context.Object);
|
||||
var roleManager = MockHelpers.MockRoleManager<TestRole>();
|
||||
var identityOptions = new IdentityOptions();
|
||||
|
|
@ -161,13 +170,17 @@ namespace Microsoft.AspNet.Identity.Test
|
|||
options.Setup(a => a.Options).Returns(identityOptions);
|
||||
var claimsFactory = new Mock<ClaimsIdentityFactory<TestUser, TestRole>>(manager.Object, roleManager.Object, options.Object);
|
||||
claimsFactory.Setup(m => m.CreateAsync(user, CancellationToken.None)).ReturnsAsync(new ClaimsIdentity("Microsoft.AspNet.Identity")).Verifiable();
|
||||
var helper = new SignInManager<TestUser>(manager.Object, contextAccessor.Object, claimsFactory.Object, options.Object);
|
||||
var logStore = new StringBuilder();
|
||||
var loggerFactory = MockHelpers.MockILoggerFactory(MockHelpers.MockILogger(logStore).Object);
|
||||
var helper = new SignInManager<TestUser>(manager.Object, contextAccessor.Object, claimsFactory.Object, options.Object, loggerFactory.Object);
|
||||
string expected = string.Format("{0} for user: {1} : Result : {2}", "PasswordSignInAsync", user.Id, "Succeeded");
|
||||
|
||||
// Act
|
||||
var result = await helper.PasswordSignInAsync(user.UserName, "password", isPersistent, false);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(SignInStatus.Success, result);
|
||||
Assert.True(result.Succeeded);
|
||||
Assert.NotEqual(-1, logStore.ToString().IndexOf(expected));
|
||||
manager.VerifyAll();
|
||||
context.VerifyAll();
|
||||
response.VerifyAll();
|
||||
|
|
@ -186,11 +199,13 @@ namespace Microsoft.AspNet.Identity.Test
|
|||
manager.Setup(m => m.FindByNameAsync(user.UserName, CancellationToken.None)).ReturnsAsync(user).Verifiable();
|
||||
manager.Setup(m => m.CheckPasswordAsync(user, "password", CancellationToken.None)).ReturnsAsync(true).Verifiable();
|
||||
manager.Setup(m => m.ResetAccessFailedCountAsync(user, CancellationToken.None)).ReturnsAsync(IdentityResult.Success).Verifiable();
|
||||
manager.Setup(m => m.GetUserIdAsync(user, CancellationToken.None)).ReturnsAsync(user.Id.ToString()).Verifiable();
|
||||
|
||||
var context = new Mock<HttpContext>();
|
||||
var response = new Mock<HttpResponse>();
|
||||
response.Setup(r => r.SignIn(It.IsAny<AuthenticationProperties>(), It.IsAny<ClaimsIdentity>())).Verifiable();
|
||||
context.Setup(c => c.Response).Returns(response.Object).Verifiable();
|
||||
var contextAccessor = new Mock<IContextAccessor<HttpContext>>();
|
||||
var contextAccessor = new Mock<IHttpContextAccessor>();
|
||||
contextAccessor.Setup(a => a.Value).Returns(context.Object);
|
||||
var roleManager = MockHelpers.MockRoleManager<TestRole>();
|
||||
var identityOptions = new IdentityOptions();
|
||||
|
|
@ -203,7 +218,7 @@ namespace Microsoft.AspNet.Identity.Test
|
|||
var result = await helper.PasswordSignInAsync(user.UserName, "password", false, false);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(SignInStatus.Success, result);
|
||||
Assert.True(result.Succeeded);
|
||||
manager.VerifyAll();
|
||||
context.VerifyAll();
|
||||
response.VerifyAll();
|
||||
|
|
@ -239,19 +254,24 @@ namespace Microsoft.AspNet.Identity.Test
|
|||
var response = new Mock<HttpResponse>();
|
||||
response.Setup(r => r.SignIn(It.Is<ClaimsIdentity>(id => id.Name == user.Id))).Verifiable();
|
||||
context.Setup(c => c.Response).Returns(response.Object).Verifiable();
|
||||
var contextAccessor = new Mock<IContextAccessor<HttpContext>>();
|
||||
var contextAccessor = new Mock<IHttpContextAccessor>();
|
||||
contextAccessor.Setup(a => a.Value).Returns(context.Object);
|
||||
var roleManager = MockHelpers.MockRoleManager<TestRole>();
|
||||
var identityOptions = new IdentityOptions();
|
||||
var options = new Mock<IOptions<IdentityOptions>>();
|
||||
options.Setup(a => a.Options).Returns(identityOptions);
|
||||
var helper = new SignInManager<TestUser>(manager.Object, contextAccessor.Object, new ClaimsIdentityFactory<TestUser, TestRole>(manager.Object, roleManager.Object, options.Object), options.Object);
|
||||
var logStore = new StringBuilder();
|
||||
var loggerFactory = MockHelpers.MockILoggerFactory(MockHelpers.MockILogger(logStore).Object);
|
||||
var helper = new SignInManager<TestUser>(manager.Object, contextAccessor.Object, new ClaimsIdentityFactory<TestUser, TestRole>(manager.Object, roleManager.Object, options.Object), options.Object, loggerFactory.Object);
|
||||
string expected = string.Format("{0} for user: {1} : Result : {2}", "PasswordSignInAsync", user.Id, "RequiresTwoFactor");
|
||||
|
||||
// Act
|
||||
var result = await helper.PasswordSignInAsync(user.UserName, "password", false, false);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(SignInStatus.RequiresVerification, result);
|
||||
Assert.False(result.Succeeded);
|
||||
Assert.True(result.RequiresTwoFactor);
|
||||
Assert.NotEqual(-1, logStore.ToString().IndexOf(expected));
|
||||
manager.VerifyAll();
|
||||
context.VerifyAll();
|
||||
response.VerifyAll();
|
||||
|
|
@ -276,13 +296,15 @@ namespace Microsoft.AspNet.Identity.Test
|
|||
manager.Setup(m => m.IsLockedOutAsync(user, CancellationToken.None)).ReturnsAsync(false).Verifiable();
|
||||
}
|
||||
manager.Setup(m => m.FindByLoginAsync(loginProvider, providerKey, CancellationToken.None)).ReturnsAsync(user).Verifiable();
|
||||
manager.Setup(m => m.GetUserIdAsync(user, CancellationToken.None)).ReturnsAsync(user.Id.ToString()).Verifiable();
|
||||
|
||||
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.Is<AuthenticationProperties>(v => v.IsPersistent == isPersistent),
|
||||
It.Is<ClaimsIdentity>(i => i.FindFirstValue(ClaimTypes.AuthenticationMethod) == loginProvider))).Verifiable();
|
||||
var contextAccessor = new Mock<IContextAccessor<HttpContext>>();
|
||||
var contextAccessor = new Mock<IHttpContextAccessor>();
|
||||
contextAccessor.Setup(a => a.Value).Returns(context.Object);
|
||||
var roleManager = MockHelpers.MockRoleManager<TestRole>();
|
||||
var identityOptions = new IdentityOptions();
|
||||
|
|
@ -291,13 +313,17 @@ namespace Microsoft.AspNet.Identity.Test
|
|||
options.Setup(a => a.Options).Returns(identityOptions);
|
||||
var claimsFactory = new Mock<ClaimsIdentityFactory<TestUser, TestRole>>(manager.Object, roleManager.Object, options.Object);
|
||||
claimsFactory.Setup(m => m.CreateAsync(user, CancellationToken.None)).ReturnsAsync(new ClaimsIdentity("Microsoft.AspNet.Identity")).Verifiable();
|
||||
var helper = new SignInManager<TestUser>(manager.Object, contextAccessor.Object, claimsFactory.Object, options.Object);
|
||||
var logStore = new StringBuilder();
|
||||
var loggerFactory = MockHelpers.MockILoggerFactory(MockHelpers.MockILogger(logStore).Object);
|
||||
var helper = new SignInManager<TestUser>(manager.Object, contextAccessor.Object, claimsFactory.Object, options.Object, loggerFactory.Object);
|
||||
string expected = string.Format("{0} for user: {1} : Result : {2}", "ExternalLoginSignInAsync", user.Id.ToString(), "Succeeded");
|
||||
|
||||
// Act
|
||||
var result = await helper.ExternalLoginSignInAsync(loginProvider, providerKey, isPersistent);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(SignInStatus.Success, result);
|
||||
Assert.True(result.Succeeded);
|
||||
Assert.NotEqual(-1, logStore.ToString().IndexOf(expected));
|
||||
manager.VerifyAll();
|
||||
context.VerifyAll();
|
||||
response.VerifyAll();
|
||||
|
|
@ -322,7 +348,6 @@ namespace Microsoft.AspNet.Identity.Test
|
|||
[InlineData(false, true, false, false)]
|
||||
[InlineData(false, false, true, false)]
|
||||
[InlineData(false, false, false, false)]
|
||||
|
||||
public async Task CanTwoFactorSignIn(bool isPersistent, bool supportsLockout, bool externalLogin, bool rememberClient)
|
||||
{
|
||||
// Setup
|
||||
|
|
@ -342,7 +367,7 @@ namespace Microsoft.AspNet.Identity.Test
|
|||
manager.Setup(m => m.GetUserNameAsync(user, CancellationToken.None)).ReturnsAsync(user.UserName).Verifiable();
|
||||
var context = new Mock<HttpContext>();
|
||||
var response = new Mock<HttpResponse>();
|
||||
var contextAccessor = new Mock<IContextAccessor<HttpContext>>();
|
||||
var contextAccessor = new Mock<IHttpContextAccessor>();
|
||||
var twoFactorInfo = new SignInManager<TestUser>.TwoFactorAuthenticationInfo { UserId = user.Id };
|
||||
var loginProvider = "loginprovider";
|
||||
var id = SignInManager<TestUser>.StoreTwoFactorInfo(user.Id, externalLogin ? loginProvider : null);
|
||||
|
|
@ -376,13 +401,17 @@ namespace Microsoft.AspNet.Identity.Test
|
|||
context.Setup(c => c.Response).Returns(response.Object).Verifiable();
|
||||
context.Setup(c => c.AuthenticateAsync(IdentityOptions.TwoFactorUserIdCookieAuthenticationType)).ReturnsAsync(authResult).Verifiable();
|
||||
contextAccessor.Setup(a => a.Value).Returns(context.Object);
|
||||
var helper = new SignInManager<TestUser>(manager.Object, contextAccessor.Object, claimsFactory, options.Object);
|
||||
var logStore = new StringBuilder();
|
||||
var loggerFactory = MockHelpers.MockILoggerFactory(MockHelpers.MockILogger(logStore).Object);
|
||||
var helper = new SignInManager<TestUser>(manager.Object, contextAccessor.Object, claimsFactory, options.Object, loggerFactory.Object);
|
||||
string expected = string.Format("{0} for user: {1} : Result : {2}", "TwoFactorSignInAsync", user.Id.ToString(), "Succeeded");
|
||||
|
||||
// Act
|
||||
var result = await helper.TwoFactorSignInAsync(provider, code, isPersistent, rememberClient);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(SignInStatus.Success, result);
|
||||
Assert.True(result.Succeeded);
|
||||
Assert.NotEqual(-1, logStore.ToString().IndexOf(expected));
|
||||
manager.VerifyAll();
|
||||
context.VerifyAll();
|
||||
response.VerifyAll();
|
||||
|
|
@ -397,7 +426,7 @@ namespace Microsoft.AspNet.Identity.Test
|
|||
var manager = MockHelpers.MockUserManager<TestUser>();
|
||||
var context = new Mock<HttpContext>();
|
||||
var response = new Mock<HttpResponse>();
|
||||
var contextAccessor = new Mock<IContextAccessor<HttpContext>>();
|
||||
var contextAccessor = new Mock<IHttpContextAccessor>();
|
||||
var roleManager = MockHelpers.MockRoleManager<TestRole>();
|
||||
var identityOptions = new IdentityOptions();
|
||||
var options = new Mock<IOptions<IdentityOptions>>();
|
||||
|
|
@ -452,7 +481,7 @@ namespace Microsoft.AspNet.Identity.Test
|
|||
id.AddClaim(new Claim(ClaimTypes.Name, user.Id));
|
||||
var authResult = new AuthenticationResult(id, new AuthenticationProperties(), new AuthenticationDescription());
|
||||
context.Setup(c => c.AuthenticateAsync(IdentityOptions.TwoFactorRememberMeCookieAuthenticationType)).ReturnsAsync(authResult).Verifiable();
|
||||
var contextAccessor = new Mock<IContextAccessor<HttpContext>>();
|
||||
var contextAccessor = new Mock<IHttpContextAccessor>();
|
||||
contextAccessor.Setup(a => a.Value).Returns(context.Object);
|
||||
var roleManager = MockHelpers.MockRoleManager<TestRole>();
|
||||
var identityOptions = new IdentityOptions();
|
||||
|
|
@ -466,7 +495,7 @@ namespace Microsoft.AspNet.Identity.Test
|
|||
var result = await helper.PasswordSignInAsync(user.UserName, "password", isPersistent, false);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(SignInStatus.Success, result);
|
||||
Assert.True(result.Succeeded);
|
||||
manager.VerifyAll();
|
||||
context.VerifyAll();
|
||||
response.VerifyAll();
|
||||
|
|
@ -487,7 +516,7 @@ namespace Microsoft.AspNet.Identity.Test
|
|||
response.Setup(r => r.SignOut(authenticationType)).Verifiable();
|
||||
response.Setup(r => r.SignOut(IdentityOptions.TwoFactorUserIdCookieAuthenticationType)).Verifiable();
|
||||
response.Setup(r => r.SignOut(IdentityOptions.ExternalCookieAuthenticationType)).Verifiable();
|
||||
var contextAccessor = new Mock<IContextAccessor<HttpContext>>();
|
||||
var contextAccessor = new Mock<IHttpContextAccessor>();
|
||||
contextAccessor.Setup(a => a.Value).Returns(context.Object);
|
||||
var roleManager = MockHelpers.MockRoleManager<TestRole>();
|
||||
var identityOptions = new IdentityOptions();
|
||||
|
|
@ -495,7 +524,9 @@ namespace Microsoft.AspNet.Identity.Test
|
|||
options.Setup(a => a.Options).Returns(identityOptions);
|
||||
IdentityOptions.ApplicationCookieAuthenticationType = authenticationType;
|
||||
var claimsFactory = new Mock<ClaimsIdentityFactory<TestUser, TestRole>>(manager.Object, roleManager.Object, options.Object);
|
||||
var helper = new SignInManager<TestUser>(manager.Object, contextAccessor.Object, claimsFactory.Object, options.Object);
|
||||
var logStore = new StringBuilder();
|
||||
var loggerFactory = MockHelpers.MockILoggerFactory(MockHelpers.MockILogger(logStore).Object);
|
||||
var helper = new SignInManager<TestUser>(manager.Object, contextAccessor.Object, claimsFactory.Object, options.Object, loggerFactory.Object);
|
||||
|
||||
// Act
|
||||
helper.SignOut();
|
||||
|
|
@ -517,20 +548,25 @@ namespace Microsoft.AspNet.Identity.Test
|
|||
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();
|
||||
manager.Setup(m => m.GetUserIdAsync(user, CancellationToken.None)).ReturnsAsync(user.Id.ToString()).Verifiable();
|
||||
var context = new Mock<HttpContext>();
|
||||
var contextAccessor = new Mock<IContextAccessor<HttpContext>>();
|
||||
var contextAccessor = new Mock<IHttpContextAccessor>();
|
||||
contextAccessor.Setup(a => a.Value).Returns(context.Object);
|
||||
var roleManager = MockHelpers.MockRoleManager<TestRole>();
|
||||
var identityOptions = new IdentityOptions();
|
||||
var options = new Mock<IOptions<IdentityOptions>>();
|
||||
options.Setup(a => a.Options).Returns(identityOptions);
|
||||
var claimsFactory = new Mock<ClaimsIdentityFactory<TestUser, TestRole>>(manager.Object, roleManager.Object, options.Object);
|
||||
var helper = new SignInManager<TestUser>(manager.Object, contextAccessor.Object, claimsFactory.Object, options.Object);
|
||||
var logStore = new StringBuilder();
|
||||
var loggerFactory = MockHelpers.MockILoggerFactory(MockHelpers.MockILogger(logStore).Object);
|
||||
var helper = new SignInManager<TestUser>(manager.Object, contextAccessor.Object, claimsFactory.Object, options.Object, loggerFactory.Object);
|
||||
string expected = string.Format("{0} for user: {1} : Result : {2}", "PasswordSignInAsync", user.Id.ToString(), "Failed");
|
||||
// Act
|
||||
var result = await helper.PasswordSignInAsync(user.UserName, "bogus", false, false);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(SignInStatus.Failure, result);
|
||||
Assert.False(result.Succeeded);
|
||||
Assert.NotEqual(-1, logStore.ToString().IndexOf(expected));
|
||||
manager.VerifyAll();
|
||||
context.VerifyAll();
|
||||
contextAccessor.VerifyAll();
|
||||
|
|
@ -543,7 +579,7 @@ namespace Microsoft.AspNet.Identity.Test
|
|||
var manager = MockHelpers.MockUserManager<TestUser>();
|
||||
manager.Setup(m => m.FindByNameAsync("bogus", CancellationToken.None)).ReturnsAsync(null).Verifiable();
|
||||
var context = new Mock<HttpContext>();
|
||||
var contextAccessor = new Mock<IContextAccessor<HttpContext>>();
|
||||
var contextAccessor = new Mock<IHttpContextAccessor>();
|
||||
contextAccessor.Setup(a => a.Value).Returns(context.Object);
|
||||
var roleManager = MockHelpers.MockRoleManager<TestRole>();
|
||||
var identityOptions = new IdentityOptions();
|
||||
|
|
@ -556,7 +592,7 @@ namespace Microsoft.AspNet.Identity.Test
|
|||
var result = await helper.PasswordSignInAsync("bogus", "bogus", false, false);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(SignInStatus.Failure, result);
|
||||
Assert.False(result.Succeeded);
|
||||
manager.VerifyAll();
|
||||
context.VerifyAll();
|
||||
contextAccessor.VerifyAll();
|
||||
|
|
@ -579,7 +615,7 @@ namespace Microsoft.AspNet.Identity.Test
|
|||
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 context = new Mock<HttpContext>();
|
||||
var contextAccessor = new Mock<IContextAccessor<HttpContext>>();
|
||||
var contextAccessor = new Mock<IHttpContextAccessor>();
|
||||
contextAccessor.Setup(a => a.Value).Returns(context.Object);
|
||||
var roleManager = MockHelpers.MockRoleManager<TestRole>();
|
||||
var identityOptions = new IdentityOptions();
|
||||
|
|
@ -592,7 +628,8 @@ namespace Microsoft.AspNet.Identity.Test
|
|||
var result = await helper.PasswordSignInAsync(user.UserName, "bogus", false, true);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(SignInStatus.LockedOut, result);
|
||||
Assert.False(result.Succeeded);
|
||||
Assert.True(result.IsLockedOut);
|
||||
manager.VerifyAll();
|
||||
}
|
||||
|
||||
|
|
@ -609,6 +646,7 @@ namespace Microsoft.AspNet.Identity.Test
|
|||
{
|
||||
manager.Setup(m => m.CheckPasswordAsync(user, "password", CancellationToken.None)).ReturnsAsync(true).Verifiable();
|
||||
}
|
||||
manager.Setup(m => m.GetUserIdAsync(user, CancellationToken.None)).ReturnsAsync(user.Id.ToString()).Verifiable();
|
||||
var context = new Mock<HttpContext>();
|
||||
var response = new Mock<HttpResponse>();
|
||||
if (confirmed)
|
||||
|
|
@ -617,7 +655,7 @@ namespace Microsoft.AspNet.Identity.Test
|
|||
context.Setup(c => c.Response).Returns(response.Object).Verifiable();
|
||||
response.Setup(r => r.SignIn(It.Is<AuthenticationProperties>(v => v.IsPersistent == false), It.IsAny<ClaimsIdentity>())).Verifiable();
|
||||
}
|
||||
var contextAccessor = new Mock<IContextAccessor<HttpContext>>();
|
||||
var contextAccessor = new Mock<IHttpContextAccessor>();
|
||||
contextAccessor.Setup(a => a.Value).Returns(context.Object);
|
||||
var roleManager = MockHelpers.MockRoleManager<TestRole>();
|
||||
var identityOptions = new IdentityOptions();
|
||||
|
|
@ -625,13 +663,19 @@ namespace Microsoft.AspNet.Identity.Test
|
|||
var options = new Mock<IOptions<IdentityOptions>>();
|
||||
options.Setup(a => a.Options).Returns(identityOptions);
|
||||
var claimsFactory = new Mock<ClaimsIdentityFactory<TestUser, TestRole>>(manager.Object, roleManager.Object, options.Object);
|
||||
var helper = new SignInManager<TestUser>(manager.Object, contextAccessor.Object, claimsFactory.Object, options.Object);
|
||||
var logStore = new StringBuilder();
|
||||
var loggerFactory = MockHelpers.MockILoggerFactory(MockHelpers.MockILogger(logStore).Object);
|
||||
var helper = new SignInManager<TestUser>(manager.Object, contextAccessor.Object, claimsFactory.Object, options.Object, loggerFactory.Object);
|
||||
string expected = string.Format("{0} for user: {1} : Result : {2}", "CanSignInAsync", user.Id.ToString(), confirmed.ToString());
|
||||
|
||||
// Act
|
||||
var result = await helper.PasswordSignInAsync(user, "password", false, false);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(confirmed ? SignInStatus.Success : SignInStatus.NotAllowed, result);
|
||||
|
||||
Assert.Equal(confirmed, result.Succeeded);
|
||||
Assert.NotEqual(confirmed, result.IsNotAllowed);
|
||||
Assert.NotEqual(-1, logStore.ToString().IndexOf(expected));
|
||||
manager.VerifyAll();
|
||||
context.VerifyAll();
|
||||
response.VerifyAll();
|
||||
|
|
@ -646,7 +690,8 @@ namespace Microsoft.AspNet.Identity.Test
|
|||
// Setup
|
||||
var user = new TestUser { UserName = "Foo" };
|
||||
var manager = MockHelpers.MockUserManager<TestUser>();
|
||||
manager.Setup(m => m.IsEmailConfirmedAsync(user, CancellationToken.None)).ReturnsAsync(confirmed).Verifiable();
|
||||
manager.Setup(m => m.IsPhoneNumberConfirmedAsync(user, CancellationToken.None)).ReturnsAsync(confirmed).Verifiable();
|
||||
manager.Setup(m => m.GetUserIdAsync(user, CancellationToken.None)).ReturnsAsync(user.Id.ToString()).Verifiable();
|
||||
var context = new Mock<HttpContext>();
|
||||
var response = new Mock<HttpResponse>();
|
||||
if (confirmed)
|
||||
|
|
@ -656,21 +701,26 @@ namespace Microsoft.AspNet.Identity.Test
|
|||
response.Setup(r => r.SignIn(It.Is<AuthenticationProperties>(v => v.IsPersistent == false), It.IsAny<ClaimsIdentity>())).Verifiable();
|
||||
}
|
||||
|
||||
var contextAccessor = new Mock<IContextAccessor<HttpContext>>();
|
||||
var contextAccessor = new Mock<IHttpContextAccessor>();
|
||||
contextAccessor.Setup(a => a.Value).Returns(context.Object);
|
||||
var roleManager = MockHelpers.MockRoleManager<TestRole>();
|
||||
var identityOptions = new IdentityOptions();
|
||||
identityOptions.SignIn.RequireConfirmedEmail = true;
|
||||
identityOptions.SignIn.RequireConfirmedPhoneNumber = true;
|
||||
var options = new Mock<IOptions<IdentityOptions>>();
|
||||
options.Setup(a => a.Options).Returns(identityOptions);
|
||||
var claimsFactory = new Mock<ClaimsIdentityFactory<TestUser, TestRole>>(manager.Object, roleManager.Object, options.Object);
|
||||
var helper = new SignInManager<TestUser>(manager.Object, contextAccessor.Object, claimsFactory.Object, options.Object);
|
||||
var logStore = new StringBuilder();
|
||||
var loggerFactory = MockHelpers.MockILoggerFactory(MockHelpers.MockILogger(logStore).Object);
|
||||
var helper = new SignInManager<TestUser>(manager.Object, contextAccessor.Object, claimsFactory.Object, options.Object, loggerFactory.Object);
|
||||
string expected = string.Format("{0} for user: {1} : Result : {2}", "CanSignInAsync", user.Id.ToString(), confirmed.ToString());
|
||||
|
||||
// Act
|
||||
var result = await helper.PasswordSignInAsync(user, "password", false, false);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(confirmed ? SignInStatus.Success : SignInStatus.NotAllowed, result);
|
||||
Assert.Equal(confirmed, result.Succeeded);
|
||||
Assert.NotEqual(confirmed, result.IsNotAllowed);
|
||||
Assert.NotEqual(-1, logStore.ToString().IndexOf(expected));
|
||||
manager.VerifyAll();
|
||||
context.VerifyAll();
|
||||
response.VerifyAll();
|
||||
|
|
|
|||
|
|
@ -0,0 +1,71 @@
|
|||
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System.Text;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.AspNet.Identity.Test
|
||||
{
|
||||
public class SignInResultTest
|
||||
{
|
||||
[Fact]
|
||||
public void VerifyLogSuccess()
|
||||
{
|
||||
var result = SignInResult.Success;
|
||||
var logMessage = new StringBuilder();
|
||||
var logger = MockHelpers.MockILogger(logMessage);
|
||||
|
||||
result.Log(logger.Object, "Operation");
|
||||
|
||||
Assert.Equal("Operation : Result : Succeeded", logMessage.ToString());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void VerifyLogLockedOut()
|
||||
{
|
||||
var result = SignInResult.LockedOut;
|
||||
var logMessage = new StringBuilder();
|
||||
var logger = MockHelpers.MockILogger(logMessage);
|
||||
|
||||
result.Log(logger.Object, "Operation");
|
||||
|
||||
Assert.Equal("Operation : Result : Lockedout", logMessage.ToString());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void VerifyLogNotAllowed()
|
||||
{
|
||||
var result = SignInResult.NotAllowed;
|
||||
var logMessage = new StringBuilder();
|
||||
var logger = MockHelpers.MockILogger(logMessage);
|
||||
|
||||
result.Log(logger.Object, "Operation");
|
||||
|
||||
Assert.Equal("Operation : Result : NotAllowed", logMessage.ToString());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void VerifyLogRequiresTwoFactor()
|
||||
{
|
||||
var result = SignInResult.TwoFactorRequired;
|
||||
var logMessage = new StringBuilder();
|
||||
var logger = MockHelpers.MockILogger(logMessage);
|
||||
|
||||
result.Log(logger.Object, "Operation");
|
||||
|
||||
Assert.Equal("Operation : Result : RequiresTwoFactor", logMessage.ToString());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void VerifyLogRequiresFailed()
|
||||
{
|
||||
var result = SignInResult.Failed;
|
||||
var logMessage = new StringBuilder();
|
||||
var logger = MockHelpers.MockILogger(logMessage);
|
||||
|
||||
result.Log(logger.Object, "Operation");
|
||||
|
||||
Assert.Equal("Operation : Result : Failed", logMessage.ToString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,16 +1,15 @@
|
|||
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using Microsoft.Framework.DependencyInjection;
|
||||
using Microsoft.Framework.DependencyInjection.Fallback;
|
||||
using Microsoft.Framework.OptionsModel;
|
||||
using Moq;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Security.Claims;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Framework.DependencyInjection;
|
||||
using Microsoft.Framework.DependencyInjection.Fallback;
|
||||
using Moq;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.AspNet.Identity.Test
|
||||
|
|
@ -21,10 +20,7 @@ namespace Microsoft.AspNet.Identity.Test
|
|||
{
|
||||
public IUserStore<TestUser> StorePublic { get { return Store; } }
|
||||
|
||||
public TestManager(IUserStore<TestUser> store, IOptions<IdentityOptions> optionsAccessor,
|
||||
IPasswordHasher<TestUser> passwordHasher, IEnumerable<IUserValidator<TestUser>> userValidator,
|
||||
IEnumerable<IPasswordValidator<TestUser>> passwordValidator)
|
||||
: base(store, optionsAccessor, passwordHasher, userValidator, passwordValidator, null, null, null) { }
|
||||
public TestManager(IUserStore<TestUser> store) : base(store) { }
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
|
@ -36,8 +32,6 @@ namespace Microsoft.AspNet.Identity.Test
|
|||
services.AddIdentity<TestUser, IdentityRole>();
|
||||
var manager = services.BuildServiceProvider().GetRequiredService<TestManager>();
|
||||
Assert.NotNull(manager.PasswordHasher);
|
||||
Assert.Equal(1, manager.PasswordValidators.Count);
|
||||
Assert.Equal(1, manager.UserValidators.Count);
|
||||
Assert.NotNull(manager.StorePublic);
|
||||
Assert.NotNull(manager.Options);
|
||||
}
|
||||
|
|
@ -48,7 +42,30 @@ namespace Microsoft.AspNet.Identity.Test
|
|||
// Setup
|
||||
var store = new Mock<IUserStore<TestUser>>();
|
||||
var user = new TestUser { UserName = "Foo" };
|
||||
store.Setup(s => s.CreateAsync(user, CancellationToken.None)).Returns(Task.FromResult(0)).Verifiable();
|
||||
store.Setup(s => s.CreateAsync(user, CancellationToken.None)).ReturnsAsync(IdentityResult.Success).Verifiable();
|
||||
store.Setup(s => s.GetUserNameAsync(user, CancellationToken.None)).Returns(Task.FromResult(user.UserName)).Verifiable();
|
||||
store.Setup(s => s.SetNormalizedUserNameAsync(user, user.UserName.ToUpperInvariant(), CancellationToken.None)).Returns(Task.FromResult(0)).Verifiable();
|
||||
var userManager = MockHelpers.TestUserManager<TestUser>(store.Object);
|
||||
|
||||
// Act
|
||||
var result = await userManager.CreateAsync(user);
|
||||
|
||||
// Assert
|
||||
Assert.True(result.Succeeded);
|
||||
store.VerifyAll();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task CreateCallsUpdateEmailStore()
|
||||
{
|
||||
// Setup
|
||||
var store = new Mock<IUserEmailStore<TestUser>>();
|
||||
var user = new TestUser { UserName = "Foo", Email = "Foo@foo.com" };
|
||||
store.Setup(s => s.CreateAsync(user, CancellationToken.None)).ReturnsAsync(IdentityResult.Success).Verifiable();
|
||||
store.Setup(s => s.GetUserNameAsync(user, CancellationToken.None)).Returns(Task.FromResult(user.UserName)).Verifiable();
|
||||
store.Setup(s => s.GetEmailAsync(user, CancellationToken.None)).Returns(Task.FromResult(user.Email)).Verifiable();
|
||||
store.Setup(s => s.SetNormalizedEmailAsync(user, user.Email.ToUpperInvariant(), CancellationToken.None)).Returns(Task.FromResult(0)).Verifiable();
|
||||
store.Setup(s => s.SetNormalizedUserNameAsync(user, user.UserName.ToUpperInvariant(), CancellationToken.None)).Returns(Task.FromResult(0)).Verifiable();
|
||||
var userManager = MockHelpers.TestUserManager<TestUser>(store.Object);
|
||||
|
||||
// Act
|
||||
|
|
@ -65,8 +82,8 @@ namespace Microsoft.AspNet.Identity.Test
|
|||
// Setup
|
||||
var store = new Mock<IUserStore<TestUser>>();
|
||||
var user = new TestUser { UserName = "Foo" };
|
||||
store.Setup(s => s.DeleteAsync(user, CancellationToken.None)).Returns(Task.FromResult(0)).Verifiable();
|
||||
var userManager = MockHelpers.TestUserManager<TestUser>(store.Object);
|
||||
store.Setup(s => s.DeleteAsync(user, CancellationToken.None)).ReturnsAsync(IdentityResult.Success).Verifiable();
|
||||
var userManager = MockHelpers.TestUserManager(store.Object);
|
||||
|
||||
// Act
|
||||
var result = await userManager.DeleteAsync(user);
|
||||
|
|
@ -82,8 +99,31 @@ namespace Microsoft.AspNet.Identity.Test
|
|||
// Setup
|
||||
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 userManager = MockHelpers.TestUserManager<TestUser>(store.Object);
|
||||
store.Setup(s => s.GetUserNameAsync(user, CancellationToken.None)).Returns(Task.FromResult(user.UserName)).Verifiable();
|
||||
store.Setup(s => s.SetNormalizedUserNameAsync(user, user.UserName.ToUpperInvariant(), CancellationToken.None)).Returns(Task.FromResult(0)).Verifiable();
|
||||
store.Setup(s => s.UpdateAsync(user, CancellationToken.None)).ReturnsAsync(IdentityResult.Success).Verifiable();
|
||||
var userManager = MockHelpers.TestUserManager(store.Object);
|
||||
|
||||
// Act
|
||||
var result = await userManager.UpdateAsync(user);
|
||||
|
||||
// Assert
|
||||
Assert.True(result.Succeeded);
|
||||
store.VerifyAll();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task UpdateWillUpdateNormalizedEmail()
|
||||
{
|
||||
// Setup
|
||||
var store = new Mock<IUserEmailStore<TestUser>>();
|
||||
var user = new TestUser { UserName = "Foo", Email = "email" };
|
||||
store.Setup(s => s.GetUserNameAsync(user, CancellationToken.None)).Returns(Task.FromResult(user.UserName)).Verifiable();
|
||||
store.Setup(s => s.GetEmailAsync(user, CancellationToken.None)).Returns(Task.FromResult(user.Email)).Verifiable();
|
||||
store.Setup(s => s.SetNormalizedUserNameAsync(user, user.UserName.ToUpperInvariant(), CancellationToken.None)).Returns(Task.FromResult(0)).Verifiable();
|
||||
store.Setup(s => s.SetNormalizedEmailAsync(user, user.Email.ToUpperInvariant(), CancellationToken.None)).Returns(Task.FromResult(0)).Verifiable();
|
||||
store.Setup(s => s.UpdateAsync(user, CancellationToken.None)).ReturnsAsync(IdentityResult.Success).Verifiable();
|
||||
var userManager = MockHelpers.TestUserManager(store.Object);
|
||||
|
||||
// Act
|
||||
var result = await userManager.UpdateAsync(user);
|
||||
|
|
@ -99,8 +139,11 @@ namespace Microsoft.AspNet.Identity.Test
|
|||
// Setup
|
||||
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 userManager = MockHelpers.TestUserManager<TestUser>(store.Object);
|
||||
store.Setup(s => s.SetUserNameAsync(user, "foo", CancellationToken.None)).Returns(Task.FromResult(0)).Verifiable();
|
||||
store.Setup(s => s.GetUserNameAsync(user, CancellationToken.None)).Returns(Task.FromResult("foo")).Verifiable();
|
||||
store.Setup(s => s.SetNormalizedUserNameAsync(user, "FOO", CancellationToken.None)).Returns(Task.FromResult(0)).Verifiable();
|
||||
store.Setup(s => s.UpdateAsync(user, CancellationToken.None)).Returns(Task.FromResult(IdentityResult.Success)).Verifiable();
|
||||
var userManager = MockHelpers.TestUserManager(store.Object);
|
||||
|
||||
// Act
|
||||
var result = await userManager.SetUserNameAsync(user, "foo");
|
||||
|
|
@ -132,7 +175,7 @@ namespace Microsoft.AspNet.Identity.Test
|
|||
{
|
||||
// Setup
|
||||
var store = new Mock<IUserStore<TestUser>>();
|
||||
var user = new TestUser {UserName="Foo"};
|
||||
var user = new TestUser { UserName = "Foo" };
|
||||
store.Setup(s => s.FindByNameAsync(user.UserName.ToUpperInvariant(), CancellationToken.None)).Returns(Task.FromResult(user)).Verifiable();
|
||||
var userManager = MockHelpers.TestUserManager<TestUser>(store.Object);
|
||||
|
||||
|
|
@ -149,10 +192,10 @@ namespace Microsoft.AspNet.Identity.Test
|
|||
{
|
||||
// Setup
|
||||
var store = new Mock<IUserStore<TestUser>>();
|
||||
var user = new TestUser {UserName="Foo"};
|
||||
var user = new TestUser { UserName = "Foo" };
|
||||
store.Setup(s => s.FindByNameAsync(user.UserName, CancellationToken.None)).Returns(Task.FromResult(user)).Verifiable();
|
||||
var userManager = MockHelpers.TestUserManager<TestUser>(store.Object);
|
||||
userManager.UserNameNormalizer = null;
|
||||
var userManager = MockHelpers.TestUserManager(store.Object);
|
||||
userManager.KeyNormalizer = null;
|
||||
|
||||
// Act
|
||||
var result = await userManager.FindByNameAsync(user.UserName);
|
||||
|
|
@ -162,13 +205,48 @@ namespace Microsoft.AspNet.Identity.Test
|
|||
store.VerifyAll();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task FindByEmailCallsStoreWithNormalizedEmail()
|
||||
{
|
||||
// Setup
|
||||
var store = new Mock<IUserEmailStore<TestUser>>();
|
||||
var user = new TestUser { Email = "Foo" };
|
||||
store.Setup(s => s.FindByEmailAsync(user.Email.ToUpperInvariant(), CancellationToken.None)).Returns(Task.FromResult(user)).Verifiable();
|
||||
var userManager = MockHelpers.TestUserManager(store.Object);
|
||||
|
||||
// Act
|
||||
var result = await userManager.FindByEmailAsync(user.Email);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(user, result);
|
||||
store.VerifyAll();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task CanFindByEmailCallsStoreWithoutNormalizedEmail()
|
||||
{
|
||||
// Setup
|
||||
var store = new Mock<IUserEmailStore<TestUser>>();
|
||||
var user = new TestUser { Email = "Foo" };
|
||||
store.Setup(s => s.FindByEmailAsync(user.Email, CancellationToken.None)).Returns(Task.FromResult(user)).Verifiable();
|
||||
var userManager = MockHelpers.TestUserManager(store.Object);
|
||||
userManager.KeyNormalizer = null;
|
||||
|
||||
// Act
|
||||
var result = await userManager.FindByEmailAsync(user.Email);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(user, result);
|
||||
store.VerifyAll();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task AddToRolesCallsStore()
|
||||
{
|
||||
// Setup
|
||||
var store = new Mock<IUserRoleStore<TestUser>>();
|
||||
var user = new TestUser { UserName = "Foo" };
|
||||
var roles = new string[] {"A", "B", "C"};
|
||||
var roles = new string[] { "A", "B", "C" };
|
||||
store.Setup(s => s.AddToRoleAsync(user, "A", CancellationToken.None))
|
||||
.Returns(Task.FromResult(0))
|
||||
.Verifiable();
|
||||
|
|
@ -178,7 +256,7 @@ namespace Microsoft.AspNet.Identity.Test
|
|||
store.Setup(s => s.AddToRoleAsync(user, "C", CancellationToken.None))
|
||||
.Returns(Task.FromResult(0))
|
||||
.Verifiable();
|
||||
store.Setup(s => s.UpdateAsync(user, CancellationToken.None)).Returns(Task.FromResult(0)).Verifiable();
|
||||
store.Setup(s => s.UpdateAsync(user, CancellationToken.None)).ReturnsAsync(IdentityResult.Success).Verifiable();
|
||||
store.Setup(s => s.GetRolesAsync(user, CancellationToken.None)).ReturnsAsync(new List<string>()).Verifiable();
|
||||
var userManager = MockHelpers.TestUserManager<TestUser>(store.Object);
|
||||
|
||||
|
|
@ -207,7 +285,7 @@ namespace Microsoft.AspNet.Identity.Test
|
|||
var result = await userManager.AddToRolesAsync(user, roles);
|
||||
|
||||
// Assert
|
||||
IdentityResultAssert.IsFailure(result, "User already in role.");
|
||||
IdentityResultAssert.IsFailure(result, IdentityErrorDescriber.Default.UserAlreadyInRole("B"));
|
||||
store.VerifyAll();
|
||||
}
|
||||
|
||||
|
|
@ -227,7 +305,7 @@ namespace Microsoft.AspNet.Identity.Test
|
|||
store.Setup(s => s.RemoveFromRoleAsync(user, "C", CancellationToken.None))
|
||||
.Returns(Task.FromResult(0))
|
||||
.Verifiable();
|
||||
store.Setup(s => s.UpdateAsync(user, CancellationToken.None)).Returns(Task.FromResult(0)).Verifiable();
|
||||
store.Setup(s => s.UpdateAsync(user, CancellationToken.None)).ReturnsAsync(IdentityResult.Success).Verifiable();
|
||||
store.Setup(s => s.IsInRoleAsync(user, "A", CancellationToken.None))
|
||||
.Returns(Task.FromResult(true))
|
||||
.Verifiable();
|
||||
|
|
@ -269,7 +347,7 @@ namespace Microsoft.AspNet.Identity.Test
|
|||
var result = await userManager.RemoveFromRolesAsync(user, roles);
|
||||
|
||||
// Assert
|
||||
IdentityResultAssert.IsFailure(result, "User is not in role.");
|
||||
IdentityResultAssert.IsFailure(result, IdentityErrorDescriber.Default.UserNotInRole("B"));
|
||||
store.VerifyAll();
|
||||
}
|
||||
|
||||
|
|
@ -283,8 +361,8 @@ namespace Microsoft.AspNet.Identity.Test
|
|||
store.Setup(s => s.AddClaimsAsync(user, claims, CancellationToken.None))
|
||||
.Returns(Task.FromResult(0))
|
||||
.Verifiable();
|
||||
store.Setup(s => s.UpdateAsync(user, CancellationToken.None)).Returns(Task.FromResult(0)).Verifiable();
|
||||
var userManager = MockHelpers.TestUserManager<TestUser>(store.Object);
|
||||
store.Setup(s => s.UpdateAsync(user, CancellationToken.None)).ReturnsAsync(IdentityResult.Success).Verifiable();
|
||||
var userManager = MockHelpers.TestUserManager(store.Object);
|
||||
|
||||
// Act
|
||||
var result = await userManager.AddClaimsAsync(user, claims);
|
||||
|
|
@ -304,8 +382,8 @@ namespace Microsoft.AspNet.Identity.Test
|
|||
store.Setup(s => s.AddClaimsAsync(user, It.IsAny<IEnumerable<Claim>>(), CancellationToken.None))
|
||||
.Returns(Task.FromResult(0))
|
||||
.Verifiable();
|
||||
store.Setup(s => s.UpdateAsync(user, CancellationToken.None)).Returns(Task.FromResult(0)).Verifiable();
|
||||
var userManager = MockHelpers.TestUserManager<TestUser>(store.Object);
|
||||
store.Setup(s => s.UpdateAsync(user, CancellationToken.None)).ReturnsAsync(IdentityResult.Success).Verifiable();
|
||||
var userManager = MockHelpers.TestUserManager(store.Object);
|
||||
|
||||
// Act
|
||||
var result = await userManager.AddClaimAsync(user, claim);
|
||||
|
|
@ -326,7 +404,8 @@ namespace Microsoft.AspNet.Identity.Test
|
|||
store.Setup(s => s.ReplaceClaimAsync(user, It.IsAny<Claim>(), It.IsAny<Claim>(), CancellationToken.None))
|
||||
.Returns(Task.FromResult(0))
|
||||
.Verifiable();
|
||||
var userManager = MockHelpers.TestUserManager<TestUser>(store.Object);
|
||||
store.Setup(s => s.UpdateAsync(user, CancellationToken.None)).Returns(Task.FromResult(IdentityResult.Success)).Verifiable();
|
||||
var userManager = MockHelpers.TestUserManager(store.Object);
|
||||
|
||||
// Act
|
||||
var result = await userManager.ReplaceClaimAsync(user, claim, newClaim);
|
||||
|
|
@ -336,6 +415,34 @@ namespace Microsoft.AspNet.Identity.Test
|
|||
store.VerifyAll();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task CheckPasswordWillRehashPasswordWhenNeeded()
|
||||
{
|
||||
// Setup
|
||||
var store = new Mock<IUserPasswordStore<TestUser>>();
|
||||
var hasher = new Mock<IPasswordHasher<TestUser>>();
|
||||
var user = new TestUser { UserName = "Foo" };
|
||||
var pwd = "password";
|
||||
var hashed = "hashed";
|
||||
var rehashed = "rehashed";
|
||||
|
||||
store.Setup(s => s.GetPasswordHashAsync(user, CancellationToken.None))
|
||||
.ReturnsAsync(hashed)
|
||||
.Verifiable();
|
||||
hasher.Setup(s => s.VerifyHashedPassword(user, hashed, pwd)).Returns(PasswordVerificationResult.SuccessRehashNeeded).Verifiable();
|
||||
hasher.Setup(s => s.HashPassword(user, pwd)).Returns(rehashed).Verifiable();
|
||||
var userManager = MockHelpers.TestUserManager(store.Object);
|
||||
userManager.PasswordHasher = hasher.Object;
|
||||
|
||||
// Act
|
||||
var result = await userManager.CheckPasswordAsync(user, pwd);
|
||||
|
||||
// Assert
|
||||
Assert.True(result);
|
||||
store.VerifyAll();
|
||||
hasher.VerifyAll();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task RemoveClaimsCallsStore()
|
||||
{
|
||||
|
|
@ -346,8 +453,8 @@ namespace Microsoft.AspNet.Identity.Test
|
|||
store.Setup(s => s.RemoveClaimsAsync(user, claims, CancellationToken.None))
|
||||
.Returns(Task.FromResult(0))
|
||||
.Verifiable();
|
||||
store.Setup(s => s.UpdateAsync(user, CancellationToken.None)).Returns(Task.FromResult(0)).Verifiable();
|
||||
var userManager = MockHelpers.TestUserManager<TestUser>(store.Object);
|
||||
store.Setup(s => s.UpdateAsync(user, CancellationToken.None)).ReturnsAsync(IdentityResult.Success).Verifiable();
|
||||
var userManager = MockHelpers.TestUserManager(store.Object);
|
||||
|
||||
// Act
|
||||
var result = await userManager.RemoveClaimsAsync(user, claims);
|
||||
|
|
@ -367,7 +474,7 @@ namespace Microsoft.AspNet.Identity.Test
|
|||
store.Setup(s => s.RemoveClaimsAsync(user, It.IsAny<IEnumerable<Claim>>(), CancellationToken.None))
|
||||
.Returns(Task.FromResult(0))
|
||||
.Verifiable();
|
||||
store.Setup(s => s.UpdateAsync(user, CancellationToken.None)).Returns(Task.FromResult(0)).Verifiable();
|
||||
store.Setup(s => s.UpdateAsync(user, CancellationToken.None)).ReturnsAsync(IdentityResult.Success).Verifiable();
|
||||
var userManager = MockHelpers.TestUserManager<TestUser>(store.Object);
|
||||
|
||||
// Act
|
||||
|
|
@ -533,17 +640,11 @@ namespace Microsoft.AspNet.Identity.Test
|
|||
public async Task ManagerPublicNullChecks()
|
||||
{
|
||||
var store = new NotImplementedStore();
|
||||
var optionsAccessor = new OptionsManager<IdentityOptions>(null);
|
||||
var passwordHasher = new PasswordHasher<TestUser>(new PasswordHasherOptionsAccessor());
|
||||
|
||||
Assert.Throws<ArgumentNullException>("store",
|
||||
() => new UserManager<TestUser>(null, null, null, null, null, null, null, null));
|
||||
Assert.Throws<ArgumentNullException>("optionsAccessor",
|
||||
() => new UserManager<TestUser>(store, null, null, null, null, null, null, null));
|
||||
Assert.Throws<ArgumentNullException>("passwordHasher",
|
||||
() => new UserManager<TestUser>(store, optionsAccessor, null, null, null, null, null, null));
|
||||
() => new UserManager<TestUser>(null, null));
|
||||
|
||||
var manager = new UserManager<TestUser>(store, optionsAccessor, passwordHasher, null, null, null, null, null);
|
||||
var manager = new UserManager<TestUser>(store);
|
||||
|
||||
Assert.Throws<ArgumentNullException>("value", () => manager.PasswordHasher = null);
|
||||
Assert.Throws<ArgumentNullException>("value", () => manager.Options = null);
|
||||
|
|
@ -581,7 +682,7 @@ namespace Microsoft.AspNet.Identity.Test
|
|||
await Assert.ThrowsAsync<ArgumentNullException>("user",
|
||||
async () => await manager.AddClaimAsync(null, new Claim("a", "b")));
|
||||
await Assert.ThrowsAsync<ArgumentNullException>("user",
|
||||
async () => await manager.AddLoginAsync(null, new UserLoginInfo("","","")));
|
||||
async () => await manager.AddLoginAsync(null, new UserLoginInfo("", "", "")));
|
||||
await Assert.ThrowsAsync<ArgumentNullException>("user",
|
||||
async () => await manager.AddPasswordAsync(null, null));
|
||||
await Assert.ThrowsAsync<ArgumentNullException>("user",
|
||||
|
|
@ -714,7 +815,7 @@ namespace Microsoft.AspNet.Identity.Test
|
|||
|
||||
private class BadPasswordValidator<TUser> : IPasswordValidator<TUser> where TUser : class
|
||||
{
|
||||
public const string ErrorMessage = "I'm Bad.";
|
||||
public static readonly IdentityError ErrorMessage = new IdentityError { Description = "I'm Bad." };
|
||||
|
||||
public Task<IdentityResult> ValidateAsync(UserManager<TUser> manager, TUser user, string password, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
|
|
@ -842,19 +943,19 @@ namespace Microsoft.AspNet.Identity.Test
|
|||
return Task.FromResult(0);
|
||||
}
|
||||
|
||||
public Task CreateAsync(TestUser user, CancellationToken cancellationToken = default(CancellationToken))
|
||||
public Task<IdentityResult> CreateAsync(TestUser user, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
return Task.FromResult(0);
|
||||
return Task.FromResult(IdentityResult.Success);
|
||||
}
|
||||
|
||||
public Task UpdateAsync(TestUser user, CancellationToken cancellationToken = default(CancellationToken))
|
||||
public Task<IdentityResult> UpdateAsync(TestUser user, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
return Task.FromResult(0);
|
||||
return Task.FromResult(IdentityResult.Success);
|
||||
}
|
||||
|
||||
public Task DeleteAsync(TestUser user, CancellationToken cancellationToken = default(CancellationToken))
|
||||
public Task<IdentityResult> DeleteAsync(TestUser user, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
return Task.FromResult(0);
|
||||
return Task.FromResult(IdentityResult.Success);
|
||||
}
|
||||
|
||||
public Task<TestUser> FindByIdAsync(string userId, CancellationToken cancellationToken = default(CancellationToken))
|
||||
|
|
@ -961,6 +1062,26 @@ namespace Microsoft.AspNet.Identity.Test
|
|||
{
|
||||
return Task.FromResult(0);
|
||||
}
|
||||
|
||||
public Task<IList<TestUser>> GetUsersForClaimAsync(Claim claim, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
return Task.FromResult<IList<TestUser>>(new List<TestUser>());
|
||||
}
|
||||
|
||||
public Task<IList<TestUser>> GetUsersInRoleAsync(string roleName, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
return Task.FromResult<IList<TestUser>>(new List<TestUser>());
|
||||
}
|
||||
|
||||
public Task<string> GetNormalizedEmailAsync(TestUser user, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
return Task.FromResult("");
|
||||
}
|
||||
|
||||
public Task SetNormalizedEmailAsync(TestUser user, string normalizedEmail, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
return Task.FromResult(0);
|
||||
}
|
||||
}
|
||||
|
||||
private class NoOpTokenProvider : IUserTokenProvider<TestUser>
|
||||
|
|
@ -1119,21 +1240,6 @@ namespace Microsoft.AspNet.Identity.Test
|
|||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task CreateAsync(TestUser user, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task UpdateAsync(TestUser user, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task DeleteAsync(TestUser user, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task<TestUser> FindByIdAsync(string userId, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
|
|
@ -1218,6 +1324,87 @@ namespace Microsoft.AspNet.Identity.Test
|
|||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task<IList<TestUser>> GetUsersForClaimAsync(Claim claim, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task<IList<TestUser>> GetUsersInRoleAsync(string roleName, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
Task<IdentityResult> IUserStore<TestUser>.CreateAsync(TestUser user, CancellationToken cancellationToken)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
Task<IdentityResult> IUserStore<TestUser>.UpdateAsync(TestUser user, CancellationToken cancellationToken)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
Task<IdentityResult> IUserStore<TestUser>.DeleteAsync(TestUser user, CancellationToken cancellationToken)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task<string> GetNormalizedEmailAsync(TestUser user, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task SetNormalizedEmailAsync(TestUser user, string normalizedEmail, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task CanCustomizeUserValidatorErrors()
|
||||
{
|
||||
var services = new ServiceCollection();
|
||||
var store = new Mock<IUserEmailStore<TestUser>>();
|
||||
var describer = new TestErrorDescriber();
|
||||
services.AddInstance<IdentityErrorDescriber>(describer)
|
||||
.AddInstance<IUserStore<TestUser>>(store.Object)
|
||||
.AddIdentity<TestUser, IdentityRole>();
|
||||
|
||||
var manager = services.BuildServiceProvider().GetRequiredService<UserManager<TestUser>>();
|
||||
|
||||
manager.Options.User.RequireUniqueEmail = true;
|
||||
var user = new TestUser() { UserName = "dupeEmail", Email = "dupe@email.com" };
|
||||
var user2 = new TestUser() { UserName = "dupeEmail2", Email = "dupe@email.com" };
|
||||
store.Setup(s => s.FindByEmailAsync("DUPE@EMAIL.COM", CancellationToken.None))
|
||||
.Returns(Task.FromResult(user2))
|
||||
.Verifiable();
|
||||
store.Setup(s => s.GetUserIdAsync(user2, CancellationToken.None))
|
||||
.Returns(Task.FromResult(user2.Id))
|
||||
.Verifiable();
|
||||
store.Setup(s => s.GetUserNameAsync(user, CancellationToken.None))
|
||||
.Returns(Task.FromResult(user.UserName))
|
||||
.Verifiable();
|
||||
store.Setup(s => s.GetEmailAsync(user, CancellationToken.None))
|
||||
.Returns(Task.FromResult(user.Email))
|
||||
.Verifiable();
|
||||
|
||||
Assert.Same(describer, manager.ErrorDescriber);
|
||||
IdentityResultAssert.IsFailure(await manager.CreateAsync(user), describer.DuplicateEmail(user.Email));
|
||||
|
||||
store.VerifyAll();
|
||||
}
|
||||
|
||||
public class TestErrorDescriber : IdentityErrorDescriber
|
||||
{
|
||||
public static string Code = "Error";
|
||||
public static string FormatError = "FormatError {0}";
|
||||
|
||||
public override IdentityError DuplicateEmail(string email)
|
||||
{
|
||||
return new IdentityError { Code = Code, Description = string.Format(FormatError, email) };
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -36,7 +36,7 @@ namespace Microsoft.AspNet.Identity.Test
|
|||
var result = await validator.ValidateAsync(manager, user);
|
||||
|
||||
// Assert
|
||||
IdentityResultAssert.IsFailure(result, "UserName cannot be null or empty.");
|
||||
IdentityResultAssert.IsFailure(result, IdentityErrorDescriber.Default.InvalidUserName(input));
|
||||
}
|
||||
|
||||
[Theory]
|
||||
|
|
|
|||
|
|
@ -3,13 +3,12 @@
|
|||
"Microsoft.AspNet.Hosting" : "1.0.0-*",
|
||||
"Microsoft.AspNet.Http" : "1.0.0-*",
|
||||
"Microsoft.AspNet.Identity" : "3.0.0-*",
|
||||
"Microsoft.AspNet.PipelineCore" : "1.0.0-*",
|
||||
"Microsoft.AspNet.RequestContainer" : "1.0.0-*",
|
||||
"Microsoft.AspNet.Testing" : "1.0.0-*",
|
||||
"Microsoft.Framework.ConfigurationModel" : "1.0.0-*",
|
||||
"Microsoft.Framework.DependencyInjection" : "1.0.0-*",
|
||||
"Microsoft.Framework.OptionsModel" : "1.0.0-*",
|
||||
"Xunit.KRunner": "1.0.0-*"
|
||||
"xunit.runner.kre": "1.0.0-*"
|
||||
},
|
||||
"code": "**\\*.cs;..\\Shared\\*.cs",
|
||||
"frameworks": {
|
||||
|
|
@ -20,6 +19,6 @@
|
|||
}
|
||||
},
|
||||
"commands": {
|
||||
"test": "Xunit.KRunner"
|
||||
"test": "xunit.runner.kre"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System.Linq;
|
||||
using Microsoft.Framework.Logging;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.AspNet.Identity.Test
|
||||
|
|
@ -24,7 +25,79 @@ namespace Microsoft.AspNet.Identity.Test
|
|||
{
|
||||
Assert.NotNull(result);
|
||||
Assert.False(result.Succeeded);
|
||||
Assert.Equal(error, result.Errors.First());
|
||||
Assert.Equal(error, result.Errors.First().Description);
|
||||
}
|
||||
|
||||
public static void IsFailure(IdentityResult result, IdentityError error)
|
||||
{
|
||||
Assert.NotNull(result);
|
||||
Assert.False(result.Succeeded);
|
||||
Assert.Equal(error.Description, result.Errors.First().Description);
|
||||
Assert.Equal(error.Code, result.Errors.First().Code);
|
||||
}
|
||||
|
||||
public static void VerifyUserManagerFailureLog(ILogger logger, string methodName, string userId, params IdentityError[] errors)
|
||||
{
|
||||
VerifyFailureLog(logger, "UserManager", methodName, userId, "user", errors);
|
||||
}
|
||||
|
||||
public static void VerifyRoleManagerFailureLog(ILogger logger, string methodName, string roleId, params IdentityError[] errors)
|
||||
{
|
||||
VerifyFailureLog(logger, "RoleManager", methodName, roleId, "role", errors);
|
||||
}
|
||||
|
||||
public static void VerifyUserManagerSuccessLog(ILogger logger, string methodName, string userId)
|
||||
{
|
||||
VerifySuccessLog(logger, "UserManager", methodName, userId, "user");
|
||||
|
||||
}
|
||||
|
||||
public static void VerifyRoleManagerSuccessLog(ILogger logger, string methodName, string roleId)
|
||||
{
|
||||
VerifySuccessLog(logger, "RoleManager", methodName, roleId, "role");
|
||||
|
||||
}
|
||||
private static void VerifySuccessLog(ILogger logger, string className, string methodName, string id, string userOrRole = "user")
|
||||
{
|
||||
TestLogger testlogger = logger as TestLogger;
|
||||
if (testlogger != null)
|
||||
{
|
||||
string expected = string.Format("{0} for {1}: {2} : Success", methodName, userOrRole, id);
|
||||
Assert.True(testlogger.LogMessages.Contains(expected));
|
||||
}
|
||||
else
|
||||
{
|
||||
Assert.True(true, "No logger registered");
|
||||
}
|
||||
}
|
||||
|
||||
public static void VerifyLogMessage(ILogger logger, string expectedLog)
|
||||
{
|
||||
TestLogger testlogger = logger as TestLogger;
|
||||
if (testlogger != null)
|
||||
{
|
||||
Assert.True(testlogger.LogMessages.Contains(expectedLog));
|
||||
}
|
||||
else
|
||||
{
|
||||
Assert.True(true, "No logger registered");
|
||||
}
|
||||
}
|
||||
|
||||
private static void VerifyFailureLog(ILogger logger, string className, string methodName, string userId, string userOrRole = "user", params IdentityError[] errors)
|
||||
{
|
||||
TestLogger testlogger = logger as TestLogger;
|
||||
if (testlogger != null)
|
||||
{
|
||||
errors = errors ?? new IdentityError[] { new IdentityError() };
|
||||
string expected = string.Format("{0} for {1}: {2} : Failed : {3}", methodName, userOrRole, userId, string.Join(",", errors.Select(x => x.Code).ToList()));
|
||||
|
||||
Assert.True(testlogger.LogMessages.Contains(expected));
|
||||
}
|
||||
else
|
||||
{
|
||||
Assert.True(true, "No logger registered");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,59 +1,86 @@
|
|||
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Framework.OptionsModel;
|
||||
using Microsoft.Framework.Logging;
|
||||
using Moq;
|
||||
using System.Text;
|
||||
|
||||
namespace Microsoft.AspNet.Identity.Test
|
||||
{
|
||||
public static class MockHelpers
|
||||
{
|
||||
public static StringBuilder LogMessage = new StringBuilder();
|
||||
|
||||
public static Mock<UserManager<TUser>> MockUserManager<TUser>() where TUser : class
|
||||
{
|
||||
var store = new Mock<IUserStore<TUser>>();
|
||||
var options = new OptionsManager<IdentityOptions>(null);
|
||||
var userValidators = new List<IUserValidator<TUser>>();
|
||||
userValidators.Add(new UserValidator<TUser>());
|
||||
var pwdValidators = new List<IPasswordValidator<TUser>>();
|
||||
pwdValidators.Add(new PasswordValidator<TUser>());
|
||||
return new Mock<UserManager<TUser>>(
|
||||
store.Object,
|
||||
options,
|
||||
new PasswordHasher<TUser>(new PasswordHasherOptionsAccessor()),
|
||||
userValidators,
|
||||
pwdValidators,
|
||||
new UpperInvariantUserNameNormalizer(),
|
||||
new List<IUserTokenProvider<TUser>>(),
|
||||
new List<IIdentityMessageProvider>());
|
||||
var mgr = new Mock<UserManager<TUser>>(store.Object, null, null, null, null, null, null, null, null, null);
|
||||
mgr.Object.UserValidators.Add(new UserValidator<TUser>());
|
||||
mgr.Object.PasswordValidators.Add(new PasswordValidator<TUser>());
|
||||
return mgr;
|
||||
}
|
||||
|
||||
public static Mock<RoleManager<TRole>> MockRoleManager<TRole>() where TRole : class
|
||||
public static Mock<RoleManager<TRole>> MockRoleManager<TRole>(IRoleStore<TRole> store = null) where TRole : class
|
||||
{
|
||||
var store = new Mock<IRoleStore<TRole>>();
|
||||
store = store ?? new Mock<IRoleStore<TRole>>().Object;
|
||||
var roles = new List<IRoleValidator<TRole>>();
|
||||
roles.Add(new RoleValidator<TRole>());
|
||||
return new Mock<RoleManager<TRole>>(store.Object, roles);
|
||||
return new Mock<RoleManager<TRole>>(store, roles, null, null,null);
|
||||
}
|
||||
|
||||
public static UserManager<TUser> TestUserManager<TUser>() where TUser : class
|
||||
public static Mock<ILogger> MockILogger(StringBuilder logStore = null)
|
||||
{
|
||||
return TestUserManager(new Mock<IUserStore<TUser>>().Object);
|
||||
logStore = logStore ?? LogMessage;
|
||||
var logger = new Mock<ILogger>();
|
||||
logger.Setup(x => x.Write(It.IsAny<LogLevel>(), It.IsAny<int>(), It.IsAny<object>(),
|
||||
It.IsAny<Exception>(), It.IsAny<Func<object, Exception, string>>()))
|
||||
.Callback((LogLevel logLevel, int eventId, object state, Exception exception, Func<object, Exception, string> formatter) =>
|
||||
{ logStore.Append(state.ToString()); });
|
||||
logger.Setup(x => x.IsEnabled(LogLevel.Information)).Returns(true);
|
||||
logger.Setup(x => x.IsEnabled(LogLevel.Warning)).Returns(true);
|
||||
|
||||
return logger;
|
||||
}
|
||||
|
||||
public static UserManager<TUser> TestUserManager<TUser>(IUserStore<TUser> store) where TUser : class
|
||||
public static Mock<ILoggerFactory> MockILoggerFactory(ILogger logger = null)
|
||||
{
|
||||
var options = new OptionsManager<IdentityOptions>(null);
|
||||
var validator = new Mock<UserValidator<TUser>>();
|
||||
var userManager = new UserManager<TUser>(store, options, new PasswordHasher<TUser>(new PasswordHasherOptionsAccessor()),
|
||||
null, null, new UpperInvariantUserNameNormalizer(), null, null);
|
||||
logger = logger ?? MockILogger().Object;
|
||||
var loggerFactory = new Mock<ILoggerFactory>();
|
||||
loggerFactory.Setup(x => x.Create(It.IsAny<string>())).Returns(logger);
|
||||
return loggerFactory;
|
||||
}
|
||||
|
||||
public static UserManager<TUser> UserManagerWithMockLogger<TUser>(ILoggerFactory loggerFactory = null) where TUser : class
|
||||
{
|
||||
var userstore = new Mock<IUserStore<TUser>>().Object;
|
||||
var userManager = new UserManager<TUser>(userstore, loggerFactory: loggerFactory ?? MockILoggerFactory().Object);
|
||||
|
||||
return userManager;
|
||||
}
|
||||
|
||||
public static UserManager<TUser> TestUserManager<TUser>(IUserStore<TUser> store = null) where TUser : class
|
||||
{
|
||||
store = store ?? new Mock<IUserStore<TUser>>().Object;
|
||||
var validator = new Mock<IUserValidator<TUser>>();
|
||||
var userManager = new UserManager<TUser>(store);
|
||||
userManager.UserValidators.Add(validator.Object);
|
||||
userManager.PasswordValidators.Add(new PasswordValidator<TUser>());
|
||||
validator.Setup(v => v.ValidateAsync(userManager, It.IsAny<TUser>(), CancellationToken.None))
|
||||
.Returns(Task.FromResult(IdentityResult.Success)).Verifiable();
|
||||
return userManager;
|
||||
}
|
||||
|
||||
public static RoleManager<TRole> TestRoleManager<TRole>(IRoleStore<TRole> store = null) where TRole : class
|
||||
{
|
||||
store = store ?? new Mock<IRoleStore<TRole>>().Object;
|
||||
var roles = new List<IRoleValidator<TRole>>();
|
||||
roles.Add(new RoleValidator<TRole>());
|
||||
return new RoleManager<TRole>(store, roles);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -30,7 +30,7 @@ namespace Microsoft.AspNet.Identity.Test
|
|||
{
|
||||
int priority = 0;
|
||||
|
||||
foreach (IAttributeInfo attr in testCase.Method.GetCustomAttributes((typeof(TestPriorityAttribute))))
|
||||
foreach (IAttributeInfo attr in testCase.TestMethod.Method.GetCustomAttributes((typeof(TestPriorityAttribute))))
|
||||
priority = attr.GetNamedArgument<int>("Priority");
|
||||
|
||||
GetOrCreate(sortedMethods, priority).Add(testCase);
|
||||
|
|
@ -38,7 +38,7 @@ namespace Microsoft.AspNet.Identity.Test
|
|||
|
||||
foreach (var list in sortedMethods.Keys.Select(priority => sortedMethods[priority]))
|
||||
{
|
||||
list.Sort((x, y) => StringComparer.OrdinalIgnoreCase.Compare(x.Method.Name, y.Method.Name));
|
||||
list.Sort((x, y) => StringComparer.OrdinalIgnoreCase.Compare(x.TestMethod.Method.Name, y.TestMethod.Method.Name));
|
||||
foreach (XunitTestCase testCase in list)
|
||||
yield return testCase;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,29 @@
|
|||
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.Framework.Logging;
|
||||
|
||||
namespace Microsoft.AspNet.Identity.Test
|
||||
{
|
||||
public class TestLogger : ILogger
|
||||
{
|
||||
public IList<string> LogMessages { get; private set; } = new List<string>();
|
||||
|
||||
public IDisposable BeginScope(object state)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public bool IsEnabled(LogLevel logLevel)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public void Write(LogLevel logLevel, int eventId, object state, Exception exception, Func<object, Exception, string> formatter)
|
||||
{
|
||||
LogMessages.Add(state.ToString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using Microsoft.Framework.Logging;
|
||||
|
||||
namespace Microsoft.AspNet.Identity.Test
|
||||
{
|
||||
public class TestLoggerFactory : ILoggerFactory
|
||||
{
|
||||
public void AddProvider(ILoggerProvider provider)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public ILogger Create(string name)
|
||||
{
|
||||
return new TestLogger();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -14,5 +14,6 @@ namespace Microsoft.AspNet.Identity.Test
|
|||
|
||||
public string Id { get; private set; }
|
||||
public string UserName { get; set; }
|
||||
public string Email { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
@ -10,6 +10,7 @@ using System.Threading.Tasks;
|
|||
using Microsoft.AspNet.Testing;
|
||||
using Microsoft.Framework.DependencyInjection;
|
||||
using Microsoft.Framework.DependencyInjection.Fallback;
|
||||
using Microsoft.Framework.Logging;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.AspNet.Identity.Test
|
||||
|
|
@ -20,17 +21,25 @@ namespace Microsoft.AspNet.Identity.Test
|
|||
where TRole : IdentityRole, new()
|
||||
{ }
|
||||
|
||||
public abstract class UserManagerTestBase<TUser, TRole, TKey>
|
||||
where TUser: IdentityUser<TKey>, new()
|
||||
where TRole: IdentityRole<TKey>, new()
|
||||
public abstract class UserManagerTestBase<TUser, TRole, TKey>
|
||||
where TUser : IdentityUser<TKey>, new()
|
||||
where TRole : IdentityRole<TKey>, new()
|
||||
where TKey : IEquatable<TKey>
|
||||
{
|
||||
protected TestLoggerFactory loggerFactory;
|
||||
|
||||
public UserManagerTestBase()
|
||||
{
|
||||
loggerFactory = new TestLoggerFactory();
|
||||
}
|
||||
|
||||
protected virtual void SetupIdentityServices(IServiceCollection services, object context = null)
|
||||
{
|
||||
services.AddHosting();
|
||||
services.AddIdentity<TUser, TRole>().AddDefaultTokenProviders();
|
||||
AddUserStore(services, context);
|
||||
AddRoleStore(services, context);
|
||||
services.AddInstance<ILoggerFactory>(loggerFactory);
|
||||
services.ConfigureIdentity(options =>
|
||||
{
|
||||
options.Password.RequireDigit = false;
|
||||
|
|
@ -74,11 +83,13 @@ namespace Microsoft.AspNet.Identity.Test
|
|||
protected abstract void AddUserStore(IServiceCollection services, object context = null);
|
||||
protected abstract void AddRoleStore(IServiceCollection services, object context = null);
|
||||
|
||||
protected TUser CreateTestUser(string namePrefix = "") {
|
||||
protected TUser CreateTestUser(string namePrefix = "")
|
||||
{
|
||||
return new TUser() { UserName = namePrefix + Guid.NewGuid().ToString() };
|
||||
}
|
||||
|
||||
protected TRole CreateRole(string namePrefix = "") {
|
||||
protected TRole CreateRole(string namePrefix = "")
|
||||
{
|
||||
return new TRole() { Name = namePrefix + Guid.NewGuid().ToString() };
|
||||
}
|
||||
|
||||
|
|
@ -88,7 +99,11 @@ namespace Microsoft.AspNet.Identity.Test
|
|||
var manager = CreateManager();
|
||||
var user = CreateTestUser();
|
||||
IdentityResultAssert.IsSuccess(await manager.CreateAsync(user));
|
||||
IdentityResultAssert.VerifyUserManagerSuccessLog(manager.Logger, "CreateAsync", user.Id.ToString());
|
||||
|
||||
IdentityResultAssert.IsSuccess(await manager.DeleteAsync(user));
|
||||
IdentityResultAssert.VerifyUserManagerSuccessLog(manager.Logger, "DeleteAsync", user.Id.ToString());
|
||||
|
||||
Assert.Null(await manager.FindByIdAsync(user.Id.ToString()));
|
||||
}
|
||||
|
||||
|
|
@ -103,6 +118,7 @@ namespace Microsoft.AspNet.Identity.Test
|
|||
Assert.Null(await manager.FindByNameAsync(newName));
|
||||
user.UserName = newName;
|
||||
IdentityResultAssert.IsSuccess(await manager.UpdateAsync(user));
|
||||
IdentityResultAssert.VerifyUserManagerSuccessLog(manager.Logger, "UpdateAsync", user.Id.ToString());
|
||||
Assert.NotNull(await manager.FindByNameAsync(newName));
|
||||
Assert.Null(await manager.FindByNameAsync(name));
|
||||
}
|
||||
|
|
@ -126,9 +142,14 @@ namespace Microsoft.AspNet.Identity.Test
|
|||
var user = new TUser() { UserName = "UpdatePassword" };
|
||||
IdentityResultAssert.IsSuccess(await manager.CreateAsync(user, "password"));
|
||||
Assert.True(await manager.CheckPasswordAsync(user, "password"));
|
||||
string expectedLog = string.Format("{0} for user: {1} : {2}", "CheckPasswordAsync", user.Id.ToString(), true.ToString());
|
||||
IdentityResultAssert.VerifyLogMessage(manager.Logger, expectedLog);
|
||||
|
||||
user.PasswordHash = manager.PasswordHasher.HashPassword(user, "New");
|
||||
IdentityResultAssert.IsSuccess(await manager.UpdateAsync(user));
|
||||
Assert.False(await manager.CheckPasswordAsync(user, "password"));
|
||||
expectedLog = string.Format("{0} for user: {1} : {2}", "CheckPasswordAsync", user.Id.ToString(), false.ToString());
|
||||
IdentityResultAssert.VerifyLogMessage(manager.Logger, expectedLog);
|
||||
Assert.True(await manager.CheckPasswordAsync(user, "New"));
|
||||
}
|
||||
|
||||
|
|
@ -160,6 +181,7 @@ namespace Microsoft.AspNet.Identity.Test
|
|||
manager.UserValidators.Clear();
|
||||
manager.UserValidators.Add(new AlwaysBadValidator());
|
||||
IdentityResultAssert.IsFailure(await manager.UpdateAsync(user), AlwaysBadValidator.ErrorMessage);
|
||||
IdentityResultAssert.VerifyUserManagerFailureLog(manager.Logger, "UpdateAsync", user.Id.ToString(), AlwaysBadValidator.ErrorMessage);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
|
@ -182,7 +204,7 @@ namespace Microsoft.AspNet.Identity.Test
|
|||
var manager = CreateManager();
|
||||
var user = CreateTestUser();
|
||||
manager.Options.User.RequireUniqueEmail = true;
|
||||
IdentityResultAssert.IsFailure(await manager.CreateAsync(user), "Email cannot be null or empty.");
|
||||
IdentityResultAssert.IsFailure(await manager.CreateAsync(user), IdentityErrorDescriber.Default.InvalidEmail(email));
|
||||
}
|
||||
|
||||
#if ASPNET50
|
||||
|
|
@ -194,7 +216,7 @@ namespace Microsoft.AspNet.Identity.Test
|
|||
var manager = CreateManager();
|
||||
var user = new TUser() { UserName = "UpdateBlocked", Email = email };
|
||||
manager.Options.User.RequireUniqueEmail = true;
|
||||
IdentityResultAssert.IsFailure(await manager.CreateAsync(user), "Email '" + email + "' is invalid.");
|
||||
IdentityResultAssert.IsFailure(await manager.CreateAsync(user), IdentityErrorDescriber.Default.InvalidEmail(email));
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
@ -208,6 +230,7 @@ namespace Microsoft.AspNet.Identity.Test
|
|||
manager.PasswordValidators.Add(new AlwaysBadValidator());
|
||||
IdentityResultAssert.IsFailure(await manager.AddPasswordAsync(user, "password"),
|
||||
AlwaysBadValidator.ErrorMessage);
|
||||
IdentityResultAssert.VerifyUserManagerFailureLog(manager.Logger, "AddPasswordAsync", user.Id.ToString(), AlwaysBadValidator.ErrorMessage);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
|
@ -234,6 +257,17 @@ namespace Microsoft.AspNet.Identity.Test
|
|||
manager.PasswordValidators.Add(new AlwaysBadValidator());
|
||||
IdentityResultAssert.IsFailure(await manager.ChangePasswordAsync(user, "password", "new"),
|
||||
AlwaysBadValidator.ErrorMessage);
|
||||
IdentityResultAssert.VerifyUserManagerFailureLog(manager.Logger, "ChangePasswordAsync", user.Id.ToString(), AlwaysBadValidator.ErrorMessage);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task PasswordValidatorCanBlockCreateUser()
|
||||
{
|
||||
var manager = CreateManager();
|
||||
var user = CreateTestUser();
|
||||
manager.PasswordValidators.Clear();
|
||||
manager.PasswordValidators.Add(new AlwaysBadValidator());
|
||||
IdentityResultAssert.IsFailure(await manager.CreateAsync(user, "password"), AlwaysBadValidator.ErrorMessage);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
|
@ -260,6 +294,7 @@ namespace Microsoft.AspNet.Identity.Test
|
|||
IdentityResultAssert.IsSuccess(await manager.CreateAsync(user));
|
||||
user = await manager.FindByNameAsync(user.UserName);
|
||||
IdentityResultAssert.IsSuccess(await manager.AddLoginAsync(user, new UserLoginInfo(provider, providerKey, display)));
|
||||
IdentityResultAssert.VerifyUserManagerSuccessLog(manager.Logger, "AddLoginAsync", user.Id.ToString());
|
||||
var logins = await manager.GetLoginsAsync(user);
|
||||
Assert.NotNull(logins);
|
||||
Assert.Equal(1, logins.Count());
|
||||
|
|
@ -278,6 +313,7 @@ namespace Microsoft.AspNet.Identity.Test
|
|||
IdentityResultAssert.IsSuccess(await manager.AddLoginAsync(user, login));
|
||||
Assert.False(await manager.HasPasswordAsync(user));
|
||||
IdentityResultAssert.IsSuccess(await manager.AddPasswordAsync(user, "password"));
|
||||
IdentityResultAssert.VerifyUserManagerSuccessLog(manager.Logger, "AddPasswordAsync", user.Id.ToString());
|
||||
Assert.True(await manager.HasPasswordAsync(user));
|
||||
var logins = await manager.GetLoginsAsync(user);
|
||||
Assert.NotNull(logins);
|
||||
|
|
@ -295,6 +331,7 @@ namespace Microsoft.AspNet.Identity.Test
|
|||
Assert.True(await manager.HasPasswordAsync(user));
|
||||
IdentityResultAssert.IsFailure(await manager.AddPasswordAsync(user, "password"),
|
||||
"User already has a password set.");
|
||||
IdentityResultAssert.VerifyUserManagerFailureLog(manager.Logger, "AddPasswordAsync", user.Id.ToString(), IdentityErrorDescriber.Default.UserAlreadyHasPassword());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
|
@ -316,6 +353,7 @@ namespace Microsoft.AspNet.Identity.Test
|
|||
Assert.Equal(login.ProviderDisplayName, logins.Last().ProviderDisplayName);
|
||||
var stamp = user.SecurityStamp;
|
||||
IdentityResultAssert.IsSuccess(await manager.RemoveLoginAsync(user, login.LoginProvider, login.ProviderKey));
|
||||
IdentityResultAssert.VerifyUserManagerSuccessLog(manager.Logger, "RemoveLoginAsync", user.Id.ToString());
|
||||
Assert.Null(await manager.FindByLoginAsync(login.LoginProvider, login.ProviderKey));
|
||||
logins = await manager.GetLoginsAsync(user);
|
||||
Assert.NotNull(logins);
|
||||
|
|
@ -332,6 +370,7 @@ namespace Microsoft.AspNet.Identity.Test
|
|||
IdentityResultAssert.IsSuccess(await manager.CreateAsync(user, password));
|
||||
var stamp = user.SecurityStamp;
|
||||
IdentityResultAssert.IsSuccess(await manager.RemovePasswordAsync(user));
|
||||
IdentityResultAssert.VerifyUserManagerSuccessLog(manager.Logger, "RemovePasswordAsync", user.Id.ToString());
|
||||
var u = await manager.FindByNameAsync(user.UserName);
|
||||
Assert.NotNull(u);
|
||||
Assert.Null(u.PasswordHash);
|
||||
|
|
@ -351,6 +390,7 @@ namespace Microsoft.AspNet.Identity.Test
|
|||
IdentityResultAssert.IsSuccess(await manager.ChangePasswordAsync(user, password, newPassword));
|
||||
Assert.False(await manager.CheckPasswordAsync(user, password));
|
||||
Assert.True(await manager.CheckPasswordAsync(user, newPassword));
|
||||
IdentityResultAssert.VerifyUserManagerSuccessLog(manager.Logger, "ChangePasswordAsync", user.Id.ToString());
|
||||
Assert.NotEqual(stamp, user.SecurityStamp);
|
||||
}
|
||||
|
||||
|
|
@ -365,6 +405,35 @@ namespace Microsoft.AspNet.Identity.Test
|
|||
{
|
||||
IdentityResultAssert.IsSuccess(await manager.AddClaimAsync(user, c));
|
||||
}
|
||||
IdentityResultAssert.VerifyUserManagerSuccessLog(manager.Logger, "AddClaimsAsync", user.Id.ToString());
|
||||
var userClaims = await manager.GetClaimsAsync(user);
|
||||
Assert.Equal(3, userClaims.Count);
|
||||
IdentityResultAssert.IsSuccess(await manager.RemoveClaimAsync(user, claims[0]));
|
||||
IdentityResultAssert.VerifyUserManagerSuccessLog(manager.Logger, "RemoveClaimsAsync", user.Id.ToString());
|
||||
userClaims = await manager.GetClaimsAsync(user);
|
||||
Assert.Equal(2, userClaims.Count);
|
||||
IdentityResultAssert.IsSuccess(await manager.RemoveClaimAsync(user, claims[1]));
|
||||
userClaims = await manager.GetClaimsAsync(user);
|
||||
Assert.Equal(1, userClaims.Count);
|
||||
IdentityResultAssert.IsSuccess(await manager.RemoveClaimAsync(user, claims[2]));
|
||||
userClaims = await manager.GetClaimsAsync(user);
|
||||
Assert.Equal(0, userClaims.Count);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task RemoveClaimOnlyAffectsUser()
|
||||
{
|
||||
var manager = CreateManager();
|
||||
var user = CreateTestUser();
|
||||
var user2 = CreateTestUser();
|
||||
IdentityResultAssert.IsSuccess(await manager.CreateAsync(user));
|
||||
IdentityResultAssert.IsSuccess(await manager.CreateAsync(user2));
|
||||
Claim[] claims = { new Claim("c", "v"), new Claim("c2", "v2"), new Claim("c2", "v3") };
|
||||
foreach (Claim c in claims)
|
||||
{
|
||||
IdentityResultAssert.IsSuccess(await manager.AddClaimAsync(user, c));
|
||||
IdentityResultAssert.IsSuccess(await manager.AddClaimAsync(user2, c));
|
||||
}
|
||||
var userClaims = await manager.GetClaimsAsync(user);
|
||||
Assert.Equal(3, userClaims.Count);
|
||||
IdentityResultAssert.IsSuccess(await manager.RemoveClaimAsync(user, claims[0]));
|
||||
|
|
@ -376,6 +445,8 @@ namespace Microsoft.AspNet.Identity.Test
|
|||
IdentityResultAssert.IsSuccess(await manager.RemoveClaimAsync(user, claims[2]));
|
||||
userClaims = await manager.GetClaimsAsync(user);
|
||||
Assert.Equal(0, userClaims.Count);
|
||||
var userClaims2 = await manager.GetClaimsAsync(user2);
|
||||
Assert.Equal(3, userClaims2.Count);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
|
@ -390,6 +461,7 @@ namespace Microsoft.AspNet.Identity.Test
|
|||
Claim claim = new Claim("c", "b");
|
||||
Claim oldClaim = userClaims.FirstOrDefault();
|
||||
IdentityResultAssert.IsSuccess(await manager.ReplaceClaimAsync(user, oldClaim, claim));
|
||||
IdentityResultAssert.VerifyUserManagerSuccessLog(manager.Logger, "ReplaceClaimAsync", user.Id.ToString());
|
||||
var newUserClaims = await manager.GetClaimsAsync(user);
|
||||
Assert.Equal(1, newUserClaims.Count);
|
||||
Claim newClaim = newUserClaims.FirstOrDefault();
|
||||
|
|
@ -397,6 +469,35 @@ namespace Microsoft.AspNet.Identity.Test
|
|||
Assert.Equal(claim.Value, newClaim.Value);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ReplaceUserClaimOnlyAffectsUser()
|
||||
{
|
||||
var manager = CreateManager();
|
||||
var user = CreateTestUser();
|
||||
var user2 = CreateTestUser();
|
||||
IdentityResultAssert.IsSuccess(await manager.CreateAsync(user));
|
||||
IdentityResultAssert.IsSuccess(await manager.CreateAsync(user2));
|
||||
IdentityResultAssert.IsSuccess(await manager.AddClaimAsync(user, new Claim("c", "a")));
|
||||
IdentityResultAssert.IsSuccess(await manager.AddClaimAsync(user2, new Claim("c", "a")));
|
||||
var userClaims = await manager.GetClaimsAsync(user);
|
||||
Assert.Equal(1, userClaims.Count);
|
||||
var userClaims2 = await manager.GetClaimsAsync(user);
|
||||
Assert.Equal(1, userClaims2.Count);
|
||||
Claim claim = new Claim("c", "b");
|
||||
Claim oldClaim = userClaims.FirstOrDefault();
|
||||
IdentityResultAssert.IsSuccess(await manager.ReplaceClaimAsync(user, oldClaim, claim));
|
||||
var newUserClaims = await manager.GetClaimsAsync(user);
|
||||
Assert.Equal(1, newUserClaims.Count);
|
||||
Claim newClaim = newUserClaims.FirstOrDefault();
|
||||
Assert.Equal(claim.Type, newClaim.Type);
|
||||
Assert.Equal(claim.Value, newClaim.Value);
|
||||
userClaims2 = await manager.GetClaimsAsync(user2);
|
||||
Assert.Equal(1, userClaims2.Count);
|
||||
Claim oldClaim2 = userClaims2.FirstOrDefault();
|
||||
Assert.Equal("c", oldClaim2.Type);
|
||||
Assert.Equal("a", oldClaim2.Value);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ChangePasswordFallsIfPasswordWrong()
|
||||
{
|
||||
|
|
@ -405,6 +506,7 @@ namespace Microsoft.AspNet.Identity.Test
|
|||
IdentityResultAssert.IsSuccess(await manager.CreateAsync(user, "password"));
|
||||
var result = await manager.ChangePasswordAsync(user, "bogus", "newpassword");
|
||||
IdentityResultAssert.IsFailure(result, "Incorrect password.");
|
||||
IdentityResultAssert.VerifyUserManagerFailureLog(manager.Logger, "ChangePasswordAsync", user.Id.ToString(), IdentityErrorDescriber.Default.PasswordMismatch());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
|
@ -414,7 +516,7 @@ namespace Microsoft.AspNet.Identity.Test
|
|||
var user = CreateTestUser();
|
||||
var user2 = new TUser() { UserName = user.UserName };
|
||||
IdentityResultAssert.IsSuccess(await manager.CreateAsync(user));
|
||||
IdentityResultAssert.IsFailure(await manager.CreateAsync(user2), "Name "+user.UserName+" is already taken.");
|
||||
IdentityResultAssert.IsFailure(await manager.CreateAsync(user2), IdentityErrorDescriber.Default.DuplicateUserName(user.UserName));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
|
@ -440,7 +542,7 @@ namespace Microsoft.AspNet.Identity.Test
|
|||
user.Email = email;
|
||||
user2.Email = email;
|
||||
IdentityResultAssert.IsSuccess(await manager.CreateAsync(user));
|
||||
IdentityResultAssert.IsFailure(await manager.CreateAsync(user2), "Email '"+email+"' is already taken.");
|
||||
IdentityResultAssert.IsFailure(await manager.CreateAsync(user2), IdentityErrorDescriber.Default.DuplicateEmail(user.Email));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
|
@ -453,6 +555,7 @@ namespace Microsoft.AspNet.Identity.Test
|
|||
var stamp = user.SecurityStamp;
|
||||
Assert.NotNull(stamp);
|
||||
IdentityResultAssert.IsSuccess(await manager.UpdateSecurityStampAsync(user));
|
||||
IdentityResultAssert.VerifyUserManagerSuccessLog(manager.Logger, "UpdateSecurityStampAsync", user.Id.ToString());
|
||||
Assert.NotEqual(stamp, user.SecurityStamp);
|
||||
}
|
||||
|
||||
|
|
@ -465,7 +568,8 @@ namespace Microsoft.AspNet.Identity.Test
|
|||
IdentityResultAssert.IsSuccess(await manager.CreateAsync(user));
|
||||
IdentityResultAssert.IsSuccess(await manager.AddLoginAsync(user, login));
|
||||
var result = await manager.AddLoginAsync(user, login);
|
||||
IdentityResultAssert.IsFailure(result, "A user with that external login already exists.");
|
||||
IdentityResultAssert.IsFailure(result, IdentityErrorDescriber.Default.LoginAlreadyAssociated());
|
||||
IdentityResultAssert.VerifyUserManagerFailureLog(manager.Logger, "AddLoginAsync", user.Id.ToString(), IdentityErrorDescriber.Default.LoginAlreadyAssociated());
|
||||
}
|
||||
|
||||
// Email tests
|
||||
|
|
@ -549,7 +653,9 @@ namespace Microsoft.AspNet.Identity.Test
|
|||
Assert.NotNull(stamp);
|
||||
var token = await manager.GeneratePasswordResetTokenAsync(user);
|
||||
Assert.NotNull(token);
|
||||
IdentityResultAssert.VerifyUserManagerSuccessLog(manager.Logger, "GeneratePasswordResetTokenAsync", user.Id.ToString());
|
||||
IdentityResultAssert.IsSuccess(await manager.ResetPasswordAsync(user, token, newPassword));
|
||||
IdentityResultAssert.VerifyUserManagerSuccessLog(manager.Logger, "ResetPasswordAsync", user.Id.ToString());
|
||||
Assert.False(await manager.CheckPasswordAsync(user, password));
|
||||
Assert.True(await manager.CheckPasswordAsync(user, newPassword));
|
||||
Assert.NotEqual(stamp, user.SecurityStamp);
|
||||
|
|
@ -572,6 +678,7 @@ namespace Microsoft.AspNet.Identity.Test
|
|||
manager.PasswordValidators.Add(new AlwaysBadValidator());
|
||||
IdentityResultAssert.IsFailure(await manager.ResetPasswordAsync(user, token, newPassword),
|
||||
AlwaysBadValidator.ErrorMessage);
|
||||
IdentityResultAssert.VerifyUserManagerFailureLog(manager.Logger, "ResetPasswordAsync", user.Id.ToString(), AlwaysBadValidator.ErrorMessage);
|
||||
Assert.True(await manager.CheckPasswordAsync(user, password));
|
||||
Assert.Equal(stamp, user.SecurityStamp);
|
||||
}
|
||||
|
|
@ -589,6 +696,7 @@ namespace Microsoft.AspNet.Identity.Test
|
|||
var stamp = user.SecurityStamp;
|
||||
Assert.NotNull(stamp);
|
||||
IdentityResultAssert.IsFailure(await manager.ResetPasswordAsync(user, "bogus", newPassword), "Invalid token.");
|
||||
IdentityResultAssert.VerifyUserManagerFailureLog(manager.Logger, "ResetPasswordAsync", user.Id.ToString(), IdentityErrorDescriber.Default.InvalidToken());
|
||||
Assert.True(await manager.CheckPasswordAsync(user, password));
|
||||
Assert.Equal(stamp, user.SecurityStamp);
|
||||
}
|
||||
|
|
@ -603,8 +711,14 @@ namespace Microsoft.AspNet.Identity.Test
|
|||
IdentityResultAssert.IsSuccess(await manager.CreateAsync(user));
|
||||
IdentityResultAssert.IsSuccess(await manager.CreateAsync(user2));
|
||||
var token = await manager.GenerateUserTokenAsync(user, "Static", "test");
|
||||
IdentityResultAssert.VerifyUserManagerSuccessLog(manager.Logger, "GenerateUserTokenAsync", user.Id.ToString());
|
||||
|
||||
Assert.True(await manager.VerifyUserTokenAsync(user, "Static", "test", token));
|
||||
IdentityResultAssert.VerifyUserManagerSuccessLog(manager.Logger, "VerifyUserTokenAsync", user.Id.ToString());
|
||||
|
||||
Assert.False(await manager.VerifyUserTokenAsync(user, "Static", "test2", token));
|
||||
IdentityResultAssert.VerifyUserManagerFailureLog(manager.Logger, "VerifyUserTokenAsync", user.Id.ToString(), IdentityErrorDescriber.Default.InvalidToken());
|
||||
|
||||
Assert.False(await manager.VerifyUserTokenAsync(user, "Static", "test", token + "a"));
|
||||
Assert.False(await manager.VerifyUserTokenAsync(user2, "Static", "test", token));
|
||||
}
|
||||
|
|
@ -620,7 +734,9 @@ namespace Microsoft.AspNet.Identity.Test
|
|||
IdentityResultAssert.IsSuccess(await manager.CreateAsync(user));
|
||||
var token = await manager.GenerateEmailConfirmationTokenAsync(user);
|
||||
Assert.NotNull(token);
|
||||
IdentityResultAssert.VerifyUserManagerSuccessLog(manager.Logger, "GenerateEmailConfirmationTokenAsync", user.Id.ToString());
|
||||
IdentityResultAssert.IsSuccess(await manager.ConfirmEmailAsync(user, token));
|
||||
IdentityResultAssert.VerifyUserManagerSuccessLog(manager.Logger, "ConfirmEmailAsync", user.Id.ToString());
|
||||
Assert.True(await manager.IsEmailConfirmedAsync(user));
|
||||
IdentityResultAssert.IsSuccess(await manager.SetEmailAsync(user, null));
|
||||
Assert.False(await manager.IsEmailConfirmedAsync(user));
|
||||
|
|
@ -637,6 +753,7 @@ namespace Microsoft.AspNet.Identity.Test
|
|||
IdentityResultAssert.IsSuccess(await manager.CreateAsync(user));
|
||||
IdentityResultAssert.IsFailure(await manager.ConfirmEmailAsync(user, "bogus"), "Invalid token.");
|
||||
Assert.False(await manager.IsEmailConfirmedAsync(user));
|
||||
IdentityResultAssert.VerifyUserManagerFailureLog(manager.Logger, "ConfirmEmailAsync", user.Id.ToString(), IdentityErrorDescriber.Default.InvalidToken());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
|
@ -712,6 +829,7 @@ namespace Microsoft.AspNet.Identity.Test
|
|||
Assert.False(await mgr.GetLockoutEndDateAsync(user) > DateTimeOffset.UtcNow.AddMinutes(55));
|
||||
Assert.Equal(1, await mgr.GetAccessFailedCountAsync(user));
|
||||
IdentityResultAssert.IsSuccess(await mgr.ResetAccessFailedCountAsync(user));
|
||||
IdentityResultAssert.VerifyUserManagerSuccessLog(mgr.Logger, "ResetAccessFailedCountAsync", user.Id.ToString());
|
||||
Assert.Equal(0, await mgr.GetAccessFailedCountAsync(user));
|
||||
Assert.False(await mgr.IsLockedOutAsync(user));
|
||||
Assert.False(await mgr.GetLockoutEndDateAsync(user) > DateTimeOffset.UtcNow.AddMinutes(55));
|
||||
|
|
@ -734,8 +852,10 @@ namespace Microsoft.AspNet.Identity.Test
|
|||
IdentityResultAssert.IsSuccess(await mgr.SetLockoutEnabledAsync(user, true));
|
||||
Assert.True(await mgr.GetLockoutEnabledAsync(user));
|
||||
Assert.True(user.LockoutEnabled);
|
||||
IdentityResultAssert.VerifyUserManagerSuccessLog(mgr.Logger, "SetLockoutEnabledAsync", user.Id.ToString());
|
||||
Assert.False(await mgr.IsLockedOutAsync(user));
|
||||
IdentityResultAssert.IsSuccess(await mgr.AccessFailedAsync(user));
|
||||
IdentityResultAssert.VerifyUserManagerSuccessLog(mgr.Logger, "AccessFailedAsync", user.Id.ToString());
|
||||
Assert.False(await mgr.IsLockedOutAsync(user));
|
||||
Assert.False(await mgr.GetLockoutEndDateAsync(user) > DateTimeOffset.UtcNow.AddMinutes(55));
|
||||
Assert.Equal(1, await mgr.GetAccessFailedCountAsync(user));
|
||||
|
|
@ -756,6 +876,7 @@ namespace Microsoft.AspNet.Identity.Test
|
|||
Assert.True(user.LockoutEnabled);
|
||||
IdentityResultAssert.IsSuccess(await mgr.SetLockoutEndDateAsync(user, new DateTimeOffset()));
|
||||
Assert.False(await mgr.IsLockedOutAsync(user));
|
||||
IdentityResultAssert.VerifyUserManagerSuccessLog(mgr.Logger, "SetLockoutEndDateAsync", user.Id.ToString());
|
||||
Assert.Equal(new DateTimeOffset(), await mgr.GetLockoutEndDateAsync(user));
|
||||
Assert.Equal(new DateTimeOffset(), user.LockoutEnd);
|
||||
}
|
||||
|
|
@ -842,7 +963,7 @@ namespace Microsoft.AspNet.Identity.Test
|
|||
private class AlwaysBadValidator : IUserValidator<TUser>, IRoleValidator<TRole>,
|
||||
IPasswordValidator<TUser>
|
||||
{
|
||||
public const string ErrorMessage = "I'm Bad.";
|
||||
public static readonly IdentityError ErrorMessage = new IdentityError { Description = "I'm Bad.", Code = "BadValidator" };
|
||||
|
||||
public Task<IdentityResult> ValidateAsync(UserManager<TUser> manager, TUser user, string password, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
|
|
@ -892,6 +1013,7 @@ namespace Microsoft.AspNet.Identity.Test
|
|||
manager.RoleValidators.Clear();
|
||||
manager.RoleValidators.Add(new AlwaysBadValidator());
|
||||
IdentityResultAssert.IsFailure(await manager.UpdateAsync(role), error);
|
||||
IdentityResultAssert.VerifyRoleManagerFailureLog(manager.Logger, "UpdateAsync", role.Id.ToString(), AlwaysBadValidator.ErrorMessage);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
|
@ -903,6 +1025,7 @@ namespace Microsoft.AspNet.Identity.Test
|
|||
IdentityResultAssert.IsSuccess(await manager.CreateAsync(role));
|
||||
IdentityResultAssert.IsSuccess(await manager.DeleteAsync(role));
|
||||
Assert.False(await manager.RoleExistsAsync(role.Name));
|
||||
IdentityResultAssert.VerifyRoleManagerSuccessLog(manager.Logger, "DeleteAsync", role.Id.ToString());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
|
@ -916,6 +1039,7 @@ namespace Microsoft.AspNet.Identity.Test
|
|||
{
|
||||
IdentityResultAssert.IsSuccess(await manager.AddClaimAsync(role, c));
|
||||
}
|
||||
IdentityResultAssert.VerifyRoleManagerSuccessLog(manager.Logger, "AddClaimAsync", role.Id.ToString());
|
||||
var roleClaims = await manager.GetClaimsAsync(role);
|
||||
Assert.Equal(3, roleClaims.Count);
|
||||
IdentityResultAssert.IsSuccess(await manager.RemoveClaimAsync(role, claims[0]));
|
||||
|
|
@ -927,6 +1051,8 @@ namespace Microsoft.AspNet.Identity.Test
|
|||
IdentityResultAssert.IsSuccess(await manager.RemoveClaimAsync(role, claims[2]));
|
||||
roleClaims = await manager.GetClaimsAsync(role);
|
||||
Assert.Equal(0, roleClaims.Count);
|
||||
|
||||
IdentityResultAssert.VerifyRoleManagerSuccessLog(manager.Logger, "RemoveClaimAsync", role.Id.ToString());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
|
@ -958,10 +1084,11 @@ namespace Microsoft.AspNet.Identity.Test
|
|||
Assert.False(await manager.RoleExistsAsync(role.Name));
|
||||
IdentityResultAssert.IsSuccess(await manager.CreateAsync(role));
|
||||
Assert.True(await manager.RoleExistsAsync(role.Name));
|
||||
role.Name = "Changed";
|
||||
IdentityResultAssert.IsSuccess(await manager.SetRoleNameAsync(role, "Changed"));
|
||||
IdentityResultAssert.IsSuccess(await manager.UpdateAsync(role));
|
||||
IdentityResultAssert.VerifyRoleManagerSuccessLog(manager.Logger, "UpdateAsync", role.Id.ToString());
|
||||
Assert.False(await manager.RoleExistsAsync("update"));
|
||||
Assert.Equal(role, await manager.FindByNameAsync(role.Name));
|
||||
Assert.Equal(role, await manager.FindByNameAsync("Changed"));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
|
@ -1027,6 +1154,7 @@ namespace Microsoft.AspNet.Identity.Test
|
|||
var role = CreateRole("dupeRole");
|
||||
Assert.False(await manager.RoleExistsAsync(role.Name));
|
||||
IdentityResultAssert.IsSuccess(await manager.CreateAsync(role));
|
||||
IdentityResultAssert.VerifyRoleManagerSuccessLog(manager.Logger, "CreateAsync", role.Id.ToString());
|
||||
Assert.True(await manager.RoleExistsAsync(role.Name));
|
||||
var role2 = CreateRole();
|
||||
role2.Name = role.Name;
|
||||
|
|
@ -1051,6 +1179,8 @@ namespace Microsoft.AspNet.Identity.Test
|
|||
IdentityResultAssert.IsSuccess(await manager.CreateAsync(u));
|
||||
IdentityResultAssert.IsSuccess(await manager.AddToRoleAsync(u, role.Name));
|
||||
Assert.True(await manager.IsInRoleAsync(u, role.Name));
|
||||
IdentityResultAssert.VerifyUserManagerSuccessLog(manager.Logger, "AddToRoleAsync", u.Id.ToString());
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1103,6 +1233,7 @@ namespace Microsoft.AspNet.Identity.Test
|
|||
Assert.True(await userManager.IsInRoleAsync(user, r.Name));
|
||||
}
|
||||
IdentityResultAssert.IsSuccess(await userManager.RemoveFromRoleAsync(user, roles[2].Name));
|
||||
IdentityResultAssert.VerifyUserManagerSuccessLog(userManager.Logger, "RemoveFromRoleAsync", user.Id.ToString());
|
||||
Assert.False(await userManager.IsInRoleAsync(user, roles[2].Name));
|
||||
}
|
||||
|
||||
|
|
@ -1142,7 +1273,8 @@ namespace Microsoft.AspNet.Identity.Test
|
|||
IdentityResultAssert.IsSuccess(await userMgr.CreateAsync(user));
|
||||
IdentityResultAssert.IsSuccess(await roleMgr.CreateAsync(role));
|
||||
var result = await userMgr.RemoveFromRoleAsync(user, role.Name);
|
||||
IdentityResultAssert.IsFailure(result, "User is not in role.");
|
||||
IdentityResultAssert.IsFailure(result, IdentityErrorDescriber.Default.UserNotInRole(role.Name));
|
||||
IdentityResultAssert.VerifyUserManagerFailureLog(userMgr.Logger, "RemoveFromRoleAsync", user.Id.ToString(), IdentityErrorDescriber.Default.UserNotInRole(role.Name));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
|
@ -1157,7 +1289,8 @@ namespace Microsoft.AspNet.Identity.Test
|
|||
IdentityResultAssert.IsSuccess(await roleMgr.CreateAsync(role));
|
||||
IdentityResultAssert.IsSuccess(await userMgr.AddToRoleAsync(user, role.Name));
|
||||
Assert.True(await userMgr.IsInRoleAsync(user, role.Name));
|
||||
IdentityResultAssert.IsFailure(await userMgr.AddToRoleAsync(user, role.Name), "User already in role.");
|
||||
IdentityResultAssert.IsFailure(await userMgr.AddToRoleAsync(user, role.Name), IdentityErrorDescriber.Default.UserAlreadyInRole(role.Name));
|
||||
IdentityResultAssert.VerifyUserManagerFailureLog(userMgr.Logger, "AddToRoleAsync", user.Id.ToString(), IdentityErrorDescriber.Default.UserAlreadyInRole(role.Name));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
|
@ -1203,6 +1336,7 @@ namespace Microsoft.AspNet.Identity.Test
|
|||
var stamp = await manager.GetSecurityStampAsync(user);
|
||||
var token1 = await manager.GenerateChangePhoneNumberTokenAsync(user, "111-111-1111");
|
||||
IdentityResultAssert.IsSuccess(await manager.ChangePhoneNumberAsync(user, "111-111-1111", token1));
|
||||
IdentityResultAssert.VerifyUserManagerSuccessLog(manager.Logger, "ChangePhoneNumberAsync", user.Id.ToString());
|
||||
Assert.True(await manager.IsPhoneNumberConfirmedAsync(user));
|
||||
Assert.Equal(await manager.GetPhoneNumberAsync(user), "111-111-1111");
|
||||
Assert.NotEqual(stamp, user.SecurityStamp);
|
||||
|
|
@ -1219,6 +1353,7 @@ namespace Microsoft.AspNet.Identity.Test
|
|||
var stamp = await manager.GetSecurityStampAsync(user);
|
||||
IdentityResultAssert.IsFailure(await manager.ChangePhoneNumberAsync(user, "111-111-1111", "bogus"),
|
||||
"Invalid token.");
|
||||
IdentityResultAssert.VerifyUserManagerFailureLog(manager.Logger, "ChangePhoneNumberAsync", user.Id.ToString(), IdentityErrorDescriber.Default.InvalidToken());
|
||||
Assert.False(await manager.IsPhoneNumberConfirmedAsync(user));
|
||||
Assert.Equal(await manager.GetPhoneNumberAsync(user), "123-456-7890");
|
||||
Assert.Equal(stamp, user.SecurityStamp);
|
||||
|
|
@ -1250,12 +1385,16 @@ namespace Microsoft.AspNet.Identity.Test
|
|||
const string num1 = "111-123-4567";
|
||||
const string num2 = "111-111-1111";
|
||||
var token1 = await manager.GenerateChangePhoneNumberTokenAsync(user, num1);
|
||||
IdentityResultAssert.VerifyUserManagerSuccessLog(manager.Logger, "GenerateChangePhoneNumberTokenAsync", user.Id.ToString());
|
||||
|
||||
var token2 = await manager.GenerateChangePhoneNumberTokenAsync(user, num2);
|
||||
Assert.NotEqual(token1, token2);
|
||||
Assert.True(await manager.VerifyChangePhoneNumberTokenAsync(user, token1, num1));
|
||||
IdentityResultAssert.VerifyUserManagerSuccessLog(manager.Logger, "VerifyChangePhoneNumberTokenAsync", user.Id.ToString());
|
||||
Assert.True(await manager.VerifyChangePhoneNumberTokenAsync(user, token2, num2));
|
||||
Assert.False(await manager.VerifyChangePhoneNumberTokenAsync(user, token2, num1));
|
||||
Assert.False(await manager.VerifyChangePhoneNumberTokenAsync(user, token1, num2));
|
||||
IdentityResultAssert.VerifyUserManagerFailureLog(manager.Logger, "VerifyChangePhoneNumberTokenAsync", user.Id.ToString(), IdentityErrorDescriber.Default.InvalidToken());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
|
@ -1270,6 +1409,7 @@ namespace Microsoft.AspNet.Identity.Test
|
|||
string newEmail = user.UserName + "@en.vec";
|
||||
var token1 = await manager.GenerateChangeEmailTokenAsync(user, newEmail);
|
||||
IdentityResultAssert.IsSuccess(await manager.ChangeEmailAsync(user, newEmail, token1));
|
||||
IdentityResultAssert.VerifyUserManagerSuccessLog(manager.Logger, "ChangeEmailAsync", user.Id.ToString());
|
||||
Assert.True(await manager.IsEmailConfirmedAsync(user));
|
||||
Assert.Equal(await manager.GetEmailAsync(user), newEmail);
|
||||
Assert.NotEqual(stamp, user.SecurityStamp);
|
||||
|
|
@ -1287,6 +1427,7 @@ namespace Microsoft.AspNet.Identity.Test
|
|||
var stamp = await manager.GetSecurityStampAsync(user);
|
||||
IdentityResultAssert.IsFailure(await manager.ChangeEmailAsync(user, "whatevah@foo.barf", "bogus"),
|
||||
"Invalid token.");
|
||||
IdentityResultAssert.VerifyUserManagerFailureLog(manager.Logger, "ChangeEmailAsync", user.Id.ToString(), IdentityErrorDescriber.Default.InvalidToken());
|
||||
Assert.False(await manager.IsEmailConfirmedAsync(user));
|
||||
Assert.Equal(await manager.GetEmailAsync(user), oldEmail);
|
||||
Assert.Equal(stamp, user.SecurityStamp);
|
||||
|
|
@ -1328,8 +1469,9 @@ namespace Microsoft.AspNet.Identity.Test
|
|||
Assert.Null(messageService.Message);
|
||||
IdentityResultAssert.IsSuccess(await manager.NotifyTwoFactorTokenAsync(user, factorId, token));
|
||||
Assert.NotNull(messageService.Message);
|
||||
Assert.Equal("Your security code is: "+token, messageService.Message.Body);
|
||||
Assert.Equal("Your security code is: " + token, messageService.Message.Body);
|
||||
Assert.True(await manager.VerifyTwoFactorTokenAsync(user, factorId, token));
|
||||
IdentityResultAssert.VerifyUserManagerSuccessLog(manager.Logger, "VerifyTwoFactorTokenAsync", user.Id.ToString());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
|
@ -1369,11 +1511,13 @@ namespace Microsoft.AspNet.Identity.Test
|
|||
Assert.NotNull(stamp);
|
||||
var token = await manager.GenerateTwoFactorTokenAsync(user, factorId);
|
||||
Assert.NotNull(token);
|
||||
IdentityResultAssert.VerifyUserManagerSuccessLog(manager.Logger, "GenerateTwoFactorTokenAsync", user.Id.ToString());
|
||||
Assert.Null(messageService.Message);
|
||||
IdentityResultAssert.IsSuccess(await manager.NotifyTwoFactorTokenAsync(user, factorId, token));
|
||||
Assert.NotNull(messageService.Message);
|
||||
Assert.Equal(subject, messageService.Message.Subject);
|
||||
Assert.Equal(string.Format(body, token), messageService.Message.Body);
|
||||
IdentityResultAssert.VerifyUserManagerSuccessLog(manager.Logger, "NotifyTwoFactorTokenAsync", user.Id.ToString());
|
||||
Assert.True(await manager.VerifyTwoFactorTokenAsync(user, factorId, token));
|
||||
}
|
||||
|
||||
|
|
@ -1403,6 +1547,7 @@ namespace Microsoft.AspNet.Identity.Test
|
|||
var stamp = user.SecurityStamp;
|
||||
Assert.NotNull(stamp);
|
||||
IdentityResultAssert.IsSuccess(await manager.SetTwoFactorEnabledAsync(user, true));
|
||||
IdentityResultAssert.VerifyUserManagerSuccessLog(manager.Logger, "SetTwoFactorEnabledAsync", user.Id.ToString());
|
||||
Assert.NotEqual(stamp, await manager.GetSecurityStampAsync(user));
|
||||
Assert.True(await manager.GetTwoFactorEnabledAsync(user));
|
||||
}
|
||||
|
|
@ -1439,7 +1584,7 @@ namespace Microsoft.AspNet.Identity.Test
|
|||
Assert.Null(messageService.Message);
|
||||
IdentityResultAssert.IsSuccess(await manager.NotifyTwoFactorTokenAsync(user, factorId, token));
|
||||
Assert.NotNull(messageService.Message);
|
||||
Assert.Equal("Your security code is: "+token, messageService.Message.Body);
|
||||
Assert.Equal("Your security code is: " + token, messageService.Message.Body);
|
||||
Assert.True(await manager.VerifyTwoFactorTokenAsync(user, factorId, token));
|
||||
}
|
||||
|
||||
|
|
@ -1505,6 +1650,7 @@ namespace Microsoft.AspNet.Identity.Test
|
|||
Assert.NotNull(factors);
|
||||
Assert.False(factors.Any());
|
||||
IdentityResultAssert.IsSuccess(await manager.SetPhoneNumberAsync(user, "111-111-1111"));
|
||||
IdentityResultAssert.VerifyUserManagerSuccessLog(manager.Logger, "SetPhoneNumberAsync", user.Id.ToString());
|
||||
user.PhoneNumberConfirmed = true;
|
||||
await manager.UpdateAsync(user);
|
||||
factors = await manager.GetValidTwoFactorProvidersAsync(user);
|
||||
|
|
@ -1512,6 +1658,7 @@ namespace Microsoft.AspNet.Identity.Test
|
|||
Assert.Equal(1, factors.Count());
|
||||
Assert.Equal("Phone", factors[0]);
|
||||
IdentityResultAssert.IsSuccess(await manager.SetEmailAsync(user, "test@test.com"));
|
||||
IdentityResultAssert.VerifyUserManagerSuccessLog(manager.Logger, "SetEmailAsync", user.Id.ToString());
|
||||
user.EmailConfirmed = true;
|
||||
await manager.UpdateAsync(user);
|
||||
factors = await manager.GetValidTwoFactorProvidersAsync(user);
|
||||
|
|
@ -1560,6 +1707,7 @@ namespace Microsoft.AspNet.Identity.Test
|
|||
user.PhoneNumber = "4251234567";
|
||||
IdentityResultAssert.IsSuccess(await manager.CreateAsync(user));
|
||||
Assert.False(await manager.VerifyTwoFactorTokenAsync(user, "Phone", "bogus"));
|
||||
IdentityResultAssert.VerifyUserManagerFailureLog(manager.Logger, "VerifyTwoFactorTokenAsync", user.Id.ToString(), IdentityErrorDescriber.Default.InvalidToken());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
|
@ -1581,6 +1729,60 @@ namespace Microsoft.AspNet.Identity.Test
|
|||
Assert.Equal(DateTimeOffset.Parse("01/01/2014"), await userMgr.GetLockoutEndDateAsync(user));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task CanGetUsersWithClaims()
|
||||
{
|
||||
var manager = CreateManager();
|
||||
|
||||
for (int i = 0; i < 6; i++)
|
||||
{
|
||||
var user = CreateTestUser();
|
||||
IdentityResultAssert.IsSuccess(await manager.CreateAsync(user));
|
||||
|
||||
if ((i % 2) == 0)
|
||||
{
|
||||
IdentityResultAssert.IsSuccess(await manager.AddClaimAsync(user, new Claim("foo", "bar")));
|
||||
}
|
||||
}
|
||||
|
||||
Assert.Equal(3, (await manager.GetUsersForClaimAsync(new Claim("foo", "bar"))).Count);
|
||||
|
||||
Assert.Equal(0, (await manager.GetUsersForClaimAsync(new Claim("123", "456"))).Count);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task CanGetUsersInRole()
|
||||
{
|
||||
var context = CreateTestContext();
|
||||
var manager = CreateManager(context);
|
||||
var roleManager = CreateRoleManager(context);
|
||||
var roles = GenerateRoles("UsersInRole", 4);
|
||||
|
||||
foreach (var role in roles)
|
||||
{
|
||||
IdentityResultAssert.IsSuccess(await roleManager.CreateAsync(role));
|
||||
}
|
||||
|
||||
for (int i = 0; i < 6; i++)
|
||||
{
|
||||
var user = CreateTestUser();
|
||||
IdentityResultAssert.IsSuccess(await manager.CreateAsync(user));
|
||||
|
||||
if ((i % 2) == 0)
|
||||
{
|
||||
IdentityResultAssert.IsSuccess(await manager.AddToRolesAsync(user, roles.Select(x => x.Name).AsEnumerable()));
|
||||
IdentityResultAssert.VerifyUserManagerSuccessLog(manager.Logger, "AddToRolesAsync", user.Id.ToString());
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var role in roles)
|
||||
{
|
||||
Assert.Equal(3, (await manager.GetUsersInRoleAsync(role.Name)).Count);
|
||||
}
|
||||
|
||||
Assert.Equal(0, (await manager.GetUsersInRoleAsync("123456")).Count);
|
||||
}
|
||||
|
||||
public List<TUser> GenerateUsers(string userNamePrefix, int count)
|
||||
{
|
||||
var users = new List<TUser>(count);
|
||||
|
|
@ -1600,6 +1802,5 @@ namespace Microsoft.AspNet.Identity.Test
|
|||
}
|
||||
return roles;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue