diff --git a/src/Umbraco.Core/Models/ContentBase.cs b/src/Umbraco.Core/Models/ContentBase.cs
index f90e847289..011726e615 100644
--- a/src/Umbraco.Core/Models/ContentBase.cs
+++ b/src/Umbraco.Core/Models/ContentBase.cs
@@ -464,7 +464,7 @@ namespace Umbraco.Core.Models
/// also reset the dirty changes made to the content's Properties (user defined)
///
///
- internal override void ResetDirtyProperties(bool rememberPreviouslyChangedProperties)
+ public override void ResetDirtyProperties(bool rememberPreviouslyChangedProperties)
{
base.ResetDirtyProperties(rememberPreviouslyChangedProperties);
diff --git a/src/Umbraco.Core/Models/EntityBase/IRememberBeingDirty.cs b/src/Umbraco.Core/Models/EntityBase/IRememberBeingDirty.cs
index 94a88d312e..efebbd7c74 100644
--- a/src/Umbraco.Core/Models/EntityBase/IRememberBeingDirty.cs
+++ b/src/Umbraco.Core/Models/EntityBase/IRememberBeingDirty.cs
@@ -9,5 +9,6 @@
bool WasDirty();
bool WasPropertyDirty(string propertyName);
void ForgetPreviouslyDirtyProperties();
+ void ResetDirtyProperties(bool rememberPreviouslyChangedProperties);
}
}
\ No newline at end of file
diff --git a/src/Umbraco.Core/Models/EntityBase/TracksChangesEntityBase.cs b/src/Umbraco.Core/Models/EntityBase/TracksChangesEntityBase.cs
index dc65c583bc..cf34296281 100644
--- a/src/Umbraco.Core/Models/EntityBase/TracksChangesEntityBase.cs
+++ b/src/Umbraco.Core/Models/EntityBase/TracksChangesEntityBase.cs
@@ -108,7 +108,7 @@ namespace Umbraco.Core.Models.EntityBase
/// Please note that resetting the dirty properties could potentially
/// obstruct the saving of a new or updated entity.
///
- internal virtual void ResetDirtyProperties(bool rememberPreviouslyChangedProperties)
+ public virtual void ResetDirtyProperties(bool rememberPreviouslyChangedProperties)
{
if (rememberPreviouslyChangedProperties)
{
diff --git a/src/Umbraco.Core/Models/Macro.cs b/src/Umbraco.Core/Models/Macro.cs
index c754cab326..a0f0bd9651 100644
--- a/src/Umbraco.Core/Models/Macro.cs
+++ b/src/Umbraco.Core/Models/Macro.cs
@@ -172,7 +172,7 @@ namespace Umbraco.Core.Models
OnPropertyChanged(PropertiesSelector);
}
- internal override void ResetDirtyProperties(bool rememberPreviouslyChangedProperties)
+ public override void ResetDirtyProperties(bool rememberPreviouslyChangedProperties)
{
_addedProperties.Clear();
_removedProperties.Clear();
diff --git a/src/Umbraco.Core/Models/Membership/UserProfile.cs b/src/Umbraco.Core/Models/Membership/UserProfile.cs
index 1e3ab541e7..61a0d68ba7 100644
--- a/src/Umbraco.Core/Models/Membership/UserProfile.cs
+++ b/src/Umbraco.Core/Models/Membership/UserProfile.cs
@@ -133,7 +133,7 @@ namespace Umbraco.Core.Models.Membership
/// be flagged as dirty.
///
///
- internal override void ResetDirtyProperties(bool rememberPreviouslyChangedProperties)
+ public override void ResetDirtyProperties(bool rememberPreviouslyChangedProperties)
{
_addedSections.Clear();
_removedSections.Clear();
diff --git a/src/Umbraco.Web.UI.Client/src/common/services/util.service.js b/src/Umbraco.Web.UI.Client/src/common/services/util.service.js
index a66c3b549e..1fc040527a 100644
--- a/src/Umbraco.Web.UI.Client/src/common/services/util.service.js
+++ b/src/Umbraco.Web.UI.Client/src/common/services/util.service.js
@@ -221,12 +221,7 @@ function umbDataFormatter() {
});
saveModel.email = propEmail.value;
saveModel.username = propLogin.value;
- //NOTE: This would only be set for new members!
- if (angular.isString(propPass.value)) {
- // if we are resetting or changing passwords then that data will come from the property editor and
- // it's value will be an object not just a string.
- saveModel.password = propPass.value;
- }
+ saveModel.password = propPass.value;
return saveModel;
},
diff --git a/src/Umbraco.Web.UI.Client/src/views/member/edit.html b/src/Umbraco.Web.UI.Client/src/views/member/edit.html
index 3fccfda95d..5501ccb381 100644
--- a/src/Umbraco.Web.UI.Client/src/views/member/edit.html
+++ b/src/Umbraco.Web.UI.Client/src/views/member/edit.html
@@ -36,6 +36,7 @@
+
\ No newline at end of file
diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/changepassword/changepassword.controller.js b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/changepassword/changepassword.controller.js
index 9f60d300cd..e5d8739d51 100644
--- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/changepassword/changepassword.controller.js
+++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/changepassword/changepassword.controller.js
@@ -6,29 +6,44 @@ angular.module("umbraco").controller("Umbraco.PropertyEditors.ChangePasswordCont
//based on the membership provider cannot always be ported to js from .net directly.
/*
{
+ hasPassword: true/false,
requiresQuestionAnswer: true/false,
enableReset: true/false,
+ enablePasswordRetrieval: true/false,
minPasswordLength: 10
}
*/
//set defaults if they are not available
- if (!$scope.model.config || !$scope.model.config.requiresQuestionAnswer) {
+ if (!$scope.model.config || $scope.model.config.hasPassword === undefined) {
+ $scope.model.config.hasPassword = false;
+ }
+ if (!$scope.model.config || $scope.model.config.enablePasswordRetrieval === undefined) {
+ $scope.model.config.enablePasswordRetrieval = true;
+ }
+ if (!$scope.model.config || $scope.model.config.requiresQuestionAnswer === undefined) {
$scope.model.config.requiresQuestionAnswer = false;
}
- if (!$scope.model.config || !$scope.model.config.enableReset) {
+ if (!$scope.model.config || $scope.model.config.enableReset === undefined) {
$scope.model.config.enableReset = true;
}
- if (!$scope.model.config || !$scope.model.config.minPasswordLength) {
- $scope.model.config.minPasswordLength = 7;
+ if (!$scope.model.config || $scope.model.config.minPasswordLength === undefined) {
+ $scope.model.config.minPasswordLength = 0;
}
-
+ //set the model defaults - we never get supplied a password from the server so this is ok to overwrite.
+ $scope.model.value = {
+ newPassword: "",
+ oldPassword: null,
+ reset: null,
+ answer: null
+ };
+ //the value to compare to match passwords
$scope.confirm = "";
- $scope.hasPassword = $scope.model.value !== undefined && $scope.model.value !== null && $scope.model.value !== "";
-
- $scope.changing = !$scope.hasPassword;
+ //if there is no password saved for this entity , it must be new so we do not allow toggling of the change password, it is always there
+ //with validators turned on.
+ $scope.changing = !$scope.model.config.hasPassword;
$scope.doChange = function() {
$scope.changing = true;
diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/changepassword/changepassword.html b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/changepassword/changepassword.html
index c624a81cc2..fa67b50b53 100644
--- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/changepassword/changepassword.html
+++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/changepassword/changepassword.html
@@ -1,33 +1,58 @@
-
-
- Password changing or resetting is currently not supported
-
\ No newline at end of file
diff --git a/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj b/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj
index 9784c9e309..3b98328238 100644
--- a/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj
+++ b/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj
@@ -2167,7 +2167,6 @@
- Web.Template.configDesigner
diff --git a/src/Umbraco.Web/Editors/MemberController.cs b/src/Umbraco.Web/Editors/MemberController.cs
index a17817ced4..8ad5f68422 100644
--- a/src/Umbraco.Web/Editors/MemberController.cs
+++ b/src/Umbraco.Web/Editors/MemberController.cs
@@ -11,6 +11,8 @@ using System.Web.Security;
using AutoMapper;
using Examine.LuceneEngine.SearchCriteria;
using Examine.SearchCriteria;
+using Umbraco.Core;
+using Umbraco.Core.Logging;
using Umbraco.Core.Models;
using Umbraco.Core.Models.EntityBase;
using Umbraco.Web.WebApi;
@@ -21,7 +23,6 @@ using Umbraco.Web.WebApi.Filters;
using umbraco;
using Constants = Umbraco.Core.Constants;
using Examine;
-using Member = umbraco.cms.businesslogic.member.Member;
namespace Umbraco.Web.Editors
{
@@ -38,7 +39,7 @@ namespace Umbraco.Web.Editors
///
public MemberController()
: this(UmbracoContext.Current)
- {
+ {
}
///
@@ -57,7 +58,7 @@ namespace Umbraco.Web.Editors
///
public MemberDisplay GetByKey(Guid key)
{
- if (Member.InUmbracoMemberMode())
+ if (Membership.Provider.Name == Constants.Conventions.Member.UmbracoMemberProviderName)
{
var foundMember = Services.MemberService.GetByKey(key);
if (foundMember == null)
@@ -71,7 +72,7 @@ namespace Umbraco.Web.Editors
//TODO: Support this
throw new HttpResponseException(Request.CreateValidationErrorResponse("Editing member with a non-umbraco membership provider is currently not supported"));
}
-
+
}
///
@@ -118,7 +119,7 @@ namespace Umbraco.Web.Editors
//Unlike content/media - if there are errors for a member, we do NOT proceed to save them, we cannot so return the errors
if (ModelState.IsValid == false)
- {
+ {
var forDisplay = Mapper.Map(contentItem.PersistedContent);
forDisplay.Errors = ModelState.ToErrorDictionary();
throw new HttpResponseException(Request.CreateValidationErrorResponse(forDisplay));
@@ -135,7 +136,7 @@ namespace Umbraco.Web.Editors
switch (contentItem.Action)
{
case ContentSaveAction.Save:
- //TODO: Update with the provider! - change password, etc...
+ UpdateWithMembershipProvider(contentItem);
break;
case ContentSaveAction.SaveNew:
MembershipCreateStatus status;
@@ -144,7 +145,7 @@ namespace Umbraco.Web.Editors
default:
//we don't support anything else for members
throw new HttpResponseException(HttpStatusCode.NotFound);
- }
+ }
//If we've had problems creating/updating the user with the provider then return the error
if (ModelState.IsValid == false)
@@ -153,7 +154,7 @@ namespace Umbraco.Web.Editors
forDisplay.Errors = ModelState.ToErrorDictionary();
throw new HttpResponseException(Request.CreateValidationErrorResponse(forDisplay));
}
-
+
//save the item
//NOTE: We are setting the password to NULL - this indicates to the system to not actually save the password
// so it will not get overwritten!
@@ -196,6 +197,177 @@ namespace Umbraco.Web.Editors
base.MapPropertyValues(contentItem);
}
+ ///
+ /// Update the membership user using the membership provider (for things like email, etc...)
+ /// If a password change is detected then we'll try that too.
+ ///
+ ///
+ ///
+ ///
+ /// YES! It is completely insane how many options you have to take into account based on the membership provider. yikes!
+ ///
+ /// TODO: We need to update this method to return the new password if it has been reset and then show that to the UI!
+ ///
+ ///
+ private void UpdateWithMembershipProvider(MemberSave contentItem)
+ {
+ //Get the member from the provider
+ var membershipUser = Membership.Provider.GetUser(contentItem.PersistedContent.Username, false);
+ if (membershipUser == null)
+ {
+ //This should never happen! so we'll let it YSOD if it does.
+ throw new InvalidOperationException("Could not get member from membership provider " + Membership.Provider.Name + " with username " + contentItem.PersistedContent.Username);
+ }
+
+ //ok, first thing to do is check if they've changed their email
+ //TODO: When we support the other membership provider data then we'll check if any of that's changed too.
+ if (contentItem.Email.Trim().InvariantEquals(membershipUser.Email) == false)
+ {
+ membershipUser.Email = contentItem.Email.Trim();
+
+ try
+ {
+ Membership.Provider.UpdateUser(membershipUser);
+ }
+ catch (Exception ex)
+ {
+ LogHelper.WarnWithException("Could not update member, the provider returned an error", ex);
+ ModelState.AddPropertyError(
+ //specify 'default' just so that it shows up as a notification - is not assigned to a property
+ new ValidationResult("Could not update member, the provider returned an error: " + ex.Message + " (see log for full details)"), "default");
+ }
+ }
+
+ //password changes ?
+ if (contentItem.Password == null) return;
+
+ //Are we resetting the password??
+ if (contentItem.Password.Reset.HasValue && contentItem.Password.Reset.Value)
+ {
+ if (Membership.Provider.EnablePasswordReset == false)
+ {
+ ModelState.AddPropertyError(
+ new ValidationResult("Password reset is not enabled", new[] { "resetPassword" }),
+ string.Format("{0}password", Constants.PropertyEditors.InternalGenericPropertiesPrefix));
+ }
+ else if (Membership.Provider.RequiresQuestionAndAnswer && contentItem.Password.Answer.IsNullOrWhiteSpace())
+ {
+ ModelState.AddPropertyError(
+ new ValidationResult("Password reset requires a password answer", new[] {"resetPassword"}),
+ string.Format("{0}password", Constants.PropertyEditors.InternalGenericPropertiesPrefix));
+ }
+ else
+ {
+ //ok, we should be able to reset it
+ try
+ {
+ var newPass = Membership.Provider.ResetPassword(
+ membershipUser.UserName,
+ Membership.Provider.RequiresQuestionAndAnswer ? contentItem.Password.Answer : null);
+
+ //TODO: How do we show this new password to the front-end ???
+ }
+ catch (Exception ex)
+ {
+ LogHelper.WarnWithException("Could not reset member password", ex);
+ ModelState.AddPropertyError(
+ new ValidationResult("Could not reset password, error: " + ex.Message + " (see log for full details)", new[] {"resetPassword"}),
+ string.Format("{0}password", Constants.PropertyEditors.InternalGenericPropertiesPrefix));
+ }
+ }
+ }
+ else if (contentItem.Password.NewPassword.IsNullOrWhiteSpace() == false)
+ {
+ //we're not resetting it so we need to try to change it.
+
+ if (contentItem.Password.OldPassword.IsNullOrWhiteSpace() && Membership.Provider.EnablePasswordRetrieval == false)
+ {
+ //if password retrieval is not enabled but there is no old password we cannot continue
+
+ ModelState.AddPropertyError(
+ new ValidationResult("Password cannot be changed without the old password", new[] {"value"}),
+ string.Format("{0}password", Constants.PropertyEditors.InternalGenericPropertiesPrefix));
+ }
+ else if (contentItem.Password.OldPassword.IsNullOrWhiteSpace() == false)
+ {
+ //if an old password is suplied try to change it
+
+ try
+ {
+ var result = Membership.Provider.ChangePassword(membershipUser.UserName, contentItem.Password.OldPassword, contentItem.Password.NewPassword);
+ if (result == false)
+ {
+ ModelState.AddPropertyError(
+ new ValidationResult("Could not change password", new[] {"value"}),
+ string.Format("{0}password", Constants.PropertyEditors.InternalGenericPropertiesPrefix));
+ }
+ }
+ catch (Exception ex)
+ {
+ LogHelper.WarnWithException("Could not change member password", ex);
+ ModelState.AddPropertyError(
+ new ValidationResult("Could not change password, error: " + ex.Message + " (see log for full details)", new[] {"value"}),
+ string.Format("{0}password", Constants.PropertyEditors.InternalGenericPropertiesPrefix));
+ }
+ }
+ else if (Membership.Provider.EnablePasswordRetrieval == false)
+ {
+ //we cannot continue if we cannot get the current password
+
+ ModelState.AddPropertyError(
+ new ValidationResult("Password cannot be changed without the old password", new[] {"value"}),
+ string.Format("{0}password", Constants.PropertyEditors.InternalGenericPropertiesPrefix));
+ }
+ else if (Membership.Provider.RequiresQuestionAndAnswer && contentItem.Password.Answer.IsNullOrWhiteSpace())
+ {
+ //if the question answer is required but there isn't one, we cannot continue
+
+ ModelState.AddPropertyError(
+ new ValidationResult("Password cannot be changed without the password answer", new[] {"value"}),
+ string.Format("{0}password", Constants.PropertyEditors.InternalGenericPropertiesPrefix));
+
+ }
+ else
+ {
+ //lets try to get the old one so we can change it
+
+ try
+ {
+ var oldPassword = Membership.Provider.GetPassword(
+ membershipUser.UserName,
+ Membership.Provider.RequiresQuestionAndAnswer ? contentItem.Password.Answer : null);
+
+ try
+ {
+ var result = Membership.Provider.ChangePassword(membershipUser.UserName, oldPassword, contentItem.Password.NewPassword);
+ if (result == false)
+ {
+ ModelState.AddPropertyError(
+ new ValidationResult("Could not change password", new[] {"value"}),
+ string.Format("{0}password", Constants.PropertyEditors.InternalGenericPropertiesPrefix));
+ }
+ }
+ catch (Exception ex1)
+ {
+ LogHelper.WarnWithException("Could not change member password", ex1);
+ ModelState.AddPropertyError(
+ new ValidationResult("Could not change password, error: " + ex1.Message + " (see log for full details)", new[] { "value" }),
+ string.Format("{0}password", Constants.PropertyEditors.InternalGenericPropertiesPrefix));
+ }
+
+ }
+ catch (Exception ex2)
+ {
+ LogHelper.WarnWithException("Could not retrieve member password", ex2);
+ ModelState.AddPropertyError(
+ new ValidationResult("Could not change password, error: " + ex2.Message + " (see log for full details)", new[] { "value" }),
+ string.Format("{0}password", Constants.PropertyEditors.InternalGenericPropertiesPrefix));
+ }
+
+ }
+ }
+ }
+
///
/// This is going to create the user with the membership provider and check for validation
///
@@ -212,18 +384,20 @@ namespace Umbraco.Web.Editors
//TODO: I think we should detect if the Umbraco membership provider is active, if so then we'll create the member first and the provider key doesn't matter
// but if we are using a 3rd party membership provider - then we should create our IMember first and use it's key as their provider user key!
-
+
//NOTE: We are casting directly to the umbraco membership provider so we can specify the member type that we want to use!
-
+
var umbracoMembershipProvider = (global::umbraco.providers.members.UmbracoMembershipProvider)Membership.Provider;
var membershipUser = umbracoMembershipProvider.CreateUser(
- contentItem.ContentTypeAlias, contentItem.Username, contentItem.Password, contentItem.Email, "", "", true, Guid.NewGuid(), out status);
+ contentItem.ContentTypeAlias, contentItem.Username,
+ contentItem.Password.NewPassword,
+ contentItem.Email, "", "", true, Guid.NewGuid(), out status);
//TODO: Localize these!
switch (status)
{
case MembershipCreateStatus.Success:
-
+
//Go and re-fetch the persisted item
contentItem.PersistedContent = Services.MemberService.GetByUsername(contentItem.Username.Trim());
//remap the values to save
diff --git a/src/Umbraco.Web/Editors/MembershipProviderValidationFilterAttribute.cs b/src/Umbraco.Web/Editors/MembershipProviderValidationFilterAttribute.cs
index 8fbd226f0f..71943baea2 100644
--- a/src/Umbraco.Web/Editors/MembershipProviderValidationFilterAttribute.cs
+++ b/src/Umbraco.Web/Editors/MembershipProviderValidationFilterAttribute.cs
@@ -57,7 +57,7 @@ namespace Umbraco.Web.Editors
{
//they are changing their login name
if (existingByEmail.Cast().Select(x => x.UserName)
- .Any(x => x.InvariantEquals(contentItem.Username.Trim())))
+ .Any(x => x == contentItem.Username.Trim()))
{
//the user cannot use this login
return false;
@@ -67,7 +67,7 @@ namespace Umbraco.Web.Editors
case ContentSaveAction.SaveNew:
//check if the user's login already exists
if (existingByEmail.Cast().Select(x => x.UserName)
- .Any(x => x.InvariantEquals(contentItem.Username.Trim())))
+ .Any(x => x == contentItem.Username.Trim()))
{
//the user cannot use this login
return false;
diff --git a/src/Umbraco.Web/Models/ContentEditing/MemberPassword.cs b/src/Umbraco.Web/Models/ContentEditing/MemberPassword.cs
new file mode 100644
index 0000000000..3a1c67842c
--- /dev/null
+++ b/src/Umbraco.Web/Models/ContentEditing/MemberPassword.cs
@@ -0,0 +1,37 @@
+using System.Runtime.Serialization;
+
+namespace Umbraco.Web.Models.ContentEditing
+{
+ ///
+ /// A model representing the data required to set a member/user password depending on the provider installed.
+ ///
+ public class MemberPassword
+ {
+ ///
+ /// The password value
+ ///
+ ///
+ /// This
+ ///
+ [DataMember(Name = "newPassword")]
+ public string NewPassword { get; set; }
+
+ ///
+ /// The old password - used to change a password when: EnablePasswordRetrieval = false
+ ///
+ [DataMember(Name = "oldPassword")]
+ public string OldPassword { get; set; }
+
+ ///
+ /// Set to true if the password is to be reset - only valid when: EnablePasswordReset = true
+ ///
+ [DataMember(Name = "reset")]
+ public bool? Reset { get; set; }
+
+ ///
+ /// The password answer - required for reset when: RequiresQuestionAndAnswer = true
+ ///
+ [DataMember(Name = "answer")]
+ public string Answer { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Umbraco.Web/Models/ContentEditing/MemberSave.cs b/src/Umbraco.Web/Models/ContentEditing/MemberSave.cs
index 8de5f3647c..ace4d576f9 100644
--- a/src/Umbraco.Web/Models/ContentEditing/MemberSave.cs
+++ b/src/Umbraco.Web/Models/ContentEditing/MemberSave.cs
@@ -1,4 +1,5 @@
using System.Runtime.Serialization;
+using Newtonsoft.Json.Linq;
using Umbraco.Core.Models;
using Umbraco.Core.Models.Validation;
@@ -9,6 +10,11 @@ namespace Umbraco.Web.Models.ContentEditing
///
public class MemberSave : ContentBaseItemSave
{
+ public MemberSave()
+ {
+ Password = new MemberPassword();
+ }
+
[DataMember(Name = "username", IsRequired = true)]
[RequiredForPersistence(AllowEmptyStrings = false, ErrorMessage = "Required")]
public string Username { get; set; }
@@ -16,8 +22,8 @@ namespace Umbraco.Web.Models.ContentEditing
[DataMember(Name = "email", IsRequired = true)]
[RequiredForPersistence(AllowEmptyStrings = false, ErrorMessage = "Required")]
public string Email { get; set; }
-
- [DataMember(Name = "password")]
- public string Password { get; set; }
+
+ [DataMember(Name = "password")]
+ public MemberPassword Password { get; set; }
}
}
\ No newline at end of file
diff --git a/src/Umbraco.Web/Models/Mapping/MemberModelMapper.cs b/src/Umbraco.Web/Models/Mapping/MemberModelMapper.cs
index 37690321c9..da490d6f31 100644
--- a/src/Umbraco.Web/Models/Mapping/MemberModelMapper.cs
+++ b/src/Umbraco.Web/Models/Mapping/MemberModelMapper.cs
@@ -1,4 +1,5 @@
using System.Collections.Generic;
+using System.Web.Security;
using AutoMapper;
using Umbraco.Core;
using Umbraco.Core.Models;
@@ -66,6 +67,8 @@ namespace Umbraco.Web.Models.Mapping
///
private static void MapGenericCustomProperties(IMember member, MemberDisplay display)
{
+ var membershipProvider = Membership.Provider;
+
TabsAndPropertiesResolver.MapGenericProperties(
member, display,
new ContentPropertyDisplay
@@ -81,7 +84,17 @@ namespace Umbraco.Web.Models.Mapping
Alias = string.Format("{0}password", Constants.PropertyEditors.InternalGenericPropertiesPrefix),
Label = ui.Text("password"),
Value = "",
- View = "changepassword" //TODO: Hard coding this because the templatepicker doesn't necessarily need to be a resolvable (real) property editor
+ View = "changepassword",//TODO: Hard coding this because the templatepicker doesn't necessarily need to be a resolvable (real) property editor
+ Config = new Dictionary
+ {
+ //the password change toggle will only be displayed if there is already a password assigned.
+ { "hasPassword", member.Password.IsNullOrWhiteSpace() == false },
+ { "minPasswordLength", membershipProvider.MinRequiredPasswordLength },
+ { "enableReset", membershipProvider.EnablePasswordReset },
+ { "enablePasswordRetrieval" , membershipProvider.EnablePasswordRetrieval },
+ { "requiresQuestionAnswer", membershipProvider.RequiresQuestionAndAnswer }
+ //TODO: Inject the other parameters in here to change the behavior of this control - based on the membership provider settings.
+ }
},
new ContentPropertyDisplay
{
diff --git a/src/Umbraco.Web/Umbraco.Web.csproj b/src/Umbraco.Web/Umbraco.Web.csproj
index dbf529f4ce..e1747a481f 100644
--- a/src/Umbraco.Web/Umbraco.Web.csproj
+++ b/src/Umbraco.Web/Umbraco.Web.csproj
@@ -311,6 +311,7 @@
+
diff --git a/src/Umbraco.Web/WebApi/Binders/MemberBinder.cs b/src/Umbraco.Web/WebApi/Binders/MemberBinder.cs
index aabfdcb7b9..44499fd6b2 100644
--- a/src/Umbraco.Web/WebApi/Binders/MemberBinder.cs
+++ b/src/Umbraco.Web/WebApi/Binders/MemberBinder.cs
@@ -54,7 +54,7 @@ namespace Umbraco.Web.WebApi.Binders
}
//return the new member with the details filled in
- return new Member(model.Name, model.Email, model.Username, model.Password, -1, contentType);
+ return new Member(model.Name, model.Email, model.Username, model.Password.NewPassword, -1, contentType);
}
protected override ContentItemDto MapFromPersisted(MemberSave model)