diff --git a/src/Umbraco.Core/Models/Membership/Providers/MembersMembershipProvider.cs b/src/Umbraco.Core/Models/Membership/Providers/MembersMembershipProvider.cs new file mode 100644 index 0000000000..b3e95da7f7 --- /dev/null +++ b/src/Umbraco.Core/Models/Membership/Providers/MembersMembershipProvider.cs @@ -0,0 +1,160 @@ +using System.Web.Security; +using Umbraco.Core.Services; + +namespace Umbraco.Core.Models.Membership.Providers +{ + /// + /// Custom Membership Provider for Umbraco Members (User authentication for Umbraco based Websites) + /// + internal class MembersMembershipProvider : MembershipProvider + { + private IMemberService _memberService; + + protected IMemberService MemberService + { + get + { + if (_memberService == null) + { + _memberService = ApplicationContext.Current.Services.MemberService; + } + + return _memberService; + } + } + + public override MembershipUser CreateUser(string username, string password, string email, string passwordQuestion, string passwordAnswer, + bool isApproved, object providerUserKey, out MembershipCreateStatus status) + { + throw new System.NotImplementedException(); + } + + public override bool ChangePasswordQuestionAndAnswer(string username, string password, string newPasswordQuestion, + string newPasswordAnswer) + { + throw new System.NotImplementedException(); + } + + public override string GetPassword(string username, string answer) + { + throw new System.NotImplementedException(); + } + + public override bool ChangePassword(string username, string oldPassword, string newPassword) + { + throw new System.NotImplementedException(); + } + + public override string ResetPassword(string username, string answer) + { + throw new System.NotImplementedException(); + } + + public override void UpdateUser(MembershipUser user) + { + throw new System.NotImplementedException(); + } + + public override bool ValidateUser(string username, string password) + { + throw new System.NotImplementedException(); + } + + public override bool UnlockUser(string userName) + { + throw new System.NotImplementedException(); + } + + public override MembershipUser GetUser(object providerUserKey, bool userIsOnline) + { + throw new System.NotImplementedException(); + } + + public override MembershipUser GetUser(string username, bool userIsOnline) + { + throw new System.NotImplementedException(); + } + + public override string GetUserNameByEmail(string email) + { + throw new System.NotImplementedException(); + } + + public override bool DeleteUser(string username, bool deleteAllRelatedData) + { + throw new System.NotImplementedException(); + } + + public override MembershipUserCollection GetAllUsers(int pageIndex, int pageSize, out int totalRecords) + { + throw new System.NotImplementedException(); + } + + public override int GetNumberOfUsersOnline() + { + throw new System.NotImplementedException(); + } + + public override MembershipUserCollection FindUsersByName(string usernameToMatch, int pageIndex, int pageSize, out int totalRecords) + { + throw new System.NotImplementedException(); + } + + public override MembershipUserCollection FindUsersByEmail(string emailToMatch, int pageIndex, int pageSize, out int totalRecords) + { + throw new System.NotImplementedException(); + } + + public override bool EnablePasswordRetrieval + { + get { throw new System.NotImplementedException(); } + } + + public override bool EnablePasswordReset + { + get { throw new System.NotImplementedException(); } + } + + public override bool RequiresQuestionAndAnswer + { + get { throw new System.NotImplementedException(); } + } + + public override string ApplicationName { get; set; } + + public override int MaxInvalidPasswordAttempts + { + get { throw new System.NotImplementedException(); } + } + + public override int PasswordAttemptWindow + { + get { throw new System.NotImplementedException(); } + } + + public override bool RequiresUniqueEmail + { + get { throw new System.NotImplementedException(); } + } + + public override MembershipPasswordFormat PasswordFormat + { + get { throw new System.NotImplementedException(); } + } + + public override int MinRequiredPasswordLength + { + get { throw new System.NotImplementedException(); } + } + + public override int MinRequiredNonAlphanumericCharacters + { + get { throw new System.NotImplementedException(); } + } + + public override string PasswordStrengthRegularExpression + { + get { throw new System.NotImplementedException(); } + } + } +} \ No newline at end of file diff --git a/src/Umbraco.Core/Models/Membership/Providers/UsersMembershipProvider.cs b/src/Umbraco.Core/Models/Membership/Providers/UsersMembershipProvider.cs new file mode 100644 index 0000000000..591c02eecf --- /dev/null +++ b/src/Umbraco.Core/Models/Membership/Providers/UsersMembershipProvider.cs @@ -0,0 +1,171 @@ +using System; +using System.Security.Cryptography; +using System.Text; +using System.Web.Security; +using Umbraco.Core.Services; + +namespace Umbraco.Core.Models.Membership.Providers +{ + /// + /// Custom Membership Provider for Umbraco Users (User authentication for Umbraco Backend CMS) + /// + internal class UsersMembershipProvider : MembershipProvider + { + private IUserService _userService; + + protected IUserService MemberService + { + get + { + if (_userService == null) + { + _userService = ApplicationContext.Current.Services.UserService; + } + + return _userService; + } + } + + public override MembershipUser CreateUser(string username, string password, string email, string passwordQuestion, string passwordAnswer, + bool isApproved, object providerUserKey, out MembershipCreateStatus status) + { + //Assuming the password is hashed + var hash = new HMACSHA1(); + hash.Key = Encoding.Unicode.GetBytes(password); + var encodedPassword = Convert.ToBase64String(hash.ComputeHash(Encoding.Unicode.GetBytes(password))); + + //var user = _userService.CreateUser(); + //status = MembershipCreateStatus.Success; + //return new UmbracoMembershipUser(user); + throw new System.NotImplementedException(); + } + + public override bool ChangePasswordQuestionAndAnswer(string username, string password, string newPasswordQuestion, + string newPasswordAnswer) + { + throw new System.NotImplementedException(); + } + + public override string GetPassword(string username, string answer) + { + throw new System.NotImplementedException(); + } + + public override bool ChangePassword(string username, string oldPassword, string newPassword) + { + throw new System.NotImplementedException(); + } + + public override string ResetPassword(string username, string answer) + { + throw new System.NotImplementedException(); + } + + public override void UpdateUser(MembershipUser user) + { + throw new System.NotImplementedException(); + } + + public override bool ValidateUser(string username, string password) + { + throw new System.NotImplementedException(); + } + + public override bool UnlockUser(string userName) + { + throw new System.NotImplementedException(); + } + + public override MembershipUser GetUser(object providerUserKey, bool userIsOnline) + { + throw new System.NotImplementedException(); + } + + public override MembershipUser GetUser(string username, bool userIsOnline) + { + throw new System.NotImplementedException(); + } + + public override string GetUserNameByEmail(string email) + { + throw new System.NotImplementedException(); + } + + public override bool DeleteUser(string username, bool deleteAllRelatedData) + { + throw new System.NotImplementedException(); + } + + public override MembershipUserCollection GetAllUsers(int pageIndex, int pageSize, out int totalRecords) + { + throw new System.NotImplementedException(); + } + + public override int GetNumberOfUsersOnline() + { + throw new System.NotImplementedException(); + } + + public override MembershipUserCollection FindUsersByName(string usernameToMatch, int pageIndex, int pageSize, out int totalRecords) + { + throw new System.NotImplementedException(); + } + + public override MembershipUserCollection FindUsersByEmail(string emailToMatch, int pageIndex, int pageSize, out int totalRecords) + { + throw new System.NotImplementedException(); + } + + public override bool EnablePasswordRetrieval + { + get { throw new System.NotImplementedException(); } + } + + public override bool EnablePasswordReset + { + get { throw new System.NotImplementedException(); } + } + + public override bool RequiresQuestionAndAnswer + { + get { throw new System.NotImplementedException(); } + } + + public override string ApplicationName { get; set; } + + public override int MaxInvalidPasswordAttempts + { + get { throw new System.NotImplementedException(); } + } + + public override int PasswordAttemptWindow + { + get { throw new System.NotImplementedException(); } + } + + public override bool RequiresUniqueEmail + { + get { throw new System.NotImplementedException(); } + } + + public override MembershipPasswordFormat PasswordFormat + { + get { throw new System.NotImplementedException(); } + } + + public override int MinRequiredPasswordLength + { + get { throw new System.NotImplementedException(); } + } + + public override int MinRequiredNonAlphanumericCharacters + { + get { throw new System.NotImplementedException(); } + } + + public override string PasswordStrengthRegularExpression + { + get { throw new System.NotImplementedException(); } + } + } +} \ No newline at end of file diff --git a/src/Umbraco.Core/Models/Membership/UmbracoMembershipUser.cs b/src/Umbraco.Core/Models/Membership/UmbracoMembershipUser.cs new file mode 100644 index 0000000000..ada2a7102d --- /dev/null +++ b/src/Umbraco.Core/Models/Membership/UmbracoMembershipUser.cs @@ -0,0 +1,51 @@ +using System; +using System.Web.Security; + +namespace Umbraco.Core.Models.Membership +{ + internal class UmbracoMembershipUser : MembershipUser where T : IMembershipUser + { + private T _user; + + #region Constructors + /// + /// Initializes a new instance of the class. + /// + public UmbracoMembershipUser(T user) + { + _user = user; + } + + /// + /// Initializes a new instance of the class. + /// + /// Name of the provider. + /// The name. + /// The provider user key. + /// The email. + /// The password question. + /// The comment. + /// if set to true [is approved]. + /// if set to true [is locked out]. + /// The creation date. + /// The last login date. + /// The last activity date. + /// The last password changed date. + /// The last lockout date. + /// The full name. + /// The language. + /// Type of the user. + /// + public UmbracoMembershipUser(string providerName, string name, object providerUserKey, string email, + string passwordQuestion, string comment, bool isApproved, bool isLockedOut, + DateTime creationDate, DateTime lastLoginDate, DateTime lastActivityDate, DateTime lastPasswordChangedDate, + DateTime lastLockoutDate, string fullName, string language, IUserType userType, T user) + : base( providerName, name, providerUserKey, email, passwordQuestion, comment, isApproved, isLockedOut, + creationDate, lastLoginDate, lastActivityDate, lastPasswordChangedDate, lastLockoutDate) + { + _user = user; + } + + #endregion + } +} \ No newline at end of file diff --git a/src/Umbraco.Core/Services/IMemberService.cs b/src/Umbraco.Core/Services/IMemberService.cs new file mode 100644 index 0000000000..1f792d63dc --- /dev/null +++ b/src/Umbraco.Core/Services/IMemberService.cs @@ -0,0 +1,7 @@ +namespace Umbraco.Core.Services +{ + internal interface IMemberService : IService + { + + } +} \ No newline at end of file diff --git a/src/Umbraco.Core/Services/IUserService.cs b/src/Umbraco.Core/Services/IUserService.cs index dea53e5612..34c3313f41 100644 --- a/src/Umbraco.Core/Services/IUserService.cs +++ b/src/Umbraco.Core/Services/IUserService.cs @@ -8,22 +8,6 @@ namespace Umbraco.Core.Services /// internal interface IUserService : IService { - /// - /// Gets an for the current BackOffice User - /// - /// HttpContext to fetch the user through - /// containing the Name and Id of the logged in BackOffice User - IProfile GetCurrentBackOfficeUser(HttpContextBase httpContext); - - /// - /// Gets an for the current BackOffice User. - /// - /// - /// Requests the current HttpContext, so this method will only work in a web context. - /// - /// containing the Name and Id of the logged in BackOffice User - IProfile GetCurrentBackOfficeUser(); - /// /// Gets an IProfile by User Id. /// diff --git a/src/Umbraco.Core/Services/MemberService.cs b/src/Umbraco.Core/Services/MemberService.cs new file mode 100644 index 0000000000..a977069045 --- /dev/null +++ b/src/Umbraco.Core/Services/MemberService.cs @@ -0,0 +1,30 @@ +using Umbraco.Core.Persistence; +using Umbraco.Core.Persistence.UnitOfWork; + +namespace Umbraco.Core.Services +{ + /// + /// Represents the MemberService. + /// + internal class MemberService : IMemberService + { + private readonly RepositoryFactory _repositoryFactory; + private readonly IDatabaseUnitOfWorkProvider _uowProvider; + + public MemberService(RepositoryFactory repositoryFactory) + : this(new PetaPocoUnitOfWorkProvider(), repositoryFactory) + { + } + + public MemberService(IDatabaseUnitOfWorkProvider provider) + : this(provider, new RepositoryFactory()) + { + } + + public MemberService(IDatabaseUnitOfWorkProvider provider, RepositoryFactory repositoryFactory) + { + _repositoryFactory = repositoryFactory; + _uowProvider = provider; + } + } +} \ No newline at end of file diff --git a/src/Umbraco.Core/Services/ServiceContext.cs b/src/Umbraco.Core/Services/ServiceContext.cs index dbd50d7677..d03307eaa5 100644 --- a/src/Umbraco.Core/Services/ServiceContext.cs +++ b/src/Umbraco.Core/Services/ServiceContext.cs @@ -14,6 +14,7 @@ namespace Umbraco.Core.Services { private Lazy _contentService; private Lazy _userService; + private Lazy _memberService; private Lazy _mediaService; private Lazy _contentTypeService; private Lazy _dataTypeService; @@ -56,6 +57,9 @@ namespace Umbraco.Core.Services if (_userService == null) _userService = new Lazy(() => new UserService(provider, repositoryFactory.Value)); + if (_memberService == null) + _memberService = new Lazy(() => new MemberService(provider, repositoryFactory.Value)); + if (_contentService == null) _contentService = new Lazy(() => new ContentService(provider, repositoryFactory.Value, publishingStrategy)); @@ -171,5 +175,13 @@ namespace Umbraco.Core.Services { get { return _userService.Value; } } + + /// + /// Gets the + /// + internal IMemberService MemberService + { + get { return _memberService.Value; } + } } } \ No newline at end of file diff --git a/src/Umbraco.Core/Services/UserService.cs b/src/Umbraco.Core/Services/UserService.cs index f7a73b9d78..f56fa55c6d 100644 --- a/src/Umbraco.Core/Services/UserService.cs +++ b/src/Umbraco.Core/Services/UserService.cs @@ -1,13 +1,13 @@ -using System; -using System.Web; +using System.Globalization; using Umbraco.Core.Models.Membership; +using Umbraco.Core.Models.Rdbms; using Umbraco.Core.Persistence; using Umbraco.Core.Persistence.UnitOfWork; namespace Umbraco.Core.Services { /// - /// Represents the UserService, which is an easy access to operations involving and eventually Users and Members. + /// Represents the UserService, which is an easy access to operations involving , and eventually Backoffice Users. /// internal class UserService : IUserService { @@ -28,69 +28,6 @@ namespace Umbraco.Core.Services #region Implementation of IUserService - /// - /// Gets an for the current BackOffice User. - /// - /// HttpContext to fetch the user through - /// containing the Name and Id of the logged in BackOffice User - public IProfile GetCurrentBackOfficeUser(HttpContextBase httpContext) - { - Mandate.That(httpContext != null, - () => - new ArgumentException( - "The HttpContext which is used to retrieve information about the currently logged in backoffice user was null and can therefor not be used", - "HttpContextBase")); - if (httpContext == null) return null; - - var cookie = httpContext.Request.Cookies["UMB_UCONTEXT"]; - Mandate.That(cookie != null, () => new ArgumentException("The Cookie containing the UserContext Guid Id was null", "Cookie")); - if (cookie == null) return null; - - string contextId = cookie.Value; - string cacheKey = string.Concat("UmbracoUserContext", contextId); - - int userId = 0; - - if(HttpRuntime.Cache[cacheKey] == null) - { - using (var uow = _uowProvider.GetUnitOfWork()) - { - userId = - uow.Database.ExecuteScalar( - "select userID from umbracoUserLogins where contextID = @ContextId", - new { ContextId = new Guid(contextId) }); - - HttpRuntime.Cache.Insert(cacheKey, userId, - null, - System.Web.Caching.Cache.NoAbsoluteExpiration, - new TimeSpan(0, (int)(Umbraco.Core.Configuration.GlobalSettings.TimeOutInMinutes / 10), 0)); - } - } - else - { - userId = (int) HttpRuntime.Cache[cacheKey]; - } - - var profile = GetProfileById(userId); - return profile; - } - - /// - /// Gets an for the current BackOffice User. - /// - /// - /// Requests the current HttpContext, so this method will only work in a web context. - /// - /// containing the Name and Id of the logged in BackOffice User - public IProfile GetCurrentBackOfficeUser() - { - var context = HttpContext.Current; - Mandate.That(context != null); - - var wrapper = new HttpContextWrapper(context); - return GetCurrentBackOfficeUser(wrapper); - } - /// /// Gets an IProfile by User Id. /// @@ -104,6 +41,35 @@ namespace Umbraco.Core.Services } } + public IMembershipUser CreateUser(string name, string login, string password, IUserType userType) + { + return CreateUser(name, login, password, userType.Id); + } + + public IMembershipUser CreateUser(string name, string login, string password, int userTypeId) + { + var uow = _uowProvider.GetUnitOfWork(); + using (var repository = _repositoryFactory.CreateUserRepository(uow)) + { + var dto = new UserDto + { + UserLanguage = Umbraco.Core.Configuration.GlobalSettings.DefaultUILanguage, + Login = login, + UserName = name, + Email = string.Empty, + Type = short.Parse(userTypeId.ToString(CultureInfo.InvariantCulture)), + ContentStartId = -1, + MediaStartId = -1, + Password = password + }; + + //TODO Check if user exists and throw? + uow.Database.Insert(dto); + + return new User(new UserType()); + } + } + #endregion } } \ No newline at end of file diff --git a/src/Umbraco.Core/Umbraco.Core.csproj b/src/Umbraco.Core/Umbraco.Core.csproj index 5e2d413292..f3f4f72b3b 100644 --- a/src/Umbraco.Core/Umbraco.Core.csproj +++ b/src/Umbraco.Core/Umbraco.Core.csproj @@ -64,6 +64,7 @@ + True @@ -195,6 +196,9 @@ + + + @@ -687,10 +691,12 @@ + +