Skip to content

Commit

Permalink
V14: Merge 13 to 14 (#16340)
Browse files Browse the repository at this point in the history
* Updates JSON schema for Umbraco 10 with latest references for Forms and Deploy (#15918)

* Ported over #15928 changes for 13.3 RC (#16023)

* Ported over #15928 changes for 13.3 RC

* Use GetOrAdd()

* Lock dictionary initialization

---------

Co-authored-by: Jason Elkin <jasonelkin86@gmail.com>

* Make the API content response builder extendable (#16056)

* Make the API content response builder extendable

* DeliveryApiJsonTypeResolver needs to be extendable too

* bump rc to regular

* Bump to next minor

* Add blocks in RTE telemetry (#16104)

* Add blocks telemetry

* Use constants and update tests

* V13: Add property type information to telemetry (#16109)

* Add property type counts to telemetry

* Use constants and fix tests

* Update description

* V10: Fix for fallback file upload (#14892) (#15868)

* Fix for fallback file upload (#14892)

* Added check for file type

* Removed unneeded null checks and fixed tabs

* Cleaning

* Cleanups, cleanups, and removal of unneeded null checks

* Reverted removal of relationshipservice

* Revert null check removals (too risky)

---------

Co-authored-by: Ambert van Unen <AvanUnen@ilionx.com>
Co-authored-by: Laura Neto <12862535+lauraneto@users.noreply.github.com>

(cherry picked from commit 0b5d1f8)

* Fix up formatting

---------

Co-authored-by: Ambert van Unen <ambertvu@gmail.com>

* Implementors using Umbraco.Tests.Integration won't have to override GetLocalizedTextService

(cherry picked from commit b001668)
(cherry picked from commit 2bb56f1)

* Fix logic for retrieving lastKnownElement

(cherry picked from commit cae106b)

* bump version

* Bump version

* Bump version

* Since v13 properties can sometimes be of type IRichTextEditorIntermediateValue - this was unexpected in the XPath navigator code (#16121)

* Webhook log improvements (#16200)

* fix: include all headers in webhook log

* feat: return webhook log status from server

* feat: make webhook logs deep linkable

* feat: add webhook log pagination

* feat: improve webhook request/response body preview

* V13: Optimize custom MVC routing (#16218)

* Introduce EagerMatcherPolicy to conditionally bypass content routing

* Ensure that the candidate we disable dynamic routing for is valid

* Skip Umbraco endpoints

* Simplify logic a bit

* Move install logic to matcher

* Ensure that dynamic routing is still skipped when in upgrade state

* Fixup comments

* Reduce nesting a bit

* Don't show maintenance page when statically routed controllers are hít

* Remove excess check, since installer requests are statically routed

* V13: Optimize custom MVC routing (#16218)

* Introduce EagerMatcherPolicy to conditionally bypass content routing

* Ensure that the candidate we disable dynamic routing for is valid

* Skip Umbraco endpoints

* Simplify logic a bit

* Move install logic to matcher

* Ensure that dynamic routing is still skipped when in upgrade state

* Fixup comments

* Reduce nesting a bit

* Don't show maintenance page when statically routed controllers are hít

* Remove excess check, since installer requests are statically routed

(cherry picked from commit ba9ddd1)

* Property source level variation should only be applied when configured (#16270)

* Property source level variation should only be applied when configured (#16270)

(cherry picked from commit ab32bac)

* Merge pull request from GHSA-j74q-mv2c-rxmp

* Merge pull request from GHSA-j74q-mv2c-rxmp

* Merge pull request from GHSA-j74q-mv2c-rxmp

* Fix up after merge

* Remove obselete test

---------

Co-authored-by: Andy Butland <abutland73@gmail.com>
Co-authored-by: Kenn Jacobsen <kja@umbraco.dk>
Co-authored-by: Jason Elkin <jasonelkin86@gmail.com>
Co-authored-by: Sven Geusens <sge@umbraco.dk>
Co-authored-by: Mole <nikolajlauridsen@protonmail.ch>
Co-authored-by: Ambert van Unen <ambertvu@gmail.com>
Co-authored-by: Lars-Erik <lars-erik@aabech.no>
Co-authored-by: Joshua Daniel Pratt Nielsen <jdpnielsen@gmail.com>
Co-authored-by: Bjarke Berg <mail@bergmania.dk>
Co-authored-by: Sebastiaan Janssen <sebastiaan@umbraco.com>
Co-authored-by: Rasmus John Pedersen <mail@rjp.dk>
  • Loading branch information
12 people authored May 22, 2024
1 parent 8ddb911 commit a4a9a27
Show file tree
Hide file tree
Showing 23 changed files with 548 additions and 145 deletions.
27 changes: 20 additions & 7 deletions src/Umbraco.Cms.Api.Delivery/Json/DeliveryApiJsonTypeResolver.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,23 +12,36 @@ public override JsonTypeInfo GetTypeInfo(Type type, JsonSerializerOptions option
{
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))
{
ConfigureJsonPolymorphismOptions(jsonTypeInfo, typeof(ApiContent));
return new[] { typeof(ApiContent) };
}
else if (jsonTypeInfo.Type == typeof(IApiContentResponse))

if (jsonTypeInfo.Type == typeof(IApiContentResponse))
{
ConfigureJsonPolymorphismOptions(jsonTypeInfo, typeof(ApiContentResponse));
return new[] { typeof(ApiContentResponse) };
}
else if (jsonTypeInfo.Type == typeof(IRichTextElement))

if (jsonTypeInfo.Type == typeof(IRichTextElement))
{
ConfigureJsonPolymorphismOptions(jsonTypeInfo, typeof(RichTextRootElement), typeof(RichTextGenericElement), typeof(RichTextTextElement));
return new[] { typeof(RichTextRootElement), typeof(RichTextGenericElement), typeof(RichTextTextElement) };
}

return jsonTypeInfo;
return Array.Empty<Type>();
}

private void ConfigureJsonPolymorphismOptions(JsonTypeInfo jsonTypeInfo, params Type[] derivedTypes)
protected void ConfigureJsonPolymorphismOptions(JsonTypeInfo jsonTypeInfo, params Type[] derivedTypes)
{
jsonTypeInfo.PolymorphismOptions = new JsonPolymorphismOptions
{
Expand Down
5 changes: 5 additions & 0 deletions src/Umbraco.Core/Constants-Telemetry.cs
Original file line number Diff line number Diff line change
Expand Up @@ -35,5 +35,10 @@ public static class Telemetry
public static string WebhookTotal = $"{WebhookPrefix}Total";
public static string WebhookCustomHeaders = $"{WebhookPrefix}CustomHeaders";
public static string WebhookCustomEvent = $"{WebhookPrefix}CustomEvent";
public static string RichTextEditorCount = "RichTextEditorCount";
public static string RichTextBlockCount = "RichTextBlockCount";
public static string TotalPropertyCount = "TotalPropertyCount";
public static string HighestPropertyCount = "HighestPropertyCount";
public static string TotalCompositions = "TotalCompositions";
}
}
1 change: 1 addition & 0 deletions src/Umbraco.Core/Constants-Web.cs
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ public static class Routing
public const string ControllerToken = "controller";
public const string ActionToken = "action";
public const string AreaToken = "area";
public const string DynamicRoutePattern = "/{**umbracoSlug}";
}

public static class RoutePath
Expand Down
11 changes: 8 additions & 3 deletions src/Umbraco.Core/DeliveryApi/ApiContentResponseBuilder.cs
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
using Umbraco.Cms.Core.Models.DeliveryApi;
using Umbraco.Cms.Core.Models.PublishedContent;
using Umbraco.Cms.Core.Routing;
using Umbraco.Extensions;

namespace Umbraco.Cms.Core.DeliveryApi;

public sealed class ApiContentResponseBuilder : ApiContentBuilderBase<IApiContentResponse>, IApiContentResponseBuilder
public class ApiContentResponseBuilder : ApiContentBuilderBase<IApiContentResponse>, IApiContentResponseBuilder
{
private readonly IApiContentRouteBuilder _apiContentRouteBuilder;

Expand All @@ -14,6 +13,12 @@ public ApiContentResponseBuilder(IApiContentNameProvider apiContentNameProvider,
=> _apiContentRouteBuilder = apiContentRouteBuilder;

protected override IApiContentResponse Create(IPublishedContent content, string name, IApiContentRoute route, IDictionary<string, object?> properties)
{
IDictionary<string, IApiContentRoute> cultures = GetCultures(content);
return new ApiContentResponse(content.Key, name, content.ContentType.Alias, content.CreateDate, content.UpdateDate, route, properties, cultures);
}

protected virtual IDictionary<string, IApiContentRoute> GetCultures(IPublishedContent content)
{
var routesByCulture = new Dictionary<string, IApiContentRoute>();

Expand All @@ -35,6 +40,6 @@ protected override IApiContentResponse Create(IPublishedContent content, string
routesByCulture[publishedCultureInfo.Culture] = cultureRoute;
}

return new ApiContentResponse(content.Key, name, content.ContentType.Alias, content.CreateDate, content.UpdateDate, route, properties, routesByCulture);
return routesByCulture;
}
}
2 changes: 1 addition & 1 deletion src/Umbraco.Core/EmbeddedResources/Lang/en.xml
Original file line number Diff line number Diff line change
Expand Up @@ -476,7 +476,7 @@
<key alias="detailedLevelDescription"><![CDATA[We will send:
<ul>
<li>Anonymized site ID, Umbraco version, and packages installed.</li>
<li>Number of: Root nodes, Content nodes, Macros, Media, Document Types, Templates, Languages, Domains, User Group, Users, Members, Backoffice external login providers, Webhooks, and Property Editors in use.</li>
<li>Number of: Root nodes, Content nodes, Macros, Media, Document Types, Property Types, Compositions, Templates, Languages, Domains, User Group, Users, Members, Backoffice external login providers, Webhooks, rich text datatypes, blocks used in rich text datatypes, and Property Editors in use.</li>
<li>System information: Webserver, server OS, server framework, server OS language, and database provider.</li>
<li>Configuration settings: Modelsbuilder mode, if custom Umbraco path exists, ASP environment, whether the delivery API is enabled, and allows public access, and if you are in debug mode.</li>
</ul>
Expand Down
2 changes: 1 addition & 1 deletion src/Umbraco.Core/EmbeddedResources/Lang/en_us.xml
Original file line number Diff line number Diff line change
Expand Up @@ -470,7 +470,7 @@
We will send:
<ul>
<li>Anonymized site ID, Umbraco version, and packages installed.</li>
<li>Number of: Root nodes, Content nodes, Macros, Media, Document Types, Templates, Languages, Domains, User Group, Users, Members, Backoffice external login providers, and Property Editors in use.</li>
<li>Number of: Root nodes, Content nodes, Macros, Media, Document Types, Property Types, Compositions, Templates, Languages, Domains, User Group, Users, Members, Backoffice external login providers, Webhooks, rich text datatypes, blocks used in rich text datatypes, and Property Editors in use.</li>
<li>System information: Webserver, server OS, server framework, server OS language, and database provider.</li>
<li>Configuration settings: Modelsbuilder mode, if custom Umbraco path exists, ASP environment, whether the delivery API is enabled, and allows public access, and if you are in debug mode.</li>
</ul>
Expand Down
2 changes: 2 additions & 0 deletions src/Umbraco.Core/Models/WebhookLog.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,4 +27,6 @@ public class WebhookLog
public string ResponseBody { get; set; } = string.Empty;

public bool ExceptionOccured { get; set; }

public bool IsSuccessStatusCode { get; set; }
}
2 changes: 1 addition & 1 deletion src/Umbraco.Core/Routing/UmbracoRequestPaths.cs
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ private static bool IsPluginControllerRoute(string path)
/// <summary>
/// Checks if the current uri is an install request
/// </summary>
public bool IsInstallerRequest(string absPath) => absPath.InvariantStartsWith(_installPath);
public bool IsInstallerRequest(string absPath) => absPath.InvariantStartsWith(_managementApiPath);

/// <summary>
/// Rudimentary check to see if it's not a server side request
Expand Down
24 changes: 24 additions & 0 deletions src/Umbraco.Core/Routing/WebPath.cs
Original file line number Diff line number Diff line change
Expand Up @@ -50,4 +50,28 @@ public static string Combine(params string[]? paths)

return sb.ToString();
}


/// <summary>
/// Determines whether the provided web path is well-formed according to the specified UriKind.
/// </summary>
/// <param name="webPath">The web path to check. This can be null.</param>
/// <param name="uriKind">The kind of Uri (Absolute, Relative, or RelativeOrAbsolute).</param>
/// <returns>
/// true if <paramref name="webPath"/> is well-formed; otherwise, false.
/// </returns>
public static bool IsWellFormedWebPath(string? webPath, UriKind uriKind)
{
if (string.IsNullOrWhiteSpace(webPath))
{
return false;
}

if (webPath.StartsWith("//"))
{
return uriKind is not UriKind.Relative;
}

return Uri.IsWellFormedUriString(webPath, uriKind);
}
}
5 changes: 3 additions & 2 deletions src/Umbraco.Core/Services/WebhookLogFactory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,16 @@ public async Task<WebhookLog> CreateAsync(string eventAlias, HttpRequestMessage
Url = webhook.Url,
WebhookKey = webhook.Key,
RetryCount = retryCount,
RequestHeaders = requestMessage.Headers.ToString(),
RequestHeaders = $"{requestMessage.Content?.Headers}{requestMessage.Headers}",
RequestBody = await requestMessage.Content?.ReadAsStringAsync(cancellationToken)!,
ExceptionOccured = exception is not null,
};

if (httpResponseMessage is not null)
{
log.StatusCode = MapStatusCodeToMessage(httpResponseMessage.StatusCode);
log.ResponseHeaders = httpResponseMessage.Headers.ToString();
log.IsSuccessStatusCode = httpResponseMessage.IsSuccessStatusCode;
log.ResponseHeaders = $"{httpResponseMessage.Content.Headers}{httpResponseMessage.Headers}";
log.ResponseBody = await httpResponseMessage.Content.ReadAsStringAsync(cancellationToken);
}
else if (exception is HttpRequestException httpRequestException)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ public static IUmbracoBuilder AddTelemetryProviders(this IUmbracoBuilder builder
builder.Services.AddTransient<IDetailedTelemetryProvider, SystemTroubleshootingInformationTelemetryProvider>();
builder.Services.AddTransient<IDetailedTelemetryProvider, DeliveryApiTelemetryProvider>();
builder.Services.AddTransient<IDetailedTelemetryProvider, WebhookTelemetryProvider>();
builder.Services.AddTransient<IDetailedTelemetryProvider, BlocksInRichTextTelemetryProvider>();
return builder;
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using Umbraco.Cms.Core.Models;
using System.Text.RegularExpressions;
using Umbraco.Cms.Core.Models;
using Umbraco.Cms.Core.Webhooks;
using Umbraco.Cms.Infrastructure.Persistence.Dtos;

Expand Down Expand Up @@ -33,6 +34,7 @@ public static WebhookLog DtoToEntity(WebhookLogDto dto) =>
ResponseBody = dto.ResponseBody,
RetryCount = dto.RetryCount,
StatusCode = dto.StatusCode,
IsSuccessStatusCode = Regex.IsMatch(dto.StatusCode, "^.*\\(2(\\d{2})\\)$"),
Key = dto.Key,
Id = dto.Id,
Url = dto.Url,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
using Umbraco.Cms.Core;
using Umbraco.Cms.Core.Models;
using Umbraco.Cms.Core.PropertyEditors;
using Umbraco.Cms.Core.Services;
using Umbraco.Cms.Infrastructure.Telemetry.Interfaces;

namespace Umbraco.Cms.Infrastructure.Telemetry.Providers;

public class BlocksInRichTextTelemetryProvider : IDetailedTelemetryProvider
{
private readonly IDataTypeService _dataTypeService;

public BlocksInRichTextTelemetryProvider(IDataTypeService dataTypeService)
{
_dataTypeService = dataTypeService;
}

public IEnumerable<UsageInformation> GetInformation()
{
IEnumerable<IDataType> richTextDataTypes = _dataTypeService.GetByEditorAliasAsync(Constants.PropertyEditors.Aliases.RichText).GetAwaiter().GetResult().ToArray();
int registeredBlocks = 0;
yield return new UsageInformation(Constants.Telemetry.RichTextEditorCount, richTextDataTypes.Count());

foreach (IDataType richTextDataType in richTextDataTypes)
{
if (richTextDataType.ConfigurationObject is not RichTextConfiguration richTextConfiguration)
{
// Might be some custom data type, skip it
continue;
}

if (richTextConfiguration.Blocks is null)
{
continue;
}

registeredBlocks += richTextConfiguration.Blocks.Length;
}

yield return new UsageInformation(Constants.Telemetry.RichTextBlockCount, registeredBlocks);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,19 @@ public IEnumerable<UsageInformation> GetInformation()
{
IEnumerable<IContentType> contentTypes = _contentTypeService.GetAll();
var propertyTypes = new HashSet<string>();
var propertyTypeCounts = new List<int>();
var totalCompositions = 0;

foreach (IContentType contentType in contentTypes)
{
propertyTypes.UnionWith(contentType.PropertyTypes.Select(x => x.PropertyEditorAlias));
propertyTypeCounts.Add(contentType.CompositionPropertyTypes.Count());
totalCompositions += contentType.CompositionAliases().Count();
}

yield return new UsageInformation(Constants.Telemetry.Properties, propertyTypes);
yield return new UsageInformation(Constants.Telemetry.TotalPropertyCount, propertyTypeCounts.Sum());
yield return new UsageInformation(Constants.Telemetry.HighestPropertyCount, propertyTypeCounts.Count > 0 ? propertyTypeCounts.Max() : 0);
yield return new UsageInformation(Constants.Telemetry.TotalCompositions, totalCompositions);
}
}
Loading

0 comments on commit a4a9a27

Please sign in to comment.