Skip to content

Commit 4b922c6

Browse files
committed
Merge branch 'v14/dev' into release/14.0
2 parents ca0c90e + f4cc408 commit 4b922c6

File tree

42 files changed

+334
-195
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

42 files changed

+334
-195
lines changed

src/Umbraco.Cms.Api.Management/OpenApi/IOpenApiDiscriminator.cs renamed to src/Umbraco.Cms.Api.Common/OpenApi/IOpenApiDiscriminator.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
namespace Umbraco.Cms.Api.Management.OpenApi;
1+
namespace Umbraco.Cms.Api.Common.OpenApi;
22

33
/// <summary>
44
/// Marker interface that ensure the type have a "$type" discriminator in the open api schema.

src/Umbraco.Cms.Api.Common/OpenApi/SwaggerRouteTemplatePipelineFilter.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,10 @@ protected virtual void SwaggerUiConfiguration(
6262
swaggerUiOptions.SwaggerEndpoint($"{name}/swagger.json", $"{apiInfo.Title}");
6363
}
6464

65+
// Add custom configuration from https://swagger.io/docs/open-source-tools/swagger-ui/usage/configuration/
66+
swaggerUiOptions.ConfigObject.PersistAuthorization = true; // persists authorization data so it would not be lost on browser close/refresh
67+
swaggerUiOptions.ConfigObject.Filter = string.Empty; // Enable the filter with an empty string as default filter.
68+
6569
swaggerUiOptions.OAuthClientId(Constants.OAuthClientIds.Swagger);
6670
swaggerUiOptions.OAuthUsePkce();
6771
}

src/Umbraco.Cms.Api.Common/Serialization/IUmbracoJsonTypeInfoResolver.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,6 @@ namespace Umbraco.Cms.Api.Common.Serialization;
55
public interface IUmbracoJsonTypeInfoResolver : IJsonTypeInfoResolver
66
{
77
IEnumerable<Type> FindSubTypes(Type type);
8+
9+
string? GetTypeDiscriminatorValue(Type type);
810
}

src/Umbraco.Cms.Api.Common/Serialization/UmbracoJsonTypeInfoResolver.cs

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
11
using System.Collections.Concurrent;
22
using System.Text.Json;
3+
using System.Text.Json.Serialization;
34
using System.Text.Json.Serialization.Metadata;
5+
using Umbraco.Cms.Api.Common.OpenApi;
46
using Umbraco.Cms.Core.Composing;
7+
using Umbraco.Extensions;
58

69
namespace Umbraco.Cms.Api.Common.Serialization;
710

@@ -15,6 +18,14 @@ public UmbracoJsonTypeInfoResolver(ITypeFinder typeFinder)
1518

1619
public IEnumerable<Type> FindSubTypes(Type type)
1720
{
21+
JsonDerivedTypeAttribute[] explicitJsonDerivedTypes = type
22+
.GetCustomAttributes<JsonDerivedTypeAttribute>(false)
23+
.ToArray();
24+
if (explicitJsonDerivedTypes.Any())
25+
{
26+
return explicitJsonDerivedTypes.Select(a => a.DerivedType);
27+
}
28+
1829
if (type.IsInterface is false)
1930
{
2031
// IMPORTANT: do NOT return an empty enumerable here. it will cause nullability to fail on reference
@@ -33,6 +44,24 @@ public IEnumerable<Type> FindSubTypes(Type type)
3344
return result;
3445
}
3546

47+
public string? GetTypeDiscriminatorValue(Type type)
48+
{
49+
JsonDerivedTypeAttribute? jsonDerivedTypeAttribute = type
50+
.GetBaseTypes(false)
51+
.WhereNotNull()
52+
.SelectMany(baseType => baseType.GetCustomAttributes<JsonDerivedTypeAttribute>(false))
53+
.FirstOrDefault(attr => attr.DerivedType == type);
54+
55+
if (jsonDerivedTypeAttribute is not null)
56+
{
57+
// IMPORTANT: do NOT perform fallback to type.Name here - it will work for the schema generation,
58+
// but not for the actual serialization, and then it's only going to cause confusion.
59+
return jsonDerivedTypeAttribute.TypeDiscriminator?.ToString();
60+
}
61+
62+
return typeof(IOpenApiDiscriminator).IsAssignableFrom(type) ? type.Name : null;
63+
}
64+
3665
public override JsonTypeInfo GetTypeInfo(Type type, JsonSerializerOptions options)
3766
{
3867
JsonTypeInfo result = base.GetTypeInfo(type, options);

src/Umbraco.Cms.Api.Management/Configuration/ConfigureUmbracoManagementApiSwaggerGenOptions.cs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
using Microsoft.Extensions.Options;
33
using Microsoft.OpenApi.Models;
44
using Swashbuckle.AspNetCore.SwaggerGen;
5+
using Umbraco.Cms.Api.Common.OpenApi;
56
using Umbraco.Cms.Api.Common.Serialization;
67
using Umbraco.Cms.Api.Management.DependencyInjection;
78
using Umbraco.Cms.Api.Management.OpenApi;
@@ -34,8 +35,8 @@ public void Configure(SwaggerGenOptions swaggerGenOptions)
3435
swaggerGenOptions.UseOneOfForPolymorphism();
3536

3637
// Ensure all types that implements the IOpenApiDiscriminator have a $type property in the OpenApi schema with the default value (The class name) that is expected by the server
37-
swaggerGenOptions.SelectDiscriminatorNameUsing(type => typeof(IOpenApiDiscriminator).IsAssignableFrom(type) ? "$type" : null);
38-
swaggerGenOptions.SelectDiscriminatorValueUsing(type => typeof(IOpenApiDiscriminator).IsAssignableFrom(type) ? type.Name : null);
38+
swaggerGenOptions.SelectDiscriminatorNameUsing(type => _umbracoJsonTypeInfoResolver.GetTypeDiscriminatorValue(type) is not null ? "$type" : null);
39+
swaggerGenOptions.SelectDiscriminatorValueUsing(_umbracoJsonTypeInfoResolver.GetTypeDiscriminatorValue);
3940

4041

4142
swaggerGenOptions.AddSecurityDefinition(

src/Umbraco.Cms.Api.Management/Controllers/DataType/Item/ItemDatatypeItemController.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,11 @@ public async Task<ActionResult> Item(
2727
CancellationToken cancellationToken,
2828
[FromQuery(Name = "id")] HashSet<Guid> ids)
2929
{
30+
if (ids.Count is 0)
31+
{
32+
return Ok(Enumerable.Empty<DataTypeItemResponseModel>());
33+
}
34+
3035
var dataTypes = new List<IDataType>();
3136
foreach (Guid id in ids)
3237
{

src/Umbraco.Cms.Api.Management/Controllers/Dictionary/Item/ItemDictionaryItemController.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,11 @@ public async Task<ActionResult> Item(
2727
CancellationToken cancellationToken,
2828
[FromQuery(Name = "id")] HashSet<Guid> ids)
2929
{
30+
if (ids.Count is 0)
31+
{
32+
return Ok(Enumerable.Empty<DictionaryItemItemResponseModel>());
33+
}
34+
3035
IEnumerable<IDictionaryItem> dictionaryItems = await _dictionaryItemService.GetManyAsync(ids.ToArray());
3136

3237
List<DictionaryItemItemResponseModel> responseModels = _mapper.MapEnumerable<IDictionaryItem, DictionaryItemItemResponseModel>(dictionaryItems);

src/Umbraco.Cms.Api.Management/Controllers/Document/Item/ItemDocumentItemController.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,11 @@ public async Task<ActionResult> Item(
2828
CancellationToken cancellationToken,
2929
[FromQuery(Name = "id")] HashSet<Guid> ids)
3030
{
31+
if (ids.Count is 0)
32+
{
33+
return Ok(Enumerable.Empty<DocumentItemResponseModel>());
34+
}
35+
3136
IEnumerable<IDocumentEntitySlim> documents = _entityService
3237
.GetAll(UmbracoObjectTypes.Document, ids.ToArray())
3338
.OfType<IDocumentEntitySlim>();

src/Umbraco.Cms.Api.Management/Controllers/DocumentType/Item/ItemDocumentTypeItemController.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,11 @@ public async Task<IActionResult> Item(
2727
CancellationToken cancellationToken,
2828
[FromQuery(Name = "id")] HashSet<Guid> ids)
2929
{
30+
if (ids.Count is 0)
31+
{
32+
return Ok(Enumerable.Empty<DocumentTypeItemResponseModel>());
33+
}
34+
3035
IEnumerable<IContentType> contentTypes = _contentTypeService.GetAll(ids);
3136
List<DocumentTypeItemResponseModel> responseModels = _mapper.MapEnumerable<IContentType, DocumentTypeItemResponseModel>(contentTypes);
3237
return await Task.FromResult(Ok(responseModels));
Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,12 @@
99
namespace Umbraco.Cms.Api.Management.Controllers.Language.Item;
1010

1111
[ApiVersion("1.0")]
12-
public class ItemsLanguageEntityController : LanguageEntityControllerBase
12+
public class ItemLanguageItemController : LanguageItemControllerBase
1313
{
1414
private readonly ILanguageService _languageService;
1515
private readonly IUmbracoMapper _mapper;
1616

17-
public ItemsLanguageEntityController(ILanguageService languageService, IUmbracoMapper mapper)
17+
public ItemLanguageItemController(ILanguageService languageService, IUmbracoMapper mapper)
1818
{
1919
_languageService = languageService;
2020
_mapper = mapper;
@@ -23,10 +23,15 @@ public ItemsLanguageEntityController(ILanguageService languageService, IUmbracoM
2323
[HttpGet]
2424
[MapToApiVersion("1.0")]
2525
[ProducesResponseType(typeof(IEnumerable<LanguageItemResponseModel>), StatusCodes.Status200OK)]
26-
public async Task<ActionResult> Items(
26+
public async Task<IActionResult> Item(
2727
CancellationToken cancellationToken,
2828
[FromQuery(Name = "isoCode")] HashSet<string> isoCodes)
2929
{
30+
if (isoCodes.Count is 0)
31+
{
32+
return Ok(Enumerable.Empty<LanguageItemResponseModel>());
33+
}
34+
3035
IEnumerable<ILanguage> languages = await _languageService.GetMultipleAsync(isoCodes);
3136
List<LanguageItemResponseModel> entityResponseModels = _mapper.MapEnumerable<ILanguage, LanguageItemResponseModel>(languages);
3237
return Ok(entityResponseModels);

0 commit comments

Comments
 (0)