Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implements Public Access in netcore #10137

Merged
merged 30 commits into from
Apr 20, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
e2b5c28
Getting new netcore PublicAccessChecker in place
Shazwazza Apr 12, 2021
8ec0d3f
Adds full test coverage for PublicAccessChecker
Shazwazza Apr 13, 2021
a5daad6
Merge branch 'netcore/task/member-macros-10577' into netcore/task/pub…
Shazwazza Apr 13, 2021
ad755ab
Merge remote-tracking branch 'origin/netcore/dev' into netcore/task/p…
Shazwazza Apr 13, 2021
3a31c73
remove PublicAccessComposer
Shazwazza Apr 13, 2021
41a10dc
adjust namespaces, ensure RoleManager works, separate public access c…
Shazwazza Apr 14, 2021
0f4a1c6
Merge remote-tracking branch 'origin/netcore/dev' into netcore/task/p…
Shazwazza Apr 14, 2021
d4382be
Implements the required methods on IMemberManager, removes old migrat…
Shazwazza Apr 14, 2021
2907ac7
Updates routing to be able to re-route, Fixes middleware ordering ens…
Shazwazza Apr 15, 2021
07e1ffe
adds note
Shazwazza Apr 15, 2021
e0abd35
adds note
Shazwazza Apr 15, 2021
abdb199
Cleans up ext methods, ensures that members identity is added on both…
Shazwazza Apr 15, 2021
3dfd4d7
Changes name to IUmbracoEndpointBuilder
Shazwazza Apr 15, 2021
cf770a5
adds note
Shazwazza Apr 15, 2021
cfcbe36
Fixing tests, fixing error describers so there's 2x one for back offi…
Shazwazza Apr 15, 2021
583a15c
fixing build
Shazwazza Apr 15, 2021
a4007eb
Fixes keepalive, fixes PublicAccessMiddleware to not throw, updates s…
Shazwazza Apr 19, 2021
eba8616
adds note
Shazwazza Apr 19, 2021
70b1513
removes unused filter, fixes build
Shazwazza Apr 19, 2021
fe7975d
fixes WebPath and tests
Shazwazza Apr 19, 2021
fd86c98
Looks up entities in one query
Shazwazza Apr 19, 2021
5678256
remove usings
Shazwazza Apr 19, 2021
bafa2ac
Fix test, remove stylesheet
Shazwazza Apr 19, 2021
821a699
Set status code before we write to response to avoid error
bergmania Apr 19, 2021
f98a99c
Ensures that users and members are validated when logging in. Shares …
Shazwazza Apr 19, 2021
ec3acc4
Merge branch 'netcore/task/public-access-10578' of https://github.com…
Shazwazza Apr 19, 2021
73600dc
Fixes RepositoryCacheKeys to ensure the keys are normalized
Shazwazza Apr 20, 2021
774e05a
oops didn't mean to commit this
Shazwazza Apr 20, 2021
8326b04
Fix casing issues with caching, stop boxing value types for all cache…
Shazwazza Apr 20, 2021
afb8022
bah, far out this keeps getting recommitted. sorry
Shazwazza Apr 20, 2021
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion src/Umbraco.Core/Cache/CacheRefresherBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,12 @@ protected CacheRefresherBase(AppCaches appCaches, IEventAggregator eventAggregat
/// </summary>
public virtual void RefreshAll()
{
OnCacheUpdated(NotificationFactory.Create<TNotification>(null, MessageType.RefreshAll));
// NOTE: We pass in string.Empty here because if we pass in NULL this causes problems with
// the underlying ActivatorUtilities.CreateInstance which doesn't seem to support passing in
// null to an 'object' parameter and we end up with "A suitable constructor for type 'ZYZ' could not be located."
// In this case, all cache refreshers should be checking for the type first before checking for a msg value
// so this shouldn't cause any issues.
OnCacheUpdated(NotificationFactory.Create<TNotification>(string.Empty, MessageType.RefreshAll));
}

/// <summary>
Expand Down
4 changes: 2 additions & 2 deletions src/Umbraco.Core/Cache/ContentCacheRefresher.cs
Original file line number Diff line number Diff line change
Expand Up @@ -55,9 +55,9 @@ public override void Refresh(JsonPayload[] payloads)
foreach (var payload in payloads.Where(x => x.Id != default))
{
//By INT Id
isolatedCache.Clear(RepositoryCacheKeys.GetKey<IContent>(payload.Id));
isolatedCache.Clear(RepositoryCacheKeys.GetKey<IContent, int>(payload.Id));
//By GUID Key
isolatedCache.Clear(RepositoryCacheKeys.GetKey<IContent>(payload.Key));
isolatedCache.Clear(RepositoryCacheKeys.GetKey<IContent, Guid?>(payload.Key));

_idKeyMap.ClearCache(payload.Id);

Expand Down
2 changes: 1 addition & 1 deletion src/Umbraco.Core/Cache/MacroCacheRefresher.cs
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ public override void Refresh(string json)
var macroRepoCache = AppCaches.IsolatedCaches.Get<IMacro>();
if (macroRepoCache)
{
macroRepoCache.Result.Clear(RepositoryCacheKeys.GetKey<IMacro>(payload.Id));
macroRepoCache.Result.Clear(RepositoryCacheKeys.GetKey<IMacro, int>(payload.Id));
}
}

Expand Down
4 changes: 2 additions & 2 deletions src/Umbraco.Core/Cache/MediaCacheRefresher.cs
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,8 @@ public override void Refresh(JsonPayload[] payloads)
// repository cache
// it *was* done for each pathId but really that does not make sense
// only need to do it for the current media
mediaCache.Result.Clear(RepositoryCacheKeys.GetKey<IMedia>(payload.Id));
mediaCache.Result.Clear(RepositoryCacheKeys.GetKey<IMedia>(payload.Key));
mediaCache.Result.Clear(RepositoryCacheKeys.GetKey<IMedia, int>(payload.Id));
mediaCache.Result.Clear(RepositoryCacheKeys.GetKey<IMedia, Guid?>(payload.Key));

// remove those that are in the branch
if (payload.ChangeTypes.HasTypesAny(TreeChangeTypes.RefreshBranch | TreeChangeTypes.Remove))
Expand Down
4 changes: 2 additions & 2 deletions src/Umbraco.Core/Cache/MemberCacheRefresher.cs
Original file line number Diff line number Diff line change
Expand Up @@ -75,8 +75,8 @@ private void ClearCache(params JsonPayload[] payloads)
_idKeyMap.ClearCache(p.Id);
if (memberCache)
{
memberCache.Result.Clear(RepositoryCacheKeys.GetKey<IMember>(p.Id));
memberCache.Result.Clear(RepositoryCacheKeys.GetKey<IMember>(p.Username));
memberCache.Result.Clear(RepositoryCacheKeys.GetKey<IMember, int>(p.Id));
memberCache.Result.Clear(RepositoryCacheKeys.GetKey<IMember, string>(p.Username));
}
}

Expand Down
4 changes: 2 additions & 2 deletions src/Umbraco.Core/Cache/RelationTypeCacheRefresher.cs
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ public override void RefreshAll()
public override void Refresh(int id)
{
var cache = AppCaches.IsolatedCaches.Get<IRelationType>();
if (cache) cache.Result.Clear(RepositoryCacheKeys.GetKey<IRelationType>(id));
if (cache) cache.Result.Clear(RepositoryCacheKeys.GetKey<IRelationType, int>(id));
base.Refresh(id);
}

Expand All @@ -45,7 +45,7 @@ public override void Refresh(Guid id)
public override void Remove(int id)
{
var cache = AppCaches.IsolatedCaches.Get<IRelationType>();
if (cache) cache.Result.Clear(RepositoryCacheKeys.GetKey<IRelationType>(id));
if (cache) cache.Result.Clear(RepositoryCacheKeys.GetKey<IRelationType, int>(id));
base.Remove(id);
}

Expand Down
2 changes: 1 addition & 1 deletion src/Umbraco.Core/Cache/UserCacheRefresher.cs
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ public override void Remove(int id)
var userCache = AppCaches.IsolatedCaches.Get<IUser>();
if (userCache)
{
userCache.Result.Clear(RepositoryCacheKeys.GetKey<IUser>(id));
userCache.Result.Clear(RepositoryCacheKeys.GetKey<IUser, int>(id));
userCache.Result.ClearByKey(CacheKeys.UserContentStartNodePathsPrefix + id);
userCache.Result.ClearByKey(CacheKeys.UserMediaStartNodePathsPrefix + id);
userCache.Result.ClearByKey(CacheKeys.UserAllContentStartNodesPrefix + id);
Expand Down
2 changes: 1 addition & 1 deletion src/Umbraco.Core/Cache/UserGroupCacheRefresher.cs
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ public override void Remove(int id)
var userGroupCache = AppCaches.IsolatedCaches.Get<IUserGroup>();
if (userGroupCache)
{
userGroupCache.Result.Clear(RepositoryCacheKeys.GetKey<IUserGroup>(id));
userGroupCache.Result.Clear(RepositoryCacheKeys.GetKey<IUserGroup, int>(id));
userGroupCache.Result.ClearByKey(CacheKeys.UserGroupGetByAliasCacheKeyPrefix);
}

Expand Down
17 changes: 0 additions & 17 deletions src/Umbraco.Core/Compose/PublicAccessComposer.cs

This file was deleted.

6 changes: 4 additions & 2 deletions src/Umbraco.Core/Composing/ICoreComposer.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
namespace Umbraco.Cms.Core.Composing
namespace Umbraco.Cms.Core.Composing
{
/// <summary>
/// Represents a core <see cref="IComposer"/>.
Expand All @@ -7,5 +7,7 @@
/// <para>Core composers compose after the initial composer, and before user composers.</para>
/// </remarks>
public interface ICoreComposer : IComposer
{ }
{
// TODO: This should die, there should be exactly zero core composers.
}
}
2 changes: 1 addition & 1 deletion src/Umbraco.Core/Configuration/Models/GlobalSettings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ internal const string
StaticReservedPaths = "~/app_plugins/,~/install/,~/mini-profiler-resources/,~/umbraco/,"; // must end with a comma!

internal const string
StaticReservedUrls = "~/config/splashes/noNodes.aspx,~/.well-known,"; // must end with a comma!
StaticReservedUrls = "~/.well-known,"; // must end with a comma!

/// <summary>
/// Gets or sets a value for the reserved URLs.
Expand Down
5 changes: 4 additions & 1 deletion src/Umbraco.Core/Configuration/Models/KeepAliveSettings.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
// Copyright (c) Umbraco.
// See LICENSE for more details.

using System;
using Umbraco.Cms.Core.Hosting;

namespace Umbraco.Cms.Core.Configuration.Models
{
/// <summary>
Expand All @@ -16,6 +19,6 @@ public class KeepAliveSettings
/// <summary>
/// Gets a value for the keep alive ping URL.
/// </summary>
public string KeepAlivePingUrl => "{umbracoApplicationUrl}/api/keepalive/ping";
public string KeepAlivePingUrl => "~/api/keepalive/ping";
}
}
38 changes: 27 additions & 11 deletions src/Umbraco.Core/DependencyInjection/UmbracoBuilder.Events.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,14 +23,7 @@ public static IUmbracoBuilder AddNotificationHandler<TNotification, TNotificatio
where TNotificationHandler : INotificationHandler<TNotification>
where TNotification : INotification
{
// Register the handler as transient. This ensures that anything can be injected into it.
var descriptor = new UniqueServiceDescriptor(typeof(INotificationHandler<TNotification>), typeof(TNotificationHandler), ServiceLifetime.Transient);

if (!builder.Services.Contains(descriptor))
{
builder.Services.Add(descriptor);
}

builder.Services.AddNotificationHandler<TNotification, TNotificationHandler>();
return builder;
}

Expand All @@ -44,16 +37,39 @@ public static IUmbracoBuilder AddNotificationHandler<TNotification, TNotificatio
public static IUmbracoBuilder AddNotificationAsyncHandler<TNotification, TNotificationAsyncHandler>(this IUmbracoBuilder builder)
where TNotificationAsyncHandler : INotificationAsyncHandler<TNotification>
where TNotification : INotification
{
builder.Services.AddNotificationAsyncHandler<TNotification, TNotificationAsyncHandler>();
return builder;
}

internal static IServiceCollection AddNotificationHandler<TNotification, TNotificationHandler>(this IServiceCollection services)
where TNotificationHandler : INotificationHandler<TNotification>
where TNotification : INotification
{
// Register the handler as transient. This ensures that anything can be injected into it.
var descriptor = new UniqueServiceDescriptor(typeof(INotificationHandler<TNotification>), typeof(TNotificationHandler), ServiceLifetime.Transient);

if (!services.Contains(descriptor))
{
services.Add(descriptor);
}

return services;
}

internal static IServiceCollection AddNotificationAsyncHandler<TNotification, TNotificationAsyncHandler>(this IServiceCollection services)
where TNotificationAsyncHandler : INotificationAsyncHandler<TNotification>
where TNotification : INotification
{
// Register the handler as transient. This ensures that anything can be injected into it.
var descriptor = new ServiceDescriptor(typeof(INotificationAsyncHandler<TNotification>), typeof(TNotificationAsyncHandler), ServiceLifetime.Transient);

if (!builder.Services.Contains(descriptor))
if (!services.Contains(descriptor))
{
builder.Services.Add(descriptor);
services.Add(descriptor);
}

return builder;
return services;
}
}
}
6 changes: 6 additions & 0 deletions src/Umbraco.Core/DependencyInjection/UmbracoBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
using Umbraco.Cms.Core.Editors;
using Umbraco.Cms.Core.Events;
using Umbraco.Cms.Core.Features;
using Umbraco.Cms.Core.Handlers;
using Umbraco.Cms.Core.Hosting;
using Umbraco.Cms.Core.Install;
using Umbraco.Cms.Core.IO;
Expand All @@ -31,6 +32,7 @@
using Umbraco.Cms.Core.Runtime;
using Umbraco.Cms.Core.Security;
using Umbraco.Cms.Core.Services;
using Umbraco.Cms.Core.Services.Notifications;
using Umbraco.Cms.Core.Sync;
using Umbraco.Cms.Core.Templates;
using Umbraco.Cms.Core.Web;
Expand Down Expand Up @@ -219,6 +221,10 @@ private void AddCoreServices()
// which may be replaced by models builder but the default is required to make plain old IPublishedContent
// instances.
Services.AddSingleton<IPublishedModelFactory>(factory => factory.CreateDefaultPublishedModelFactory());

Services
.AddNotificationHandler<MemberGroupSavedNotification, PublicAccessHandler>()
.AddNotificationHandler<MemberGroupDeletedNotification, PublicAccessHandler>();
}
}
}
20 changes: 18 additions & 2 deletions src/Umbraco.Core/Extensions/ObjectExtensions.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright (c) Umbraco.
// Copyright (c) Umbraco.
// See LICENSE for more details.

using System;
Expand Down Expand Up @@ -76,10 +76,26 @@ public static T SafeCast<T>(this object input)
/// <returns>The <see cref="Attempt{T}"/></returns>
public static Attempt<T> TryConvertTo<T>(this object input)
{
var result = TryConvertTo(input, typeof(T));
Attempt<object> result = TryConvertTo(input, typeof(T));

if (result.Success)
{
return Attempt<T>.Succeed((T)result.Result);
}

if (input == null)
{
if (typeof(T).IsValueType)
{
// fail, cannot convert null to a value type
return Attempt<T>.Fail();
}
else
{
// sure, null can be any object
return Attempt<T>.Succeed((T)input);
}
}

// just try to cast
try
Expand Down
13 changes: 13 additions & 0 deletions src/Umbraco.Core/Extensions/RuntimeStateExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
using Umbraco.Cms.Core;
using Umbraco.Cms.Core.Services;

namespace Umbraco.Extensions
{
public static class RuntimeStateExtensions
{
/// <summary>
/// Returns true if Umbraco <see cref="IRuntimeState"/> is greater than <see cref="RuntimeLevel.BootFailed"/>
/// </summary>
public static bool UmbracoCanBoot(this IRuntimeState state) => state.Level > RuntimeLevel.BootFailed;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
using Umbraco.Cms.Core.Services.Notifications;
using Umbraco.Extensions;

namespace Umbraco.Cms.Core.Compose
namespace Umbraco.Cms.Core.Handlers
{
public sealed class AuditNotificationsHandler :
INotificationHandler<MemberSavedNotification>,
Expand Down Expand Up @@ -61,7 +61,7 @@ private IUser CurrentPerformingUser
}
}

public static IUser UnknownUser(GlobalSettings globalSettings) => new User(globalSettings) { Id = Cms.Core.Constants.Security.UnknownUserId, Name = Cms.Core.Constants.Security.UnknownUserName, Email = "" };
public static IUser UnknownUser(GlobalSettings globalSettings) => new User(globalSettings) { Id = Constants.Security.UnknownUserId, Name = Constants.Security.UnknownUserName, Email = "" };

private string PerformingIp => _ipResolver.GetCurrentRequestIpAddress();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
using Umbraco.Cms.Core.Services.Notifications;
using Umbraco.Extensions;

namespace Umbraco.Cms.Core.Compose
namespace Umbraco.Cms.Core.Handlers
{
public sealed class PublicAccessHandler :
INotificationHandler<MemberGroupSavedNotification>,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
using System.Collections.Generic;
using Umbraco.Cms.Core.Models.Identity;
using Umbraco.Cms.Core.Security;

namespace Umbraco.Cms.Core.Persistence.Repositories
{
Expand Down
26 changes: 21 additions & 5 deletions src/Umbraco.Core/Persistence/Repositories/RepositoryCacheKeys.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using System;
using System;
using System.Collections.Generic;

namespace Umbraco.Cms.Core.Persistence.Repositories
Expand All @@ -8,14 +8,30 @@ namespace Umbraco.Cms.Core.Persistence.Repositories
/// </summary>
public static class RepositoryCacheKeys
{
private static readonly Dictionary<Type, string> Keys = new Dictionary<Type, string>();
// used to cache keys so we don't keep allocating strings
private static readonly Dictionary<Type, string> s_keys = new Dictionary<Type, string>();

public static string GetKey<T>()
{
var type = typeof(T);
return Keys.TryGetValue(type, out var key) ? key : (Keys[type] = "uRepo_" + type.Name + "_");
Type type = typeof(T);
return s_keys.TryGetValue(type, out var key) ? key : (s_keys[type] = "uRepo_" + type.Name + "_");
}

public static string GetKey<T>(object id) => GetKey<T>() + id;
public static string GetKey<T, TId>(TId id)
{
if (EqualityComparer<TId>.Default.Equals(id, default))
{
return string.Empty;
}

if (typeof(TId).IsValueType)
{
return GetKey<T>() + id;
}
else
{
return GetKey<T>() + id.ToString().ToUpperInvariant();
}
}
}
}
4 changes: 3 additions & 1 deletion src/Umbraco.Core/PublishedCache/IPublishedMemberCache.cs
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
using System.Xml.XPath;
using System.Xml.XPath;
using Umbraco.Cms.Core.Models;
using Umbraco.Cms.Core.Models.PublishedContent;

namespace Umbraco.Cms.Core.PublishedCache
{
// TODO: Kill this, why do we want this at all?
// See https://dev.azure.com/umbraco/D-Team%20Tracker/_workitems/edit/11487
public interface IPublishedMemberCache : IXPathNavigable
{
IPublishedContent GetByProviderKey(object key);
Expand Down
Loading