Concurrency support for EF Store

- CRUD operations on IUserStore now return IdentityResult
- Fixes: https://github.com/aspnet/Identity/issues/296,
https://github.com/aspnet/Identity/issues/245
This commit is contained in:
Hao Kung 2015-01-07 13:17:36 -08:00
parent e76d1c2809
commit a8c872aba9
21 changed files with 302 additions and 119 deletions

View File

@ -30,12 +30,14 @@ 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 =>

View File

@ -9,20 +9,21 @@ 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> :
@ -32,13 +33,14 @@ namespace Microsoft.AspNet.Identity.EntityFramework
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 +48,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,7 +66,7 @@ namespace Microsoft.AspNet.Identity.EntityFramework
}
}
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();
@ -69,9 +76,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();
@ -79,11 +87,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();
@ -92,7 +110,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))

View File

@ -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>
@ -129,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();
@ -139,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();
@ -149,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();
@ -161,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>

View File

@ -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

View File

@ -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

View File

@ -15,6 +15,15 @@ namespace Microsoft.AspNet.Identity
Description = Resources.DefaultError
};
}
public virtual IdentityError ConcurrencyFailure()
{
return new IdentityError
{
Code = nameof(ConcurrencyFailure),
Description = Resources.ConcurrencyFailure
};
}
public virtual IdentityError PasswordMismatch()
{

View File

@ -65,5 +65,10 @@ namespace Microsoft.AspNet.Identity
/// Role name
/// </summary>
public virtual string Name { 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();
}
}

View File

@ -52,6 +52,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>

View File

@ -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>
@ -410,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>

View File

@ -0,0 +1,3 @@
{
"Profiles": []
}

View File

@ -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>

View File

@ -7,7 +7,6 @@ using System.Linq;
using System.Security.Claims;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Framework.DependencyInjection;
namespace Microsoft.AspNet.Identity
{
@ -142,8 +141,7 @@ namespace Microsoft.AspNet.Identity
{
return result;
}
await Store.CreateAsync(role, cancellationToken);
return IdentityResult.Success;
return await Store.CreateAsync(role, cancellationToken);
}
/// <summary>
@ -166,8 +164,7 @@ namespace Microsoft.AspNet.Identity
{
return result;
}
await Store.UpdateAsync(role, cancellationToken);
return IdentityResult.Success;
return await Store.UpdateAsync(role, cancellationToken);
}
/// <summary>
@ -184,9 +181,7 @@ namespace Microsoft.AspNet.Identity
{
throw new ArgumentNullException("role");
}
await Store.DeleteAsync(role, cancellationToken);
return IdentityResult.Success;
return await Store.DeleteAsync(role, cancellationToken);
}
/// <summary>

View File

@ -326,6 +326,12 @@ 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>
/// Create a user with no password
/// </summary>
@ -347,8 +353,7 @@ namespace Microsoft.AspNet.Identity
await GetUserLockoutStore().SetLockoutEnabledAsync(user, true, cancellationToken);
}
await UpdateNormalizedUserNameAsync(user, cancellationToken);
await Store.CreateAsync(user, cancellationToken);
return IdentityResult.Success;
return await Store.CreateAsync(user, cancellationToken);
}
/// <summary>
@ -371,8 +376,7 @@ namespace Microsoft.AspNet.Identity
return result;
}
await UpdateNormalizedUserNameAsync(user, cancellationToken);
await Store.UpdateAsync(user, cancellationToken);
return IdentityResult.Success;
return await Store.UpdateAsync(user, cancellationToken);
}
/// <summary>
@ -389,8 +393,7 @@ namespace Microsoft.AspNet.Identity
{
throw new ArgumentNullException("user");
}
await Store.DeleteAsync(user, cancellationToken);
return IdentityResult.Success;
return await Store.DeleteAsync(user, cancellationToken);
}
/// <summary>

View File

@ -275,6 +275,108 @@ 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 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 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()

View File

@ -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))

View File

@ -209,16 +209,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))
@ -241,14 +241,14 @@ namespace Microsoft.AspNet.Identity.InMemory
Users.FirstOrDefault(u => String.Equals(u.UserName, userName, StringComparison.OrdinalIgnoreCase)));
}
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))

View File

@ -113,22 +113,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();
}
@ -188,12 +188,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();
}

View File

@ -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,9 +42,9 @@ 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))

View File

@ -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))

View File

@ -63,17 +63,17 @@ namespace Microsoft.AspNet.Identity.Test
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();
}

View File

@ -42,7 +42,7 @@ 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();
var userManager = MockHelpers.TestUserManager<TestUser>(store.Object);
// Act
@ -59,7 +59,7 @@ 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();
store.Setup(s => s.DeleteAsync(user, CancellationToken.None)).ReturnsAsync(IdentityResult.Success).Verifiable();
var userManager = MockHelpers.TestUserManager(store.Object);
// Act
@ -76,8 +76,8 @@ 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.UpdateAsync(user, CancellationToken.None)).ReturnsAsync(IdentityResult.Success).Verifiable();
var userManager = MockHelpers.TestUserManager(store.Object);
// Act
var result = await userManager.UpdateAsync(user);
@ -94,6 +94,7 @@ namespace Microsoft.AspNet.Identity.Test
var store = new Mock<IUserStore<TestUser>>();
var user = new TestUser();
store.Setup(s => s.SetUserNameAsync(user, It.IsAny<string>(), CancellationToken.None)).Returns(Task.FromResult(0)).Verifiable();
store.Setup(s => s.UpdateAsync(user, CancellationToken.None)).Returns(Task.FromResult(IdentityResult.Success)).Verifiable();
var userManager = MockHelpers.TestUserManager(store.Object);
// Act
@ -172,7 +173,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);
@ -221,7 +222,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();
@ -277,7 +278,7 @@ 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();
store.Setup(s => s.UpdateAsync(user, CancellationToken.None)).ReturnsAsync(IdentityResult.Success).Verifiable();
var userManager = MockHelpers.TestUserManager(store.Object);
// Act
@ -298,7 +299,7 @@ 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();
store.Setup(s => s.UpdateAsync(user, CancellationToken.None)).ReturnsAsync(IdentityResult.Success).Verifiable();
var userManager = MockHelpers.TestUserManager(store.Object);
// Act
@ -320,6 +321,7 @@ namespace Microsoft.AspNet.Identity.Test
store.Setup(s => s.ReplaceClaimAsync(user, It.IsAny<Claim>(), It.IsAny<Claim>(), 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
@ -340,8 +342,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);
@ -361,7 +363,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
@ -830,19 +832,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))
@ -1117,21 +1119,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();
@ -1226,6 +1213,21 @@ namespace Microsoft.AspNet.Identity.Test
{
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();
}
}
[Fact]