diff --git a/src/Umbraco.Core/Migrations/Install/DatabaseDataCreator.cs b/src/Umbraco.Core/Migrations/Install/DatabaseDataCreator.cs index f0e6dd2e5b..1de983636b 100644 --- a/src/Umbraco.Core/Migrations/Install/DatabaseDataCreator.cs +++ b/src/Umbraco.Core/Migrations/Install/DatabaseDataCreator.cs @@ -226,6 +226,8 @@ namespace Umbraco.Core.Migrations.Install _database.Insert(Constants.DatabaseSchema.Tables.PropertyType, "id", false, new PropertyTypeDto { Id = 32, UniqueId = 32.ToGuid(), DataTypeId = Constants.DataTypes.LabelDateTime, ContentTypeId = 1044, PropertyTypeGroupId = 11, Alias = Constants.Conventions.Member.LastLockoutDate, Name = Constants.Conventions.Member.LastLockoutDateLabel, SortOrder = 4, Mandatory = false, ValidationRegExp = null, Description = null, Variations = (byte) ContentVariation.Nothing }); _database.Insert(Constants.DatabaseSchema.Tables.PropertyType, "id", false, new PropertyTypeDto { Id = 33, UniqueId = 33.ToGuid(), DataTypeId = Constants.DataTypes.LabelDateTime, ContentTypeId = 1044, PropertyTypeGroupId = 11, Alias = Constants.Conventions.Member.LastLoginDate, Name = Constants.Conventions.Member.LastLoginDateLabel, SortOrder = 5, Mandatory = false, ValidationRegExp = null, Description = null, Variations = (byte) ContentVariation.Nothing }); _database.Insert(Constants.DatabaseSchema.Tables.PropertyType, "id", false, new PropertyTypeDto { Id = 34, UniqueId = 34.ToGuid(), DataTypeId = Constants.DataTypes.LabelDateTime, ContentTypeId = 1044, PropertyTypeGroupId = 11, Alias = Constants.Conventions.Member.LastPasswordChangeDate, Name = Constants.Conventions.Member.LastPasswordChangeDateLabel, SortOrder = 6, Mandatory = false, ValidationRegExp = null, Description = null, Variations = (byte) ContentVariation.Nothing }); + _database.Insert(Constants.DatabaseSchema.Tables.PropertyType, "id", false, new PropertyTypeDto { Id = 35, UniqueId = 35.ToGuid(), DataTypeId = Constants.DataTypes.LabelDateTime, ContentTypeId = 1044, PropertyTypeGroupId = null, Alias = Constants.Conventions.Member.PasswordQuestion, Name = Constants.Conventions.Member.PasswordQuestionLabel, SortOrder = 7, Mandatory = false, ValidationRegExp = null, Description = null, Variations = (byte)ContentVariation.Nothing }); + _database.Insert(Constants.DatabaseSchema.Tables.PropertyType, "id", false, new PropertyTypeDto { Id = 36, UniqueId = 36.ToGuid(), DataTypeId = Constants.DataTypes.LabelDateTime, ContentTypeId = 1044, PropertyTypeGroupId = null, Alias = Constants.Conventions.Member.PasswordAnswer, Name = Constants.Conventions.Member.PasswordAnswerLabel, SortOrder = 8, Mandatory = false, ValidationRegExp = null, Description = null, Variations = (byte)ContentVariation.Nothing }); } diff --git a/src/Umbraco.Core/Persistence/Factories/MemberTypeReadOnlyFactory.cs b/src/Umbraco.Core/Persistence/Factories/MemberTypeReadOnlyFactory.cs index 9beeddde63..bafd73067f 100644 --- a/src/Umbraco.Core/Persistence/Factories/MemberTypeReadOnlyFactory.cs +++ b/src/Umbraco.Core/Persistence/Factories/MemberTypeReadOnlyFactory.cs @@ -9,11 +9,10 @@ namespace Umbraco.Core.Persistence.Factories { internal static class MemberTypeReadOnlyFactory { - public static IMemberType BuildEntity(MemberTypeReadOnlyDto dto, out bool needsSaving) + public static IMemberType BuildEntity(MemberTypeReadOnlyDto dto) { var standardPropertyTypes = Constants.Conventions.Member.GetStandardPropertyTypeStubs(); - needsSaving = false; - + var memberType = new MemberType(dto.ParentId); try @@ -41,33 +40,29 @@ namespace Umbraco.Core.Persistence.Factories var propertyTypeGroupCollection = GetPropertyTypeGroupCollection(dto, memberType, standardPropertyTypes); memberType.PropertyGroups = propertyTypeGroupCollection; - var propertyTypes = GetPropertyTypes(dto, memberType, standardPropertyTypes); + memberType.NoGroupPropertyTypes = GetNoGroupPropertyTypes(dto, memberType, standardPropertyTypes); - //By Convention we add 9 standard PropertyTypes - This is only here to support loading of types that didn't have these conventions before. + // By Convention we add 9 standard PropertyTypes - This is only here to support loading of types that didn't have these conventions before. + // In theory this should not happen! The only reason this did happen was because: + // A) we didn't install all of the default membership properties by default + // B) the existing data is super old when we didn't store membership properties at all (very very old) + // So what to do? We absolutely do not want to update the database when only a read was requested, this will cause problems + // so we should just add these virtual properties, they will have no ids but they will have aliases and this should be perfectly + // fine for any membership provider logic to work since neither membership providers or asp.net identity care about whether a property + // has an ID or not. + // When the member type is saved, all the properties will correctly be added. + + //This will add this group if it doesn't exist, no need to error check here + memberType.AddPropertyGroup(Constants.Conventions.Member.StandardPropertiesGroupName); foreach (var standardPropertyType in standardPropertyTypes) { - if (dto.PropertyTypes.Any(x => x.Alias.Equals(standardPropertyType.Key))) continue; + //This will add the property if it doesn't exist, no need to error check here + memberType.AddPropertyType(standardPropertyType.Value, Constants.Conventions.Member.StandardPropertiesGroupName); - // beware! - // means that we can return a memberType "from database" that has some property types - // that do *not* come from the database and therefore are incomplete eg have no key, - // no id, no dataTypeDefinitionId - ouch! - better notify caller of the situation - needsSaving = true; - - //fixme - this is wrong, this will add the standard prop without a group, yet by default it is attempted to be added to the - // group with the `Membership` alias just like we do in the MemberTypeRepository.PersistNewItem: - // //By Convention we add 9 standard PropertyTypes to an Umbraco MemberType - // entity.AddPropertyGroup(Constants.Conventions.Member.StandardPropertiesGroupName); - // that's exactly how it would need to be done here too, but... need to decide where/how this is done properly. - - //Add the standard PropertyType to the current list - propertyTypes.Add(standardPropertyType.Value); - //Internal dictionary for adding "MemberCanEdit", "VisibleOnProfile", "IsSensitive" properties to each PropertyType - memberType.MemberTypePropertyTypes.Add(standardPropertyType.Key, - new MemberTypePropertyProfileAccess(false, false, false)); + if (!memberType.MemberTypePropertyTypes.TryGetValue(standardPropertyType.Key, out var memberTypePropertyProfile)) + memberType.MemberTypePropertyTypes[standardPropertyType.Key] = new MemberTypePropertyProfileAccess(false, false, false); } - memberType.NoGroupPropertyTypes = propertyTypes; return memberType; } @@ -153,7 +148,7 @@ namespace Umbraco.Core.Persistence.Factories return propertyGroups; } - private static List GetPropertyTypes(MemberTypeReadOnlyDto dto, MemberType memberType, Dictionary standardProps) + private static List GetNoGroupPropertyTypes(MemberTypeReadOnlyDto dto, MemberType memberType, Dictionary standardProps) { //Find PropertyTypes that does not belong to a PropertyTypeGroup var propertyTypes = new List(); diff --git a/src/Umbraco.Core/Persistence/Repositories/Implement/MemberTypeRepository.cs b/src/Umbraco.Core/Persistence/Repositories/Implement/MemberTypeRepository.cs index afb6ac8b43..ffeff13207 100644 --- a/src/Umbraco.Core/Persistence/Repositories/Implement/MemberTypeRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/Implement/MemberTypeRepository.cs @@ -308,13 +308,7 @@ namespace Umbraco.Core.Persistence.Repositories.Implement if (dtos == null || dtos.Any() == false) return Enumerable.Empty(); - return dtos.Select(x => - { - bool needsSaving; - var memberType = MemberTypeReadOnlyFactory.BuildEntity(x, out needsSaving); - if (needsSaving) PersistUpdatedItem(memberType); - return memberType; - }).ToList(); + return dtos.Select(MemberTypeReadOnlyFactory.BuildEntity).ToList(); } ///