diff --git a/src/Umbraco.Core/Persistence/Repositories/MemberGroupRepository.cs b/src/Umbraco.Core/Persistence/Repositories/MemberGroupRepository.cs index 2b9ec950f5..3ae62f62f9 100644 --- a/src/Umbraco.Core/Persistence/Repositories/MemberGroupRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/MemberGroupRepository.cs @@ -206,7 +206,22 @@ namespace Umbraco.Core.Persistence.Repositories public void DissociateRoles(string[] usernames, string[] roleNames) { - throw new NotImplementedException(); + using (var transaction = Database.GetTransaction()) + { + //first get the member ids based on the usernames + var memberSql = new Sql(); + var memberObjectType = new Guid(Constants.ObjectTypes.Member); + memberSql.Select("umbracoNode.id") + .From() + .InnerJoin() + .On(dto => dto.NodeId, dto => dto.NodeId) + .Where(x => x.NodeObjectType == memberObjectType) + .Where("cmsMember.LoginName in (@usernames)", new { usernames = usernames }); + var memberIds = Database.Fetch(memberSql).ToArray(); + + DissociateRolesInternal(memberIds, roleNames); + transaction.Complete(); + } } public void AssignRoles(int[] memberIds, string[] roleNames) @@ -272,7 +287,24 @@ namespace Umbraco.Core.Persistence.Repositories public void DissociateRoles(int[] memberIds, string[] roleNames) { - throw new NotImplementedException(); + using (var transaction = Database.GetTransaction()) + { + DissociateRolesInternal(memberIds, roleNames); + transaction.Complete(); + } + } + + private void DissociateRolesInternal(int[] memberIds, string[] roleNames) + { + var existingSql = new Sql() + .Select("*") + .From() + .Where(dto => dto.NodeObjectType == NodeObjectTypeId) + .Where("umbracoNode." + SqlSyntaxContext.SqlSyntaxProvider.GetQuotedColumnName("text") + " in (@names)", new { names = roleNames }); + var existingRolesIds = Database.Fetch(existingSql).Select(x => x.NodeId).ToArray(); + + Database.Execute("DELETE FROM cmsMember2MemberGroup WHERE Member IN (@memberIds) AND MemberGroup IN (@memberGroups)", + new { memberIds = memberIds, memberGroups = existingRolesIds }); } private class AssignedRolesDto diff --git a/src/Umbraco.Core/Persistence/Repositories/MemberRepository.cs b/src/Umbraco.Core/Persistence/Repositories/MemberRepository.cs index 348b342ad4..4c3810de6a 100644 --- a/src/Umbraco.Core/Persistence/Repositories/MemberRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/MemberRepository.cs @@ -427,7 +427,53 @@ namespace Umbraco.Core.Persistence.Repositories public IEnumerable FindMembersInRole(string roleName, string usernameToMatch, StringPropertyMatchType matchType = StringPropertyMatchType.StartsWith) { - throw new NotImplementedException(); + //get the group id + var grpQry = new Query().Where(group => group.Name.Equals(roleName)); + var memberGroup = _memberGroupRepository.GetByQuery(grpQry).FirstOrDefault(); + if (memberGroup == null) return Enumerable.Empty(); + + // get the members by username + var query = new Query(); + switch (matchType) + { + case StringPropertyMatchType.Exact: + query.Where(member => member.Username.Equals(usernameToMatch)); + break; + case StringPropertyMatchType.Contains: + query.Where(member => member.Username.Contains(usernameToMatch)); + break; + case StringPropertyMatchType.StartsWith: + query.Where(member => member.Username.StartsWith(usernameToMatch)); + break; + case StringPropertyMatchType.EndsWith: + query.Where(member => member.Username.EndsWith(usernameToMatch)); + break; + case StringPropertyMatchType.Wildcard: + query.Where(member => member.Username.SqlWildcard(usernameToMatch, TextColumnType.NVarchar)); + break; + default: + throw new ArgumentOutOfRangeException("matchType"); + } + var matchedMembers = GetByQuery(query).ToArray(); + + var membersInGroup = new List(); + //then we need to filter the matched members that are in the role + //since the max sql params are 2100 on sql server, we'll reduce that to be safe for potentially other servers and run the queries in batches + var inGroups = matchedMembers.InGroupsOf(1000); + foreach (var batch in inGroups) + { + var memberIdBatch = batch.Select(x => x.Id); + var sql = new Sql().Select("*").From() + .Where(dto => dto.MemberGroup == memberGroup.Id) + .Where("Member IN (@memberIds)", new { memberIds = memberIdBatch }); + var memberIdsInGroup = Database.Fetch(sql) + .Select(x => x.Member).ToArray(); + + membersInGroup.AddRange(matchedMembers.Where(x => memberIdsInGroup.Contains(x.Id))); + } + + return membersInGroup; + } /// diff --git a/src/Umbraco.Tests/Services/MemberServiceTests.cs b/src/Umbraco.Tests/Services/MemberServiceTests.cs index 7bda2ea76c..108c8f4bf8 100644 --- a/src/Umbraco.Tests/Services/MemberServiceTests.cs +++ b/src/Umbraco.Tests/Services/MemberServiceTests.cs @@ -3,6 +3,7 @@ using System.Linq; using NUnit.Framework; using Umbraco.Core; using Umbraco.Core.Models; +using Umbraco.Core.Models.Membership; using Umbraco.Core.Models.Rdbms; using Umbraco.Core.Persistence.Querying; using Umbraco.Core.Services; @@ -143,10 +144,27 @@ namespace Umbraco.Tests.Services Assert.AreEqual(2, membersInRole.Count()); } - [Test] - public void Find_Members_In_Role() + [TestCase("MyTestRole1", "test1", StringPropertyMatchType.StartsWith, 1)] + [TestCase("MyTestRole1", "test", StringPropertyMatchType.StartsWith, 3)] + [TestCase("MyTestRole1", "test1", StringPropertyMatchType.Exact, 1)] + [TestCase("MyTestRole1", "test", StringPropertyMatchType.Exact, 0)] + [TestCase("MyTestRole1", "st2", StringPropertyMatchType.EndsWith, 1)] + [TestCase("MyTestRole1", "test%", StringPropertyMatchType.Wildcard, 3)] + public void Find_Members_In_Role(string roleName1, string usernameToMatch, StringPropertyMatchType matchType, int resultCount) { + IMemberType memberType = MockedContentTypes.CreateSimpleMemberType(); + ServiceContext.MemberTypeService.Save(memberType); + var member1 = MockedMember.CreateSimpleMember(memberType, "test1", "test1@test.com", "pass", "test1"); + ServiceContext.MemberService.Save(member1); + var member2 = MockedMember.CreateSimpleMember(memberType, "test2", "test2@test.com", "pass", "test2"); + ServiceContext.MemberService.Save(member2); + var member3 = MockedMember.CreateSimpleMember(memberType, "test3", "test3@test.com", "pass", "test3"); + ServiceContext.MemberService.Save(member3); + ServiceContext.MemberService.AssignRoles(new[] { member1.Id, member2.Id, member3.Id }, new[] { roleName1 }); + + var result = ServiceContext.MemberService.FindMembersInRole(roleName1, usernameToMatch, matchType); + Assert.AreEqual(resultCount, result.Count()); } [Test] @@ -208,13 +226,43 @@ namespace Umbraco.Tests.Services [Test] public void Remove_Members_From_Roles_With_Member_Id() { + IMemberType memberType = MockedContentTypes.CreateSimpleMemberType(); + ServiceContext.MemberTypeService.Save(memberType); + var member1 = MockedMember.CreateSimpleMember(memberType, "test1", "test1@test.com", "pass", "test1"); + ServiceContext.MemberService.Save(member1); + var member2 = MockedMember.CreateSimpleMember(memberType, "test2", "test2@test.com", "pass", "test2"); + ServiceContext.MemberService.Save(member2); + ServiceContext.MemberService.AssignRoles(new[] { member1.Id, member2.Id }, new[] { "MyTestRole1", "MyTestRole2" }); + + ServiceContext.MemberService.DissociateRoles(new[] {member1.Id }, new[] {"MyTestRole1"}); + ServiceContext.MemberService.DissociateRoles(new[] { member1.Id, member2.Id }, new[] { "MyTestRole2" }); + + var membersInRole = ServiceContext.MemberService.GetMembersInRole("MyTestRole1"); + Assert.AreEqual(1, membersInRole.Count()); + membersInRole = ServiceContext.MemberService.GetMembersInRole("MyTestRole2"); + Assert.AreEqual(0, membersInRole.Count()); } [Test] public void Remove_Members_From_Roles_With_Member_Username() { + IMemberType memberType = MockedContentTypes.CreateSimpleMemberType(); + ServiceContext.MemberTypeService.Save(memberType); + var member1 = MockedMember.CreateSimpleMember(memberType, "test1", "test1@test.com", "pass", "test1"); + ServiceContext.MemberService.Save(member1); + var member2 = MockedMember.CreateSimpleMember(memberType, "test2", "test2@test.com", "pass", "test2"); + ServiceContext.MemberService.Save(member2); + ServiceContext.MemberService.AssignRoles(new[] { member1.Username, member2.Username }, new[] { "MyTestRole1", "MyTestRole2" }); + + ServiceContext.MemberService.DissociateRoles(new[] { member1.Username }, new[] { "MyTestRole1" }); + ServiceContext.MemberService.DissociateRoles(new[] { member1.Username, member2.Username }, new[] { "MyTestRole2" }); + + var membersInRole = ServiceContext.MemberService.GetMembersInRole("MyTestRole1"); + Assert.AreEqual(1, membersInRole.Count()); + membersInRole = ServiceContext.MemberService.GetMembersInRole("MyTestRole2"); + Assert.AreEqual(0, membersInRole.Count()); } [Test]