Published members cleanup (#10159)

* Getting new netcore PublicAccessChecker in place

* Adds full test coverage for PublicAccessChecker

* remove PublicAccessComposer

* adjust namespaces, ensure RoleManager works, separate public access controller, reduce content controller

* Implements the required methods on IMemberManager, removes old migrated code

* Updates routing to be able to re-route, Fixes middleware ordering ensuring endpoints are last, refactors pipeline options, adds public access middleware, ensures public access follows all hops

* adds note

* adds note

* Cleans up ext methods, ensures that members identity is added on both front-end and back ends. updates how UmbracoApplicationBuilder works in that it explicitly starts endpoints at the time of calling.

* Changes name to IUmbracoEndpointBuilder

* adds note

* Fixing tests, fixing error describers so there's 2x one for back office, one for members, fixes TryConvertTo, fixes login redirect

* fixing build

* Updates user manager to correctly validate password hashing and injects the IBackOfficeUserPasswordChecker

* Merges PR

* Fixes up build and notes

* Implements security stamp and email confirmed for members, cleans up a bunch of repo/service level member groups stuff, shares user store code between members and users and fixes the user identity object so we arent' tracking both groups and roles.

* Security stamp for members is now working

* Fixes keepalive, fixes PublicAccessMiddleware to not throw, updates startup code to be more clear and removes magic that registers middleware.

* adds note

* removes unused filter, fixes build

* fixes WebPath and tests

* Looks up entities in one query

* remove usings

* Fix test, remove stylesheet

* Set status code before we write to response to avoid error

* Ensures that users and members are validated when logging in. Shares more code between users and members.

* merge changes

* oops

* Reducing and removing published member cache

* Fixes RepositoryCacheKeys to ensure the keys are normalized

* oops didn't mean to commit this

* Fix casing issues with caching, stop boxing value types for all cache operations, stop re-creating string keys in DefaultRepositoryCachePolicy

* oops didn't mean to comit this

* bah, far out this keeps getting recommitted. sorry

* cannot inject IPublishedMemberCache and cannot have IPublishedMember

* splits out files, fixes build

* fix tests

* removes membership provider classes

* removes membership provider classes

* updates the identity map definition

* reverts commented out lines

* reverts commented out lines

Co-authored-by: Bjarke Berg <mail@bergmania.dk>
This commit is contained in:
Shannon Deminick
2021-04-22 21:21:43 +10:00
committed by GitHub
parent c991e83088
commit 3792cafb9f
40 changed files with 179 additions and 2350 deletions

View File

@@ -1,4 +1,4 @@
using System;
using System;
using System.Runtime.CompilerServices;
namespace Umbraco.Cms.Infrastructure.PublishedCache
@@ -60,20 +60,5 @@ namespace Umbraco.Cms.Infrastructure.PublishedCache
{
return "NuCache.ContentCache.ContentByRoute[" + DraftOrPub(previewing) + route + LangId(culture) + "]";
}
//public static string ContentCacheRouteByContentStartsWith()
//{
// return "NuCache.ContentCache.RouteByContent[";
//}
//public static string ContentCacheContentByRouteStartsWith()
//{
// return "NuCache.ContentCache.ContentByRoute[";
//}
public static string MemberCacheMember(string name, bool previewing, object p)
{
return "NuCache.MemberCache." + name + "[" + DraftOrPub(previewing) + p + "]";
}
}
}

View File

@@ -1,148 +1,39 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Xml.XPath;
using Umbraco.Cms.Core.Cache;
using Umbraco.Cms.Core.Models;
using Umbraco.Cms.Core.Models.PublishedContent;
using Umbraco.Cms.Core.PublishedCache;
using Umbraco.Cms.Core.Services;
using Umbraco.Cms.Core.Xml.XPath;
using Umbraco.Cms.Infrastructure.PublishedCache.Navigable;
using Umbraco.Extensions;
namespace Umbraco.Cms.Infrastructure.PublishedCache
{
internal class MemberCache : IPublishedMemberCache, INavigableData
internal class MemberCache : IPublishedMemberCache
{
private readonly IPublishedSnapshotAccessor _publishedSnapshotAccessor;
public readonly IVariationContextAccessor VariationContextAccessor;
private readonly IEntityXmlSerializer _entitySerializer;
private readonly IVariationContextAccessor _variationContextAccessor;
private readonly IPublishedModelFactory _publishedModelFactory;
private readonly IAppCache _snapshotCache;
private readonly IMemberService _memberService;
private readonly PublishedContentTypeCache _contentTypeCache;
private readonly bool _previewDefault;
public MemberCache(bool previewDefault, IAppCache snapshotCache, IMemberService memberService, PublishedContentTypeCache contentTypeCache,
IPublishedSnapshotAccessor publishedSnapshotAccessor, IVariationContextAccessor variationContextAccessor, IEntityXmlSerializer entitySerializer,
public MemberCache(
bool previewDefault,
PublishedContentTypeCache contentTypeCache,
IPublishedSnapshotAccessor publishedSnapshotAccessor,
IVariationContextAccessor variationContextAccessor,
IPublishedModelFactory publishedModelFactory)
{
_snapshotCache = snapshotCache;
_publishedSnapshotAccessor = publishedSnapshotAccessor;
VariationContextAccessor = variationContextAccessor;
_entitySerializer = entitySerializer;
_variationContextAccessor = variationContextAccessor;
_publishedModelFactory = publishedModelFactory;
_memberService = memberService;
_previewDefault = previewDefault;
_contentTypeCache = contentTypeCache;
}
private T GetCacheItem<T>(string cacheKey, Func<T> getCacheItem)
where T : class
{
var cache = _snapshotCache;
return cache == null
? getCacheItem()
: cache.GetCacheItem<T>(cacheKey, getCacheItem);
}
public IPublishedContent GetById(bool preview, int memberId)
{
return GetById(memberId);
}
public IPublishedContent /*IPublishedMember*/ GetById(int memberId)
{
return GetCacheItem(CacheKeys.MemberCacheMember("ById", _previewDefault, memberId), () =>
{
var member = _memberService.GetById(memberId);
return member == null
? null
: PublishedMember.Create(member, GetContentType(member.ContentTypeId), _previewDefault, _publishedSnapshotAccessor, VariationContextAccessor, _publishedModelFactory);
});
}
private IPublishedContent /*IPublishedMember*/ GetById(IMember member, bool previewing)
{
return GetCacheItem(CacheKeys.MemberCacheMember("ById", _previewDefault, member.Id), () =>
PublishedMember.Create(member, GetContentType(member.ContentTypeId), previewing, _publishedSnapshotAccessor, VariationContextAccessor, _publishedModelFactory));
}
public IPublishedContent /*IPublishedMember*/ GetByProviderKey(object key)
{
return GetCacheItem(CacheKeys.MemberCacheMember("ByProviderKey", _previewDefault, key), () =>
{
var member = _memberService.GetByProviderKey(key);
return member == null ? null : GetById(member, _previewDefault);
});
}
public IPublishedContent /*IPublishedMember*/ GetByUsername(string username)
{
return GetCacheItem(CacheKeys.MemberCacheMember("ByUsername", _previewDefault, username), () =>
{
var member = _memberService.GetByUsername(username);
return member == null ? null : GetById(member, _previewDefault);
});
}
public IPublishedContent /*IPublishedMember*/ GetByEmail(string email)
{
return GetCacheItem(CacheKeys.MemberCacheMember("ByEmail", _previewDefault, email), () =>
{
var member = _memberService.GetByEmail(email);
return member == null ? null : GetById(member, _previewDefault);
});
}
public IPublishedContent /*IPublishedMember*/ GetByMember(IMember member)
{
return PublishedMember.Create(member, GetContentType(member.ContentTypeId), _previewDefault, _publishedSnapshotAccessor, VariationContextAccessor, _publishedModelFactory);
}
public IEnumerable<IPublishedContent> GetAtRoot(bool preview)
{
// because members are flat (not a tree) everything is at root
// because we're loading everything... let's just not cache?
var members = _memberService.GetAllMembers();
return members.Select(m => PublishedMember.Create(m, GetContentType(m.ContentTypeId), preview, _publishedSnapshotAccessor, VariationContextAccessor, _publishedModelFactory));
}
public XPathNavigator CreateNavigator()
{
var source = new Source(this, false);
var navigator = new NavigableNavigator(source);
return navigator;
}
public XPathNavigator CreateNavigator(bool preview)
{
return CreateNavigator();
}
public XPathNavigator CreateNodeNavigator(int id, bool preview)
{
var result = _memberService.GetById(id);
if (result == null) return null;
var s = _entitySerializer.Serialize(result);
var n = s.GetXmlNode();
return n.CreateNavigator();
}
#region Content types
public IPublishedContentType GetContentType(int id)
{
return _contentTypeCache.Get(PublishedItemType.Member, id);
}
public IPublishedContentType GetContentType(int id) => _contentTypeCache.Get(PublishedItemType.Member, id);
public IPublishedContentType GetContentType(string alias)
{
return _contentTypeCache.Get(PublishedItemType.Member, alias);
}
public IPublishedContentType GetContentType(string alias) => _contentTypeCache.Get(PublishedItemType.Member, alias);
public IPublishedContent Get(IMember member)
=> PublishedMember.Create(member, GetContentType(member.ContentTypeId), _previewDefault, _publishedSnapshotAccessor, _variationContextAccessor, _publishedModelFactory);
#endregion
}

View File

@@ -12,10 +12,8 @@ namespace Umbraco.Cms.Infrastructure.PublishedCache
// note
// the whole PublishedMember thing should be refactored because as soon as a member
// is wrapped on in a model, the inner IMember and all associated properties are lost
internal class PublishedMember : PublishedContent //, IPublishedMember
internal class PublishedMember : PublishedContent
{
private readonly IMember _member;
private PublishedMember(
IMember member,
ContentNode contentNode,
@@ -25,7 +23,7 @@ namespace Umbraco.Cms.Infrastructure.PublishedCache
IPublishedModelFactory publishedModelFactory)
: base(contentNode, contentData, publishedSnapshotAccessor, variationContextAccessor, publishedModelFactory)
{
_member = member;
Member = member;
}
public static IPublishedContent Create(
@@ -45,12 +43,19 @@ namespace Umbraco.Cms.Infrastructure.PublishedCache
WriterId = member.CreatorId, // what else?
Properties = GetPropertyValues(contentType, member)
};
var n = new ContentNode(member.Id, member.Key,
var n = new ContentNode(
member.Id,
member.Key,
contentType,
member.Level, member.Path, member.SortOrder,
member.Level,
member.Path,
member.SortOrder,
member.ParentId,
member.CreateDate, member.CreatorId);
return new PublishedMember(member, n, d, publishedSnapshotAccessor, variationContextAccessor, publishedModelFactory).CreateModel(publishedModelFactory);
member.CreateDate,
member.CreatorId);
return new PublishedMember(member, n, d, publishedSnapshotAccessor, variationContextAccessor, publishedModelFactory)
.CreateModel(publishedModelFactory);
}
private static Dictionary<string, PropertyData[]> GetPropertyValues(IPublishedContentType contentType, IMember member)
@@ -99,25 +104,25 @@ namespace Umbraco.Cms.Infrastructure.PublishedCache
#region IPublishedMember
public IMember Member => _member;
public IMember Member { get; }
public string Email => _member.Email;
public string Email => Member.Email;
public string UserName => _member.Username;
public string UserName => Member.Username;
public string Comments => _member.Comments;
public string Comments => Member.Comments;
public bool IsApproved => _member.IsApproved;
public bool IsApproved => Member.IsApproved;
public bool IsLockedOut => _member.IsLockedOut;
public bool IsLockedOut => Member.IsLockedOut;
public DateTime LastLockoutDate => _member.LastLockoutDate;
public DateTime LastLockoutDate => Member.LastLockoutDate;
public DateTime CreationDate => _member.CreateDate;
public DateTime CreationDate => Member.CreateDate;
public DateTime LastLoginDate => _member.LastLoginDate;
public DateTime LastLoginDate => Member.LastLoginDate;
public DateTime LastPasswordChangedDate => _member.LastPasswordChangeDate;
public DateTime LastPasswordChangedDate => Member.LastPasswordChangeDate;
#endregion
}

View File

@@ -1092,7 +1092,7 @@ namespace Umbraco.Cms.Infrastructure.PublishedCache
{
ContentCache = new ContentCache(previewDefault, contentSnap, snapshotCache, elementsCache, domainCache, Options.Create(_globalSettings), _variationContextAccessor),
MediaCache = new MediaCache(previewDefault, mediaSnap, _variationContextAccessor),
MemberCache = new MemberCache(previewDefault, snapshotCache, _serviceContext.MemberService, memberTypeCache, _publishedSnapshotAccessor, _variationContextAccessor, _entitySerializer, _publishedModelFactory),
MemberCache = new MemberCache(previewDefault, memberTypeCache, _publishedSnapshotAccessor, _variationContextAccessor, _publishedModelFactory),
DomainCache = domainCache,
SnapshotCache = snapshotCache,
ElementsCache = elementsCache