Fixes ability to reset your own password in the user section

This commit is contained in:
Shannon
2017-09-04 20:15:46 +10:00
parent 0e0ab81155
commit a0306f9d55
8 changed files with 41 additions and 10 deletions

View File

@@ -5,7 +5,10 @@
bool KeepUserLoggedIn { get; }
bool HideDisabledUsersInBackoffice { get; }
/// <summary>
/// Used to enable/disable the forgot password functionality on the back office login screen
/// </summary>
bool AllowPasswordReset { get; }
string AuthCookieName { get; }

View File

@@ -16,6 +16,9 @@ namespace Umbraco.Core.Configuration.UmbracoSettings
get { return GetOptionalTextElement("hideDisabledUsersInBackoffice", false); }
}
/// <summary>
/// Used to enable/disable the forgot password functionality on the back office login screen
/// </summary>
[ConfigurationProperty("allowPasswordReset")]
internal InnerTextConfigurationElement<bool> AllowPasswordReset
{
@@ -44,6 +47,9 @@ namespace Umbraco.Core.Configuration.UmbracoSettings
get { return HideDisabledUsersInBackoffice; }
}
/// <summary>
/// Used to enable/disable the forgot password functionality on the back office login screen
/// </summary>
bool ISecuritySection.AllowPasswordReset
{
get { return AllowPasswordReset; }

View File

@@ -18,6 +18,9 @@ namespace Umbraco.Core.Security
/// <param name="provider"></param>
/// <param name="userService"></param>
/// <returns></returns>
/// <remarks>
/// An Admin can always reset the password
/// </remarks>
internal static bool CanResetPassword(this MembershipProvider provider, IUserService userService)
{
if (provider == null) throw new ArgumentNullException("provider");

View File

@@ -119,7 +119,7 @@ angular.module("umbraco")
$scope.changePasswordModel.config = data;
//ensure the hasPassword config option is set to true (the user of course has a password already assigned)
//this will ensure the oldPassword is shown so they can change it
// disable reset password functionality beacuse it does not make sense inside the backoffice
// disable reset password functionality beacuse it does not make sense for the current user.
$scope.changePasswordModel.config.hasPassword = true;
$scope.changePasswordModel.config.disableToggle = true;
$scope.changePasswordModel.config.enableReset = false;

View File

@@ -78,6 +78,9 @@
vm.changePasswordModel.config.hasPassword = vm.user.userState !== 3 && vm.user.userState !== 4;
vm.changePasswordModel.config.disableToggle = true;
//if it's the current user then disable password reset since that doesn't make sense.
vm.changePasswordModel.config.enableReset = !vm.user.isCurrentUser;
vm.loading = false;
});

View File

@@ -90,7 +90,7 @@ namespace Umbraco.Web.Editors
public async Task<ModelWithNotifications<string>> PostChangePassword(ChangingPasswordModel data)
{
var passwordChanger = new PasswordChanger(Logger, Services.UserService);
var passwordChangeResult = await passwordChanger.ChangePasswordWithIdentityAsync(Security.CurrentUser, data, ModelState, UserManager);
var passwordChangeResult = await passwordChanger.ChangePasswordWithIdentityAsync(Security.CurrentUser, Security.CurrentUser, data, ModelState, UserManager);
if (passwordChangeResult.Success)
{

View File

@@ -27,9 +27,19 @@ namespace Umbraco.Web.Editors
_logger = logger;
_userService = userService;
}
/// <summary>
/// Changes the password for a user based on the many different rules and config options
/// </summary>
/// <param name="currentUser">The user performing the password save action</param>
/// <param name="savingUser">The user who's password is being changed</param>
/// <param name="passwordModel"></param>
/// <param name="modelState"></param>
/// <param name="userMgr"></param>
/// <returns></returns>
public async Task<Attempt<PasswordChangedModel>> ChangePasswordWithIdentityAsync(
IUser currentUser,
IUser savingUser,
ChangingPasswordModel passwordModel,
ModelStateDictionary modelState,
BackOfficeUserManager<BackOfficeIdentityUser> userMgr)
@@ -48,7 +58,7 @@ namespace Umbraco.Web.Editors
//if this isn't using an IUserAwarePasswordHasher, then fallback to the old way
if (membershipPasswordHasher.MembershipProvider.RequiresQuestionAndAnswer)
throw new NotSupportedException("Currently the user editor does not support providers that have RequiresQuestionAndAnswer specified");
return ChangePasswordWithMembershipProvider(currentUser.Username, passwordModel, membershipPasswordHasher.MembershipProvider);
return ChangePasswordWithMembershipProvider(savingUser.Username, passwordModel, membershipPasswordHasher.MembershipProvider);
}
//if we are here, then a IUserAwarePasswordHasher is available, however we cannot proceed in that case if for some odd reason
@@ -62,10 +72,16 @@ namespace Umbraco.Web.Editors
//Are we resetting the password??
if (passwordModel.Reset.HasValue && passwordModel.Reset.Value)
{
//if it's the current user, the current user cannot reset their own password
if (currentUser.Username == savingUser.Username)
{
return Attempt.Fail(new PasswordChangedModel { ChangeError = new ValidationResult("Password reset is not allowed", new[] { "resetPassword" }) });
}
//ok, we should be able to reset it
var resetToken = await userMgr.GeneratePasswordResetTokenAsync(currentUser.Id);
var resetToken = await userMgr.GeneratePasswordResetTokenAsync(savingUser.Id);
var newPass = userMgr.GeneratePassword();
var resetResult = await userMgr.ResetPasswordAsync(currentUser.Id, resetToken, newPass);
var resetResult = await userMgr.ResetPasswordAsync(savingUser.Id, resetToken, newPass);
if (resetResult.Succeeded == false)
{
@@ -95,7 +111,7 @@ namespace Umbraco.Web.Editors
if (passwordModel.OldPassword.IsNullOrWhiteSpace() == false)
{
//if an old password is suplied try to change it
var changeResult = await userMgr.ChangePasswordAsync(currentUser.Id, passwordModel.OldPassword, passwordModel.NewPassword);
var changeResult = await userMgr.ChangePasswordAsync(savingUser.Id, passwordModel.OldPassword, passwordModel.NewPassword);
if (changeResult.Succeeded == false)
{
var errors = string.Join(". ", changeResult.Errors);
@@ -112,7 +128,7 @@ namespace Umbraco.Web.Editors
/// <summary>
/// Changes password for a member/user given the membership provider and the password change model
/// </summary>
/// <param name="username"></param>
/// <param name="username">The username of the user having their password changed</param>
/// <param name="passwordModel"></param>
/// <param name="membershipProvider"></param>
/// <returns></returns>

View File

@@ -522,7 +522,7 @@ namespace Umbraco.Web.Editors
{
var passwordChanger = new PasswordChanger(Logger, Services.UserService);
var passwordChangeResult = await passwordChanger.ChangePasswordWithIdentityAsync(found, userSave.ChangePassword, ModelState, UserManager);
var passwordChangeResult = await passwordChanger.ChangePasswordWithIdentityAsync(Security.CurrentUser, found, userSave.ChangePassword, ModelState, UserManager);
if (passwordChangeResult.Success)
{
//depending on how the provider is configured, the password may be reset so let's store that for later