From 0843388a4130ac1db23ef2e8a679f16bb703fcc0 Mon Sep 17 00:00:00 2001 From: Shannon Date: Thu, 10 Oct 2013 13:39:17 +1100 Subject: [PATCH] Fixes up and implements more if the IMemberService, repository and membership providers (both legacy and what seems to be the new one). --- src/Umbraco.Core/Constants-Conventions.cs | 4 ++ src/Umbraco.Core/Models/PagedResult.cs | 63 +++++++++++++++++++ .../Persistence/PetaPocoExtensions.cs | 14 +++++ .../Interfaces/IMemberRepository.cs | 2 + .../Repositories/MemberRepository.cs | 22 +++++++ src/Umbraco.Core/Properties/AssemblyInfo.cs | 1 + src/Umbraco.Core/Services/IMemberService.cs | 4 +- src/Umbraco.Core/Services/MemberService.cs | 8 +++ .../Providers/MembersMembershipProvider.cs | 13 +++- .../businesslogic/member/Member.cs | 4 +- .../members/MembersMembershipProvider.cs | 24 +++++-- .../umbraco.providers.csproj | 4 ++ 12 files changed, 155 insertions(+), 8 deletions(-) create mode 100644 src/Umbraco.Core/Models/PagedResult.cs diff --git a/src/Umbraco.Core/Constants-Conventions.cs b/src/Umbraco.Core/Constants-Conventions.cs index c3916a2e87..660a8073c9 100644 --- a/src/Umbraco.Core/Constants-Conventions.cs +++ b/src/Umbraco.Core/Constants-Conventions.cs @@ -99,6 +99,10 @@ namespace Umbraco.Core /// public static class Member { + public static readonly string UmbracoMemberProviderName = "UmbracoMembershipProvider"; + + public static readonly string UmbracoRoleProviderName = "UmbracoRoleProvider"; + /// /// Property alias for a Members Password Question /// diff --git a/src/Umbraco.Core/Models/PagedResult.cs b/src/Umbraco.Core/Models/PagedResult.cs new file mode 100644 index 0000000000..2e35da9a96 --- /dev/null +++ b/src/Umbraco.Core/Models/PagedResult.cs @@ -0,0 +1,63 @@ +using System; +using System.Collections.Generic; +using System.Runtime.Serialization; + +namespace Umbraco.Core.Models +{ + /// + /// Represents a paged result for a model collection + /// + /// + [DataContract(Name = "pagedCollection", Namespace = "")] + public class PagedResult + { + public PagedResult(long totalItems, long pageNumber, long pageSize) + { + TotalItems = totalItems; + PageNumber = pageNumber; + PageSize = pageSize; + + if (pageSize > 0) + { + TotalPages = (long) Math.Ceiling(totalItems/(Decimal) pageSize); + } + else + { + TotalPages = 1; + } + } + + [DataMember(Name = "pageNumber")] + public long PageNumber { get; private set; } + + [DataMember(Name = "pageSize")] + public long PageSize { get; private set; } + + [DataMember(Name = "totalPages")] + public long TotalPages { get; private set; } + + [DataMember(Name = "totalItems")] + public long TotalItems { get; private set; } + + [DataMember(Name = "items")] + public IEnumerable Items { get; set; } + + /// + /// Calculates the skip size based on the paged parameters specified + /// + /// + /// Returns 0 if the page number or page size is zero + /// + internal int SkipSize + { + get + { + if (PageNumber > 0 && PageSize > 0) + { + return Convert.ToInt32((PageNumber - 1)*PageSize); + } + return 0; + } + } + } +} \ No newline at end of file diff --git a/src/Umbraco.Core/Persistence/PetaPocoExtensions.cs b/src/Umbraco.Core/Persistence/PetaPocoExtensions.cs index eb10bf7f87..f249ca4577 100644 --- a/src/Umbraco.Core/Persistence/PetaPocoExtensions.cs +++ b/src/Umbraco.Core/Persistence/PetaPocoExtensions.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.Data; using System.Linq; +using System.Text.RegularExpressions; using Umbraco.Core.Logging; using Umbraco.Core.Models.Rdbms; using Umbraco.Core.Persistence.DatabaseModelDefinitions; @@ -17,6 +18,19 @@ namespace Umbraco.Core.Persistence internal static event CreateTableEventHandler NewTable; + /// + /// This will escape single @ symbols for peta poco values so it doesn't think it's a parameter + /// + /// + /// + /// + public static string EscapeAtSymbols(this Database db, string value) + { + //this fancy regex will only match a single @ not a double, etc... + var regex = new Regex("(?(this Database db) where T : new() { diff --git a/src/Umbraco.Core/Persistence/Repositories/Interfaces/IMemberRepository.cs b/src/Umbraco.Core/Persistence/Repositories/Interfaces/IMemberRepository.cs index db9a1b4f19..92a8b5365b 100644 --- a/src/Umbraco.Core/Persistence/Repositories/Interfaces/IMemberRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/Interfaces/IMemberRepository.cs @@ -11,5 +11,7 @@ namespace Umbraco.Core.Persistence.Repositories /// /// IEnumerable GetByMemberGroup(string groupName); + + IEnumerable GetMembersByEmails(params string[] emails); } } \ No newline at end of file diff --git a/src/Umbraco.Core/Persistence/Repositories/MemberRepository.cs b/src/Umbraco.Core/Persistence/Repositories/MemberRepository.cs index dbaec8471a..c9d716746e 100644 --- a/src/Umbraco.Core/Persistence/Repositories/MemberRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/MemberRepository.cs @@ -437,6 +437,28 @@ namespace Umbraco.Core.Persistence.Repositories return BuildFromDtos(dtos); } + public IEnumerable GetMembersByEmails(params string[] emails) + { + var sql = GetBaseQuery(false); + if (emails.Any()) + { + var statement = string.Join(" OR ", + emails.Select(x => + string.Format( + "cmsMember.Email='{0}'", + //we have to escape the @ symbol for petapoco to work!! with 2 @@ symbols + Database.EscapeAtSymbols(x)))); + sql.Where(statement); + } + sql.OrderByDescending(x => x.VersionDate); + + var dtos = + Database.Fetch( + new PropertyDataRelator().Map, sql); + + return BuildFromDtos(dtos); + } + private IMember BuildFromDto(List dtos) { if (dtos == null || dtos.Any() == false) diff --git a/src/Umbraco.Core/Properties/AssemblyInfo.cs b/src/Umbraco.Core/Properties/AssemblyInfo.cs index fabcb7fe98..2104841349 100644 --- a/src/Umbraco.Core/Properties/AssemblyInfo.cs +++ b/src/Umbraco.Core/Properties/AssemblyInfo.cs @@ -40,6 +40,7 @@ using System.Security.Permissions; [assembly: InternalsVisibleTo("Concorde.Sync")] [assembly: InternalsVisibleTo("Umbraco.Belle")] [assembly: InternalsVisibleTo("Umbraco.VisualStudio")] +[assembly: InternalsVisibleTo("umbraco.providers")] //allow this to be mocked in our unit tests [assembly: InternalsVisibleTo("DynamicProxyGenAssembly2")] \ No newline at end of file diff --git a/src/Umbraco.Core/Services/IMemberService.cs b/src/Umbraco.Core/Services/IMemberService.cs index 737e142c3b..004a66d151 100644 --- a/src/Umbraco.Core/Services/IMemberService.cs +++ b/src/Umbraco.Core/Services/IMemberService.cs @@ -14,7 +14,7 @@ namespace Umbraco.Core.Services IEnumerable GetMembersByMemberType(string memberTypeAlias); IEnumerable GetMembersByGroup(string memberGroupName); IEnumerable GetAllMembers(params int[] ids); - + //TODO: Need to get all members that start with a certain letter } @@ -37,5 +37,7 @@ namespace Umbraco.Core.Services void Delete(IMember membershipUser); void Save(IMember membershipUser); + + IEnumerable GetMembersByEmails(params string[] emails); } } \ No newline at end of file diff --git a/src/Umbraco.Core/Services/MemberService.cs b/src/Umbraco.Core/Services/MemberService.cs index 914ef70e60..21cce31400 100644 --- a/src/Umbraco.Core/Services/MemberService.cs +++ b/src/Umbraco.Core/Services/MemberService.cs @@ -108,6 +108,14 @@ namespace Umbraco.Core.Services } } + public IEnumerable GetMembersByEmails(params string[] emails) + { + using (var repository = _repositoryFactory.CreateMemberRepository(_uowProvider.GetUnitOfWork())) + { + return repository.GetMembersByEmails(emails); + } + } + /// /// Gets a list of Members with a certain string property value /// diff --git a/src/Umbraco.Web/Security/Providers/MembersMembershipProvider.cs b/src/Umbraco.Web/Security/Providers/MembersMembershipProvider.cs index b02ed4ecf2..0cc4146f85 100644 --- a/src/Umbraco.Web/Security/Providers/MembersMembershipProvider.cs +++ b/src/Umbraco.Web/Security/Providers/MembersMembershipProvider.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Specialized; using System.Configuration.Provider; +using System.Linq; using System.Security.Cryptography; using System.Text; using System.Text.RegularExpressions; @@ -8,6 +9,7 @@ using System.Web.Hosting; using System.Web.Security; using Umbraco.Core; using Umbraco.Core.Logging; +using Umbraco.Core.Models; using Umbraco.Core.Services; using Umbraco.Core.Models.Membership; @@ -687,7 +689,16 @@ namespace Umbraco.Web.Security.Providers /// public override MembershipUserCollection FindUsersByEmail(string emailToMatch, int pageIndex, int pageSize, out int totalRecords) { - throw new System.NotImplementedException(); + var byEmail = MemberService.GetMembersByEmails(emailToMatch).ToArray(); + totalRecords = byEmail.Length; + var pagedResult = new PagedResult(totalRecords, pageIndex, pageSize); + + var collection = new MembershipUserCollection(); + foreach (var m in byEmail.Skip(pagedResult.SkipSize).Take(pageSize)) + { + collection.Add(m.AsConcreteMembershipUser()); + } + return collection; } #region Private methods diff --git a/src/umbraco.cms/businesslogic/member/Member.cs b/src/umbraco.cms/businesslogic/member/Member.cs index 26497187c5..3394144096 100644 --- a/src/umbraco.cms/businesslogic/member/Member.cs +++ b/src/umbraco.cms/businesslogic/member/Member.cs @@ -31,8 +31,8 @@ namespace umbraco.cms.businesslogic.member public class Member : Content { #region Constants and static members - public static readonly string UmbracoMemberProviderName = "UmbracoMembershipProvider"; - public static readonly string UmbracoRoleProviderName = "UmbracoRoleProvider"; + public static readonly string UmbracoMemberProviderName = Constants.Conventions.Member.UmbracoMemberProviderName; + public static readonly string UmbracoRoleProviderName = Constants.Conventions.Member.UmbracoRoleProviderName; public static readonly Guid _objectType = new Guid(Constants.ObjectTypes.Member); private static readonly object m_Locker = new object(); diff --git a/src/umbraco.providers/members/MembersMembershipProvider.cs b/src/umbraco.providers/members/MembersMembershipProvider.cs index 0572613d78..7c8fe8e63a 100644 --- a/src/umbraco.providers/members/MembersMembershipProvider.cs +++ b/src/umbraco.providers/members/MembersMembershipProvider.cs @@ -1,20 +1,26 @@ #region namespace using System; using System.Collections.Generic; +using System.Linq; using System.Text; using System.Web.Security; using System.Configuration; +using Umbraco.Core; +using Umbraco.Core.Models; using umbraco.BusinessLogic; using System.Security.Cryptography; using System.Web.Util; using System.Collections.Specialized; using System.Configuration.Provider; using umbraco.cms.businesslogic; -using umbraco.cms.businesslogic.member; - using System.Security; using System.Security.Permissions; using System.Runtime.CompilerServices; +using Member = umbraco.cms.businesslogic.member.Member; +using MemberType = umbraco.cms.businesslogic.member.MemberType; +using Umbraco.Core.Models.Membership; +using User = umbraco.BusinessLogic.User; + #endregion namespace umbraco.providers.members @@ -439,7 +445,16 @@ namespace umbraco.providers.members /// public override MembershipUserCollection FindUsersByEmail(string emailToMatch, int pageIndex, int pageSize, out int totalRecords) { - throw new Exception("The method or operation is not implemented."); + var byEmail = ApplicationContext.Current.Services.MemberService.GetMembersByEmails(emailToMatch).ToArray(); + totalRecords = byEmail.Length; + var pagedResult = new PagedResult(totalRecords, pageIndex, pageSize); + + var collection = new MembershipUserCollection(); + foreach (var m in byEmail.Skip(pagedResult.SkipSize).Take(pageSize)) + { + collection.Add(m.AsConcreteMembershipUser()); + } + return collection; } /// @@ -751,7 +766,7 @@ namespace umbraco.providers.members return null; } - + /// /// Verifies that the specified user name and password exist in the data source. /// @@ -973,6 +988,7 @@ namespace umbraco.providers.members DateTime.Now, DateTime.Now, DateTime.Now); } } + #endregion } } diff --git a/src/umbraco.providers/umbraco.providers.csproj b/src/umbraco.providers/umbraco.providers.csproj index 7082890e58..41c1457c7d 100644 --- a/src/umbraco.providers/umbraco.providers.csproj +++ b/src/umbraco.providers/umbraco.providers.csproj @@ -99,6 +99,10 @@ {ccd75ec3-63db-4184-b49d-51c1dd337230} umbraco.cms + + {31785bc3-256c-4613-b2f5-a1b0bdded8c1} + Umbraco.Core + {C7CB79F0-1C97-4B33-BFA7-00731B579AE2} umbraco.datalayer