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:
tugberkugurlu 2014-10-23 15:02:24 +03:00 committed by Hao Kung
parent 0bbd7c8b48
commit d7f711bca1
8 changed files with 175 additions and 9 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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,6 +563,7 @@ 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));
@ -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();

View File

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