V14: cherry pick #17656 (#17763)

* V15: Fix webhook RTE serialization (#17656)

* Make base type resolver class

* Add new webhook serializer

* fix comment

* Update src/Umbraco.Infrastructure/Serialization/ContentJsonTypeResolverBase.cs

Co-authored-by: Elitsa Marinovska <21998037+elit0451@users.noreply.github.com>

* Update src/Umbraco.Core/Services/WebhookRequestService.cs

---------

Co-authored-by: Elitsa <elm@umbraco.dk>
Co-authored-by: Elitsa Marinovska <21998037+elit0451@users.noreply.github.com>
(cherry picked from commit 6f081785e6)

* Add back missing usings
This commit is contained in:
Nikolaj Geisle
2024-12-09 16:09:54 +01:00
committed by GitHub
parent f048cfe62d
commit 82e58eae3e
8 changed files with 117 additions and 59 deletions

View File

@@ -1,56 +1,7 @@
using System.Text.Json;
using System.Text.Json.Serialization;
using System.Text.Json.Serialization.Metadata;
using Umbraco.Cms.Core.Models.DeliveryApi;
using Umbraco.Cms.Infrastructure.Serialization;
namespace Umbraco.Cms.Api.Delivery.Json;
// see https://learn.microsoft.com/en-us/dotnet/standard/serialization/system-text-json/polymorphism?pivots=dotnet-7-0
public class DeliveryApiJsonTypeResolver : DefaultJsonTypeInfoResolver
{
public override JsonTypeInfo GetTypeInfo(Type type, JsonSerializerOptions options)
{
JsonTypeInfo jsonTypeInfo = base.GetTypeInfo(type, options);
Type[] derivedTypes = GetDerivedTypes(jsonTypeInfo);
if (derivedTypes.Length > 0)
{
ConfigureJsonPolymorphismOptions(jsonTypeInfo, derivedTypes);
}
return jsonTypeInfo;
}
protected virtual Type[] GetDerivedTypes(JsonTypeInfo jsonTypeInfo)
{
if (jsonTypeInfo.Type == typeof(IApiContent))
{
return new[] { typeof(ApiContent) };
}
if (jsonTypeInfo.Type == typeof(IApiContentResponse))
{
return new[] { typeof(ApiContentResponse) };
}
if (jsonTypeInfo.Type == typeof(IRichTextElement))
{
return new[] { typeof(RichTextRootElement), typeof(RichTextGenericElement), typeof(RichTextTextElement) };
}
return Array.Empty<Type>();
}
protected void ConfigureJsonPolymorphismOptions(JsonTypeInfo jsonTypeInfo, params Type[] derivedTypes)
{
jsonTypeInfo.PolymorphismOptions = new JsonPolymorphismOptions
{
UnknownDerivedTypeHandling = JsonUnknownDerivedTypeHandling.FailSerialization,
};
foreach (Type derivedType in derivedTypes)
{
jsonTypeInfo.PolymorphismOptions.DerivedTypes.Add(new JsonDerivedType(derivedType));
}
}
}
public class DeliveryApiJsonTypeResolver : ContentJsonTypeResolverBase
{ }

View File

@@ -26,8 +26,6 @@ using Umbraco.Cms.Core.Notifications;
using Umbraco.Cms.Core.Packaging;
using Umbraco.Cms.Core.Persistence.Repositories;
using Umbraco.Cms.Core.PropertyEditors;
using Umbraco.Cms.Core.PublishedCache;
using Umbraco.Cms.Core.PublishedCache.Internal;
using Umbraco.Cms.Core.Routing;
using Umbraco.Cms.Core.Runtime;
using Umbraco.Cms.Core.Scoping;
@@ -36,7 +34,10 @@ using Umbraco.Cms.Core.Services;
using Umbraco.Cms.Core.Services.ContentTypeEditing;
using Umbraco.Cms.Core.DynamicRoot;
using Umbraco.Cms.Core.Preview;
using Umbraco.Cms.Core.PublishedCache;
using Umbraco.Cms.Core.PublishedCache.Internal;
using Umbraco.Cms.Core.Security.Authorization;
using Umbraco.Cms.Core.Serialization;
using Umbraco.Cms.Core.Services.FileSystem;
using Umbraco.Cms.Core.Services.ImportExport;
using Umbraco.Cms.Core.Services.Querying.RecycleBin;
@@ -373,7 +374,10 @@ namespace Umbraco.Cms.Core.DependencyInjection
Services.AddUnique<IWebhookService, WebhookService>();
Services.AddUnique<IWebhookLogService, WebhookLogService>();
Services.AddUnique<IWebhookLogFactory, WebhookLogFactory>();
Services.AddUnique<IWebhookRequestService, WebhookRequestService>();
Services.AddUnique<IWebhookRequestService>(factory => new WebhookRequestService(
factory.GetRequiredService<ICoreScopeProvider>(),
factory.GetRequiredService<IWebhookRequestRepository>(),
factory.GetRequiredService<IWebhookJsonSerializer>()));
// Data type configuration cache
Services.AddUnique<IDataTypeConfigurationCache, DataTypeConfigurationCache>();

View File

@@ -0,0 +1,4 @@
namespace Umbraco.Cms.Core.Serialization;
public interface IWebhookJsonSerializer : IJsonSerializer
{ }

View File

@@ -1,4 +1,6 @@
using Umbraco.Cms.Core.Models;
using Microsoft.Extensions.DependencyInjection;
using Umbraco.Cms.Core.DependencyInjection;
using Umbraco.Cms.Core.Models;
using Umbraco.Cms.Core.Persistence.Repositories;
using Umbraco.Cms.Core.Scoping;
using Umbraco.Cms.Core.Serialization;
@@ -9,13 +11,19 @@ public class WebhookRequestService : IWebhookRequestService
{
private readonly ICoreScopeProvider _coreScopeProvider;
private readonly IWebhookRequestRepository _webhookRequestRepository;
private readonly IJsonSerializer _jsonSerializer;
private readonly IWebhookJsonSerializer _webhookJsonSerializer;
[Obsolete("This constructor is obsolete and will be removed in future versions. Scheduled for removal in V17")]
public WebhookRequestService(ICoreScopeProvider coreScopeProvider, IWebhookRequestRepository webhookRequestRepository, IJsonSerializer jsonSerializer)
: this (coreScopeProvider, webhookRequestRepository, StaticServiceProvider.Instance.GetRequiredService<IWebhookJsonSerializer>())
{
}
public WebhookRequestService(ICoreScopeProvider coreScopeProvider, IWebhookRequestRepository webhookRequestRepository, IWebhookJsonSerializer webhookJsonSerializer)
{
_coreScopeProvider = coreScopeProvider;
_webhookRequestRepository = webhookRequestRepository;
_jsonSerializer = jsonSerializer;
_webhookJsonSerializer = webhookJsonSerializer;
}
public async Task<WebhookRequest> CreateAsync(Guid webhookKey, string eventAlias, object? payload)
@@ -26,7 +34,7 @@ public class WebhookRequestService : IWebhookRequestService
{
WebhookKey = webhookKey,
EventAlias = eventAlias,
RequestObject = _jsonSerializer.Serialize(payload),
RequestObject = _webhookJsonSerializer.Serialize(payload),
RetryCount = 0,
};

View File

@@ -123,6 +123,7 @@ public static partial class UmbracoBuilderExtensions
builder.Services.AddSingleton<IJsonSerializer, SystemTextJsonSerializer>();
builder.Services.AddSingleton<IConfigurationEditorJsonSerializer, SystemTextConfigurationEditorJsonSerializer>();
builder.Services.AddUnique<IWebhookJsonSerializer, SystemTextWebhookJsonSerializer>();
// register database builder
// *not* a singleton, don't want to keep it around

View File

@@ -0,0 +1,55 @@
using System.Text.Json;
using System.Text.Json.Serialization;
using System.Text.Json.Serialization.Metadata;
using Umbraco.Cms.Core.Models.DeliveryApi;
namespace Umbraco.Cms.Infrastructure.Serialization;
public abstract class ContentJsonTypeResolverBase : DefaultJsonTypeInfoResolver
{
public override JsonTypeInfo GetTypeInfo(Type type, JsonSerializerOptions options)
{
JsonTypeInfo jsonTypeInfo = base.GetTypeInfo(type, options);
Type[] derivedTypes = GetDerivedTypes(jsonTypeInfo);
if (derivedTypes.Length > 0)
{
ConfigureJsonPolymorphismOptions(jsonTypeInfo, derivedTypes);
}
return jsonTypeInfo;
}
public virtual Type[] GetDerivedTypes(JsonTypeInfo jsonTypeInfo)
{
if (jsonTypeInfo.Type == typeof(IApiContent))
{
return new[] { typeof(ApiContent) };
}
if (jsonTypeInfo.Type == typeof(IApiContentResponse))
{
return new[] { typeof(ApiContentResponse) };
}
if (jsonTypeInfo.Type == typeof(IRichTextElement))
{
return new[] { typeof(RichTextRootElement), typeof(RichTextGenericElement), typeof(RichTextTextElement) };
}
return Array.Empty<Type>();
}
public void ConfigureJsonPolymorphismOptions(JsonTypeInfo jsonTypeInfo, params Type[] derivedTypes)
{
jsonTypeInfo.PolymorphismOptions = new JsonPolymorphismOptions
{
UnknownDerivedTypeHandling = JsonUnknownDerivedTypeHandling.FailSerialization,
};
foreach (Type derivedType in derivedTypes)
{
jsonTypeInfo.PolymorphismOptions.DerivedTypes.Add(new JsonDerivedType(derivedType));
}
}
}

View File

@@ -0,0 +1,31 @@
using System.Text.Json;
using System.Text.Json.Serialization;
using Umbraco.Cms.Core.Serialization;
namespace Umbraco.Cms.Infrastructure.Serialization;
/// <inheritdoc />
public sealed class SystemTextWebhookJsonSerializer : SystemTextJsonSerializerBase, IWebhookJsonSerializer
{
private readonly JsonSerializerOptions _jsonSerializerOptions;
/// <summary>
/// Initializes a new instance of the <see cref="SystemTextWebhookJsonSerializer" /> class.
/// </summary>
public SystemTextWebhookJsonSerializer()
=> _jsonSerializerOptions = new JsonSerializerOptions()
{
PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
Converters =
{
new JsonStringEnumConverter(),
new JsonUdiConverter(),
new JsonUdiRangeConverter(),
new JsonObjectConverter(), // Required for block editor values
new JsonBlockValueConverter()
},
TypeInfoResolver = new WebhookJsonTypeResolver(),
};
protected override JsonSerializerOptions JsonSerializerOptions => _jsonSerializerOptions;
}

View File

@@ -0,0 +1,4 @@
namespace Umbraco.Cms.Infrastructure.Serialization;
public class WebhookJsonTypeResolver : ContentJsonTypeResolverBase
{ }