diff --git a/src/Microsoft.AspNet.Identity/UserManager.cs b/src/Microsoft.AspNet.Identity/UserManager.cs
index c5cf9da653..4e1e7f3af5 100644
--- a/src/Microsoft.AspNet.Identity/UserManager.cs
+++ b/src/Microsoft.AspNet.Identity/UserManager.cs
@@ -958,6 +958,37 @@ namespace Microsoft.AspNet.Identity
return await UpdateAsync(user, cancellationToken);
}
+ ///
+ /// Add a user to roles
+ ///
+ ///
+ ///
+ ///
+ ///
+ public virtual async Task AddToRolesAsync(TUser user, IEnumerable roles, CancellationToken cancellationToken = default(CancellationToken))
+ {
+ ThrowIfDisposed();
+ var userRoleStore = GetUserRoleStore();
+ if (user == null)
+ {
+ throw new ArgumentNullException("user");
+ }
+ if (roles == null)
+ {
+ throw new ArgumentNullException("roles");
+ }
+ var userRoles = await userRoleStore.GetRolesAsync(user, cancellationToken);
+ foreach (var role in roles)
+ {
+ if (userRoles.Contains(role))
+ {
+ return new IdentityResult(Resources.UserAlreadyInRole);
+ }
+ await userRoleStore.AddToRoleAsync(user, role, cancellationToken);
+ }
+ return await UpdateAsync(user, cancellationToken);
+ }
+
///
/// Remove a user from a role.
///
@@ -981,6 +1012,36 @@ namespace Microsoft.AspNet.Identity
return await UpdateAsync(user, cancellationToken);
}
+ ///
+ /// Remove a user from a specified roles.
+ ///
+ ///
+ ///
+ ///
+ ///
+ public virtual async Task RemoveFromRolesAsync(TUser user, IEnumerable roles, CancellationToken cancellationToken = default(CancellationToken))
+ {
+ ThrowIfDisposed();
+ var userRoleStore = GetUserRoleStore();
+ if (user == null)
+ {
+ throw new ArgumentNullException("user");
+ }
+ if (roles == null)
+ {
+ throw new ArgumentNullException("roles");
+ }
+ foreach (var role in roles)
+ {
+ if (!await userRoleStore.IsInRoleAsync(user, role, cancellationToken))
+ {
+ return new IdentityResult(Resources.UserNotInRole);
+ }
+ await userRoleStore.RemoveFromRoleAsync(user, role, cancellationToken);
+ }
+ return await UpdateAsync(user, cancellationToken);
+ }
+
///
/// Returns the roles for the user
///
diff --git a/test/Microsoft.AspNet.Identity.Test/UserManagerTest.cs b/test/Microsoft.AspNet.Identity.Test/UserManagerTest.cs
index 383b19883e..1690ee5b1f 100644
--- a/test/Microsoft.AspNet.Identity.Test/UserManagerTest.cs
+++ b/test/Microsoft.AspNet.Identity.Test/UserManagerTest.cs
@@ -142,6 +142,117 @@ namespace Microsoft.AspNet.Identity.Test
store.VerifyAll();
}
+ [Fact]
+ public async Task AddToRolesCallsStore()
+ {
+ // Setup
+ var store = new Mock>();
+ var user = new TestUser { UserName = "Foo" };
+ var roles = new string[] {"A", "B", "C"};
+ store.Setup(s => s.AddToRoleAsync(user, "A", CancellationToken.None))
+ .Returns(Task.FromResult(0))
+ .Verifiable();
+ store.Setup(s => s.AddToRoleAsync(user, "B", CancellationToken.None))
+ .Returns(Task.FromResult(0))
+ .Verifiable();
+ 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.GetRolesAsync(user, CancellationToken.None)).ReturnsAsync(new List()).Verifiable();
+ var userManager = new UserManager(store.Object) {UserValidator = null};
+
+ // Act
+ var result = await userManager.AddToRolesAsync(user, roles);
+
+ // Assert
+ Assert.True(result.Succeeded);
+ store.VerifyAll();
+ }
+
+ [Fact]
+ public async Task AddToRolesFailsIfUserInRole()
+ {
+ // Setup
+ var store = new Mock>();
+ var user = new TestUser { UserName = "Foo" };
+ var roles = new string[] { "A", "B", "C" };
+ store.Setup(s => s.AddToRoleAsync(user, "A", CancellationToken.None))
+ .Returns(Task.FromResult(0))
+ .Verifiable();
+ store.Setup(s => s.GetRolesAsync(user, CancellationToken.None)).ReturnsAsync(new List { "B" }).Verifiable();
+ var userManager = new UserManager(store.Object) { UserValidator = null };
+
+ // Act
+ var result = await userManager.AddToRolesAsync(user, roles);
+
+ // Assert
+ IdentityResultAssert.IsFailure(result, "User already in role.");
+ store.VerifyAll();
+ }
+
+ [Fact]
+ public async Task RemoveFromRolesCallsStore()
+ {
+ // Setup
+ var store = new Mock>();
+ var user = new TestUser { UserName = "Foo" };
+ var roles = new string[] { "A", "B", "C" };
+ store.Setup(s => s.RemoveFromRoleAsync(user, "A", CancellationToken.None))
+ .Returns(Task.FromResult(0))
+ .Verifiable();
+ store.Setup(s => s.RemoveFromRoleAsync(user, "B", CancellationToken.None))
+ .Returns(Task.FromResult(0))
+ .Verifiable();
+ 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.IsInRoleAsync(user, "A", CancellationToken.None))
+ .Returns(Task.FromResult(true))
+ .Verifiable();
+ store.Setup(s => s.IsInRoleAsync(user, "B", CancellationToken.None))
+ .Returns(Task.FromResult(true))
+ .Verifiable();
+ store.Setup(s => s.IsInRoleAsync(user, "C", CancellationToken.None))
+ .Returns(Task.FromResult(true))
+ .Verifiable();
+ var userManager = new UserManager(store.Object) { UserValidator = null };
+
+ // Act
+ var result = await userManager.RemoveFromRolesAsync(user, roles);
+
+ // Assert
+ Assert.True(result.Succeeded);
+ store.VerifyAll();
+ }
+
+ [Fact]
+ public async Task RemoveFromRolesFailsIfNotInRole()
+ {
+ // Setup
+ var store = new Mock>();
+ var user = new TestUser { UserName = "Foo" };
+ var roles = new string[] { "A", "B", "C" };
+ store.Setup(s => s.RemoveFromRoleAsync(user, "A", CancellationToken.None))
+ .Returns(Task.FromResult(0))
+ .Verifiable();
+ store.Setup(s => s.IsInRoleAsync(user, "A", CancellationToken.None))
+ .Returns(Task.FromResult(true))
+ .Verifiable();
+ store.Setup(s => s.IsInRoleAsync(user, "B", CancellationToken.None))
+ .Returns(Task.FromResult(false))
+ .Verifiable();
+ var userManager = new UserManager(store.Object) { UserValidator = null };
+
+ // Act
+ var result = await userManager.RemoveFromRolesAsync(user, roles);
+
+ // Assert
+ IdentityResultAssert.IsFailure(result, "User is not in role.");
+ store.VerifyAll();
+ }
+
#endif
[Fact]
@@ -278,8 +389,10 @@ namespace Microsoft.AspNet.Identity.Test
var manager = new UserManager(new NoopUserStore());
Assert.False(manager.SupportsUserRole);
await Assert.ThrowsAsync(async () => await manager.AddToRoleAsync(null, "bogus"));
+ await Assert.ThrowsAsync(async () => await manager.AddToRolesAsync(null, null));
await Assert.ThrowsAsync(async () => await manager.GetRolesAsync(null));
await Assert.ThrowsAsync(async () => await manager.RemoveFromRoleAsync(null, "bogus"));
+ await Assert.ThrowsAsync(async () => await manager.RemoveFromRolesAsync(null, null));
await Assert.ThrowsAsync(async () => await manager.IsInRoleAsync(null, "bogus"));
}
@@ -333,6 +446,8 @@ namespace Microsoft.AspNet.Identity.Test
Assert.Throws("twoFactorProvider",
() => manager.RegisterTwoFactorProvider(null, null));
Assert.Throws("provider", () => manager.RegisterTwoFactorProvider("bogus", null));
+ await Assert.ThrowsAsync("roles", async () => await manager.AddToRolesAsync(new TestUser(), null));
+ await Assert.ThrowsAsync("roles", async () => await manager.RemoveFromRolesAsync(new TestUser(), null));
}
[Fact]
@@ -354,6 +469,8 @@ namespace Microsoft.AspNet.Identity.Test
async () => await manager.AddPasswordAsync(null, null));
await Assert.ThrowsAsync("user",
async () => await manager.AddToRoleAsync(null, null));
+ await Assert.ThrowsAsync("user",
+ async () => await manager.AddToRolesAsync(null, null));
await Assert.ThrowsAsync("user",
async () => await manager.ChangePasswordAsync(null, null, null));
await Assert.ThrowsAsync("user",
@@ -372,6 +489,8 @@ namespace Microsoft.AspNet.Identity.Test
async () => await manager.RemovePasswordAsync(null));
await Assert.ThrowsAsync("user",
async () => await manager.RemoveFromRoleAsync(null, null));
+ await Assert.ThrowsAsync("user",
+ async () => await manager.RemoveFromRolesAsync(null, null));
await Assert.ThrowsAsync("user",
async () => await manager.UpdateSecurityStampAsync(null));
await Assert.ThrowsAsync("user",
@@ -448,6 +567,7 @@ namespace Microsoft.AspNet.Identity.Test
await Assert.ThrowsAsync(() => manager.AddLoginAsync(null, null));
await Assert.ThrowsAsync(() => manager.AddPasswordAsync(null, null));
await Assert.ThrowsAsync(() => manager.AddToRoleAsync(null, null));
+ await Assert.ThrowsAsync(() => manager.AddToRolesAsync(null, null));
await Assert.ThrowsAsync(() => manager.ChangePasswordAsync(null, null, null));
await Assert.ThrowsAsync(() => manager.GetClaimsAsync(null));
await Assert.ThrowsAsync(() => manager.GetLoginsAsync(null));
@@ -457,6 +577,7 @@ namespace Microsoft.AspNet.Identity.Test
await Assert.ThrowsAsync(() => manager.RemoveLoginAsync(null, null));
await Assert.ThrowsAsync(() => manager.RemovePasswordAsync(null));
await Assert.ThrowsAsync(() => manager.RemoveFromRoleAsync(null, null));
+ await Assert.ThrowsAsync(() => manager.RemoveFromRolesAsync(null, null));
await Assert.ThrowsAsync(() => manager.RemoveClaimAsync(null, null));
await Assert.ThrowsAsync(() => manager.FindByUserNamePasswordAsync(null, null));
await Assert.ThrowsAsync(() => manager.FindByLoginAsync(null));
@@ -740,6 +861,7 @@ namespace Microsoft.AspNet.Identity.Test
IUserPasswordStore,
IUserClaimStore,
IUserLoginStore,
+ IUserRoleStore,
IUserEmailStore,
IUserPhoneNumberStore,
IUserLockoutStore,
@@ -929,6 +1051,26 @@ namespace Microsoft.AspNet.Identity.Test
{
throw new NotImplementedException();
}
+
+ public Task AddToRoleAsync(TestUser user, string roleName, CancellationToken cancellationToken = new CancellationToken())
+ {
+ throw new NotImplementedException();
+ }
+
+ public Task RemoveFromRoleAsync(TestUser user, string roleName, CancellationToken cancellationToken = new CancellationToken())
+ {
+ throw new NotImplementedException();
+ }
+
+ public Task> GetRolesAsync(TestUser user, CancellationToken cancellationToken = new CancellationToken())
+ {
+ throw new NotImplementedException();
+ }
+
+ public Task IsInRoleAsync(TestUser user, string roleName, CancellationToken cancellationToken = new CancellationToken())
+ {
+ throw new NotImplementedException();
+ }
}
}
}
\ No newline at end of file