added replace claim functionality. fixes #232
- added ReplaceClaimAsync method to IUserClaimStore interface - implemented ReplaceClaimAsync method from IUserClaimStore inside the Microsoft.AspNet.Identity.EntityFramework.UserStore<TUser, TRole, TContext, TKey> - added ReplaceClaimAsync method to UserManager - added UserManager tests for ReplaceClaimAsync method. - added some UserStore tests for ReplaceClaimAsync implementation of IUserClaimStore
This commit is contained in:
parent
0bbd7c8b48
commit
d7f711bca1
|
|
@ -441,6 +441,32 @@ namespace Microsoft.AspNet.Identity.EntityFramework
|
|||
return Task.FromResult(0);
|
||||
}
|
||||
|
||||
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 matchedClaims = UserClaims.Where(uc => uc.ClaimValue == claim.Value && uc.ClaimType == claim.Type).ToList();
|
||||
foreach(var matchedClaim in matchedClaims)
|
||||
{
|
||||
matchedClaim.ClaimValue = newClaim.Value;
|
||||
matchedClaim.ClaimType = newClaim.Type;
|
||||
}
|
||||
|
||||
return Task.FromResult(0);
|
||||
}
|
||||
|
||||
public Task RemoveClaimsAsync(TUser user, IEnumerable<Claim> claims, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
ThrowIfDisposed();
|
||||
|
|
@ -530,7 +556,7 @@ namespace Microsoft.AspNet.Identity.EntityFramework
|
|||
cancellationToken.ThrowIfCancellationRequested();
|
||||
ThrowIfDisposed();
|
||||
// todo: ensure logins loaded
|
||||
var userLogin =
|
||||
var userLogin =
|
||||
UserLogins.FirstOrDefault(l => l.LoginProvider == loginProvider && l.ProviderKey == providerKey);
|
||||
if (userLogin != null)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ namespace Microsoft.AspNet.Identity
|
|||
/// <param name="user"></param>
|
||||
/// <param name="cancellationToken"></param>
|
||||
/// <returns></returns>
|
||||
Task<IList<Claim>> GetClaimsAsync(TUser user,
|
||||
Task<IList<Claim>> GetClaimsAsync(TUser user,
|
||||
CancellationToken cancellationToken = default(CancellationToken));
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -32,6 +32,16 @@ namespace Microsoft.AspNet.Identity
|
|||
/// <returns></returns>
|
||||
Task AddClaimsAsync(TUser user, IEnumerable<Claim> claims, CancellationToken cancellationToken = default(CancellationToken));
|
||||
|
||||
/// <summary>
|
||||
/// Updates the give claim information with the given new claim information
|
||||
/// </summary>
|
||||
/// <param name="user"></param>
|
||||
/// <param name="claim"></param>
|
||||
/// <param name="newClaim"></param>
|
||||
/// <param name="cancellationToken"></param>
|
||||
/// <returns></returns>
|
||||
Task ReplaceClaimAsync(TUser user, Claim claim, Claim newClaim, CancellationToken cancellationToken = default(CancellationToken));
|
||||
|
||||
/// <summary>
|
||||
/// Remove a user claim
|
||||
/// </summary>
|
||||
|
|
@ -39,7 +49,7 @@ namespace Microsoft.AspNet.Identity
|
|||
/// <param name="claims"></param>
|
||||
/// <param name="cancellationToken"></param>
|
||||
/// <returns></returns>
|
||||
Task RemoveClaimsAsync(TUser user, IEnumerable<Claim> claims,
|
||||
Task RemoveClaimsAsync(TUser user, IEnumerable<Claim> claims,
|
||||
CancellationToken cancellationToken = default(CancellationToken));
|
||||
}
|
||||
}
|
||||
|
|
@ -708,7 +708,7 @@ namespace Microsoft.AspNet.Identity
|
|||
/// <param name="user"></param>
|
||||
/// <param name="cancellationToken"></param>
|
||||
/// <returns></returns>
|
||||
public virtual async Task<IdentityResult> UpdateSecurityStampAsync(TUser user,
|
||||
public virtual async Task<IdentityResult> UpdateSecurityStampAsync(TUser user,
|
||||
CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
ThrowIfDisposed();
|
||||
|
|
@ -727,7 +727,7 @@ namespace Microsoft.AspNet.Identity
|
|||
/// <param name="user"></param>
|
||||
/// <param name="cancellationToken"></param>
|
||||
/// <returns></returns>
|
||||
public virtual async Task<string> GeneratePasswordResetTokenAsync(TUser user,
|
||||
public virtual async Task<string> GeneratePasswordResetTokenAsync(TUser user,
|
||||
CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
ThrowIfDisposed();
|
||||
|
|
@ -946,6 +946,35 @@ namespace Microsoft.AspNet.Identity
|
|||
return await UpdateAsync(user, cancellationToken);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Updates the give claim information with the given new claim information
|
||||
/// </summary>
|
||||
/// <param name="user"></param>
|
||||
/// <param name="claim"></param>
|
||||
/// <param name="newClaim"></param>
|
||||
/// <param name="cancellationToken"></param>
|
||||
/// <returns></returns>
|
||||
public virtual async Task<IdentityResult> ReplaceClaimAsync(TUser user, Claim claim, Claim newClaim,
|
||||
CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
ThrowIfDisposed();
|
||||
var claimStore = GetClaimStore();
|
||||
if (claim == null)
|
||||
{
|
||||
throw new ArgumentNullException("claim");
|
||||
}
|
||||
if (newClaim == null)
|
||||
{
|
||||
throw new ArgumentNullException("newClaim");
|
||||
}
|
||||
if (user == null)
|
||||
{
|
||||
throw new ArgumentNullException("user");
|
||||
}
|
||||
await claimStore.ReplaceClaimAsync(user, claim, newClaim, cancellationToken);
|
||||
return await UpdateAsync(user, cancellationToken);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Remove a user claim
|
||||
/// </summary>
|
||||
|
|
@ -1598,7 +1627,7 @@ namespace Microsoft.AspNet.Identity
|
|||
}
|
||||
if (!_tokenProviders.ContainsKey(tokenProvider))
|
||||
{
|
||||
throw new NotSupportedException(String.Format(CultureInfo.CurrentCulture,
|
||||
throw new NotSupportedException(String.Format(CultureInfo.CurrentCulture,
|
||||
Resources.NoTokenProvider, tokenProvider));
|
||||
}
|
||||
await _tokenProviders[tokenProvider].NotifyAsync(token, this, user, cancellationToken);
|
||||
|
|
@ -1827,7 +1856,7 @@ namespace Microsoft.AspNet.Identity
|
|||
|
||||
/// <summary>
|
||||
/// Increments the access failed count for the user and if the failed access account is greater than or equal
|
||||
/// to the MaxFailedAccessAttempsBeforeLockout, the user will be locked out for the next
|
||||
/// to the MaxFailedAccessAttempsBeforeLockout, the user will be locked out for the next
|
||||
/// DefaultAccountLockoutTimeSpan and the AccessFailedCount will be reset to 0.
|
||||
/// </summary>
|
||||
/// <param name="user"></param>
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ namespace Microsoft.AspNet.Identity.EntityFramework.InMemory.Test
|
|||
public InMemoryUserStore(InMemoryContext context) : base(context) { }
|
||||
}
|
||||
|
||||
public class InMemoryUserStore<TUser, TContext> : InMemoryUserStore<TUser, IdentityRole, string, IdentityUserLogin, IdentityUserRole, IdentityUserClaim, TContext>
|
||||
public class InMemoryUserStore<TUser, TContext> : InMemoryUserStore<TUser, IdentityRole, string, IdentityUserLogin, IdentityUserRole, IdentityUserClaim, TContext>
|
||||
where TUser:IdentityUser
|
||||
where TContext : DbContext
|
||||
{
|
||||
|
|
@ -370,6 +370,39 @@ namespace Microsoft.AspNet.Identity.EntityFramework.InMemory.Test
|
|||
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>
|
||||
|
|
|
|||
|
|
@ -172,6 +172,7 @@ namespace Microsoft.AspNet.Identity.EntityFramework.Test
|
|||
await Assert.ThrowsAsync<ObjectDisposedException>(
|
||||
async () => await store.RemoveFromRoleAsync(null, null));
|
||||
await Assert.ThrowsAsync<ObjectDisposedException>(async () => await store.RemoveClaimsAsync(null, null));
|
||||
await Assert.ThrowsAsync<ObjectDisposedException>(async () => await store.ReplaceClaimAsync(null, null, null));
|
||||
await Assert.ThrowsAsync<ObjectDisposedException>(async () => await store.FindByLoginAsync(null, null));
|
||||
await Assert.ThrowsAsync<ObjectDisposedException>(async () => await store.FindByIdAsync(null));
|
||||
await Assert.ThrowsAsync<ObjectDisposedException>(async () => await store.FindByNameAsync(null));
|
||||
|
|
@ -199,6 +200,7 @@ namespace Microsoft.AspNet.Identity.EntityFramework.Test
|
|||
await Assert.ThrowsAsync<ArgumentNullException>("user", async () => await store.UpdateAsync(null));
|
||||
await Assert.ThrowsAsync<ArgumentNullException>("user", async () => await store.DeleteAsync(null));
|
||||
await Assert.ThrowsAsync<ArgumentNullException>("user", async () => await store.AddClaimsAsync(null, null));
|
||||
await Assert.ThrowsAsync<ArgumentNullException>("user", async () => await store.ReplaceClaimAsync(null, null, null));
|
||||
await Assert.ThrowsAsync<ArgumentNullException>("user", async () => await store.RemoveClaimsAsync(null, null));
|
||||
await Assert.ThrowsAsync<ArgumentNullException>("user", async () => await store.GetClaimsAsync(null));
|
||||
await Assert.ThrowsAsync<ArgumentNullException>("user", async () => await store.GetLoginsAsync(null));
|
||||
|
|
|
|||
|
|
@ -47,6 +47,17 @@ namespace Microsoft.AspNet.Identity.InMemory
|
|||
return Task.FromResult(0);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
matchedClaim.ClaimValue = newClaim.Value;
|
||||
matchedClaim.ClaimType = newClaim.Type;
|
||||
}
|
||||
return Task.FromResult(0);
|
||||
}
|
||||
|
||||
public Task RemoveClaimsAsync(TUser user, IEnumerable<Claim> claims, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
foreach (var claim in claims)
|
||||
|
|
|
|||
|
|
@ -315,6 +315,27 @@ namespace Microsoft.AspNet.Identity.Test
|
|||
store.VerifyAll();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task UpdateClaimCallsStore()
|
||||
{
|
||||
// Setup
|
||||
var store = new Mock<IUserClaimStore<TestUser>>();
|
||||
var user = new TestUser { UserName = "Foo" };
|
||||
var claim = new Claim("1", "1");
|
||||
var newClaim = new Claim("1", "2");
|
||||
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);
|
||||
|
||||
// Act
|
||||
var result = await userManager.ReplaceClaimAsync(user, claim, newClaim);
|
||||
|
||||
// Assert
|
||||
Assert.True(result.Succeeded);
|
||||
store.VerifyAll();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task RemoveClaimsCallsStore()
|
||||
{
|
||||
|
|
@ -455,6 +476,7 @@ namespace Microsoft.AspNet.Identity.Test
|
|||
var manager = MockHelpers.TestUserManager(new NoopUserStore());
|
||||
Assert.False(manager.SupportsUserClaim);
|
||||
await Assert.ThrowsAsync<NotSupportedException>(async () => await manager.AddClaimAsync(null, null));
|
||||
await Assert.ThrowsAsync<NotSupportedException>(async () => await manager.ReplaceClaimAsync(null, null, null));
|
||||
await Assert.ThrowsAsync<NotSupportedException>(async () => await manager.RemoveClaimAsync(null, null));
|
||||
await Assert.ThrowsAsync<NotSupportedException>(async () => await manager.GetClaimsAsync(null));
|
||||
}
|
||||
|
|
@ -541,11 +563,12 @@ namespace Microsoft.AspNet.Identity.Test
|
|||
await Assert.ThrowsAsync<ArgumentNullException>("user", async () => await manager.UpdateAsync(null));
|
||||
await Assert.ThrowsAsync<ArgumentNullException>("user", async () => await manager.DeleteAsync(null));
|
||||
await Assert.ThrowsAsync<ArgumentNullException>("claim", async () => await manager.AddClaimAsync(null, null));
|
||||
await Assert.ThrowsAsync<ArgumentNullException>("claim", async () => await manager.ReplaceClaimAsync(null, null, null));
|
||||
await Assert.ThrowsAsync<ArgumentNullException>("claims", async () => await manager.AddClaimsAsync(null, null));
|
||||
await Assert.ThrowsAsync<ArgumentNullException>("userName", async () => await manager.FindByNameAsync(null));
|
||||
await Assert.ThrowsAsync<ArgumentNullException>("userName", async () => await manager.FindByUserNamePasswordAsync(null, null));
|
||||
await Assert.ThrowsAsync<ArgumentNullException>("login", async () => await manager.AddLoginAsync(null, null));
|
||||
await Assert.ThrowsAsync<ArgumentNullException>("loginProvider",
|
||||
await Assert.ThrowsAsync<ArgumentNullException>("loginProvider",
|
||||
async () => await manager.RemoveLoginAsync(null, null, null));
|
||||
await Assert.ThrowsAsync<ArgumentNullException>("providerKey",
|
||||
async () => await manager.RemoveLoginAsync(null, "", null));
|
||||
|
|
@ -594,6 +617,8 @@ namespace Microsoft.AspNet.Identity.Test
|
|||
async () => await manager.RemoveFromRoleAsync(null, null));
|
||||
await Assert.ThrowsAsync<ArgumentNullException>("user",
|
||||
async () => await manager.RemoveFromRolesAsync(null, null));
|
||||
await Assert.ThrowsAsync<ArgumentNullException>("user",
|
||||
async () => await manager.ReplaceClaimAsync(null, new Claim("a", "b"), new Claim("a", "c")));
|
||||
await Assert.ThrowsAsync<ArgumentNullException>("user",
|
||||
async () => await manager.UpdateSecurityStampAsync(null));
|
||||
await Assert.ThrowsAsync<ArgumentNullException>("user",
|
||||
|
|
@ -690,6 +715,7 @@ namespace Microsoft.AspNet.Identity.Test
|
|||
await Assert.ThrowsAsync<ObjectDisposedException>(() => manager.CreateAsync(null, null));
|
||||
await Assert.ThrowsAsync<ObjectDisposedException>(() => manager.UpdateAsync(null));
|
||||
await Assert.ThrowsAsync<ObjectDisposedException>(() => manager.DeleteAsync(null));
|
||||
await Assert.ThrowsAsync<ObjectDisposedException>(() => manager.ReplaceClaimAsync(null, null, null));
|
||||
await Assert.ThrowsAsync<ObjectDisposedException>(() => manager.UpdateSecurityStampAsync(null));
|
||||
await Assert.ThrowsAsync<ObjectDisposedException>(() => manager.GetSecurityStampAsync(null));
|
||||
await Assert.ThrowsAsync<ObjectDisposedException>(() => manager.GeneratePasswordResetTokenAsync(null));
|
||||
|
|
@ -730,6 +756,11 @@ namespace Microsoft.AspNet.Identity.Test
|
|||
return Task.FromResult(0);
|
||||
}
|
||||
|
||||
public Task ReplaceClaimAsync(TestUser user, Claim claim, Claim newClaim, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
return Task.FromResult(0);
|
||||
}
|
||||
|
||||
public Task RemoveClaimsAsync(TestUser user, IEnumerable<Claim> claim, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
return Task.FromResult(0);
|
||||
|
|
@ -991,6 +1022,11 @@ namespace Microsoft.AspNet.Identity.Test
|
|||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task ReplaceClaimAsync(TestUser user, Claim claim, Claim newClaim, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task RemoveClaimsAsync(TestUser user, IEnumerable<Claim> claims, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
|
|
|
|||
|
|
@ -353,6 +353,25 @@ namespace Microsoft.AspNet.Identity.Test
|
|||
Assert.Equal(0, userClaims.Count);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task CanReplaceUserClaim()
|
||||
{
|
||||
var manager = CreateManager();
|
||||
var user = CreateTestUser();
|
||||
IdentityResultAssert.IsSuccess(await manager.CreateAsync(user));
|
||||
IdentityResultAssert.IsSuccess(await manager.AddClaimAsync(user, new Claim("c", "a")));
|
||||
var userClaims = await manager.GetClaimsAsync(user);
|
||||
Assert.Equal(1, userClaims.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);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ChangePasswordFallsIfPasswordWrong()
|
||||
{
|
||||
|
|
|
|||
Loading…
Reference in New Issue