diff --git a/src/Microsoft.AspNet.Identity.EntityFramework/IdentityDbContext.cs b/src/Microsoft.AspNet.Identity.EntityFramework/IdentityDbContext.cs index baf7a99e6e..65f8e2fe2c 100644 --- a/src/Microsoft.AspNet.Identity.EntityFramework/IdentityDbContext.cs +++ b/src/Microsoft.AspNet.Identity.EntityFramework/IdentityDbContext.cs @@ -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(b => { b.Key(r => r.Id); b.ForRelational().Table("AspNetRoles"); + b.Property(r => r.ConcurrencyStamp).ConcurrencyToken(); }); builder.Entity>(b => diff --git a/src/Microsoft.AspNet.Identity.EntityFramework/RoleStore.cs b/src/Microsoft.AspNet.Identity.EntityFramework/RoleStore.cs index b3d7988dc5..884b7a5b30 100644 --- a/src/Microsoft.AspNet.Identity.EntityFramework/RoleStore.cs +++ b/src/Microsoft.AspNet.Identity.EntityFramework/RoleStore.cs @@ -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 : RoleStore where TRole : IdentityRole { - public RoleStore(DbContext context) : base(context) { } + public RoleStore(DbContext context, IdentityErrorDescriber describer = null) : base(context, describer) { } } public class RoleStore : RoleStore 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 : @@ -32,13 +33,14 @@ namespace Microsoft.AspNet.Identity.EntityFramework where TKey : IEquatable 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; } + /// + /// Used to generate public API error messages + /// + public IdentityErrorDescriber ErrorDescriber { get; set; } + /// /// If true will call SaveChanges after CreateAsync/UpdateAsync/DeleteAsync /// @@ -59,7 +66,7 @@ namespace Microsoft.AspNet.Identity.EntityFramework } } - public async virtual Task CreateAsync(TRole role, CancellationToken cancellationToken = default(CancellationToken)) + public async virtual Task 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 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 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 GetRoleIdAsync(TRole role, CancellationToken cancellationToken = default(CancellationToken)) diff --git a/src/Microsoft.AspNet.Identity.EntityFramework/UserStore.cs b/src/Microsoft.AspNet.Identity.EntityFramework/UserStore.cs index 8dfe8ba828..c21198dcbf 100644 --- a/src/Microsoft.AspNet.Identity.EntityFramework/UserStore.cs +++ b/src/Microsoft.AspNet.Identity.EntityFramework/UserStore.cs @@ -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 { - public UserStore(DbContext context) : base(context) { } + public UserStore(DbContext context, IdentityErrorDescriber describer = null) : base(context, describer) { } } public class UserStore : UserStore where TUser : IdentityUser, new() { - public UserStore(DbContext context) : base(context) { } + public UserStore(DbContext context, IdentityErrorDescriber describer = null) : base(context, describer) { } } public class UserStore : UserStore @@ -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 : @@ -49,19 +49,25 @@ namespace Microsoft.AspNet.Identity.EntityFramework where TKey : IEquatable { - 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; } + /// + /// Used to generate public API error messages + /// + public IdentityErrorDescriber ErrorDescriber { get; set; } + /// /// If true will call SaveChanges after CreateAsync/UpdateAsync/DeleteAsync /// @@ -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 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 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 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; } /// diff --git a/src/Microsoft.AspNet.Identity/IRoleStore.cs b/src/Microsoft.AspNet.Identity/IRoleStore.cs index 4c4fc16f46..e4fb97e532 100644 --- a/src/Microsoft.AspNet.Identity/IRoleStore.cs +++ b/src/Microsoft.AspNet.Identity/IRoleStore.cs @@ -19,7 +19,7 @@ namespace Microsoft.AspNet.Identity /// /// /// - Task CreateAsync(TRole role, CancellationToken cancellationToken = default(CancellationToken)); + Task CreateAsync(TRole role, CancellationToken cancellationToken = default(CancellationToken)); /// /// Update a role @@ -27,7 +27,7 @@ namespace Microsoft.AspNet.Identity /// /// /// - Task UpdateAsync(TRole role, CancellationToken cancellationToken = default(CancellationToken)); + Task UpdateAsync(TRole role, CancellationToken cancellationToken = default(CancellationToken)); /// /// DeleteAsync a role @@ -35,7 +35,7 @@ namespace Microsoft.AspNet.Identity /// /// /// - Task DeleteAsync(TRole role, CancellationToken cancellationToken = default(CancellationToken)); + Task DeleteAsync(TRole role, CancellationToken cancellationToken = default(CancellationToken)); /// /// Returns a role's id diff --git a/src/Microsoft.AspNet.Identity/IUserStore.cs b/src/Microsoft.AspNet.Identity/IUserStore.cs index 93a8fcae36..d6cd313733 100644 --- a/src/Microsoft.AspNet.Identity/IUserStore.cs +++ b/src/Microsoft.AspNet.Identity/IUserStore.cs @@ -63,7 +63,7 @@ namespace Microsoft.AspNet.Identity /// /// /// - Task CreateAsync(TUser user, CancellationToken cancellationToken = default(CancellationToken)); + Task CreateAsync(TUser user, CancellationToken cancellationToken = default(CancellationToken)); /// /// UpdateAsync a user @@ -71,7 +71,7 @@ namespace Microsoft.AspNet.Identity /// /// /// - Task UpdateAsync(TUser user, CancellationToken cancellationToken = default(CancellationToken)); + Task UpdateAsync(TUser user, CancellationToken cancellationToken = default(CancellationToken)); /// /// DeleteAsync a user @@ -79,7 +79,7 @@ namespace Microsoft.AspNet.Identity /// /// /// - Task DeleteAsync(TUser user, CancellationToken cancellationToken = default(CancellationToken)); + Task DeleteAsync(TUser user, CancellationToken cancellationToken = default(CancellationToken)); /// /// Finds a user diff --git a/src/Microsoft.AspNet.Identity/IdentityErrorDescriber.cs b/src/Microsoft.AspNet.Identity/IdentityErrorDescriber.cs index 05fcef7fe0..9c998bc6a4 100644 --- a/src/Microsoft.AspNet.Identity/IdentityErrorDescriber.cs +++ b/src/Microsoft.AspNet.Identity/IdentityErrorDescriber.cs @@ -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() { diff --git a/src/Microsoft.AspNet.Identity/IdentityRole.cs b/src/Microsoft.AspNet.Identity/IdentityRole.cs index e9206c92ad..711ff58f32 100644 --- a/src/Microsoft.AspNet.Identity/IdentityRole.cs +++ b/src/Microsoft.AspNet.Identity/IdentityRole.cs @@ -65,5 +65,10 @@ namespace Microsoft.AspNet.Identity /// Role name /// public virtual string Name { get; set; } + + /// + /// A random value that should change whenever a role is persisted to the store + /// + public virtual string ConcurrencyStamp { get; set; } = Guid.NewGuid().ToString(); } } \ No newline at end of file diff --git a/src/Microsoft.AspNet.Identity/IdentityUser.cs b/src/Microsoft.AspNet.Identity/IdentityUser.cs index 210791c26f..ce273deaae 100644 --- a/src/Microsoft.AspNet.Identity/IdentityUser.cs +++ b/src/Microsoft.AspNet.Identity/IdentityUser.cs @@ -52,6 +52,11 @@ namespace Microsoft.AspNet.Identity /// public virtual string SecurityStamp { get; set; } + /// + /// A random value that should change whenever a user is persisted to the store + /// + public virtual string ConcurrencyStamp { get; set; } = Guid.NewGuid().ToString(); + /// /// PhoneNumber for the user /// diff --git a/src/Microsoft.AspNet.Identity/Properties/Resources.Designer.cs b/src/Microsoft.AspNet.Identity/Properties/Resources.Designer.cs index 8caeda20b2..11169b63ea 100644 --- a/src/Microsoft.AspNet.Identity/Properties/Resources.Designer.cs +++ b/src/Microsoft.AspNet.Identity/Properties/Resources.Designer.cs @@ -10,6 +10,22 @@ namespace Microsoft.AspNet.Identity private static readonly ResourceManager _resourceManager = new ResourceManager("Microsoft.AspNet.Identity.Resources", typeof(Resources).GetTypeInfo().Assembly); + /// + /// Optimistic concurrency failure, object has been modified. + /// + internal static string ConcurrencyFailure + { + get { return GetString("ConcurrencyFailure"); } + } + + /// + /// Optimistic concurrency failure, object has been modified. + /// + internal static string FormatConcurrencyFailure() + { + return GetString("ConcurrencyFailure"); + } + /// /// Your security code is: {0} /// @@ -410,22 +426,6 @@ namespace Microsoft.AspNet.Identity return string.Format(CultureInfo.CurrentCulture, GetString("PasswordTooShort"), p0); } - /// - /// {0} cannot be null or empty. - /// - internal static string PropertyTooShort - { - get { return GetString("PropertyTooShort"); } - } - - /// - /// {0} cannot be null or empty. - /// - internal static string FormatPropertyTooShort(object p0) - { - return string.Format(CultureInfo.CurrentCulture, GetString("PropertyTooShort"), p0); - } - /// /// Role {0} does not exist. /// diff --git a/src/Microsoft.AspNet.Identity/Properties/debugSettings.json b/src/Microsoft.AspNet.Identity/Properties/debugSettings.json new file mode 100644 index 0000000000..a44fad34a3 --- /dev/null +++ b/src/Microsoft.AspNet.Identity/Properties/debugSettings.json @@ -0,0 +1,3 @@ +{ + "Profiles": [] +} \ No newline at end of file diff --git a/src/Microsoft.AspNet.Identity/Resources.resx b/src/Microsoft.AspNet.Identity/Resources.resx index 79f668637f..2592527afb 100644 --- a/src/Microsoft.AspNet.Identity/Resources.resx +++ b/src/Microsoft.AspNet.Identity/Resources.resx @@ -117,6 +117,10 @@ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + Optimistic concurrency failure, object has been modified. + Error when optimistic concurrency fails + Your security code is: {0} Default body format for the email diff --git a/src/Microsoft.AspNet.Identity/RoleManager.cs b/src/Microsoft.AspNet.Identity/RoleManager.cs index 3189f253a4..cf13cee60a 100644 --- a/src/Microsoft.AspNet.Identity/RoleManager.cs +++ b/src/Microsoft.AspNet.Identity/RoleManager.cs @@ -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); } /// @@ -166,8 +164,7 @@ namespace Microsoft.AspNet.Identity { return result; } - await Store.UpdateAsync(role, cancellationToken); - return IdentityResult.Success; + return await Store.UpdateAsync(role, cancellationToken); } /// @@ -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); } /// diff --git a/src/Microsoft.AspNet.Identity/UserManager.cs b/src/Microsoft.AspNet.Identity/UserManager.cs index 6caed539c2..d57b654505 100644 --- a/src/Microsoft.AspNet.Identity/UserManager.cs +++ b/src/Microsoft.AspNet.Identity/UserManager.cs @@ -326,6 +326,12 @@ namespace Microsoft.AspNet.Identity return errors.Count > 0 ? IdentityResult.Failed(errors.ToArray()) : IdentityResult.Success; } + public virtual Task GenerateConcurrencyStampAsync(TUser user, + CancellationToken token = default(CancellationToken)) + { + return Task.FromResult(Guid.NewGuid().ToString()); + } + /// /// Create a user with no password /// @@ -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); } /// @@ -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); } /// @@ -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); } /// diff --git a/test/Microsoft.AspNet.Identity.EntityFramework.Test/UserStoreTest.cs b/test/Microsoft.AspNet.Identity.EntityFramework.Test/UserStoreTest.cs index 6e9c937274..950189dfb5 100644 --- a/test/Microsoft.AspNet.Identity.EntityFramework.Test/UserStoreTest.cs +++ b/test/Microsoft.AspNet.Identity.EntityFramework.Test/UserStoreTest.cs @@ -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() diff --git a/test/Microsoft.AspNet.Identity.InMemory.Test/InMemoryRoleStore.cs b/test/Microsoft.AspNet.Identity.InMemory.Test/InMemoryRoleStore.cs index 0404ef3939..352311b56c 100644 --- a/test/Microsoft.AspNet.Identity.InMemory.Test/InMemoryRoleStore.cs +++ b/test/Microsoft.AspNet.Identity.InMemory.Test/InMemoryRoleStore.cs @@ -15,20 +15,20 @@ namespace Microsoft.AspNet.Identity.InMemory { private readonly Dictionary _roles = new Dictionary(); - public Task CreateAsync(TRole role, CancellationToken cancellationToken = default(CancellationToken)) + public Task 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 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 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 UpdateAsync(TRole role, CancellationToken cancellationToken = default(CancellationToken)) { _roles[role.Id] = role; - return Task.FromResult(0); + return Task.FromResult(IdentityResult.Success); } public Task FindByIdAsync(string roleId, CancellationToken cancellationToken = default(CancellationToken)) diff --git a/test/Microsoft.AspNet.Identity.InMemory.Test/InMemoryUserStore.cs b/test/Microsoft.AspNet.Identity.InMemory.Test/InMemoryUserStore.cs index 2590eccba7..3f6ef090d5 100644 --- a/test/Microsoft.AspNet.Identity.InMemory.Test/InMemoryUserStore.cs +++ b/test/Microsoft.AspNet.Identity.InMemory.Test/InMemoryUserStore.cs @@ -209,16 +209,16 @@ namespace Microsoft.AspNet.Identity.InMemory return Task.FromResult(0); } - public Task CreateAsync(TUser user, CancellationToken cancellationToken = default(CancellationToken)) + public Task 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 UpdateAsync(TUser user, CancellationToken cancellationToken = default(CancellationToken)) { _users[user.Id] = user; - return Task.FromResult(0); + return Task.FromResult(IdentityResult.Success); } public Task 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 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)) diff --git a/test/Microsoft.AspNet.Identity.Test/IdentityBuilderTest.cs b/test/Microsoft.AspNet.Identity.Test/IdentityBuilderTest.cs index 1d0b2fcc90..01c7f8281e 100644 --- a/test/Microsoft.AspNet.Identity.Test/IdentityBuilderTest.cs +++ b/test/Microsoft.AspNet.Identity.Test/IdentityBuilderTest.cs @@ -113,22 +113,22 @@ namespace Microsoft.AspNet.Identity.Test private class MyUberThingy : IUserValidator, IPasswordValidator, IRoleValidator, IUserStore, IRoleStore { - public Task CreateAsync(IdentityRole role, CancellationToken cancellationToken = default(CancellationToken)) + public Task CreateAsync(IdentityRole role, CancellationToken cancellationToken = default(CancellationToken)) { throw new NotImplementedException(); } - public Task CreateAsync(IdentityUser user, CancellationToken cancellationToken = default(CancellationToken)) + public Task CreateAsync(IdentityUser user, CancellationToken cancellationToken = default(CancellationToken)) { throw new NotImplementedException(); } - public Task DeleteAsync(IdentityRole role, CancellationToken cancellationToken = default(CancellationToken)) + public Task DeleteAsync(IdentityRole role, CancellationToken cancellationToken = default(CancellationToken)) { throw new NotImplementedException(); } - public Task DeleteAsync(IdentityUser user, CancellationToken cancellationToken = default(CancellationToken)) + public Task 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 UpdateAsync(IdentityRole role, CancellationToken cancellationToken = default(CancellationToken)) { throw new NotImplementedException(); } - public Task UpdateAsync(IdentityUser user, CancellationToken cancellationToken = default(CancellationToken)) + public Task UpdateAsync(IdentityUser user, CancellationToken cancellationToken = default(CancellationToken)) { throw new NotImplementedException(); } diff --git a/test/Microsoft.AspNet.Identity.Test/NoopRoleStore.cs b/test/Microsoft.AspNet.Identity.Test/NoopRoleStore.cs index 004d960841..a3c576ca51 100644 --- a/test/Microsoft.AspNet.Identity.Test/NoopRoleStore.cs +++ b/test/Microsoft.AspNet.Identity.Test/NoopRoleStore.cs @@ -8,14 +8,14 @@ namespace Microsoft.AspNet.Identity.Test { public class NoopRoleStore : IRoleStore { - public Task CreateAsync(TestRole user, CancellationToken cancellationToken = default(CancellationToken)) + public Task 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 UpdateAsync(TestRole user, CancellationToken cancellationToken = default(CancellationToken)) { - return Task.FromResult(0); + return Task.FromResult(IdentityResult.Success); } public Task 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 DeleteAsync(TestRole user, CancellationToken cancellationToken = default(CancellationToken)) { - return Task.FromResult(0); + return Task.FromResult(IdentityResult.Success); } public Task GetRoleIdAsync(TestRole role, CancellationToken cancellationToken = default(CancellationToken)) diff --git a/test/Microsoft.AspNet.Identity.Test/NoopUserStore.cs b/test/Microsoft.AspNet.Identity.Test/NoopUserStore.cs index 026784e489..86078e2c0e 100644 --- a/test/Microsoft.AspNet.Identity.Test/NoopUserStore.cs +++ b/test/Microsoft.AspNet.Identity.Test/NoopUserStore.cs @@ -24,14 +24,14 @@ namespace Microsoft.AspNet.Identity.Test return Task.FromResult(0); } - public Task CreateAsync(TestUser user, CancellationToken cancellationToken = default(CancellationToken)) + public Task 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 UpdateAsync(TestUser user, CancellationToken cancellationToken = default(CancellationToken)) { - return Task.FromResult(0); + return Task.FromResult(IdentityResult.Success); } public Task 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 DeleteAsync(TestUser user, CancellationToken cancellationToken = default(CancellationToken)) { - return Task.FromResult(0); + return Task.FromResult(IdentityResult.Success); } public Task GetNormalizedUserNameAsync(TestUser user, CancellationToken cancellationToken = default(CancellationToken)) diff --git a/test/Microsoft.AspNet.Identity.Test/RoleManagerTest.cs b/test/Microsoft.AspNet.Identity.Test/RoleManagerTest.cs index 31fa379c79..d57c4f2c25 100644 --- a/test/Microsoft.AspNet.Identity.Test/RoleManagerTest.cs +++ b/test/Microsoft.AspNet.Identity.Test/RoleManagerTest.cs @@ -63,17 +63,17 @@ namespace Microsoft.AspNet.Identity.Test private class NotImplementedStore : IRoleStore { - public Task CreateAsync(TestRole role, CancellationToken cancellationToken = default(CancellationToken)) + public Task CreateAsync(TestRole role, CancellationToken cancellationToken = default(CancellationToken)) { throw new NotImplementedException(); } - public Task UpdateAsync(TestRole role, CancellationToken cancellationToken = default(CancellationToken)) + public Task UpdateAsync(TestRole role, CancellationToken cancellationToken = default(CancellationToken)) { throw new NotImplementedException(); } - public Task DeleteAsync(TestRole role, CancellationToken cancellationToken = default(CancellationToken)) + public Task DeleteAsync(TestRole role, CancellationToken cancellationToken = default(CancellationToken)) { throw new NotImplementedException(); } diff --git a/test/Microsoft.AspNet.Identity.Test/UserManagerTest.cs b/test/Microsoft.AspNet.Identity.Test/UserManagerTest.cs index 21cdf3d03d..cb3530fb25 100644 --- a/test/Microsoft.AspNet.Identity.Test/UserManagerTest.cs +++ b/test/Microsoft.AspNet.Identity.Test/UserManagerTest.cs @@ -42,7 +42,7 @@ namespace Microsoft.AspNet.Identity.Test // Setup var store = new Mock>(); 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(store.Object); // Act @@ -59,7 +59,7 @@ namespace Microsoft.AspNet.Identity.Test // Setup var store = new Mock>(); 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>(); var user = new TestUser { UserName = "Foo" }; - store.Setup(s => s.UpdateAsync(user, CancellationToken.None)).Returns(Task.FromResult(0)).Verifiable(); - var userManager = MockHelpers.TestUserManager(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>(); var user = new TestUser(); store.Setup(s => s.SetUserNameAsync(user, It.IsAny(), 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()).Verifiable(); var userManager = MockHelpers.TestUserManager(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>(), 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(), It.IsAny(), 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(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>(), 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 @@ -830,19 +832,19 @@ namespace Microsoft.AspNet.Identity.Test return Task.FromResult(0); } - public Task CreateAsync(TestUser user, CancellationToken cancellationToken = default(CancellationToken)) + public Task 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 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 DeleteAsync(TestUser user, CancellationToken cancellationToken = default(CancellationToken)) { - return Task.FromResult(0); + return Task.FromResult(IdentityResult.Success); } public Task 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 FindByIdAsync(string userId, CancellationToken cancellationToken = default(CancellationToken)) { throw new NotImplementedException(); @@ -1226,6 +1213,21 @@ namespace Microsoft.AspNet.Identity.Test { throw new NotImplementedException(); } + + Task IUserStore.CreateAsync(TestUser user, CancellationToken cancellationToken) + { + throw new NotImplementedException(); + } + + Task IUserStore.UpdateAsync(TestUser user, CancellationToken cancellationToken) + { + throw new NotImplementedException(); + } + + Task IUserStore.DeleteAsync(TestUser user, CancellationToken cancellationToken) + { + throw new NotImplementedException(); + } } [Fact]