From ea4f07bd088ed8024999fb96bb914f6b19c2409e Mon Sep 17 00:00:00 2001 From: Kenn Jacobsen Date: Tue, 17 Oct 2023 08:55:09 +0200 Subject: [PATCH] Create matcher policy to pick the correct item endpoint (#14987) --- .../UmbracoBuilderExtensions.cs | 5 ++ .../DeliveryApiItemsEndpointsMatcherPolicy.cs | 55 +++++++++++++++++++ 2 files changed, 60 insertions(+) create mode 100644 src/Umbraco.Cms.Api.Delivery/Routing/DeliveryApiItemsEndpointsMatcherPolicy.cs diff --git a/src/Umbraco.Cms.Api.Delivery/DependencyInjection/UmbracoBuilderExtensions.cs b/src/Umbraco.Cms.Api.Delivery/DependencyInjection/UmbracoBuilderExtensions.cs index 8609450f3c..86c8583708 100644 --- a/src/Umbraco.Cms.Api.Delivery/DependencyInjection/UmbracoBuilderExtensions.cs +++ b/src/Umbraco.Cms.Api.Delivery/DependencyInjection/UmbracoBuilderExtensions.cs @@ -1,5 +1,6 @@ using System.Text.Json; using System.Text.Json.Serialization; +using Microsoft.AspNetCore.Routing; using Microsoft.Extensions.DependencyInjection; using Umbraco.Cms.Api.Common.DependencyInjection; using Umbraco.Cms.Api.Delivery.Accessors; @@ -7,6 +8,7 @@ using Umbraco.Cms.Api.Delivery.Configuration; using Umbraco.Cms.Api.Delivery.Handlers; using Umbraco.Cms.Api.Delivery.Json; using Umbraco.Cms.Api.Delivery.Rendering; +using Umbraco.Cms.Api.Delivery.Routing; using Umbraco.Cms.Api.Delivery.Security; using Umbraco.Cms.Api.Delivery.Services; using Umbraco.Cms.Core; @@ -57,6 +59,9 @@ public static class UmbracoBuilderExtensions builder.AddNotificationAsyncHandler(); builder.AddNotificationAsyncHandler(); builder.AddNotificationAsyncHandler(); + + // FIXME: remove this when Delivery API V1 is removed + builder.Services.AddSingleton(); return builder; } } diff --git a/src/Umbraco.Cms.Api.Delivery/Routing/DeliveryApiItemsEndpointsMatcherPolicy.cs b/src/Umbraco.Cms.Api.Delivery/Routing/DeliveryApiItemsEndpointsMatcherPolicy.cs new file mode 100644 index 0000000000..ec1b222cd0 --- /dev/null +++ b/src/Umbraco.Cms.Api.Delivery/Routing/DeliveryApiItemsEndpointsMatcherPolicy.cs @@ -0,0 +1,55 @@ +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc.Controllers; +using Microsoft.AspNetCore.Routing; +using Microsoft.AspNetCore.Routing.Matching; +using Umbraco.Cms.Api.Delivery.Controllers; + +namespace Umbraco.Cms.Api.Delivery.Routing; + +// FIXME: remove this when Delivery API V1 is removed +internal sealed class DeliveryApiItemsEndpointsMatcherPolicy : MatcherPolicy, IEndpointSelectorPolicy +{ + public override int Order => 100; + + public bool AppliesToEndpoints(IReadOnlyList endpoints) + { + for (var i = 0; i < endpoints.Count; i++) + { + ControllerActionDescriptor? controllerActionDescriptor = endpoints[i].Metadata.GetMetadata(); + if (IsByIdsController(controllerActionDescriptor) || IsByRouteController(controllerActionDescriptor)) + { + return true; + } + } + + return false; + } + + public Task ApplyAsync(HttpContext httpContext, CandidateSet candidates) + { + var hasIdQueryParameter = httpContext.Request.Query.ContainsKey("id"); + for (var i = 0; i < candidates.Count; i++) + { + ControllerActionDescriptor? controllerActionDescriptor = candidates[i].Endpoint?.Metadata.GetMetadata(); + if (IsByIdsController(controllerActionDescriptor)) + { + candidates.SetValidity(i, hasIdQueryParameter); + } + else if (IsByRouteController(controllerActionDescriptor)) + { + candidates.SetValidity(i, hasIdQueryParameter is false); + } + } + + return Task.CompletedTask; + } + + private static bool IsByIdsController(ControllerActionDescriptor? controllerActionDescriptor) + => IsControllerType(controllerActionDescriptor) || IsControllerType(controllerActionDescriptor); + + private static bool IsByRouteController(ControllerActionDescriptor? controllerActionDescriptor) + => IsControllerType(controllerActionDescriptor) || IsControllerType(controllerActionDescriptor); + + private static bool IsControllerType(ControllerActionDescriptor? controllerActionDescriptor) + => controllerActionDescriptor?.MethodInfo.DeclaringType == typeof(T); +}