Gets password resetting working and displaying the generated one in the UI.

This commit is contained in:
Shannon
2013-10-11 12:25:10 +11:00
parent b63135771e
commit b9975ad1f5
7 changed files with 69 additions and 32 deletions

View File

@@ -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();
});
});

View File

@@ -1,6 +1,13 @@
<div ng-controller="Umbraco.PropertyEditors.ChangePasswordController" ng-switch="changing">
<div ng-switch-when="false">
<a href="" ng-click="doChange()" class="text-info">Change password</a>
<div class="alert alert-success text-center" ng-hide="!model.value.generatedPassword">
<small>Password has been reset to:</small>
<br/>
<strong>{{model.value.generatedPassword}}</strong>
</div>
<a href="" ng-click="doChange()" class="btn btn-small">Change password</a>
</div>
<div ng-switch-when="true">
@@ -53,6 +60,6 @@
</div>
</div>
<a href="" ng-click="cancelChange()" ng-show="model.config.hasPassword" class="text-warning">Cancel</a>
<a href="" ng-click="cancelChange()" ng-show="model.config.hasPassword" class="btn btn-small">Cancel</a>
</div>
</div>

View File

@@ -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<IMember, MemberDisplay>(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.
/// </summary>
/// <param name="contentItem"></param>
/// <returns>
/// If the password has been reset then this method will return the reset/generated password, otherwise will return null.
/// </returns>
/// <remarks>
///
/// 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
///
/// </remarks>
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;
}
/// <summary>

View File

@@ -23,6 +23,9 @@ namespace Umbraco.Web.Models.ContentEditing
[DataMember(Name = "icon")]
public string Icon { get; set; }
/// <summary>
/// This is the unique Id stored in the database - but could also be the unique id for a custom membership provider
/// </summary>
[DataMember(Name = "key")]
public Guid Key { get; set; }

View File

@@ -16,12 +16,6 @@ namespace Umbraco.Web.Models.ContentEditing
[DataMember(Name = "email")]
public string Email { get; set; }
/// <summary>
/// This is the unique Id stored in the database - but could also be the unique id for a custom membership provider
/// </summary>
[DataMember(Name = "key")]
public Guid Key { get; set; }
}
}

View File

@@ -33,5 +33,11 @@ namespace Umbraco.Web.Models.ContentEditing
/// </summary>
[DataMember(Name = "answer")]
public string Answer { get; set; }
/// <summary>
/// This is filled in on the server side if the password has been reset/generated
/// </summary>
[DataMember(Name = "generatedPassword")]
public string GeneratedPassword { get; set; }
}
}

View File

@@ -77,22 +77,27 @@ namespace Umbraco.Web.Models.Mapping
Label = ui.Text("login"),
Value = display.Username,
View = "textbox",
Config = new Dictionary<string, object> { { "IsRequired", true } }
Config = new Dictionary<string, object> {{"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<string, object>
{
{"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<string, object>
{
//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.
}
},