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 5dab4f62e7..0c879d0164 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 @@ -32,13 +32,23 @@ angular.module("umbraco").controller("Umbraco.PropertyEditors.ChangePasswordCont $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 - }; + //set the model defaults + if (!angular.isObject($scope.model.value)) { + //if it's not an object then just create a new one + $scope.model.value = { + newPassword: "", + oldPassword: null, + reset: null, + answer: null + }; + } + else { + //just reset the values we need to + $scope.model.value.newPassword = ""; + $scope.model.value.oldPassword = null; + $scope.model.value.reset = null; + $scope.model.value.answer = null; + } //the value to compare to match passwords $scope.model.confirm = ""; @@ -52,6 +62,8 @@ angular.module("umbraco").controller("Umbraco.PropertyEditors.ChangePasswordCont $scope.doChange = function() { $scope.changing = true; + //if there was a previously generated password displaying, clear it + $scope.model.value.generatedPassword = null; }; $scope.cancelChange = function() { @@ -64,4 +76,5 @@ angular.module("umbraco").controller("Umbraco.PropertyEditors.ChangePasswordCont $scope.changing = false; resetModel(); }); + }); 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 e73757e382..ca6ef1ce71 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,6 +1,13 @@ 
- Change password + +
+ Password has been reset to: +
+ {{model.value.generatedPassword}} +
+ + Change password
@@ -53,6 +60,6 @@
- Cancel + Cancel \ No newline at end of file diff --git a/src/Umbraco.Web/Editors/MemberController.cs b/src/Umbraco.Web/Editors/MemberController.cs index 47d02e11cb..fb36cfeca6 100644 --- a/src/Umbraco.Web/Editors/MemberController.cs +++ b/src/Umbraco.Web/Editors/MemberController.cs @@ -131,12 +131,13 @@ namespace Umbraco.Web.Editors throw new NotSupportedException("Currently the member editor does not support providers that have RequiresQuestionAndAnswer specified"); } + string generatedPassword = null; //Depending on the action we need to first do a create or update using the membership provider // this ensures that passwords are formatted correclty and also performs the validation on the provider itself. switch (contentItem.Action) { case ContentSaveAction.Save: - UpdateWithMembershipProvider(contentItem); + generatedPassword = UpdateWithMembershipProvider(contentItem); break; case ContentSaveAction.SaveNew: MembershipCreateStatus status; @@ -163,9 +164,14 @@ namespace Umbraco.Web.Editors //create/save the IMember Services.MemberService.Save(contentItem.PersistedContent); + //set the generated password (if there was one) - in order to do this we'll chuck the gen'd password into the + // additional data of the IUmbracoEntity of the persisted item - then we can retreive this in the model mapper and set + // the value to be given to the UI. Hooray for AdditionalData :) + contentItem.PersistedContent.AdditionalData["GeneratedPassword"] = generatedPassword; + //return the updated model var display = Mapper.Map(contentItem.PersistedContent); - + //lasty, if it is not valid, add the modelstate to the outgoing object and throw a 403 HandleInvalidModelState(display); @@ -202,16 +208,17 @@ namespace Umbraco.Web.Editors /// If a password change is detected then we'll try that too. /// /// + /// + /// If the password has been reset then this method will return the reset/generated password, otherwise will return null. + /// /// /// - /// 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! + /// YES! It is completely insane how many options you have to take into account based on the membership provider. yikes! /// /// TODO We should move this logic to a central helper class so we can re-use it when it comes to integrating with WebSecurity /// /// - private void UpdateWithMembershipProvider(MemberSave contentItem) + private string UpdateWithMembershipProvider(MemberSave contentItem) { //Get the member from the provider var membershipUser = Membership.Provider.GetUser(contentItem.PersistedContent.Username, false); @@ -241,7 +248,7 @@ namespace Umbraco.Web.Editors } //password changes ? - if (contentItem.Password == null) return; + if (contentItem.Password == null) return null; //Are we resetting the password?? if (contentItem.Password.Reset.HasValue && contentItem.Password.Reset.Value) @@ -267,7 +274,8 @@ namespace Umbraco.Web.Editors membershipUser.UserName, Membership.Provider.RequiresQuestionAndAnswer ? contentItem.Password.Answer : null); - //TODO: How do we show this new password to the front-end ??? + //return the generated pword + return newPass; } catch (Exception ex) { @@ -368,6 +376,7 @@ namespace Umbraco.Web.Editors } } + return null; } /// diff --git a/src/Umbraco.Web/Models/ContentEditing/EntityBasic.cs b/src/Umbraco.Web/Models/ContentEditing/EntityBasic.cs index 8c3513e6e1..cbdecb0ca7 100644 --- a/src/Umbraco.Web/Models/ContentEditing/EntityBasic.cs +++ b/src/Umbraco.Web/Models/ContentEditing/EntityBasic.cs @@ -23,6 +23,9 @@ namespace Umbraco.Web.Models.ContentEditing [DataMember(Name = "icon")] public string Icon { get; set; } + /// + /// This is the unique Id stored in the database - but could also be the unique id for a custom membership provider + /// [DataMember(Name = "key")] public Guid Key { get; set; } diff --git a/src/Umbraco.Web/Models/ContentEditing/MemberDisplay.cs b/src/Umbraco.Web/Models/ContentEditing/MemberDisplay.cs index 48c6a43322..32838d950a 100644 --- a/src/Umbraco.Web/Models/ContentEditing/MemberDisplay.cs +++ b/src/Umbraco.Web/Models/ContentEditing/MemberDisplay.cs @@ -16,12 +16,6 @@ namespace Umbraco.Web.Models.ContentEditing [DataMember(Name = "email")] public string Email { get; set; } - - /// - /// This is the unique Id stored in the database - but could also be the unique id for a custom membership provider - /// - [DataMember(Name = "key")] - public Guid Key { get; set; } - + } } \ No newline at end of file diff --git a/src/Umbraco.Web/Models/ContentEditing/MemberPassword.cs b/src/Umbraco.Web/Models/ContentEditing/MemberPassword.cs index 3a1c67842c..a6867b5778 100644 --- a/src/Umbraco.Web/Models/ContentEditing/MemberPassword.cs +++ b/src/Umbraco.Web/Models/ContentEditing/MemberPassword.cs @@ -33,5 +33,11 @@ namespace Umbraco.Web.Models.ContentEditing /// [DataMember(Name = "answer")] public string Answer { get; set; } + + /// + /// This is filled in on the server side if the password has been reset/generated + /// + [DataMember(Name = "generatedPassword")] + public string GeneratedPassword { 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 da490d6f31..8ead3f2b11 100644 --- a/src/Umbraco.Web/Models/Mapping/MemberModelMapper.cs +++ b/src/Umbraco.Web/Models/Mapping/MemberModelMapper.cs @@ -77,22 +77,27 @@ namespace Umbraco.Web.Models.Mapping Label = ui.Text("login"), Value = display.Username, View = "textbox", - Config = new Dictionary { { "IsRequired", true } } + Config = new Dictionary {{"IsRequired", true}} }, new ContentPropertyDisplay { 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 + //NOTE: The value here is a json value - but the only property we care about is the generatedPassword one if it exists - this is the only value we'll ever supply to the front-end + Value = new Dictionary + { + {"generatedPassword", member.AdditionalData.ContainsKey("GeneratedPassword") ? member.AdditionalData["GeneratedPassword"] : null} + }, + //TODO: Hard coding this because the changepassword doesn't necessarily need to be a resolvable (real) property editor + View = "changepassword", 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 } + {"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. } },