v14: Remove mentions of UmbracoApiController (#15863)
* Remove mentions of UmbracoApiController * Remove last mentions of UmbracoApi controller
This commit is contained in:
@@ -19,7 +19,6 @@ namespace Umbraco.Cms.Api.Management.Routing;
|
||||
/// </summary>
|
||||
public sealed class BackOfficeAreaRoutes : IAreaRoutes
|
||||
{
|
||||
private readonly UmbracoApiControllerTypeCollection _apiControllers;
|
||||
private readonly GlobalSettings _globalSettings;
|
||||
private readonly IHostingEnvironment _hostingEnvironment;
|
||||
private readonly IRuntimeState _runtimeState;
|
||||
@@ -31,13 +30,11 @@ public sealed class BackOfficeAreaRoutes : IAreaRoutes
|
||||
public BackOfficeAreaRoutes(
|
||||
IOptions<GlobalSettings> globalSettings,
|
||||
IHostingEnvironment hostingEnvironment,
|
||||
IRuntimeState runtimeState,
|
||||
UmbracoApiControllerTypeCollection apiControllers)
|
||||
IRuntimeState runtimeState)
|
||||
{
|
||||
_globalSettings = globalSettings.Value;
|
||||
_hostingEnvironment = hostingEnvironment;
|
||||
_runtimeState = runtimeState;
|
||||
_apiControllers = apiControllers;
|
||||
_umbracoPathSegment = _globalSettings.GetUmbracoMvcArea(_hostingEnvironment);
|
||||
}
|
||||
|
||||
@@ -53,7 +50,6 @@ public sealed class BackOfficeAreaRoutes : IAreaRoutes
|
||||
case RuntimeLevel.Run:
|
||||
|
||||
MapMinimalBackOffice(endpoints);
|
||||
AutoRouteBackOfficeApiControllers(endpoints);
|
||||
break;
|
||||
case RuntimeLevel.BootFailed:
|
||||
case RuntimeLevel.Unknown:
|
||||
@@ -87,33 +83,4 @@ public sealed class BackOfficeAreaRoutes : IAreaRoutes
|
||||
Action = nameof(BackOfficeDefaultController.Index)
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Auto-routes all back office api controllers
|
||||
/// </summary>
|
||||
private void AutoRouteBackOfficeApiControllers(IEndpointRouteBuilder endpoints)
|
||||
{
|
||||
// TODO: We could investigate dynamically routing plugin controllers so we don't have to eagerly type scan for them,
|
||||
// it would probably work well, see https://www.strathweb.com/2019/08/dynamic-controller-routing-in-asp-net-core-3-0/
|
||||
// will probably be what we use for front-end routing too. BTW the orig article about migrating from IRouter to endpoint
|
||||
// routing for things like a CMS is here https://github.com/dotnet/aspnetcore/issues/4221
|
||||
|
||||
foreach (Type controller in _apiControllers)
|
||||
{
|
||||
PluginControllerMetadata meta = PluginController.GetMetadata(controller);
|
||||
|
||||
// exclude front-end api controllers
|
||||
if (!meta.IsBackOffice)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
endpoints.MapUmbracoApiRoute(
|
||||
meta.ControllerType,
|
||||
_umbracoPathSegment,
|
||||
meta.AreaName,
|
||||
meta.IsBackOffice,
|
||||
string.Empty); // no default action (this is what we had before)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,11 +0,0 @@
|
||||
using Umbraco.Cms.Core.Composing;
|
||||
|
||||
namespace Umbraco.Cms.Core;
|
||||
|
||||
public class UmbracoApiControllerTypeCollection : BuilderCollectionBase<Type>
|
||||
{
|
||||
public UmbracoApiControllerTypeCollection(Func<IEnumerable<Type>> items)
|
||||
: base(items)
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
using Umbraco.Cms.Web.Common.ApplicationModels;
|
||||
|
||||
namespace Umbraco.Cms.Web.Common.Attributes;
|
||||
|
||||
/// <summary>
|
||||
/// When present on a controller then <see cref="UmbracoApiBehaviorApplicationModelProvider" /> conventions will apply
|
||||
/// </summary>
|
||||
[AttributeUsage(AttributeTargets.Class)]
|
||||
public sealed class UmbracoApiControllerAttribute : Attribute
|
||||
{
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
using Umbraco.Cms.Core.Composing;
|
||||
|
||||
namespace Umbraco.Cms.Web.Common.Controllers;
|
||||
|
||||
/// <summary>
|
||||
/// Provides a base class for auto-routed Umbraco API controllers.
|
||||
/// </summary>
|
||||
public abstract class UmbracoApiController : UmbracoApiControllerBase, IDiscoverable
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="UmbracoApiController" /> class.
|
||||
/// </summary>
|
||||
protected UmbracoApiController()
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -1,26 +0,0 @@
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Umbraco.Cms.Core.Features;
|
||||
using Umbraco.Cms.Web.Common.Attributes;
|
||||
using Umbraco.Cms.Web.Common.Authorization;
|
||||
|
||||
namespace Umbraco.Cms.Web.Common.Controllers;
|
||||
|
||||
/// <summary>
|
||||
/// Provides a base class for Umbraco API controllers.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <para>These controllers are NOT auto-routed.</para>
|
||||
/// <para>The base class is <see cref="ControllerBase" /> which are netcore API controllers without any view support</para>
|
||||
/// </remarks>
|
||||
[Authorize(Policy = AuthorizationPolicies.UmbracoFeatureEnabled)] // TODO: This could be part of our conventions
|
||||
[UmbracoApiController]
|
||||
public abstract class UmbracoApiControllerBase : ControllerBase, IUmbracoFeature
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="UmbracoApiControllerBase" /> class.
|
||||
/// </summary>
|
||||
protected UmbracoApiControllerBase()
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
using Umbraco.Cms.Core;
|
||||
using Umbraco.Cms.Core.Composing;
|
||||
|
||||
namespace Umbraco.Cms.Web.Common.Controllers;
|
||||
|
||||
public class UmbracoApiControllerTypeCollectionBuilder : TypeCollectionBuilderBase<
|
||||
UmbracoApiControllerTypeCollectionBuilder, UmbracoApiControllerTypeCollection, UmbracoApiController>
|
||||
{
|
||||
// TODO: Should this only exist in the back office project? These really are only ever used for the back office AFAIK
|
||||
protected override UmbracoApiControllerTypeCollectionBuilder This => this;
|
||||
}
|
||||
@@ -290,10 +290,6 @@ public static partial class UmbracoBuilderExtensions
|
||||
builder.Services.AddUnique<IUmbracoContextFactory, UmbracoContextFactory>();
|
||||
builder.Services.AddUnique<IBackOfficeSecurityAccessor, BackOfficeSecurityAccessor>();
|
||||
|
||||
var umbracoApiControllerTypes = builder.TypeLoader.GetUmbracoApiControllers().ToList();
|
||||
builder.WithCollectionBuilder<UmbracoApiControllerTypeCollectionBuilder>()
|
||||
.Add(umbracoApiControllerTypes);
|
||||
|
||||
builder.Services.AddSingleton<UmbracoRequestLoggingMiddleware>();
|
||||
builder.Services.AddSingleton<PreviewAuthenticationMiddleware>();
|
||||
builder.Services.AddSingleton<UmbracoRequestMiddleware>();
|
||||
|
||||
@@ -12,64 +12,6 @@ namespace Umbraco.Extensions;
|
||||
|
||||
public static class LinkGeneratorExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the Umbraco backoffice URL (if Umbraco is installed).
|
||||
/// </summary>
|
||||
/// <param name="linkGenerator">The link generator.</param>
|
||||
/// <returns>
|
||||
/// The Umbraco backoffice URL.
|
||||
/// </returns>
|
||||
public static string? GetUmbracoBackOfficeUrl(this LinkGenerator linkGenerator)
|
||||
=> linkGenerator.GetPathByAction("Default", "BackOffice", new { area = Constants.Web.Mvc.BackOfficeArea });
|
||||
|
||||
/// <summary>
|
||||
/// Gets the Umbraco backoffice URL (if Umbraco is installed) or application virtual path (in most cases just <c>"/"</c>).
|
||||
/// </summary>
|
||||
/// <param name="linkGenerator">The link generator.</param>
|
||||
/// <param name="hostingEnvironment">The hosting environment.</param>
|
||||
/// <returns>
|
||||
/// The Umbraco backoffice URL.
|
||||
/// </returns>
|
||||
public static string GetUmbracoBackOfficeUrl(this LinkGenerator linkGenerator, IHostingEnvironment hostingEnvironment)
|
||||
=> GetUmbracoBackOfficeUrl(linkGenerator) ?? hostingEnvironment.ApplicationVirtualPath;
|
||||
|
||||
/// <summary>
|
||||
/// Return the back office url if the back office is installed
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This method contained a bug that would result in always returning "/".
|
||||
/// </remarks>
|
||||
[Obsolete("Use the GetUmbracoBackOfficeUrl extension method instead. This method will be removed in Umbraco 13.")]
|
||||
public static string? GetBackOfficeUrl(this LinkGenerator linkGenerator, IHostingEnvironment hostingEnvironment)
|
||||
=> "/";
|
||||
|
||||
/// <summary>
|
||||
/// Return the Url for a Web Api service
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The <see cref="UmbracoApiControllerBase" /></typeparam>
|
||||
public static string? GetUmbracoApiService<T>(this LinkGenerator linkGenerator, string actionName, object? id = null)
|
||||
where T : UmbracoApiControllerBase => linkGenerator.GetUmbracoControllerUrl(
|
||||
actionName,
|
||||
typeof(T),
|
||||
new Dictionary<string, object?> { ["id"] = id });
|
||||
|
||||
public static string? GetUmbracoApiService<T>(this LinkGenerator linkGenerator, string actionName, IDictionary<string, object?>? values)
|
||||
where T : UmbracoApiControllerBase => linkGenerator.GetUmbracoControllerUrl(actionName, typeof(T), values);
|
||||
|
||||
public static string? GetUmbracoApiServiceBaseUrl<T>(
|
||||
this LinkGenerator linkGenerator,
|
||||
Expression<Func<T, object?>> methodSelector)
|
||||
where T : UmbracoApiControllerBase
|
||||
{
|
||||
MethodInfo? method = ExpressionHelper.GetMethodInfo(methodSelector);
|
||||
if (method == null)
|
||||
{
|
||||
throw new MissingMethodException("Could not find the method " + methodSelector + " on type " + typeof(T) +
|
||||
" or the result ");
|
||||
}
|
||||
|
||||
return linkGenerator.GetUmbracoApiService<T>(method.Name)?.TrimEnd(method.Name);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Return the Url for an Umbraco controller
|
||||
@@ -159,25 +101,4 @@ public static class LinkGeneratorExtensions
|
||||
|
||||
return linkGenerator.GetUmbracoControllerUrl(actionName, ControllerExtensions.GetControllerName(controllerType), area, values);
|
||||
}
|
||||
|
||||
public static string? GetUmbracoApiService<T>(
|
||||
this LinkGenerator linkGenerator,
|
||||
Expression<Func<T, object>> methodSelector)
|
||||
where T : UmbracoApiController
|
||||
{
|
||||
MethodInfo? method = ExpressionHelper.GetMethodInfo(methodSelector);
|
||||
IDictionary<string, object?>? methodParams = ExpressionHelper.GetMethodParams(methodSelector);
|
||||
if (method == null)
|
||||
{
|
||||
throw new MissingMethodException(
|
||||
$"Could not find the method {methodSelector} on type {typeof(T)} or the result ");
|
||||
}
|
||||
|
||||
if (methodParams?.Any() == false)
|
||||
{
|
||||
return linkGenerator.GetUmbracoApiService<T>(method.Name);
|
||||
}
|
||||
|
||||
return linkGenerator.GetUmbracoApiService<T>(method.Name, methodParams);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,13 +0,0 @@
|
||||
using Umbraco.Cms.Core.Composing;
|
||||
using Umbraco.Cms.Web.Common.Controllers;
|
||||
|
||||
namespace Umbraco.Extensions;
|
||||
|
||||
public static class TypeLoaderExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets all types implementing <see cref="UmbracoApiController" />.
|
||||
/// </summary>
|
||||
public static IEnumerable<Type> GetUmbracoApiControllers(this TypeLoader typeLoader)
|
||||
=> typeLoader.GetTypes<UmbracoApiController>();
|
||||
}
|
||||
@@ -21,236 +21,6 @@ namespace Umbraco.Extensions;
|
||||
|
||||
public static class UrlHelperExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the Umbraco backoffice URL (if Umbraco is installed).
|
||||
/// </summary>
|
||||
/// <param name="urlHelper">The URL helper.</param>
|
||||
/// <returns>
|
||||
/// The Umbraco backoffice URL.
|
||||
/// </returns>
|
||||
public static string? GetUmbracoBackOfficeUrl(this IUrlHelper urlHelper)
|
||||
=> urlHelper.Action("Default", "BackOffice", new { area = Constants.Web.Mvc.BackOfficeArea });
|
||||
|
||||
/// <summary>
|
||||
/// Return the back office url if the back office is installed
|
||||
/// </summary>
|
||||
/// <param name="url"></param>
|
||||
/// <returns></returns>
|
||||
/// <remarks>
|
||||
/// This method contained a bug that would result in always returning "/".
|
||||
/// </remarks>
|
||||
[Obsolete("Use the GetUmbracoBackOfficeUrl extension method instead. This method will be removed in Umbraco 13.")]
|
||||
public static string? GetBackOfficeUrl(this IUrlHelper url)
|
||||
=> "/";
|
||||
|
||||
/// <summary>
|
||||
/// Return the Url for a Web Api service
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="url"></param>
|
||||
/// <param name="umbracoApiControllerTypeCollection"></param>
|
||||
/// <param name="actionName"></param>
|
||||
/// <param name="id"></param>
|
||||
/// <returns></returns>
|
||||
public static string? GetUmbracoApiService<T>(
|
||||
this IUrlHelper url,
|
||||
UmbracoApiControllerTypeCollection umbracoApiControllerTypeCollection,
|
||||
string actionName,
|
||||
object? id = null)
|
||||
where T : UmbracoApiController =>
|
||||
url.GetUmbracoApiService(umbracoApiControllerTypeCollection, actionName, typeof(T), id);
|
||||
|
||||
public static string? GetUmbracoApiService<T>(
|
||||
this IUrlHelper url,
|
||||
UmbracoApiControllerTypeCollection umbracoApiControllerTypeCollection,
|
||||
Expression<Func<T, object>> methodSelector)
|
||||
where T : UmbracoApiController
|
||||
{
|
||||
MethodInfo? method = ExpressionHelper.GetMethodInfo(methodSelector);
|
||||
IDictionary<string, object?>? methodParams = ExpressionHelper.GetMethodParams(methodSelector);
|
||||
if (method == null)
|
||||
{
|
||||
throw new MissingMethodException("Could not find the method " + methodSelector + " on type " + typeof(T) +
|
||||
" or the result ");
|
||||
}
|
||||
|
||||
if (methodParams?.Any() == false)
|
||||
{
|
||||
return url.GetUmbracoApiService<T>(umbracoApiControllerTypeCollection, method.Name);
|
||||
}
|
||||
|
||||
return url.GetUmbracoApiService<T>(umbracoApiControllerTypeCollection, method.Name, methodParams?.Values.First());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Return the Url for a Web Api service
|
||||
/// </summary>
|
||||
/// <param name="url"></param>
|
||||
/// <param name="umbracoApiControllerTypeCollection"></param>
|
||||
/// <param name="actionName"></param>
|
||||
/// <param name="apiControllerType"></param>
|
||||
/// <param name="id"></param>
|
||||
/// <returns></returns>
|
||||
public static string? GetUmbracoApiService(
|
||||
this IUrlHelper url,
|
||||
UmbracoApiControllerTypeCollection umbracoApiControllerTypeCollection,
|
||||
string actionName,
|
||||
Type apiControllerType,
|
||||
object? id = null)
|
||||
{
|
||||
if (actionName == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(actionName));
|
||||
}
|
||||
|
||||
if (string.IsNullOrWhiteSpace(actionName))
|
||||
{
|
||||
throw new ArgumentException(
|
||||
"Value can't be empty or consist only of white-space characters.",
|
||||
nameof(actionName));
|
||||
}
|
||||
|
||||
if (apiControllerType == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(apiControllerType));
|
||||
}
|
||||
|
||||
var area = string.Empty;
|
||||
|
||||
Type? apiController = umbracoApiControllerTypeCollection.SingleOrDefault(x => x == apiControllerType);
|
||||
if (apiController == null)
|
||||
{
|
||||
throw new InvalidOperationException("Could not find the umbraco api controller of type " +
|
||||
apiControllerType.FullName);
|
||||
}
|
||||
|
||||
PluginControllerMetadata metaData = PluginController.GetMetadata(apiController);
|
||||
if (metaData.AreaName.IsNullOrWhiteSpace() == false)
|
||||
{
|
||||
// set the area to the plugin area
|
||||
area = metaData.AreaName;
|
||||
}
|
||||
|
||||
return url.GetUmbracoApiService(actionName, ControllerExtensions.GetControllerName(apiControllerType), area!, id);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Return the Url for a Web Api service
|
||||
/// </summary>
|
||||
/// <param name="url"></param>
|
||||
/// <param name="actionName"></param>
|
||||
/// <param name="controllerName"></param>
|
||||
/// <param name="id"></param>
|
||||
/// <returns></returns>
|
||||
public static string? GetUmbracoApiService(this IUrlHelper url, string actionName, string controllerName, object? id = null) => url.GetUmbracoApiService(actionName, controllerName, string.Empty, id);
|
||||
|
||||
/// <summary>
|
||||
/// Return the Url for a Web Api service
|
||||
/// </summary>
|
||||
/// <param name="url"></param>
|
||||
/// <param name="actionName"></param>
|
||||
/// <param name="controllerName"></param>
|
||||
/// <param name="area"></param>
|
||||
/// <param name="id"></param>
|
||||
/// <returns></returns>
|
||||
public static string? GetUmbracoApiService(
|
||||
this IUrlHelper url,
|
||||
string actionName,
|
||||
string controllerName,
|
||||
string area,
|
||||
object? id = null)
|
||||
{
|
||||
if (actionName == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(actionName));
|
||||
}
|
||||
|
||||
if (string.IsNullOrWhiteSpace(actionName))
|
||||
{
|
||||
throw new ArgumentException(
|
||||
"Value can't be empty or consist only of white-space characters.",
|
||||
nameof(actionName));
|
||||
}
|
||||
|
||||
if (controllerName == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(controllerName));
|
||||
}
|
||||
|
||||
if (string.IsNullOrWhiteSpace(controllerName))
|
||||
{
|
||||
throw new ArgumentException(
|
||||
"Value can't be empty or consist only of white-space characters.",
|
||||
nameof(controllerName));
|
||||
}
|
||||
|
||||
if (area.IsNullOrWhiteSpace())
|
||||
{
|
||||
if (id == null)
|
||||
{
|
||||
return url.Action(actionName, controllerName);
|
||||
}
|
||||
|
||||
return url.Action(actionName, controllerName, new { id });
|
||||
}
|
||||
|
||||
if (id == null)
|
||||
{
|
||||
return url.Action(actionName, controllerName, new { area });
|
||||
}
|
||||
|
||||
return url.Action(actionName, controllerName, new { area, id });
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Return the Base Url (not including the action) for a Web Api service
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="url"></param>
|
||||
/// <param name="umbracoApiControllerTypeCollection"></param>
|
||||
/// <param name="actionName"></param>
|
||||
/// <returns></returns>
|
||||
public static string? GetUmbracoApiServiceBaseUrl<T>(
|
||||
this IUrlHelper url,
|
||||
UmbracoApiControllerTypeCollection umbracoApiControllerTypeCollection,
|
||||
string actionName)
|
||||
where T : UmbracoApiController =>
|
||||
url.GetUmbracoApiService<T>(umbracoApiControllerTypeCollection, actionName)?.TrimEnd(actionName);
|
||||
|
||||
public static string? GetUmbracoApiServiceBaseUrl<T>(
|
||||
this IUrlHelper url,
|
||||
UmbracoApiControllerTypeCollection umbracoApiControllerTypeCollection,
|
||||
Expression<Func<T, object>> methodSelector)
|
||||
where T : UmbracoApiController
|
||||
{
|
||||
MethodInfo? method = ExpressionHelper.GetMethodInfo(methodSelector);
|
||||
if (method == null)
|
||||
{
|
||||
throw new MissingMethodException("Could not find the method " + methodSelector + " on type " + typeof(T) +
|
||||
" or the result ");
|
||||
}
|
||||
|
||||
return url.GetUmbracoApiService<T>(umbracoApiControllerTypeCollection, method.Name)?.TrimEnd(method.Name);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Return the Url for an action with a cache-busting hash appended
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public static string GetUrlWithCacheBust(
|
||||
this IUrlHelper url,
|
||||
string actionName,
|
||||
string controllerName,
|
||||
RouteValueDictionary routeVals,
|
||||
IHostingEnvironment hostingEnvironment,
|
||||
IUmbracoVersion umbracoVersion)
|
||||
{
|
||||
var applicationJs = url.Action(actionName, controllerName, routeVals);
|
||||
applicationJs = applicationJs + "?umb__rnd=" +
|
||||
GetCacheBustHash(hostingEnvironment, umbracoVersion);
|
||||
return applicationJs;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
|
||||
@@ -60,17 +60,7 @@ public sealed class ConfigureMemberCookieOptions : IConfigureNamedOptions<Cookie
|
||||
},
|
||||
OnRedirectToAccessDenied = ctx =>
|
||||
{
|
||||
// When the controller is an UmbracoAPIController, we want to return a StatusCode instead of a redirect.
|
||||
// All other cases should use the default Redirect of the CookieAuthenticationEvent.
|
||||
var controllerDescriptor = ctx.HttpContext.GetEndpoint()?.Metadata
|
||||
.OfType<ControllerActionDescriptor>()
|
||||
.FirstOrDefault();
|
||||
|
||||
if (!controllerDescriptor?.ControllerTypeInfo.IsSubclassOf(typeof(UmbracoApiController)) ?? false)
|
||||
{
|
||||
new CookieAuthenticationEvents().OnRedirectToAccessDenied(ctx);
|
||||
}
|
||||
|
||||
new CookieAuthenticationEvents().OnRedirectToAccessDenied(ctx);
|
||||
return Task.CompletedTask;
|
||||
},
|
||||
};
|
||||
|
||||
@@ -15,10 +15,4 @@ public static class TypeLoaderExtensions
|
||||
/// </summary>
|
||||
internal static IEnumerable<Type> GetSurfaceControllers(this TypeLoader typeLoader)
|
||||
=> typeLoader.GetTypes<SurfaceController>();
|
||||
|
||||
/// <summary>
|
||||
/// Gets all types implementing <see cref="UmbracoApiController" />.
|
||||
/// </summary>
|
||||
internal static IEnumerable<Type> GetUmbracoApiControllers(this TypeLoader typeLoader)
|
||||
=> typeLoader.GetTypes<UmbracoApiController>();
|
||||
}
|
||||
|
||||
@@ -17,7 +17,6 @@ namespace Umbraco.Cms.Web.Website.Routing;
|
||||
/// </summary>
|
||||
public sealed class FrontEndRoutes : IAreaRoutes
|
||||
{
|
||||
private readonly UmbracoApiControllerTypeCollection _apiControllers;
|
||||
private readonly IRuntimeState _runtimeState;
|
||||
private readonly SurfaceControllerTypeCollection _surfaceControllerTypeCollection;
|
||||
private readonly string _umbracoPathSegment;
|
||||
@@ -29,12 +28,10 @@ public sealed class FrontEndRoutes : IAreaRoutes
|
||||
IOptions<GlobalSettings> globalSettings,
|
||||
IHostingEnvironment hostingEnvironment,
|
||||
IRuntimeState runtimeState,
|
||||
SurfaceControllerTypeCollection surfaceControllerTypeCollection,
|
||||
UmbracoApiControllerTypeCollection apiControllers)
|
||||
SurfaceControllerTypeCollection surfaceControllerTypeCollection)
|
||||
{
|
||||
_runtimeState = runtimeState;
|
||||
_surfaceControllerTypeCollection = surfaceControllerTypeCollection;
|
||||
_apiControllers = apiControllers;
|
||||
_umbracoPathSegment = globalSettings.Value.GetUmbracoMvcArea(hostingEnvironment);
|
||||
}
|
||||
|
||||
@@ -48,7 +45,6 @@ public sealed class FrontEndRoutes : IAreaRoutes
|
||||
case RuntimeLevel.Run:
|
||||
|
||||
AutoRouteSurfaceControllers(endpoints);
|
||||
AutoRouteFrontEndApiControllers(endpoints);
|
||||
break;
|
||||
case RuntimeLevel.BootFailed:
|
||||
case RuntimeLevel.Unknown:
|
||||
@@ -75,28 +71,4 @@ public sealed class FrontEndRoutes : IAreaRoutes
|
||||
meta.AreaName);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Auto-routes all front-end api controllers
|
||||
/// </summary>
|
||||
private void AutoRouteFrontEndApiControllers(IEndpointRouteBuilder endpoints)
|
||||
{
|
||||
foreach (Type controller in _apiControllers)
|
||||
{
|
||||
PluginControllerMetadata meta = PluginController.GetMetadata(controller);
|
||||
|
||||
// exclude back-end api controllers
|
||||
if (meta.IsBackOffice)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
endpoints.MapUmbracoApiRoute(
|
||||
meta.ControllerType,
|
||||
_umbracoPathSegment,
|
||||
meta.AreaName,
|
||||
meta.IsBackOffice,
|
||||
string.Empty); // no default action (this is what we had before)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -105,18 +105,6 @@ namespace Umbraco.Cms.Tests.Integration.TestServerTest
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Prepare a url before using <see cref="Client"/>.
|
||||
/// This returns the url but also sets the HttpContext.request into to use this url.
|
||||
/// </summary>
|
||||
/// <returns>The string URL of the controller action.</returns>
|
||||
protected string PrepareApiControllerUrl<T>(Expression<Func<T, object>> methodSelector)
|
||||
where T : UmbracoApiController
|
||||
{
|
||||
var url = LinkGenerator.GetUmbracoApiService(methodSelector);
|
||||
return PrepareUrl(url);
|
||||
}
|
||||
|
||||
protected string GetManagementApiUrl<T>(Expression<Func<T, object>> methodSelector)
|
||||
where T : ManagementApiControllerBase
|
||||
{
|
||||
|
||||
@@ -67,36 +67,6 @@ namespace Umbraco.Cms.Tests.Integration.Umbraco.Web.Website.Security
|
||||
Assert.AreEqual(HttpStatusCode.Redirect, response.StatusCode);
|
||||
Assert.AreEqual(cookieAuthenticationOptions.Value.AccessDeniedPath.ToString(), response.Headers.Location?.AbsolutePath);
|
||||
}
|
||||
|
||||
[Test]
|
||||
[LongRunning]
|
||||
public async Task Secure_ApiController_Should_Return_Unauthorized_WhenNotLoggedIn()
|
||||
{
|
||||
_memberManagerMock.Setup(x => x.IsLoggedIn()).Returns(false);
|
||||
var url = PrepareApiControllerUrl<TestApiController>(x => x.Secure());
|
||||
|
||||
var response = await Client.GetAsync(url);
|
||||
|
||||
Assert.AreEqual(HttpStatusCode.Unauthorized, response.StatusCode);
|
||||
}
|
||||
|
||||
[Test]
|
||||
[LongRunning]
|
||||
public async Task Secure_ApiController_Should_Return_Forbidden_WhenNotAuthorized()
|
||||
{
|
||||
_memberManagerMock.Setup(x => x.IsLoggedIn()).Returns(true);
|
||||
_memberManagerMock.Setup(x => x.IsMemberAuthorizedAsync(
|
||||
It.IsAny<IEnumerable<string>>(),
|
||||
It.IsAny<IEnumerable<string>>(),
|
||||
It.IsAny<IEnumerable<int>>()))
|
||||
.ReturnsAsync(false);
|
||||
|
||||
var url = PrepareApiControllerUrl<TestApiController>(x => x.Secure());
|
||||
|
||||
var response = await Client.GetAsync(url);
|
||||
|
||||
Assert.AreEqual(HttpStatusCode.Forbidden, response.StatusCode);
|
||||
}
|
||||
}
|
||||
|
||||
public class TestSurfaceController : SurfaceController
|
||||
@@ -121,10 +91,4 @@ namespace Umbraco.Cms.Tests.Integration.Umbraco.Web.Website.Security
|
||||
[UmbracoMemberAuthorize]
|
||||
public IActionResult Secure() => NoContent();
|
||||
}
|
||||
|
||||
public class TestApiController : UmbracoApiController
|
||||
{
|
||||
[UmbracoMemberAuthorize]
|
||||
public IActionResult Secure() => NoContent();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -46,14 +46,6 @@ internal class UmbracoCustomizations : ICustomization
|
||||
fixture.Customize<HostingSettings>(x =>
|
||||
x.With(settings => settings.ApplicationVirtualPath, string.Empty));
|
||||
|
||||
fixture.Customize<BackOfficeAreaRoutes>(u => u.FromFactory(
|
||||
() => new BackOfficeAreaRoutes(
|
||||
Options.Create(new GlobalSettings()),
|
||||
Mock.Of<IHostingEnvironment>(x =>
|
||||
x.ToAbsolute(It.IsAny<string>()) == "/umbraco" && x.ApplicationVirtualPath == string.Empty),
|
||||
Mock.Of<IRuntimeState>(x => x.Level == RuntimeLevel.Run),
|
||||
new UmbracoApiControllerTypeCollection(Enumerable.Empty<Type>))));
|
||||
|
||||
fixture.Customize<PreviewRoutes>(u => u.FromFactory(
|
||||
() => new PreviewRoutes(
|
||||
Options.Create(new GlobalSettings()),
|
||||
|
||||
@@ -1,89 +0,0 @@
|
||||
// Copyright (c) Umbraco.
|
||||
// See LICENSE for more details.
|
||||
|
||||
using System.Linq;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Routing;
|
||||
using Microsoft.Extensions.Options;
|
||||
using Moq;
|
||||
using NUnit.Framework;
|
||||
using Umbraco.Cms.Api.Management.Controllers.Security;
|
||||
using Umbraco.Cms.Api.Management.Routing;
|
||||
using Umbraco.Cms.Core;
|
||||
using Umbraco.Cms.Core.Configuration.Models;
|
||||
using Umbraco.Cms.Core.Hosting;
|
||||
using Umbraco.Cms.Core.Services;
|
||||
using Umbraco.Cms.Web.Common.Attributes;
|
||||
using Umbraco.Cms.Web.Common.Controllers;
|
||||
using Umbraco.Extensions;
|
||||
using static Umbraco.Cms.Core.Constants.Web.Routing;
|
||||
|
||||
namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Web.Common.Routing;
|
||||
|
||||
[TestFixture]
|
||||
public class BackOfficeAreaRoutesTests
|
||||
{
|
||||
[TestCase(RuntimeLevel.BootFailed)]
|
||||
[TestCase(RuntimeLevel.Unknown)]
|
||||
[TestCase(RuntimeLevel.Boot)]
|
||||
public void RuntimeState_No_Routes(RuntimeLevel level)
|
||||
{
|
||||
var routes = GetBackOfficeAreaRoutes(level);
|
||||
var endpoints = new TestRouteBuilder();
|
||||
routes.CreateRoutes(endpoints);
|
||||
|
||||
Assert.AreEqual(0, endpoints.DataSources.Count);
|
||||
}
|
||||
|
||||
[Test]
|
||||
[TestCase(RuntimeLevel.Run)]
|
||||
[TestCase(RuntimeLevel.Upgrade)]
|
||||
[TestCase(RuntimeLevel.Install)]
|
||||
public void RuntimeState_All_Routes(RuntimeLevel level)
|
||||
{
|
||||
var routes = GetBackOfficeAreaRoutes(level);
|
||||
var endpoints = new TestRouteBuilder();
|
||||
routes.CreateRoutes(endpoints);
|
||||
|
||||
Assert.AreEqual(1, endpoints.DataSources.Count);
|
||||
var route = endpoints.DataSources.First();
|
||||
Assert.AreEqual(3, route.Endpoints.Count);
|
||||
|
||||
AssertMinimalBackOfficeRoutes(route);
|
||||
|
||||
var endpoint4 = (RouteEndpoint)route.Endpoints[2];
|
||||
var apiControllerName = ControllerExtensions.GetControllerName<Testing1Controller>();
|
||||
Assert.AreEqual(
|
||||
$"umbraco/backoffice/api/{apiControllerName.ToLowerInvariant()}/{{action}}/{{id?}}",
|
||||
endpoint4.RoutePattern.RawText);
|
||||
Assert.IsFalse(endpoint4.RoutePattern.Defaults.ContainsKey(AreaToken));
|
||||
Assert.IsFalse(endpoint4.RoutePattern.Defaults.ContainsKey(ActionToken));
|
||||
Assert.AreEqual(apiControllerName, endpoint4.RoutePattern.Defaults[ControllerToken]);
|
||||
}
|
||||
|
||||
private void AssertMinimalBackOfficeRoutes(EndpointDataSource route)
|
||||
{
|
||||
var endpoint1 = (RouteEndpoint)route.Endpoints[0];
|
||||
Assert.AreEqual("umbraco/{action}/{id?}", endpoint1.RoutePattern.RawText);
|
||||
Assert.AreEqual("Index", endpoint1.RoutePattern.Defaults[ActionToken]);
|
||||
Assert.AreEqual(ControllerExtensions.GetControllerName<BackOfficeDefaultController>(), endpoint1.RoutePattern.Defaults[ControllerToken]);
|
||||
}
|
||||
|
||||
private BackOfficeAreaRoutes GetBackOfficeAreaRoutes(RuntimeLevel level)
|
||||
{
|
||||
var globalSettings = new GlobalSettings();
|
||||
var routes = new BackOfficeAreaRoutes(
|
||||
Options.Create(globalSettings),
|
||||
Mock.Of<IHostingEnvironment>(x =>
|
||||
x.ToAbsolute(It.IsAny<string>()) == "/umbraco" && x.ApplicationVirtualPath == string.Empty),
|
||||
Mock.Of<IRuntimeState>(x => x.Level == level),
|
||||
new UmbracoApiControllerTypeCollection(() => new[] { typeof(Testing1Controller) }));
|
||||
|
||||
return routes;
|
||||
}
|
||||
|
||||
[IsBackOffice]
|
||||
private class Testing1Controller : UmbracoApiController
|
||||
{
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user