diff --git a/src/Umbraco.Core/Models/Membership/IUser.cs b/src/Umbraco.Core/Models/Membership/IUser.cs index d010d0e669..60cc0ec5f2 100644 --- a/src/Umbraco.Core/Models/Membership/IUser.cs +++ b/src/Umbraco.Core/Models/Membership/IUser.cs @@ -52,5 +52,21 @@ namespace Umbraco.Core.Models.Membership /// A Json blob stored for recording tour data for a user /// string TourData { get; set; } + + /// + /// Returns an item from the user instance's cache + /// + /// + /// + /// + T FromUserCache(string cacheKey) where T : class; + + /// + /// Puts an item in the user instance's cache + /// + /// + /// + /// + void ToUserCache(string cacheKey, T vals) where T : class; } } diff --git a/src/Umbraco.Infrastructure/Models/Membership/User.cs b/src/Umbraco.Core/Models/Membership/User.cs similarity index 96% rename from src/Umbraco.Infrastructure/Models/Membership/User.cs rename to src/Umbraco.Core/Models/Membership/User.cs index c3c26825df..80c57dccec 100644 --- a/src/Umbraco.Infrastructure/Models/Membership/User.cs +++ b/src/Umbraco.Core/Models/Membership/User.cs @@ -122,8 +122,7 @@ namespace Umbraco.Core.Models.Membership (enum1, enum2) => enum1.UnsortedSequenceEqual(enum2), enum1 => enum1.GetHashCode()); - #region Implementation of IMembershipUser - + [DataMember] public DateTime? EmailConfirmedDate { @@ -200,10 +199,6 @@ namespace Umbraco.Core.Models.Membership [IgnoreDataMember] public string Comments { get; set; } - #endregion - - #region Implementation of IUser - public UserState UserState { get @@ -236,13 +231,6 @@ namespace Umbraco.Core.Models.Membership get { return _allowedSections ?? (_allowedSections = new List(_userGroups.SelectMany(x => x.AllowedSections).Distinct())); } } - /// - /// This used purely for hacking backwards compatibility into this class for < 7.7 compat - /// - [DoNotClone] - [IgnoreDataMember] - internal List GroupsToSave = new List(); - public IProfile ProfileData => new WrappedUserProfile(this); /// @@ -361,7 +349,25 @@ namespace Umbraco.Core.Models.Membership } } - #endregion + public T FromUserCache(string cacheKey) + where T : class + { + lock (_additionalDataLock) + { + return AdditionalData.TryGetValue(cacheKey, out var allContentStartNodes) + ? allContentStartNodes as T + : null; + } + } + + public void ToUserCache(string cacheKey, T vals) + where T : class + { + lock (_additionalDataLock) + { + AdditionalData[cacheKey] = vals; + } + } /// /// This is used as an internal cache for this entity - specifically for calculating start nodes so we don't re-calculated all of the time @@ -379,10 +385,6 @@ namespace Umbraco.Core.Models.Membership } } - [IgnoreDataMember] - [DoNotClone] - internal object AdditionalDataLock => _additionalDataLock; - protected override void PerformDeepClone(object clone) { base.PerformDeepClone(clone); diff --git a/src/Umbraco.Infrastructure/Models/UserExtensions.cs b/src/Umbraco.Infrastructure/Models/UserExtensions.cs index 4fefc89d11..ca5f63ee8e 100644 --- a/src/Umbraco.Infrastructure/Models/UserExtensions.cs +++ b/src/Umbraco.Infrastructure/Models/UserExtensions.cs @@ -148,13 +148,13 @@ namespace Umbraco.Core.Models { const string cacheKey = "AllContentStartNodes"; //try to look them up from cache so we don't recalculate - var valuesInUserCache = FromUserCache(user, cacheKey); + var valuesInUserCache = user.FromUserCache(cacheKey); if (valuesInUserCache != null) return valuesInUserCache; var gsn = user.Groups.Where(x => x.StartContentId.HasValue).Select(x => x.StartContentId.Value).Distinct().ToArray(); var usn = user.StartContentIds; var vals = CombineStartNodes(UmbracoObjectTypes.Document, gsn, usn, entityService); - ToUserCache(user, cacheKey, vals); + user.ToUserCache(cacheKey, vals); return vals; } @@ -163,13 +163,13 @@ namespace Umbraco.Core.Models { const string cacheKey = "AllMediaStartNodes"; //try to look them up from cache so we don't recalculate - var valuesInUserCache = FromUserCache(user, cacheKey); + var valuesInUserCache = user.FromUserCache(cacheKey); if (valuesInUserCache != null) return valuesInUserCache; var gsn = user.Groups.Where(x => x.StartMediaId.HasValue).Select(x => x.StartMediaId.Value).Distinct().ToArray(); var usn = user.StartMediaIds; var vals = CombineStartNodes(UmbracoObjectTypes.Media, gsn, usn, entityService); - ToUserCache(user, cacheKey, vals); + user.ToUserCache(cacheKey, vals); return vals; } @@ -177,12 +177,12 @@ namespace Umbraco.Core.Models { const string cacheKey = "MediaStartNodePaths"; //try to look them up from cache so we don't recalculate - var valuesInUserCache = FromUserCache(user, cacheKey); + var valuesInUserCache = user.FromUserCache(cacheKey); if (valuesInUserCache != null) return valuesInUserCache; var startNodeIds = user.CalculateMediaStartNodeIds(entityService); var vals = entityService.GetAllPaths(UmbracoObjectTypes.Media, startNodeIds).Select(x => x.Path).ToArray(); - ToUserCache(user, cacheKey, vals); + user.ToUserCache(cacheKey, vals); return vals; } @@ -190,39 +190,15 @@ namespace Umbraco.Core.Models { const string cacheKey = "ContentStartNodePaths"; //try to look them up from cache so we don't recalculate - var valuesInUserCache = FromUserCache(user, cacheKey); + var valuesInUserCache = user.FromUserCache(cacheKey); if (valuesInUserCache != null) return valuesInUserCache; var startNodeIds = user.CalculateContentStartNodeIds(entityService); var vals = entityService.GetAllPaths(UmbracoObjectTypes.Document, startNodeIds).Select(x => x.Path).ToArray(); - ToUserCache(user, cacheKey, vals); + user.ToUserCache(cacheKey, vals); return vals; } - private static T FromUserCache(IUser user, string cacheKey) - where T: class - { - if (!(user is User entityUser)) return null; - - lock (entityUser.AdditionalDataLock) - { - return entityUser.AdditionalData.TryGetValue(cacheKey, out var allContentStartNodes) - ? allContentStartNodes as T - : null; - } - } - - private static void ToUserCache(IUser user, string cacheKey, T vals) - where T: class - { - if (!(user is User entityUser)) return; - - lock (entityUser.AdditionalDataLock) - { - entityUser.AdditionalData[cacheKey] = vals; - } - } - private static bool StartsWithPath(string test, string path) { return test.StartsWith(path) && test.Length > path.Length && test[path.Length] == ','; diff --git a/src/Umbraco.Infrastructure/Persistence/Factories/UserFactory.cs b/src/Umbraco.Infrastructure/Persistence/Factories/UserFactory.cs index c8a2f33ce4..9761fe3a00 100644 --- a/src/Umbraco.Infrastructure/Persistence/Factories/UserFactory.cs +++ b/src/Umbraco.Infrastructure/Persistence/Factories/UserFactory.cs @@ -43,7 +43,7 @@ namespace Umbraco.Core.Persistence.Factories // save it back to database (as that would create a *new* user) // see also: UserRepository.PersistNewItem if (dto.Id == 0) - user.AdditionalData["IS_V7_ZERO"] = true; + user.ToUserCache("IS_V7_ZERO", "true"); // reset dirty initial properties (U4-1946) user.ResetDirtyProperties(false); diff --git a/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/UserRepository.cs b/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/UserRepository.cs index c8de108db8..5311ee8c7f 100644 --- a/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/UserRepository.cs +++ b/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/UserRepository.cs @@ -424,7 +424,7 @@ ORDER BY colName"; // as new, as we do not want to create a new user - instead, persist // it as updated // see also: UserFactory.BuildEntity - if (((User) entity).AdditionalData.ContainsKey("IS_V7_ZERO")) + if (entity.FromUserCache("IS_V7_ZERO") != null) { PersistUpdatedItem(entity); return; diff --git a/src/Umbraco.Infrastructure/Services/Implement/UserService.cs b/src/Umbraco.Infrastructure/Services/Implement/UserService.cs index 24f1af5843..faf7889fbf 100644 --- a/src/Umbraco.Infrastructure/Services/Implement/UserService.cs +++ b/src/Umbraco.Infrastructure/Services/Implement/UserService.cs @@ -275,18 +275,6 @@ namespace Umbraco.Core.Services.Implement if (string.IsNullOrWhiteSpace(entity.Name)) throw new ArgumentException("Empty name.", nameof(entity)); - //Now we have to check for backwards compat hacks, we'll need to process any groups - //to save first before we update the user since these groups might be new groups. - - var explicitUser = entity as User; - if (explicitUser != null && explicitUser.GroupsToSave.Count > 0) - { - foreach (var userGroup in explicitUser.GroupsToSave) - { - _userGroupRepository.Save(userGroup); - } - } - try { _userRepository.Save(entity); @@ -340,15 +328,6 @@ namespace Umbraco.Core.Services.Implement _userRepository.Save(user); - //Now we have to check for backwards compat hacks - var explicitUser = user as User; - if (explicitUser != null && explicitUser.GroupsToSave.Count > 0) - { - foreach (var userGroup in explicitUser.GroupsToSave) - { - _userGroupRepository.Save(userGroup); - } - } } if (raiseEvents)