diff --git a/src/Umbraco.Core/Configuration/ClientDependencyConfiguration.cs b/src/Umbraco.Core/Configuration/ClientDependencyConfiguration.cs index 2ba3c26523..9f7ec8083c 100644 --- a/src/Umbraco.Core/Configuration/ClientDependencyConfiguration.cs +++ b/src/Umbraco.Core/Configuration/ClientDependencyConfiguration.cs @@ -29,6 +29,7 @@ namespace Umbraco.Core.Configuration var versionAttribute = clientDependencyConfigXml.Root.Attribute("version"); //Set the new version to the hashcode of now + var oldVersion = versionAttribute.Value; var newVersion = DateTime.UtcNow.GetHashCode(); versionAttribute.SetValue(newVersion); diff --git a/src/Umbraco.Web/Security/MembershipHelper.cs b/src/Umbraco.Web/Security/MembershipHelper.cs index 24acddaaba..e2477dcd03 100644 --- a/src/Umbraco.Web/Security/MembershipHelper.cs +++ b/src/Umbraco.Web/Security/MembershipHelper.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; using System.Linq; using System.Text; using System.Web; @@ -368,6 +369,156 @@ namespace Umbraco.Web.Security return allowAction; } + /// + /// Changes password for a member/user given the membership provider name and the password change model + /// + /// + /// + /// + /// + public Attempt ChangePassword(string username, ChangingPasswordModel passwordModel, string membershipProviderName) + { + var provider = Membership.Providers[membershipProviderName]; + if (provider == null) + { + throw new InvalidOperationException("Could not find provider with name " + membershipProviderName); + } + return ChangePassword(username, passwordModel, provider); + } + + /// + /// Changes password for a member/user given the membership provider and the password change model + /// + /// + /// + /// + /// + public Attempt ChangePassword(string username, ChangingPasswordModel passwordModel, MembershipProvider membershipProvider) + { + // YES! It is completely insane how many options you have to take into account based on the membership provider. yikes! + + if (passwordModel == null) throw new ArgumentNullException("passwordModel"); + if (membershipProvider == null) throw new ArgumentNullException("membershipProvider"); + + //Are we resetting the password?? + if (passwordModel.Reset.HasValue && passwordModel.Reset.Value) + { + if (membershipProvider.EnablePasswordReset == false) + { + return Attempt.Fail(new PasswordChangedModel { ChangeError = new ValidationResult("Password reset is not enabled", new[] { "resetPassword" }) }); + } + if (membershipProvider.RequiresQuestionAndAnswer && passwordModel.Answer.IsNullOrWhiteSpace()) + { + return Attempt.Fail(new PasswordChangedModel { ChangeError = new ValidationResult("Password reset requires a password answer", new[] { "resetPassword" }) }); + } + //ok, we should be able to reset it + try + { + var newPass = membershipProvider.ResetPassword( + username, + membershipProvider.RequiresQuestionAndAnswer ? passwordModel.Answer : null); + + //return the generated pword + return Attempt.Succeed(new PasswordChangedModel { ResetPassword = newPass }); + } + catch (Exception ex) + { + LogHelper.WarnWithException("Could not reset member password", ex); + return Attempt.Fail(new PasswordChangedModel { ChangeError = new ValidationResult("Could not reset password, error: " + ex.Message + " (see log for full details)", new[] { "resetPassword" }) }); + } + } + + //we're not resetting it so we need to try to change it. + + if (passwordModel.NewPassword.IsNullOrWhiteSpace()) + { + return Attempt.Fail(new PasswordChangedModel { ChangeError = new ValidationResult("Cannot set an empty password", new[] { "value" }) }); + } + + //This is an edge case and is only necessary for backwards compatibility: + var umbracoBaseProvider = membershipProvider as MembershipProviderBase; + if (umbracoBaseProvider != null && umbracoBaseProvider.AllowManuallyChangingPassword) + { + //this provider allows manually changing the password without the old password, so we can just do it + try + { + var result = umbracoBaseProvider.ChangePassword(username, "", passwordModel.NewPassword); + return result == false + ? Attempt.Fail(new PasswordChangedModel { ChangeError = new ValidationResult("Could not change password, invalid username or password", new[] { "value" }) }) + : Attempt.Succeed(new PasswordChangedModel()); + } + catch (Exception ex) + { + LogHelper.WarnWithException("Could not change member password", ex); + return Attempt.Fail(new PasswordChangedModel { ChangeError = new ValidationResult("Could not change password, error: " + ex.Message + " (see log for full details)", new[] { "value" }) }); + } + } + + //The provider does not support manually chaning the password but no old password supplied - need to return an error + if (passwordModel.OldPassword.IsNullOrWhiteSpace() && membershipProvider.EnablePasswordRetrieval == false) + { + //if password retrieval is not enabled but there is no old password we cannot continue + return Attempt.Fail(new PasswordChangedModel { ChangeError = new ValidationResult("Password cannot be changed without the old password", new[] { "value" }) }); + } + + if (passwordModel.OldPassword.IsNullOrWhiteSpace() == false) + { + //if an old password is suplied try to change it + + try + { + var result = membershipProvider.ChangePassword(username, passwordModel.OldPassword, passwordModel.NewPassword); + return result == false + ? Attempt.Fail(new PasswordChangedModel { ChangeError = new ValidationResult("Could not change password, invalid username or password", new[] { "value" }) }) + : Attempt.Succeed(new PasswordChangedModel()); + } + catch (Exception ex) + { + LogHelper.WarnWithException("Could not change member password", ex); + return Attempt.Fail(new PasswordChangedModel { ChangeError = new ValidationResult("Could not change password, error: " + ex.Message + " (see log for full details)", new[] { "value" }) }); + } + } + + if (membershipProvider.EnablePasswordRetrieval == false) + { + //we cannot continue if we cannot get the current password + return Attempt.Fail(new PasswordChangedModel { ChangeError = new ValidationResult("Password cannot be changed without the old password", new[] { "value" }) }); + } + if (membershipProvider.RequiresQuestionAndAnswer && passwordModel.Answer.IsNullOrWhiteSpace()) + { + //if the question answer is required but there isn't one, we cannot continue + return Attempt.Fail(new PasswordChangedModel { ChangeError = new ValidationResult("Password cannot be changed without the password answer", new[] { "value" }) }); + } + + //lets try to get the old one so we can change it + try + { + var oldPassword = membershipProvider.GetPassword( + username, + membershipProvider.RequiresQuestionAndAnswer ? passwordModel.Answer : null); + + try + { + var result = membershipProvider.ChangePassword(username, oldPassword, passwordModel.NewPassword); + return result == false + ? Attempt.Fail(new PasswordChangedModel { ChangeError = new ValidationResult("Could not change password", new[] { "value" }) }) + : Attempt.Succeed(new PasswordChangedModel()); + } + catch (Exception ex1) + { + LogHelper.WarnWithException("Could not change member password", ex1); + return Attempt.Fail(new PasswordChangedModel { ChangeError = new ValidationResult("Could not change password, error: " + ex1.Message + " (see log for full details)", new[] { "value" }) }); + } + + } + catch (Exception ex2) + { + LogHelper.WarnWithException("Could not retrieve member password", ex2); + return Attempt.Fail(new PasswordChangedModel { ChangeError = new ValidationResult("Could not change password, error: " + ex2.Message + " (see log for full details)", new[] { "value" }) }); + } + } + + /// /// Updates a membership user with all of it's writable properties /// diff --git a/src/Umbraco.Web/Security/WebSecurity.cs b/src/Umbraco.Web/Security/WebSecurity.cs index 94d62ba56f..fc60987563 100644 --- a/src/Umbraco.Web/Security/WebSecurity.cs +++ b/src/Umbraco.Web/Security/WebSecurity.cs @@ -138,141 +138,7 @@ namespace Umbraco.Web.Security var membershipProvider = Membership.Providers[UmbracoSettings.DefaultBackofficeProvider]; return membershipProvider != null && membershipProvider.ValidateUser(username, password); } - - //TODO: This could be moved to the MembershipHelper since it's dealing with any membership provider password change - /// - /// Changes password for a member/user given the membership provider and the password change model - /// - /// - /// - /// - /// - /// - /// YES! It is completely insane how many options you have to take into account based on the membership provider. yikes! - /// - internal Attempt ChangePassword(string username, ChangingPasswordModel passwordModel, MembershipProvider membershipProvider) - { - if (passwordModel == null) throw new ArgumentNullException("passwordModel"); - if (membershipProvider == null) throw new ArgumentNullException("membershipProvider"); - - //Are we resetting the password?? - if (passwordModel.Reset.HasValue && passwordModel.Reset.Value) - { - if (membershipProvider.EnablePasswordReset == false) - { - return Attempt.Fail(new PasswordChangedModel { ChangeError = new ValidationResult("Password reset is not enabled", new[] { "resetPassword" }) }); - } - if (membershipProvider.RequiresQuestionAndAnswer && passwordModel.Answer.IsNullOrWhiteSpace()) - { - return Attempt.Fail(new PasswordChangedModel { ChangeError = new ValidationResult("Password reset requires a password answer", new[] { "resetPassword" }) }); - } - //ok, we should be able to reset it - try - { - var newPass = membershipProvider.ResetPassword( - username, - membershipProvider.RequiresQuestionAndAnswer ? passwordModel.Answer : null); - - //return the generated pword - return Attempt.Succeed(new PasswordChangedModel { ResetPassword = newPass }); - } - catch (Exception ex) - { - LogHelper.WarnWithException("Could not reset member password", ex); - return Attempt.Fail(new PasswordChangedModel { ChangeError = new ValidationResult("Could not reset password, error: " + ex.Message + " (see log for full details)", new[] { "resetPassword" }) }); - } - } - - //we're not resetting it so we need to try to change it. - - if (passwordModel.NewPassword.IsNullOrWhiteSpace()) - { - return Attempt.Fail(new PasswordChangedModel { ChangeError = new ValidationResult("Cannot set an empty password", new[] { "value" }) }); - } - - //This is an edge case and is only necessary for backwards compatibility: - var umbracoBaseProvider = membershipProvider as MembershipProviderBase; - if (umbracoBaseProvider != null && umbracoBaseProvider.AllowManuallyChangingPassword) - { - //this provider allows manually changing the password without the old password, so we can just do it - try - { - var result = umbracoBaseProvider.ChangePassword(username, "", passwordModel.NewPassword); - return result == false - ? Attempt.Fail(new PasswordChangedModel { ChangeError = new ValidationResult("Could not change password, invalid username or password", new[] { "value" }) }) - : Attempt.Succeed(new PasswordChangedModel()); - } - catch (Exception ex) - { - LogHelper.WarnWithException("Could not change member password", ex); - return Attempt.Fail(new PasswordChangedModel { ChangeError = new ValidationResult("Could not change password, error: " + ex.Message + " (see log for full details)", new[] { "value" }) }); - } - } - - //The provider does not support manually chaning the password but no old password supplied - need to return an error - if (passwordModel.OldPassword.IsNullOrWhiteSpace() && membershipProvider.EnablePasswordRetrieval == false) - { - //if password retrieval is not enabled but there is no old password we cannot continue - return Attempt.Fail(new PasswordChangedModel { ChangeError = new ValidationResult("Password cannot be changed without the old password", new[] { "value" }) }); - } - - if (passwordModel.OldPassword.IsNullOrWhiteSpace() == false) - { - //if an old password is suplied try to change it - - try - { - var result = membershipProvider.ChangePassword(username, passwordModel.OldPassword, passwordModel.NewPassword); - return result == false - ? Attempt.Fail(new PasswordChangedModel { ChangeError = new ValidationResult("Could not change password, invalid username or password", new[] { "value" }) }) - : Attempt.Succeed(new PasswordChangedModel()); - } - catch (Exception ex) - { - LogHelper.WarnWithException("Could not change member password", ex); - return Attempt.Fail(new PasswordChangedModel { ChangeError = new ValidationResult("Could not change password, error: " + ex.Message + " (see log for full details)", new[] { "value" }) }); - } - } - - if (membershipProvider.EnablePasswordRetrieval == false) - { - //we cannot continue if we cannot get the current password - return Attempt.Fail(new PasswordChangedModel { ChangeError = new ValidationResult("Password cannot be changed without the old password", new[] { "value" }) }); - } - if (membershipProvider.RequiresQuestionAndAnswer && passwordModel.Answer.IsNullOrWhiteSpace()) - { - //if the question answer is required but there isn't one, we cannot continue - return Attempt.Fail(new PasswordChangedModel { ChangeError = new ValidationResult("Password cannot be changed without the password answer", new[] { "value" }) }); - } - - //lets try to get the old one so we can change it - try - { - var oldPassword = membershipProvider.GetPassword( - username, - membershipProvider.RequiresQuestionAndAnswer ? passwordModel.Answer : null); - - try - { - var result = membershipProvider.ChangePassword(username, oldPassword, passwordModel.NewPassword); - return result == false - ? Attempt.Fail(new PasswordChangedModel { ChangeError = new ValidationResult("Could not change password", new[] { "value" }) }) - : Attempt.Succeed(new PasswordChangedModel()); - } - catch (Exception ex1) - { - LogHelper.WarnWithException("Could not change member password", ex1); - return Attempt.Fail(new PasswordChangedModel { ChangeError = new ValidationResult("Could not change password, error: " + ex1.Message + " (see log for full details)", new[] { "value" }) }); - } - - } - catch (Exception ex2) - { - LogHelper.WarnWithException("Could not retrieve member password", ex2); - return Attempt.Fail(new PasswordChangedModel { ChangeError = new ValidationResult("Could not change password, error: " + ex2.Message + " (see log for full details)", new[] { "value" }) }); - } - } - + /// /// Validates the user node tree permissions. /// diff --git a/src/Umbraco.Web/umbraco.presentation/umbraco/members/EditMember.aspx.cs b/src/Umbraco.Web/umbraco.presentation/umbraco/members/EditMember.aspx.cs index 9fb012f9ca..0164612526 100644 --- a/src/Umbraco.Web/umbraco.presentation/umbraco/members/EditMember.aspx.cs +++ b/src/Umbraco.Web/umbraco.presentation/umbraco/members/EditMember.aspx.cs @@ -40,8 +40,11 @@ namespace umbraco.cms.presentation.members protected CustomValidator MemberEmailExistCheck = new CustomValidator(); protected DualSelectbox _memberGroups = new DualSelectbox(); + private MembershipHelper _membershipHelper; + protected void Page_Load(object sender, EventArgs e) { + _membershipHelper = new MembershipHelper(UmbracoContext.Current); // Add password changer var passwordChanger = (passwordChanger)LoadControl(SystemDirectories.Umbraco + "/controls/passwordChanger.ascx"); @@ -223,7 +226,7 @@ namespace umbraco.cms.presentation.members if (passwordChangerControl.IsChangingPassword) { - var changePassResult = UmbracoContext.Current.Security.ChangePassword( + var changePassResult = _membershipHelper.ChangePassword( membershipUser.UserName, passwordChangerControl.ChangingPasswordModel, Membership.Provider); if (changePassResult.Success) diff --git a/src/Umbraco.Web/umbraco.presentation/umbraco/users/EditUser.aspx.cs b/src/Umbraco.Web/umbraco.presentation/umbraco/users/EditUser.aspx.cs index 50d4a5d8dd..efc7e525fc 100644 --- a/src/Umbraco.Web/umbraco.presentation/umbraco/users/EditUser.aspx.cs +++ b/src/Umbraco.Web/umbraco.presentation/umbraco/users/EditUser.aspx.cs @@ -69,6 +69,8 @@ namespace umbraco.cms.presentation.user private User u; + private MembershipHelper _membershipHelper; + private MembershipProvider BackOfficeProvider { get @@ -84,7 +86,7 @@ namespace umbraco.cms.presentation.user protected void Page_Load(object sender, EventArgs e) { - + _membershipHelper = new MembershipHelper(UmbracoContext.Current); int UID = int.Parse(Request.QueryString["id"]); u = BusinessLogic.User.GetUser(UID); @@ -451,7 +453,7 @@ namespace umbraco.cms.presentation.user } //now do the actual change - var changePassResult = UmbracoContext.Current.Security.ChangePassword( + var changePassResult = _membershipHelper.ChangePassword( membershipUser.UserName, changePasswordModel, BackOfficeProvider); if (changePassResult.Success)