diff --git a/src/Umbraco.Core/Models/Membership/User.cs b/src/Umbraco.Core/Models/Membership/User.cs index be7b5d8c8a..ac072a73c2 100644 --- a/src/Umbraco.Core/Models/Membership/User.cs +++ b/src/Umbraco.Core/Models/Membership/User.cs @@ -27,6 +27,7 @@ namespace Umbraco.Core.Models.Membership if (userType == null) throw new ArgumentNullException("userType"); _userType = userType; + _defaultPermissions = _userType.Permissions; //Groups = new List { userType }; SessionTimeout = 60; _sectionCollection = new ObservableCollection(); @@ -38,6 +39,8 @@ namespace Umbraco.Core.Models.Membership _isLockedOut = false; _startContentId = -1; _startMediaId = -1; + //cannot be null + _rawPasswordValue = ""; } public User(string name, string email, string username, string rawPasswordValue, IUserType userType) diff --git a/src/Umbraco.Core/Services/IMemberService.cs b/src/Umbraco.Core/Services/IMemberService.cs index 78e7942701..f7918b2d8d 100644 --- a/src/Umbraco.Core/Services/IMemberService.cs +++ b/src/Umbraco.Core/Services/IMemberService.cs @@ -5,11 +5,17 @@ using Umbraco.Core.Persistence.Querying; namespace Umbraco.Core.Services { + /// /// Defines the MemberService, which is an easy access to operations involving (umbraco) members. /// public interface IMemberService : IMembershipMemberService { + IMember CreateMember(string username, string email, string name, string memberTypeAlias); + IMember CreateMember(string username, string email, string name, IMemberType memberType); + IMember CreateMemberWithIdentity(string username, string email, string name, string memberTypeAlias); + IMember CreateMemberWithIdentity(string username, string email, string name, IMemberType memberType); + /// /// This is simply a helper method which essentially just wraps the MembershipProvider's ChangePassword method /// diff --git a/src/Umbraco.Core/Services/IMembershipMemberService.cs b/src/Umbraco.Core/Services/IMembershipMemberService.cs index a05065eea7..d4d865614a 100644 --- a/src/Umbraco.Core/Services/IMembershipMemberService.cs +++ b/src/Umbraco.Core/Services/IMembershipMemberService.cs @@ -13,8 +13,7 @@ namespace Umbraco.Core.Services /// Idea is to have this is an isolated interface so that it can be easily 'replaced' in the membership provider impl. /// public interface IMembershipMemberService : IMembershipMemberService, IMembershipRoleService - { - IMember CreateMember(string username, string email, string memberType); + { IMember CreateMemberWithIdentity(string username, string email, IMemberType memberType); } diff --git a/src/Umbraco.Core/Services/IMembershipUserService.cs b/src/Umbraco.Core/Services/IMembershipUserService.cs index 2e4db90d3a..5739d6940c 100644 --- a/src/Umbraco.Core/Services/IMembershipUserService.cs +++ b/src/Umbraco.Core/Services/IMembershipUserService.cs @@ -10,8 +10,6 @@ namespace Umbraco.Core.Services /// public interface IMembershipUserService : IMembershipMemberService { - - IUser CreateUserWithIdentity(string username, string email, string password, IUserType userType); - + IUser CreateUserWithIdentity(string username, string email, IUserType userType); } } \ No newline at end of file diff --git a/src/Umbraco.Core/Services/IUserService.cs b/src/Umbraco.Core/Services/IUserService.cs index ba401b0e10..191f9085f6 100644 --- a/src/Umbraco.Core/Services/IUserService.cs +++ b/src/Umbraco.Core/Services/IUserService.cs @@ -9,6 +9,16 @@ namespace Umbraco.Core.Services /// public interface IUserService : IMembershipUserService { + /// + /// This is simply a helper method which essentially just wraps the MembershipProvider's ChangePassword method + /// + /// The user to save the password for + /// + /// + /// This method exists so that Umbraco developers can use one entry point to create/update users if they choose to. + /// + void SavePassword(IUser user, string password); + /// /// To permanently delete the user pass in true, otherwise they will just be disabled /// diff --git a/src/Umbraco.Core/Services/MemberService.cs b/src/Umbraco.Core/Services/MemberService.cs index d95f4f37e5..5f47bb115e 100644 --- a/src/Umbraco.Core/Services/MemberService.cs +++ b/src/Umbraco.Core/Services/MemberService.cs @@ -609,23 +609,95 @@ namespace Umbraco.Core.Services } } - public IMember CreateMember(string username, string email, string memberTypeAlias) + /// + /// Creates a member object + /// + /// + /// + /// + /// + /// + public IMember CreateMember(string username, string email, string name, string memberTypeAlias) { - var memberTypeService = ApplicationContext.Current.Services.MemberTypeService; - var memberType = memberTypeService.Get(memberTypeAlias); + var memberType = FindMemberTypeByAlias(memberTypeAlias); + return CreateMember(username, email, name, memberType); + } - var member = new Member(username, email.ToLower().Trim(), username, memberType); + /// + /// Creates a new member object + /// + /// + /// + /// + /// + /// + public IMember CreateMember(string username, string email, string name, IMemberType memberType) + { + var member = new Member(name, email.ToLower().Trim(), username, memberType); - Created.RaiseEvent(new NewEventArgs(member, false, memberTypeAlias, -1), this); + Created.RaiseEvent(new NewEventArgs(member, false, memberType.Alias, -1), this); return member; } + /// + /// Creates a member with an Id + /// + /// + /// + /// + /// + /// + public IMember CreateMemberWithIdentity(string username, string email, string name, string memberTypeAlias) + { + var memberType = FindMemberTypeByAlias(memberTypeAlias); + return CreateMemberWithIdentity(username, email, name, memberType); + } + + /// + /// Creates a member with an Id, the username will be used as their name + /// + /// + /// + /// + /// public IMember CreateMemberWithIdentity(string username, string email, IMemberType memberType) + { + return CreateMemberWithIdentity(username, email, username, memberType); + } + + /// + /// Creates a member with an Id + /// + /// + /// + /// + /// + /// + public IMember CreateMemberWithIdentity(string username, string email, string name, IMemberType memberType) + { + return CreateMemberWithIdentity(username, email, name, "", memberType); + } + + /// + /// Creates and persists a new Member + /// + /// + /// + /// + /// + /// + IMember IMembershipMemberService.CreateWithIdentity(string username, string email, string rawPasswordValue, string memberTypeAlias) + { + var memberType = FindMemberTypeByAlias(memberTypeAlias); + return CreateMemberWithIdentity(username, email, memberType); + } + + private IMember CreateMemberWithIdentity(string username, string email, string name, string rawPasswordValue, IMemberType memberType) { if (memberType == null) throw new ArgumentNullException("memberType"); - var member = new Member(username, email.ToLower().Trim(), username, memberType); + var member = new Member(name, email.ToLower().Trim(), username, rawPasswordValue, memberType); if (Saving.IsRaisedEventCancelled(new SaveEventArgs(member), this)) { @@ -649,33 +721,6 @@ namespace Umbraco.Core.Services return member; } - - /// - /// Creates and persists a new Member - /// - /// - /// - /// - /// - /// - IMember IMembershipMemberService.CreateWithIdentity(string username, string email, string rawPasswordValue, string memberTypeAlias) - { - var uow = _uowProvider.GetUnitOfWork(); - IMemberType memberType; - - using (var repository = _repositoryFactory.CreateMemberTypeRepository(uow)) - { - var query = Query.Builder.Where(x => x.Alias == memberTypeAlias); - memberType = repository.GetByQuery(query).FirstOrDefault(); - } - - if (memberType == null) - { - throw new ArgumentException(string.Format("No MemberType matching the passed in Alias: '{0}' was found", memberTypeAlias)); - } - - return CreateMemberWithIdentity(username, email, memberType); - } /// /// Gets a Member by its Id @@ -937,8 +982,33 @@ namespace Umbraco.Core.Services repository.DissociateRoles(memberIds, roleNames); } } + + + #endregion + private IMemberType FindMemberTypeByAlias(string memberTypeAlias) + { + using (var repository = _repositoryFactory.CreateMemberTypeRepository(_uowProvider.GetUnitOfWork())) + { + var query = Query.Builder.Where(x => x.Alias == memberTypeAlias); + var types = repository.GetByQuery(query); + + if (types.Any() == false) + throw new Exception( + string.Format("No MemberType matching the passed in Alias: '{0}' was found", + memberTypeAlias)); + + var contentType = types.First(); + + if (contentType == null) + throw new Exception(string.Format("MemberType matching the passed in Alias: '{0}' was null", + memberTypeAlias)); + + return contentType; + } + } + /// /// Rebuilds all xml content in the cmsContentXml table for all media /// diff --git a/src/Umbraco.Core/Services/UserService.cs b/src/Umbraco.Core/Services/UserService.cs index f24ad8ac34..d2a58b6ad8 100644 --- a/src/Umbraco.Core/Services/UserService.cs +++ b/src/Umbraco.Core/Services/UserService.cs @@ -9,6 +9,7 @@ using Umbraco.Core.Models.Rdbms; using Umbraco.Core.Persistence; using Umbraco.Core.Persistence.Querying; using Umbraco.Core.Persistence.UnitOfWork; +using Umbraco.Core.Security; namespace Umbraco.Core.Services { @@ -75,7 +76,23 @@ namespace Umbraco.Core.Services } } - public IUser CreateUserWithIdentity(string username, string email, string password, IUserType userType) + public IUser CreateUserWithIdentity(string username, string email, IUserType userType) + { + return CreateUserWithIdentity(username, email, "", userType); + } + + IUser IMembershipMemberService.CreateWithIdentity(string username, string email, string rawPasswordValue, string memberTypeAlias) + { + var userType = GetUserTypeByAlias(memberTypeAlias); + if (userType == null) + { + throw new ArgumentException("The user type " + memberTypeAlias + " could not be resolved"); + } + + return CreateUserWithIdentity(username, email, rawPasswordValue, userType); + } + + private IUser CreateUserWithIdentity(string username, string email, string rawPasswordValue, IUserType userType) { if (userType == null) throw new ArgumentNullException("userType"); @@ -94,8 +111,7 @@ namespace Umbraco.Core.Services Email = email, Language = Configuration.GlobalSettings.DefaultUILanguage, Name = username, - RawPasswordValue = password, - DefaultPermissions = userType.Permissions, + RawPasswordValue = rawPasswordValue, Username = username, StartContentId = -1, StartMediaId = -1, @@ -115,17 +131,6 @@ namespace Umbraco.Core.Services } } - IUser IMembershipMemberService.CreateWithIdentity(string username, string email, string rawPasswordValue, string memberTypeAlias) - { - var userType = GetUserTypeByAlias(memberTypeAlias); - if (userType == null) - { - throw new ArgumentException("The user type " + memberTypeAlias + " could not be resolved"); - } - - return CreateUserWithIdentity(username, email, rawPasswordValue, userType); - } - public IUser GetById(int id) { using (var repository = _repositoryFactory.CreateUserRepository(_uowProvider.GetUnitOfWork())) @@ -187,6 +192,37 @@ namespace Umbraco.Core.Services uow.Database.Execute("delete from umbracoUserLogins where userID = @id", new {id = membershipUser.Id}); } + /// + /// This is simply a helper method which essentially just wraps the MembershipProvider's ChangePassword method + /// + /// The user to save the password for + /// + /// + /// This method exists so that Umbraco developers can use one entry point to create/update users if they choose to. + /// + public void SavePassword(IUser user, string password) + { + if (user == null) throw new ArgumentNullException("user"); + + var provider = MembershipProviderExtensions.GetUsersMembershipProvider(); + if (provider.IsUmbracoMembershipProvider()) + { + provider.ChangePassword(user.Username, "", password); + } + + //go re-fetch the member and update the properties that may have changed + var result = GetByUsername(user.Username); + if (result != null) + { + //should never be null but it could have been deleted by another thread. + user.RawPasswordValue = result.RawPasswordValue; + user.LastPasswordChangeDate = result.LastPasswordChangeDate; + user.UpdateDate = user.UpdateDate; + } + + throw new NotSupportedException("When using a non-Umbraco membership provider you must change the user password by using the MembershipProvider.ChangePassword method"); + } + /// /// To permanently delete the user pass in true, otherwise they will just be disabled /// diff --git a/src/Umbraco.Tests/Services/UserServiceTests.cs b/src/Umbraco.Tests/Services/UserServiceTests.cs index 4e027c7129..f0fdc8a21d 100644 --- a/src/Umbraco.Tests/Services/UserServiceTests.cs +++ b/src/Umbraco.Tests/Services/UserServiceTests.cs @@ -37,7 +37,7 @@ namespace Umbraco.Tests.Services // Arrange var userService = ServiceContext.UserService; var userType = userService.GetUserTypeByAlias("admin"); - var user = ServiceContext.UserService.CreateUserWithIdentity("test1", "test1@test.com", "123456", userType); + var user = ServiceContext.UserService.CreateUserWithIdentity("test1", "test1@test.com", userType); var contentType = MockedContentTypes.CreateSimpleContentType(); ServiceContext.ContentTypeService.Save(contentType); var content = new[] @@ -64,7 +64,7 @@ namespace Umbraco.Tests.Services // Arrange var userService = ServiceContext.UserService; var userType = userService.GetUserTypeByAlias("admin"); - var user = ServiceContext.UserService.CreateUserWithIdentity("test1", "test1@test.com", "123456", userType); + var user = ServiceContext.UserService.CreateUserWithIdentity("test1", "test1@test.com", userType); var contentType = MockedContentTypes.CreateSimpleContentType(); ServiceContext.ContentTypeService.Save(contentType); var content = new[] @@ -98,7 +98,7 @@ namespace Umbraco.Tests.Services { var userType = MockedUserType.CreateUserType(); ServiceContext.UserService.SaveUserType(userType); - var user = ServiceContext.UserService.CreateUserWithIdentity("JohnDoe", "john@umbraco.io", "12345", userType); + var user = ServiceContext.UserService.CreateUserWithIdentity("JohnDoe", "john@umbraco.io", userType); ServiceContext.UserService.Delete(user, true); var deleted = ServiceContext.UserService.GetUserById(user.Id); @@ -112,7 +112,7 @@ namespace Umbraco.Tests.Services { var userType = MockedUserType.CreateUserType(); ServiceContext.UserService.SaveUserType(userType); - var user = ServiceContext.UserService.CreateUserWithIdentity("JohnDoe", "john@umbraco.io", "12345", userType); + var user = ServiceContext.UserService.CreateUserWithIdentity("JohnDoe", "john@umbraco.io", userType); ServiceContext.UserService.Delete(user); var deleted = ServiceContext.UserService.GetUserById(user.Id); @@ -126,7 +126,7 @@ namespace Umbraco.Tests.Services { var userType = MockedUserType.CreateUserType(); ServiceContext.UserService.SaveUserType(userType); - var user = ServiceContext.UserService.CreateUserWithIdentity("JohnDoe", "john@umbraco.io", "12345", userType); + var user = ServiceContext.UserService.CreateUserWithIdentity("JohnDoe", "john@umbraco.io", userType); Assert.IsTrue(ServiceContext.UserService.Exists("JohnDoe")); Assert.IsFalse(ServiceContext.UserService.Exists("notFound")); @@ -137,7 +137,7 @@ namespace Umbraco.Tests.Services { var userType = MockedUserType.CreateUserType(); ServiceContext.UserService.SaveUserType(userType); - var user = ServiceContext.UserService.CreateUserWithIdentity("JohnDoe", "john@umbraco.io", "12345", userType); + var user = ServiceContext.UserService.CreateUserWithIdentity("JohnDoe", "john@umbraco.io", userType); Assert.IsNotNull(ServiceContext.UserService.GetByEmail(user.Email)); Assert.IsNull(ServiceContext.UserService.GetByEmail("do@not.find")); @@ -148,7 +148,7 @@ namespace Umbraco.Tests.Services { var userType = MockedUserType.CreateUserType(); ServiceContext.UserService.SaveUserType(userType); - var user = ServiceContext.UserService.CreateUserWithIdentity("JohnDoe", "john@umbraco.io", "12345", userType); + var user = ServiceContext.UserService.CreateUserWithIdentity("JohnDoe", "john@umbraco.io", userType); Assert.IsNotNull(ServiceContext.UserService.GetByUsername(user.Username)); Assert.IsNull(ServiceContext.UserService.GetByUsername("notFound")); @@ -159,7 +159,7 @@ namespace Umbraco.Tests.Services { var userType = MockedUserType.CreateUserType(); ServiceContext.UserService.SaveUserType(userType); - var user = ServiceContext.UserService.CreateUserWithIdentity("mydomain\\JohnDoe", "john@umbraco.io", "12345", userType); + var user = ServiceContext.UserService.CreateUserWithIdentity("mydomain\\JohnDoe", "john@umbraco.io", userType); Assert.IsNotNull(ServiceContext.UserService.GetByUsername(user.Username)); Assert.IsNull(ServiceContext.UserService.GetByUsername("notFound")); @@ -170,7 +170,7 @@ namespace Umbraco.Tests.Services { var userType = MockedUserType.CreateUserType(); ServiceContext.UserService.SaveUserType(userType); - var user = ServiceContext.UserService.CreateUserWithIdentity("JohnDoe", "john@umbraco.io", "12345", userType); + var user = ServiceContext.UserService.CreateUserWithIdentity("JohnDoe", "john@umbraco.io", userType); Assert.IsNotNull(ServiceContext.UserService.GetUserById(user.Id)); Assert.IsNull(ServiceContext.UserService.GetUserById(9876)); @@ -352,7 +352,7 @@ namespace Umbraco.Tests.Services var userType = userService.GetUserTypeByAlias("admin"); // Act - var membershipUser = userService.CreateUserWithIdentity("JohnDoe", "john@umbraco.io", "12345", userType); + var membershipUser = userService.CreateUserWithIdentity("JohnDoe", "john@umbraco.io", userType); // Assert Assert.That(membershipUser.HasIdentity, Is.True); @@ -375,7 +375,8 @@ namespace Umbraco.Tests.Services var hash = new HMACSHA1(); hash.Key = Encoding.Unicode.GetBytes(password); var encodedPassword = Convert.ToBase64String(hash.ComputeHash(Encoding.Unicode.GetBytes(password))); - var membershipUser = userService.CreateUserWithIdentity("JohnDoe", "john@umbraco.io", encodedPassword, userType); + var membershipUser = new User("JohnDoe", "john@umbraco.io", encodedPassword, encodedPassword, userType); + userService.Save(membershipUser); // Assert Assert.That(membershipUser.HasIdentity, Is.True); @@ -391,8 +392,8 @@ namespace Umbraco.Tests.Services { var userType = ServiceContext.UserService.GetUserTypeByAlias("admin"); - var user1 = ServiceContext.UserService.CreateUserWithIdentity("test1", "test1@test.com", "test1", userType); - var user2 = ServiceContext.UserService.CreateUserWithIdentity("test2", "test2@test.com", "test2", userType); + var user1 = ServiceContext.UserService.CreateUserWithIdentity("test1", "test1@test.com", userType); + var user2 = ServiceContext.UserService.CreateUserWithIdentity("test2", "test2@test.com", userType); //adds some allowed sections user1.AddAllowedSection("test"); @@ -416,7 +417,7 @@ namespace Umbraco.Tests.Services { // Arrange var userType = ServiceContext.UserService.GetUserTypeByAlias("admin"); - var user = ServiceContext.UserService.CreateUserWithIdentity("test1", "test1@test.com", "test1", userType); + var user = ServiceContext.UserService.CreateUserWithIdentity("test1", "test1@test.com", userType); // Act @@ -433,7 +434,7 @@ namespace Umbraco.Tests.Services { // Arrange var userType = ServiceContext.UserService.GetUserTypeByAlias("admin"); - var user = (IUser)ServiceContext.UserService.CreateUserWithIdentity("test1", "test1@test.com", "test1", userType); + var user = (IUser)ServiceContext.UserService.CreateUserWithIdentity("test1", "test1@test.com", userType); // Act @@ -450,7 +451,7 @@ namespace Umbraco.Tests.Services { // Arrange var userType = ServiceContext.UserService.GetUserTypeByAlias("admin"); - var originalUser = (User)ServiceContext.UserService.CreateUserWithIdentity("test1", "test1@test.com", "test1", userType); + var originalUser = (User)ServiceContext.UserService.CreateUserWithIdentity("test1", "test1@test.com", userType); // Act