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 ba7a04bee2..79e0e78410 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 @@ -230,6 +230,7 @@ function umbDataFormatter() { /** formats the display model used to display the member to the model used to save the member */ formatMemberPostData: function(displayModel, action) { //this is basically the same as for media but we need to explicitly add the username,email, password to the save model + var saveModel = this.formatMediaPostData(displayModel, action); saveModel.key = displayModel.key; @@ -238,6 +239,7 @@ function umbDataFormatter() { return item.id === 0; }); + //map the member login, email, password and groups var propLogin = _.find(genericTab.properties, function (item) { return item.alias === "_umb_login"; }); @@ -262,6 +264,33 @@ function umbDataFormatter() { } saveModel.memberGroups = selectedGroups; + //turn the dictionary into an array of pairs + var memberProviderPropAliases = _.pairs(displayModel.fieldConfig); + _.each(displayModel.tabs, function (tab) { + _.each(tab.properties, function (prop) { + var foundAlias = _.find(memberProviderPropAliases, function(item) { + return prop.alias === item[1]; + }); + if (foundAlias) { + //we know the current property matches an alias, now we need to determine which membership provider property it was for + // by looking at the key + switch (foundAlias[0]) { + case "umbracoLockPropertyTypeAlias": + saveModel.isLockedOut = prop.value.toString() === "1" ? true : false; + break; + case "umbracoApprovePropertyTypeAlias": + saveModel.isApproved = prop.value.toString() === "1" ? true : false; + break; + case "umbracoCommentPropertyTypeAlias": + saveModel.comments = prop.value; + break; + } + } + }); + }); + + + return saveModel; }, diff --git a/src/Umbraco.Web.UI/install/steps/DefaultUser.ascx.cs b/src/Umbraco.Web.UI/install/steps/DefaultUser.ascx.cs index 897bb9ad85..897fcb5e5e 100644 --- a/src/Umbraco.Web.UI/install/steps/DefaultUser.ascx.cs +++ b/src/Umbraco.Web.UI/install/steps/DefaultUser.ascx.cs @@ -19,10 +19,10 @@ namespace Umbraco.Web.UI.Install.Steps { get { - var provider = Membership.Providers[UmbracoSettings.DefaultBackofficeProvider]; + var provider = Membership.Providers[UmbracoConfig.For.UmbracoSettings().Providers.DefaultBackOfficeUserProvider]; if (provider == null) { - throw new InvalidOperationException("No MembershipProvider found with name " + UmbracoSettings.DefaultBackofficeProvider); + throw new InvalidOperationException("No MembershipProvider found with name " + UmbracoConfig.For.UmbracoSettings().Providers.DefaultBackOfficeUserProvider); } return provider; } diff --git a/src/Umbraco.Web/Editors/MemberController.cs b/src/Umbraco.Web/Editors/MemberController.cs index 9e5c9af152..e04ab40622 100644 --- a/src/Umbraco.Web/Editors/MemberController.cs +++ b/src/Umbraco.Web/Editors/MemberController.cs @@ -231,13 +231,6 @@ namespace Umbraco.Web.Editors /// /// 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 should move this logic to a central helper class so we can re-use it when it comes to integrating with WebSecurity - /// - /// private string UpdateWithMembershipProvider(MemberSave contentItem) { //Get the member from the provider @@ -249,14 +242,18 @@ namespace Umbraco.Web.Editors throw new InvalidOperationException("Could not get member from membership provider " + Membership.Provider.Name + " with key " + contentItem.PersistedContent.Key); } - //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) + var shouldReFetchMember = false; + + //Update the membership user if it has changed + if (HasMembershipUserChanged(membershipUser, contentItem)) { membershipUser.Email = contentItem.Email.Trim(); + membershipUser.IsApproved = contentItem.IsApproved; + membershipUser.Comment = contentItem.Comments; try { Membership.Provider.UpdateUser(membershipUser); + shouldReFetchMember = true; } catch (Exception ex) { @@ -267,12 +264,50 @@ namespace Umbraco.Web.Editors } } + //if they were locked but now they are trying to be unlocked + if (membershipUser.IsLockedOut && contentItem.IsLockedOut == false) + { + try + { + var result = Membership.Provider.UnlockUser(membershipUser.UserName); + if (result == false) + { + //it wasn't successful - but it won't really tell us why. + ModelState.AddModelError("custom", "Could not unlock the user"); + } + else + { + shouldReFetchMember = true; + } + } + catch (Exception ex) + { + ModelState.AddModelError("custom", ex); + } + } + else if (membershipUser.IsLockedOut == false && contentItem.IsLockedOut) + { + //NOTE: This should not ever happen unless someone is mucking around with the request data. + //An admin cannot simply lock a user, they get locked out by password attempts, but an admin can un-approve them + ModelState.AddModelError("custom", "An admin cannot lock a user"); + } + //password changes ? if (contentItem.Password == null) return null; var passwordChangeResult = Security.ChangePassword(membershipUser.UserName, contentItem.Password, Membership.Provider); if (passwordChangeResult.Success) { + //If the provider has changed some values, these values need to be reflected in the member object + //that will get mapped to the display object + if (shouldReFetchMember) + { + //Go and re-fetch the persisted item + contentItem.PersistedContent = Services.MemberService.GetByUsername(contentItem.Username.Trim()); + //remap the values to save + MapPropertyValues(contentItem); + } + //even if we weren't resetting this, it is the correct value (null), otherwise if we were resetting then it will contain the new pword return passwordChangeResult.Result.ResetPassword; } @@ -282,9 +317,30 @@ namespace Umbraco.Web.Editors passwordChangeResult.Result.ChangeError, string.Format("{0}password", Constants.PropertyEditors.InternalGenericPropertiesPrefix)); + return null; } + /// + /// Quick check to see if the 'normal' settable properties for the membership provider have changed + /// + /// + /// + /// + /// + /// By 'normal' we mean that they can simply be set on the membership user and don't require method calls like ChangePassword or UnlockUser + /// + private bool HasMembershipUserChanged(MembershipUser membershipUser, MemberSave contentItem) + { + if (contentItem.Email.Trim().InvariantEquals(membershipUser.Email) == false + || contentItem.IsApproved != membershipUser.IsApproved + || contentItem.Comments != membershipUser.Comment) + { + return true; + } + return false; + } + /// /// This is going to create the user with the membership provider and check for validation /// @@ -317,6 +373,13 @@ namespace Umbraco.Web.Editors { case MembershipCreateStatus.Success: + //if the comments are there then we need to save them + if (contentItem.Comments.IsNullOrWhiteSpace() == false) + { + membershipUser.Comment = contentItem.Comments; + umbracoMembershipProvider.UpdateUser(membershipUser); + } + //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/Models/ContentEditing/MemberDisplay.cs b/src/Umbraco.Web/Models/ContentEditing/MemberDisplay.cs index 32838d950a..89b62a3ad0 100644 --- a/src/Umbraco.Web/Models/ContentEditing/MemberDisplay.cs +++ b/src/Umbraco.Web/Models/ContentEditing/MemberDisplay.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; using System.Runtime.Serialization; using Umbraco.Core.Models; @@ -10,12 +11,24 @@ namespace Umbraco.Web.Models.ContentEditing [DataContract(Name = "content", Namespace = "")] public class MemberDisplay : ContentItemDisplayBase { + public MemberDisplay() + { + MemberProviderFieldMapping = new Dictionary(); + } [DataMember(Name = "username")] public string Username { get; set; } [DataMember(Name = "email")] public string Email { get; set; } + + /// + /// This is used to indicate how to map the membership provider properties to the save model, this mapping + /// will change if a developer has opted to have custom member property aliases specified in their membership provider config, + /// or if we are editing a member that is not an Umbraco member (custom provider) + /// + [DataMember(Name = "fieldConfig")] + public IDictionary MemberProviderFieldMapping { 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 545cde515f..cb376717c8 100644 --- a/src/Umbraco.Web/Models/ContentEditing/MemberSave.cs +++ b/src/Umbraco.Web/Models/ContentEditing/MemberSave.cs @@ -30,5 +30,16 @@ namespace Umbraco.Web.Models.ContentEditing [DataMember(Name = "memberGroups")] public IEnumerable Groups { get; set; } + + [DataMember(Name = "comments")] + public string Comments { get; set; } + + [DataMember(Name = "isLockedOut")] + public bool IsLockedOut { get; set; } + + [DataMember(Name = "isApproved")] + public bool IsApproved { get; set; } + + //TODO: Need to add question / answer support } } \ 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 d4b58334c3..d54bb079e2 100644 --- a/src/Umbraco.Web/Models/Mapping/MemberModelMapper.cs +++ b/src/Umbraco.Web/Models/Mapping/MemberModelMapper.cs @@ -34,10 +34,9 @@ namespace Umbraco.Web.Models.Mapping expression => expression.MapFrom(content => content.ContentType.Name)) .ForMember(display => display.Properties, expression => expression.Ignore()) .ForMember(display => display.Tabs, - expression => expression.ResolveUsing( - new TabsAndPropertiesResolver( - //do no map this properties (currently anyways, they were never there in 6.x) - Constants.Conventions.Member.StandardPropertyTypeStubs.Select(x => x.Value.Alias)))) + expression => expression.ResolveUsing()) + .ForMember(display => display.MemberProviderFieldMapping, + expression => expression.ResolveUsing()) .AfterMap(MapGenericCustomProperties); //FROM IMember TO ContentItemBasic @@ -162,7 +161,7 @@ namespace Umbraco.Web.Models.Mapping } /// - /// This ensures that the custom membership provider properties are not mapped (currently since they weren't there in v6) + /// This ensures that the custom membership provider properties are not mapped - these property values are controller by the membership provider /// /// /// Because these properties don't exist on the form, if we don't remove them for this map we'll get validation errors when posting data @@ -171,12 +170,76 @@ namespace Umbraco.Web.Models.Mapping { protected override IEnumerable ResolveCore(IMember source) { + //remove all membership properties, these values are set with the membership provider. var exclude = Constants.Conventions.Member.StandardPropertyTypeStubs.Select(x => x.Value.Alias).ToArray(); + return source.Properties .Where(x => exclude.Contains(x.Alias) == false) .Select(Mapper.Map); } } + /// + /// A custom tab/property resolver for members which will ensure that the built-in membership properties are or arent' displayed + /// depending on if the member type has these properties + /// + /// + /// This also ensures that the IsLocked out property is readonly when the member is not locked out - this is because + /// an admin cannot actually set isLockedOut = true, they can only unlock. + /// + internal class MemberTabsAndPropertiesResolver : TabsAndPropertiesResolver + { + protected override IEnumerable> ResolveCore(IContentBase content) + { + IgnoreProperties = content.PropertyTypes + .Where(x => x.HasIdentity == false) + .Select(x => x.Alias) + .ToArray(); + + var result = base.ResolveCore(content).ToArray(); + + if (Membership.Provider.Name != Constants.Conventions.Member.UmbracoMemberProviderName) + { + throw new NotSupportedException("Editing member with a non-umbraco membership provider is currently not supported"); + } + + var umbracoProvider = (global::umbraco.providers.members.UmbracoMembershipProvider) Membership.Provider; + + //This is kind of a hack because a developer is supposed to be allowed to set their property editor - would have been much easier + // if we just had all of the membeship provider fields on the member table :( + var isLockedOutProperty = result.SelectMany(x => x.Properties).FirstOrDefault(x => x.Alias == umbracoProvider.LockPropertyTypeAlias); + if (isLockedOutProperty != null && isLockedOutProperty.Value.ToString() != "1") + { + isLockedOutProperty.View = "readonlyvalue"; + isLockedOutProperty.Value = ui.Text("general", "no"); + } + + return result; + } + } + + /// + /// A resolver to map the provider field aliases + /// + internal class MemberProviderFieldMappingResolver : ValueResolver> + { + protected override IDictionary ResolveCore(IMember source) + { + if (Membership.Provider.Name != Constants.Conventions.Member.UmbracoMemberProviderName) + { + throw new NotSupportedException("Editing member with a non-umbraco membership provider is currently not supported"); + } + + var umbracoProvider = (global::umbraco.providers.members.UmbracoMembershipProvider) Membership.Provider; + + return new Dictionary + { + {Constants.Conventions.Member.IsLockedOut, umbracoProvider.LockPropertyTypeAlias}, + {Constants.Conventions.Member.IsApproved, umbracoProvider.ApprovedPropertyTypeAlias}, + {Constants.Conventions.Member.Comments, umbracoProvider.CommentPropertyTypeAlias} + }; + } + } + } } \ No newline at end of file diff --git a/src/Umbraco.Web/Models/Mapping/TabsAndPropertiesResolver.cs b/src/Umbraco.Web/Models/Mapping/TabsAndPropertiesResolver.cs index 9dd47259a6..62485daae6 100644 --- a/src/Umbraco.Web/Models/Mapping/TabsAndPropertiesResolver.cs +++ b/src/Umbraco.Web/Models/Mapping/TabsAndPropertiesResolver.cs @@ -15,17 +15,17 @@ namespace Umbraco.Web.Models.Mapping /// internal class TabsAndPropertiesResolver : ValueResolver>> { - private readonly IEnumerable _ignoreProperties; + protected IEnumerable IgnoreProperties { get; set; } public TabsAndPropertiesResolver() { - _ignoreProperties = new List(); + IgnoreProperties = new List(); } public TabsAndPropertiesResolver(IEnumerable ignoreProperties) { if (ignoreProperties == null) throw new ArgumentNullException("ignoreProperties"); - _ignoreProperties = ignoreProperties; + IgnoreProperties = ignoreProperties; } /// @@ -155,7 +155,7 @@ namespace Umbraco.Web.Models.Mapping var current = propertyGroups.Single(x => x.ParentId == currentParentId); var propsForGroup = content.GetPropertiesForGroup(current) - .Where(x => _ignoreProperties.Contains(x.Alias) == false); //don't include ignored props + .Where(x => IgnoreProperties.Contains(x.Alias) == false); //don't include ignored props aggregateProperties.AddRange( Mapper.Map, IEnumerable>( @@ -177,7 +177,7 @@ namespace Umbraco.Web.Models.Mapping //now add the generic properties tab for any properties that don't belong to a tab var orphanProperties = content.GetNonGroupedProperties() - .Where(x => _ignoreProperties.Contains(x.Alias) == false); //don't include ignored props + .Where(x => IgnoreProperties.Contains(x.Alias) == false); //don't include ignored props //now add the generic properties tab aggregateTabs.Add(new Tab diff --git a/src/Umbraco.Web/WebApi/Binders/ContentItemBaseBinder.cs b/src/Umbraco.Web/WebApi/Binders/ContentItemBaseBinder.cs index 2d374fc529..d9da950af7 100644 --- a/src/Umbraco.Web/WebApi/Binders/ContentItemBaseBinder.cs +++ b/src/Umbraco.Web/WebApi/Binders/ContentItemBaseBinder.cs @@ -190,7 +190,7 @@ namespace Umbraco.Web.WebApi.Binders /// private static void MapPropertyValuesFromSaved(TModelSave saveModel, ContentItemDto dto) { - foreach (var p in saveModel.Properties) + foreach (var p in saveModel.Properties.Where(p => dto.Properties.Any(x => x.Alias == p.Alias))) { dto.Properties.Single(x => x.Alias == p.Alias).Value = p.Value; } diff --git a/src/Umbraco.Web/WebApi/Binders/MemberBinder.cs b/src/Umbraco.Web/WebApi/Binders/MemberBinder.cs index f0650ef8b9..7ce147b894 100644 --- a/src/Umbraco.Web/WebApi/Binders/MemberBinder.cs +++ b/src/Umbraco.Web/WebApi/Binders/MemberBinder.cs @@ -28,17 +28,16 @@ namespace Umbraco.Web.WebApi.Binders protected override IMember GetExisting(MemberSave model) { - //TODO: We're going to remove the built-in member properties from this editor - We didn't support these in 6.x so - // pretty hard to support them in 7 when the member type editor is using the old APIs! - var toRemove = Constants.Conventions.Member.StandardPropertyTypeStubs.Select(x => x.Value.Alias).ToArray(); - var member = ApplicationContext.Services.MemberService.GetByKey(model.Key); if (member == null) { throw new InvalidOperationException("Could not find member with key " + model.Key); } - foreach (var remove in toRemove) + //remove all membership properties, these values are set with the membership provider. + var exclude = Constants.Conventions.Member.StandardPropertyTypeStubs.Select(x => x.Value.Alias).ToArray(); + + foreach (var remove in exclude) { member.Properties.Remove(remove); } @@ -52,11 +51,10 @@ namespace Umbraco.Web.WebApi.Binders { throw new InvalidOperationException("No member type found wth alias " + model.ContentTypeAlias); } - - //TODO: We're going to remove the built-in member properties from this editor - We didn't support these in 6.x so - // pretty hard to support them in 7 when the member type editor is using the old APIs! - var toRemove = Constants.Conventions.Member.StandardPropertyTypeStubs.Select(x => x.Value.Alias).ToArray(); - foreach (var remove in toRemove) + + //remove all membership properties, these values are set with the membership provider. + var exclude = Constants.Conventions.Member.StandardPropertyTypeStubs.Select(x => x.Value.Alias).ToArray(); + foreach (var remove in exclude) { contentType.RemovePropertyType(remove); } diff --git a/src/Umbraco.Web/WebApi/Filters/ContentItemValidationHelper.cs b/src/Umbraco.Web/WebApi/Filters/ContentItemValidationHelper.cs index 7875bfb076..fccbe9dc68 100644 --- a/src/Umbraco.Web/WebApi/Filters/ContentItemValidationHelper.cs +++ b/src/Umbraco.Web/WebApi/Filters/ContentItemValidationHelper.cs @@ -90,16 +90,16 @@ namespace Umbraco.Web.WebApi.Filters foreach (var p in postedItem.Properties) { - //if (propertyAliases.Contains(p.Alias) == false) - if (postedItem.PersistedContent.Properties[p.Alias] == null) + if (postedItem.PersistedContent.Properties.Contains(p.Alias)) { //TODO: Do we return errors here ? If someone deletes a property whilst their editing then should we just //save the property data that remains? Or inform them they need to reload... not sure. This problem exists currently too i think. var message = string.Format("property with alias: {0} was not found", p.Alias); actionContext.Response = actionContext.Request.CreateErrorResponse(HttpStatusCode.NotFound, new InvalidOperationException(message)); - return false; + return false; } + } return true; } diff --git a/src/umbraco.providers/members/MembersMembershipProvider.cs b/src/umbraco.providers/members/MembersMembershipProvider.cs index 578f1f0bc2..49139f5e74 100644 --- a/src/umbraco.providers/members/MembersMembershipProvider.cs +++ b/src/umbraco.providers/members/MembersMembershipProvider.cs @@ -45,7 +45,26 @@ namespace umbraco.providers.members private string _passwordRetrievalAnswerPropertyTypeAlias = Constants.Conventions.Member.PasswordAnswer; private string _providerName = Member.UmbracoMemberProviderName; + + //Need to expose these publicly so we know what field aliases to use in the editor, we only care about these 3 fields + // because they are the only 'settable' provider properties that are not stored against the IMember directly (i.e. they are + // property type properties). + public string LockPropertyTypeAlias + { + get { return _lockPropertyTypeAlias; } + } + + public string ApprovedPropertyTypeAlias + { + get { return _approvedPropertyTypeAlias; } + } + + public string CommentPropertyTypeAlias + { + get { return _commentPropertyTypeAlias; } + } + #endregion #region Initialization Method @@ -158,6 +177,8 @@ namespace umbraco.providers.members UpdateMemberProperty(m, _lastPasswordChangedPropertyTypeAlias, DateTime.Now); + m.Save(); + return true; } @@ -261,8 +282,8 @@ namespace umbraco.providers.members if (string.IsNullOrEmpty(_passwordRetrievalAnswerPropertyTypeAlias) == false) UpdateMemberProperty(m, _passwordRetrievalAnswerPropertyTypeAlias, passwordAnswer); - if (string.IsNullOrEmpty(_approvedPropertyTypeAlias) == false) - UpdateMemberProperty(m, _approvedPropertyTypeAlias, isApproved ? 1 : 0); + if (string.IsNullOrEmpty(ApprovedPropertyTypeAlias) == false) + UpdateMemberProperty(m, ApprovedPropertyTypeAlias, isApproved ? 1 : 0); if (string.IsNullOrEmpty(_lastLoginPropertyTypeAlias) == false) { @@ -439,10 +460,10 @@ namespace umbraco.providers.members if (string.IsNullOrEmpty(_passwordRetrievalAnswerPropertyTypeAlias) == false) { // check if user is locked out - if (string.IsNullOrEmpty(_lockPropertyTypeAlias) == false) + if (string.IsNullOrEmpty(LockPropertyTypeAlias) == false) { var isLockedOut = false; - bool.TryParse(GetMemberProperty(m, _lockPropertyTypeAlias, true), out isLockedOut); + bool.TryParse(GetMemberProperty(m, LockPropertyTypeAlias, true), out isLockedOut); if (isLockedOut) { throw new MembershipPasswordException("The supplied user is locked out"); @@ -567,10 +588,10 @@ namespace umbraco.providers.members if (string.IsNullOrEmpty(_passwordRetrievalAnswerPropertyTypeAlias) == false) { // check if user is locked out - if (string.IsNullOrEmpty(_lockPropertyTypeAlias) == false) + if (string.IsNullOrEmpty(LockPropertyTypeAlias) == false) { var isLockedOut = false; - bool.TryParse(GetMemberProperty(m, _lockPropertyTypeAlias, true), out isLockedOut); + bool.TryParse(GetMemberProperty(m, LockPropertyTypeAlias, true), out isLockedOut); if (isLockedOut) { throw new MembershipPasswordException("The supplied user is locked out"); @@ -600,6 +621,8 @@ namespace umbraco.providers.members UpdateMemberProperty(m, _lastPasswordChangedPropertyTypeAlias, DateTime.Now); } + m.Save(); + return newPassword; } @@ -612,12 +635,13 @@ namespace umbraco.providers.members /// public override bool UnlockUser(string userName) { - if (string.IsNullOrEmpty(_lockPropertyTypeAlias) == false) + if (string.IsNullOrEmpty(LockPropertyTypeAlias) == false) { var m = Member.GetMemberFromLoginName(userName); if (m != null) { - UpdateMemberProperty(m, _lockPropertyTypeAlias, 0); + UpdateMemberProperty(m, LockPropertyTypeAlias, 0); + m.Save(); return true; } throw new Exception(String.Format("No member with the username '{0}' found", userName)); @@ -635,17 +659,17 @@ namespace umbraco.providers.members m.Email = user.Email; // if supported, update approve status - UpdateMemberProperty(m, _approvedPropertyTypeAlias, user.IsApproved ? 1 : 0); + UpdateMemberProperty(m, ApprovedPropertyTypeAlias, user.IsApproved ? 1 : 0); // if supported, update lock status - UpdateMemberProperty(m, _lockPropertyTypeAlias, user.IsLockedOut ? 1 : 0); + UpdateMemberProperty(m, LockPropertyTypeAlias, user.IsLockedOut ? 1 : 0); if (user.IsLockedOut) { UpdateMemberProperty(m, _lastLockedOutPropertyTypeAlias, DateTime.Now); } // if supported, update comment - UpdateMemberProperty(m, _commentPropertyTypeAlias, user.Comment); + UpdateMemberProperty(m, CommentPropertyTypeAlias, user.Comment); m.Save(); } @@ -713,9 +737,9 @@ namespace umbraco.providers.members if (m != null) { // check for lock status. If locked, then set the member property to null - if (string.IsNullOrEmpty(_lockPropertyTypeAlias) == false) + if (string.IsNullOrEmpty(LockPropertyTypeAlias) == false) { - string lockedStatus = GetMemberProperty(m, _lockPropertyTypeAlias, true); + string lockedStatus = GetMemberProperty(m, LockPropertyTypeAlias, true); if (string.IsNullOrEmpty(lockedStatus) == false) { var isLocked = false; @@ -750,7 +774,7 @@ namespace umbraco.providers.members if (m != null) m.Save(); } - else if (string.IsNullOrEmpty(_lockPropertyTypeAlias) == false + else if (string.IsNullOrEmpty(LockPropertyTypeAlias) == false && string.IsNullOrEmpty(_failedPasswordAttemptsPropertyTypeAlias) == false) { var updateMemberDataObject = Member.GetMemberFromLoginName(username); @@ -765,7 +789,7 @@ namespace umbraco.providers.members // lock user? if (failedAttempts >= MaxInvalidPasswordAttempts) { - UpdateMemberProperty(updateMemberDataObject, _lockPropertyTypeAlias, 1); + UpdateMemberProperty(updateMemberDataObject, LockPropertyTypeAlias, 1); UpdateMemberProperty(updateMemberDataObject, _lastLockedOutPropertyTypeAlias, DateTime.Now); } updateMemberDataObject.Save(); @@ -778,11 +802,11 @@ namespace umbraco.providers.members private bool CheckApproveStatus(Member m) { var isApproved = false; - if (string.IsNullOrEmpty(_approvedPropertyTypeAlias) == false) + if (string.IsNullOrEmpty(ApprovedPropertyTypeAlias) == false) { if (m != null) { - var approveStatus = GetMemberProperty(m, _approvedPropertyTypeAlias, true); + var approveStatus = GetMemberProperty(m, ApprovedPropertyTypeAlias, true); if (string.IsNullOrEmpty(approveStatus) == false) { bool.TryParse(approveStatus, out isApproved); @@ -869,14 +893,14 @@ namespace umbraco.providers.members DateTime.TryParse(GetMemberProperty(m, _lastLoginPropertyTypeAlias, false), out lastLogin); } // approved - if (string.IsNullOrEmpty(_approvedPropertyTypeAlias) == false) + if (string.IsNullOrEmpty(ApprovedPropertyTypeAlias) == false) { - bool.TryParse(GetMemberProperty(m, _approvedPropertyTypeAlias, true), out isApproved); + bool.TryParse(GetMemberProperty(m, ApprovedPropertyTypeAlias, true), out isApproved); } // locked - if (string.IsNullOrEmpty(_lockPropertyTypeAlias) == false) + if (string.IsNullOrEmpty(LockPropertyTypeAlias) == false) { - bool.TryParse(GetMemberProperty(m, _lockPropertyTypeAlias, true), out isLocked); + bool.TryParse(GetMemberProperty(m, LockPropertyTypeAlias, true), out isLocked); } // last locked if (string.IsNullOrEmpty(_lastLockedOutPropertyTypeAlias) == false) @@ -884,9 +908,9 @@ namespace umbraco.providers.members DateTime.TryParse(GetMemberProperty(m, _lastLockedOutPropertyTypeAlias, false), out lastLocked); } // comment - if (string.IsNullOrEmpty(_commentPropertyTypeAlias) == false) + if (string.IsNullOrEmpty(CommentPropertyTypeAlias) == false) { - comment = GetMemberProperty(m, _commentPropertyTypeAlias, false); + comment = GetMemberProperty(m, CommentPropertyTypeAlias, false); } // password question if (string.IsNullOrEmpty(_passwordRetrievalQuestionPropertyTypeAlias) == false) @@ -920,14 +944,14 @@ namespace umbraco.providers.members DateTime.TryParse(GetMemberProperty(m, _lastLoginPropertyTypeAlias, false), out lastLogin); } // approved - if (string.IsNullOrEmpty(_approvedPropertyTypeAlias) == false) + if (string.IsNullOrEmpty(ApprovedPropertyTypeAlias) == false) { - bool.TryParse(GetMemberProperty(m, _approvedPropertyTypeAlias, true), out isApproved); + bool.TryParse(GetMemberProperty(m, ApprovedPropertyTypeAlias, true), out isApproved); } // locked - if (string.IsNullOrEmpty(_lockPropertyTypeAlias) == false) + if (string.IsNullOrEmpty(LockPropertyTypeAlias) == false) { - bool.TryParse(GetMemberProperty(m, _lockPropertyTypeAlias, true), out isLocked); + bool.TryParse(GetMemberProperty(m, LockPropertyTypeAlias, true), out isLocked); } // last locked if (string.IsNullOrEmpty(_lastLockedOutPropertyTypeAlias) == false) @@ -935,9 +959,9 @@ namespace umbraco.providers.members DateTime.TryParse(GetMemberProperty(m, _lastLockedOutPropertyTypeAlias, false), out lastLocked); } // comment - if (string.IsNullOrEmpty(_commentPropertyTypeAlias) == false) + if (string.IsNullOrEmpty(CommentPropertyTypeAlias) == false) { - comment = GetMemberProperty(m, _commentPropertyTypeAlias, false); + comment = GetMemberProperty(m, CommentPropertyTypeAlias, false); } // password question if (string.IsNullOrEmpty(_passwordRetrievalQuestionPropertyTypeAlias) == false)