diff --git a/src/Umbraco.Web/Security/MembershipHelper.cs b/src/Umbraco.Web/Security/MembershipHelper.cs
index fa00cb4105..4695a74154 100644
--- a/src/Umbraco.Web/Security/MembershipHelper.cs
+++ b/src/Umbraco.Web/Security/MembershipHelper.cs
@@ -73,7 +73,8 @@ namespace Umbraco.Web.Security
if (model.Email.InvariantEquals(membershipUser.Email) == false)
{
//Use the membership provider to change the email since that is configured to do the checks to check for unique emails if that is configured.
- membershipUser = UpdateMember(membershipUser, Membership.Provider, model.Email);
+ var requiresUpdating = UpdateMember(membershipUser, Membership.Provider, model.Email);
+ membershipUser = requiresUpdating.Result;
}
}
catch (Exception ex)
@@ -554,8 +555,7 @@ namespace Umbraco.Web.Security
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
///
@@ -563,55 +563,56 @@ namespace Umbraco.Web.Security
///
///
///
- ///
///
///
///
- ///
- internal MembershipUser UpdateMember(MembershipUser member, MembershipProvider provider,
+ ///
+ /// Returns successful if the membershipuser required updating, otherwise returns failed if it didn't require updating.
+ ///
+ internal Attempt UpdateMember(MembershipUser member, MembershipProvider provider,
string email = null,
bool? isApproved = null,
- bool? isLocked = null,
DateTime? lastLoginDate = null,
DateTime? lastActivityDate = null,
string comment = null)
{
+ var needsUpdating = false;
+
//set the writable properties
if (email != null)
{
+ needsUpdating = member.Email != email;
member.Email = email;
}
if (isApproved.HasValue)
{
+ needsUpdating = member.IsApproved != isApproved.Value;
member.IsApproved = isApproved.Value;
}
if (lastLoginDate.HasValue)
{
+ needsUpdating = member.LastLoginDate != lastLoginDate.Value;
member.LastLoginDate = lastLoginDate.Value;
}
if (lastActivityDate.HasValue)
{
+ needsUpdating = member.LastActivityDate != lastActivityDate.Value;
member.LastActivityDate = lastActivityDate.Value;
}
if (comment != null)
{
+ needsUpdating = member.Comment != comment;
member.Comment = comment;
}
- if (isLocked.HasValue)
+ //Don't persist anything if nothing has changed
+ if (needsUpdating)
{
- //there is no 'setter' on IsLockedOut but you can ctor a new membership user with it set, so i guess that's what we'll do,
- // this does mean however if it was a typed membership user object that it will no longer be typed
- //membershipUser.IsLockedOut = true;
- member = new MembershipUser(member.ProviderName, member.UserName,
- member.ProviderUserKey, member.Email, member.PasswordQuestion, member.Comment, member.IsApproved,
- isLocked.Value, //new value
- member.CreationDate, member.LastLoginDate, member.LastActivityDate, member.LastPasswordChangedDate, member.LastLockoutDate);
+ provider.UpdateUser(member);
+ return Attempt.Succeed(member);
}
- provider.UpdateUser(member);
-
- return member;
+ return Attempt.Fail(member);
}
///
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 a6bbebe8fe..4151c3cecd 100644
--- a/src/Umbraco.Web/umbraco.presentation/umbraco/members/EditMember.aspx.cs
+++ b/src/Umbraco.Web/umbraco.presentation/umbraco/members/EditMember.aspx.cs
@@ -1,12 +1,17 @@
using System;
+using System.Collections.Generic;
+using System.Linq;
using System.Configuration.Provider;
using System.Web;
using System.Web.UI;
using System.Web.UI.Design.WebControls;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
+using Umbraco.Core;
using Umbraco.Core.IO;
+using Umbraco.Core.Logging;
using Umbraco.Core.Security;
+using umbraco.interfaces;
using Umbraco.Web;
using Umbraco.Web.Security;
using umbraco.cms.businesslogic.member;
@@ -26,8 +31,8 @@ namespace umbraco.cms.presentation.members
}
protected uicontrols.TabView TabView1;
protected TextBox documentName;
- private Member _document;
- private MembershipUser _member;
+ private Member _memberEntity;
+ private MembershipUser _membershipUser;
ContentControl _contentControl;
protected uicontrols.UmbracoPanel m_MemberShipPanel = new uicontrols.UmbracoPanel();
@@ -42,7 +47,7 @@ namespace umbraco.cms.presentation.members
private MembershipHelper _membershipHelper;
- protected void Page_Load(object sender, EventArgs e)
+ protected override void OnLoad(EventArgs e)
{
_membershipHelper = new MembershipHelper(UmbracoContext.Current);
@@ -70,10 +75,10 @@ namespace umbraco.cms.presentation.members
if (Membership.Provider.IsUmbracoMembershipProvider())
{
- _document = new Member(int.Parse(Request.QueryString["id"]));
+ _memberEntity = new Member(int.Parse(Request.QueryString["id"]));
- _member = Membership.GetUser(_document.LoginName, false);
- _contentControl = new ContentControl(_document, ContentControl.publishModes.NoPublish, "TabView1");
+ _membershipUser = Membership.GetUser(_memberEntity.LoginName, false);
+ _contentControl = new ContentControl(_memberEntity, ContentControl.publishModes.NoPublish, "TabView1");
_contentControl.Width = Unit.Pixel(666);
_contentControl.Height = Unit.Pixel(666);
@@ -82,10 +87,13 @@ namespace umbraco.cms.presentation.members
plc.Controls.Add(_contentControl);
+ //once we add the content control, the controls are created, here we need to handle the islockedout property
+ HandleIsLockedOutProperty(_membershipUser.IsLockedOut);
+
if (!IsPostBack)
{
- MemberLoginNameTxt.Text = _document.LoginName;
- MemberEmail.Text = _document.Email;
+ MemberLoginNameTxt.Text = _memberEntity.LoginName;
+ MemberEmail.Text = _memberEntity.Email;
}
var ph = new PlaceHolder();
MemberLoginNameTxt.ID = "loginname";
@@ -124,15 +132,15 @@ namespace umbraco.cms.presentation.members
menuSave.Click += MenuSaveClick;
menuSave.AltText = ui.Text("buttons", "save", null);
- _member = Membership.GetUser(Request.QueryString["id"], false);
- MemberLoginNameTxt.Text = _member.UserName;
+ _membershipUser = Membership.GetUser(Request.QueryString["id"], false);
+ MemberLoginNameTxt.Text = _membershipUser.UserName;
if (IsPostBack == false)
{
- MemberEmail.Text = _member.Email;
+ MemberEmail.Text = _membershipUser.Email;
}
m_MemberShipPanel.Width = 300;
- m_MemberShipPanel.Text = ui.Text("edit") + " " + _member.UserName;
+ m_MemberShipPanel.Text = ui.Text("edit") + " " + _membershipUser.UserName;
var props = new uicontrols.Pane();
MemberLoginNameTxt.Enabled = false;
@@ -157,7 +165,7 @@ namespace umbraco.cms.presentation.members
if (IsPostBack == false)
{
- if (Roles.IsUserInRole(_member.UserName, role))
+ if (Roles.IsUserInRole(_membershipUser.UserName, role))
{
selectedMembers += role + ",";
}
@@ -183,7 +191,7 @@ namespace umbraco.cms.presentation.members
void MemberLoginNameExistCheck_ServerValidate(object source, ServerValidateEventArgs args)
{
- var oldLoginName = _document.LoginName.Replace(" ", "").ToLower();
+ var oldLoginName = _memberEntity.LoginName.Replace(" ", "").ToLower();
var newLoginName = MemberLoginNameTxt.Text.Replace(" ", "").ToLower();
if (oldLoginName != newLoginName && newLoginName != "" && Member.GetMemberFromLoginName(newLoginName) != null)
@@ -194,7 +202,7 @@ namespace umbraco.cms.presentation.members
void MemberEmailExistCheck_ServerValidate(object source, ServerValidateEventArgs args)
{
- var oldEmail = _document.Email.ToLower();
+ var oldEmail = _memberEntity.Email.ToLower();
var newEmail = MemberEmail.Text.ToLower();
var requireUniqueEmail = Membership.Provider.RequiresUniqueEmail;
@@ -221,6 +229,30 @@ namespace umbraco.cms.presentation.members
}
+ ///
+ /// This is a special case, we're going to check for the is locked out property, if it is found
+ /// and they are not locked out, we'll remove the check box since an admin can't actually lock a member out,
+ /// they lock themselves out. All an admin can do is disable a member. So this will swap the check box for a 'No' label.
+ ///
+ private void HandleIsLockedOutProperty(bool isLockedOut)
+ {
+ var lockedOutCtrl = _contentControl.FindControlRecursive("prop_" + Constants.Conventions.Member.IsLockedOut);
+ if (lockedOutCtrl != null)
+ {
+ var noLabel = lockedOutCtrl.Parent.FindControl("NoLabel");
+ if (noLabel == null)
+ {
+ noLabel = new Label() { Text = ui.Text("general", "no"), Visible = false, ID = "NoLabel" };
+ lockedOutCtrl.Parent.Controls.Add(noLabel);
+ }
+ if (isLockedOut == false)
+ {
+ lockedOutCtrl.Visible = false;
+ noLabel.Visible = true;
+ }
+ }
+ }
+
private void ChangePassword(passwordChanger passwordChangerControl, MembershipUser membershipUser, CustomValidator passwordChangerValidator)
{
//Change the password
@@ -245,11 +277,47 @@ namespace umbraco.cms.presentation.members
}
}
- private void UpdateMembershipProvider(MembershipUser membershipUser)
+ private bool UpdateWithMembershipProvider(MembershipUser membershipUser, string email, IDataType isApprovedDt, IDataType commentsDt, bool performUnlock)
{
var membershipHelper = new MembershipHelper(ApplicationContext, new HttpContextWrapper(Context));
//set the writable properties that we are editing
- membershipHelper.UpdateMember(membershipUser, Membership.Provider, MemberEmail.Text.Trim());
+
+ bool? isApproved = null;
+ if (isApprovedDt != null)
+ {
+ var tryApproved = isApprovedDt.Data.Value.TryConvertTo();
+ if (tryApproved)
+ {
+ isApproved = tryApproved.Result;
+ }
+ }
+
+ string comments = null;
+ if (commentsDt != null)
+ {
+ var tryComments = commentsDt.Data.Value.TryConvertTo();
+ if (tryComments)
+ {
+ comments = tryComments.Result;
+ }
+ }
+
+ var unlockSuccess = false;
+ if (performUnlock)
+ {
+ unlockSuccess = Membership.Provider.UnlockUser(membershipUser.UserName);
+ if (unlockSuccess == false)
+ {
+ LogHelper.Warn("Could not unlock the member " + membershipUser.UserName);
+ }
+ else
+ {
+ HandleIsLockedOutProperty(false);
+ }
+ }
+
+ return membershipHelper.UpdateMember(membershipUser, Membership.Provider, email, isApproved, comment: comments).Success
+ || unlockSuccess;
}
private void UpdateRoles(MembershipUser membershipUser)
@@ -284,44 +352,81 @@ namespace umbraco.cms.presentation.members
else
{
// hide validation summaries
+
if (Membership.Provider.IsUmbracoMembershipProvider())
- {
+ {
foreach (uicontrols.TabPage tp in _contentControl.GetPanels())
{
tp.ErrorControl.Visible = false;
}
+
+ var memberTypeProvider = (IUmbracoContentTypeMembershipProvider) Membership.Provider;
+
+ //update the membership provider
+ var commentsProp = _contentControl.DataTypes.GetValue(memberTypeProvider.CommentPropertyTypeAlias);
+ var approvedProp = _contentControl.DataTypes.GetValue(memberTypeProvider.ApprovedPropertyTypeAlias);
+ var lockedProp = _contentControl.DataTypes.GetValue(memberTypeProvider.LockPropertyTypeAlias);
+ var doUnlock = false;
+ if (lockedProp != null)
+ {
+ var tryGetLockedVal = lockedProp.Data.Value.TryConvertTo();
+ if (tryGetLockedVal)
+ {
+ doUnlock = _membershipUser.IsLockedOut && tryGetLockedVal.Result == false;
+ }
+ }
+
+ if (UpdateWithMembershipProvider(_membershipUser,
+ MemberEmail.Text.Trim(),
+ approvedProp,
+ commentsProp,
+ doUnlock))
+ {
+ //if an update was required we need to re-fetch the member
+ _memberEntity = new Member(_memberEntity.Id);
+ }
+
+ }
+ else
+ {
+ UpdateWithMembershipProvider(_membershipUser,
+ MemberEmail.Text.Trim(),
+ null, null,
+ false);
}
//Change the password
var passwordChangerControl = (passwordChanger)MemberPasswordTxt.Controls[0];
var passwordChangerValidator = (CustomValidator)MemberPasswordTxt.Controls[1].Controls[0].Controls[0];
- ChangePassword(passwordChangerControl, _member, passwordChangerValidator);
-
- //update the membership provider
- UpdateMembershipProvider(_member);
+ ChangePassword(passwordChangerControl, _membershipUser, passwordChangerValidator);
if (Membership.Provider.IsUmbracoMembershipProvider())
{
//Hrm, with the membership provider you cannot change the login name - I guess this will do that
// in the underlying data layer
- _document.LoginName = MemberLoginNameTxt.Text;
+ _memberEntity.LoginName = MemberLoginNameTxt.Text;
- UpdateRoles(_member);
+ UpdateRoles(_membershipUser);
+
+ //filter out all of the membership provider built-in properties, these should only be saved via the membership
+ // providers, not directly to our services
+ var builtInAliases = Constants.Conventions.Member.GetStandardPropertyTypeStubs().Select(x => x.Key).ToArray();
+ var filteredProperties = _contentControl.DataTypes.Where(x => builtInAliases.Contains(x.Key) == false);
//The value of the properties has been set on IData through IDataEditor in the ContentControl
//so we need to 'retrieve' that value and set it on the property of the new IContent object.
//NOTE This is a workaround for the legacy approach to saving values through the DataType instead of the Property
//- (The DataType shouldn't be responsible for saving the value - especically directly to the db).
- foreach (var item in _contentControl.DataTypes)
+ foreach (var item in filteredProperties)
{
- _document.getProperty(item.Key).Value = item.Value.Data.Value;
+ _memberEntity.getProperty(item.Key).Value = item.Value.Data.Value;
}
- _document.Save();
+ _memberEntity.Save();
}
else
{
- UpdateRoles(_member);
+ UpdateRoles(_membershipUser);
}
ClientTools.ShowSpeechBubble(speechBubbleIcon.save, ui.Text("speechBubbles", "editMemberSaved", UmbracoUser), "");
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 1df2c849a0..84b8f42e96 100644
--- a/src/Umbraco.Web/umbraco.presentation/umbraco/users/EditUser.aspx.cs
+++ b/src/Umbraco.Web/umbraco.presentation/umbraco/users/EditUser.aspx.cs
@@ -561,8 +561,7 @@ namespace umbraco.cms.presentation.user
//set the writable properties that we are editing
membershipHelper.UpdateMember(membershipUser, BackOfficeProvider,
email.Text.Trim(),
- Disabled.Checked == false,
- NoConsole.Checked);
+ Disabled.Checked == false);
}
}