Merge branch 'v13/dev' into v13/feature/extension-model

This commit is contained in:
kjac
2023-02-15 14:06:15 +01:00
21 changed files with 199 additions and 2638 deletions

View File

@@ -110,7 +110,10 @@ stages:
}
}
dotnet pack $(solution) --configuration $(buildConfiguration) --no-build --output $(Build.ArtifactStagingDirectory)/nupkg
foreach($csproj in Get-ChildItem Path "src/" -Recurse -Filter *.csproj)
{
dotnet pack $csproj --configuration $(buildConfiguration) --no-build --output $(Build.ArtifactStagingDirectory)/nupkg
}
- script: |
sha="$(Build.SourceVersion)"
sha=${sha:0:7}

View File

@@ -0,0 +1,12 @@
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Options;
namespace Umbraco.Cms.Api.Common.Configuration;
public class ConfigureApiBehaviorOptions : IConfigureOptions<ApiBehaviorOptions>
{
public void Configure(ApiBehaviorOptions options) =>
// disable ProblemDetails as default result type for every non-success response (i.e. 404)
// - see https://learn.microsoft.com/en-us/dotnet/api/microsoft.aspnetcore.mvc.apibehavioroptions.suppressmapclienterrors
options.SuppressMapClientErrors = true;
}

View File

@@ -4,7 +4,7 @@ using Microsoft.Extensions.Logging;
namespace Umbraco.Cms.Api.Common.Json;
public class NamedSystemTextJsonInputFormatter : SystemTextJsonInputFormatter
internal class NamedSystemTextJsonInputFormatter : SystemTextJsonInputFormatter
{
private readonly string _jsonOptionsName;

View File

@@ -3,7 +3,8 @@ using Microsoft.AspNetCore.Mvc.Formatters;
namespace Umbraco.Cms.Api.Common.Json;
public class NamedSystemTextJsonOutputFormatter : SystemTextJsonOutputFormatter
internal class NamedSystemTextJsonOutputFormatter : SystemTextJsonOutputFormatter
{
private readonly string _jsonOptionsName;

View File

@@ -5,6 +5,7 @@ using Umbraco.Cms.Core.Models;
using Umbraco.Cms.Core.Services;
using Umbraco.Cms.Api.Management.ViewModels.Dictionary;
using Umbraco.Cms.Api.Common.ViewModels.Pagination;
using Umbraco.Cms.Core;
namespace Umbraco.Cms.Api.Management.Controllers.Dictionary;
@@ -25,7 +26,7 @@ public class AllDictionaryController : DictionaryControllerBase
public async Task<ActionResult<PagedViewModel<DictionaryOverviewViewModel>>> All(int skip = 0, int take = 100)
{
// unfortunately we can't paginate here...we'll have to get all and paginate in memory
IDictionaryItem[] items = (await _dictionaryItemService.GetDescendantsAsync(null)).ToArray();
IDictionaryItem[] items = (await _dictionaryItemService.GetDescendantsAsync(Constants.System.RootKey)).ToArray();
var model = new PagedViewModel<DictionaryOverviewViewModel>
{
Total = items.Length,

View File

@@ -23,7 +23,7 @@ public class ExportDictionaryController : DictionaryControllerBase
[HttpGet("{key:guid}/export")]
[MapToApiVersion("1.0")]
[ProducesResponseType(typeof(FileContentResult), StatusCodes.Status200OK)]
[ProducesResponseType(typeof(NotFoundResult), StatusCodes.Status404NotFound)]
[ProducesResponseType(StatusCodes.Status404NotFound)]
public async Task<IActionResult> Export(Guid key, bool includeChildren = false)
{
IDictionaryItem? dictionaryItem = await _dictionaryItemService.GetAsync(key);

View File

@@ -41,7 +41,6 @@ public class SetupInstallController : InstallControllerBase
InstallData data = _mapper.Map<InstallData>(installData)!;
await _installService.Install(data);
var backOfficePath = _globalSettings.GetBackOfficePath(_hostingEnvironment);
return Created(backOfficePath, null);
return Ok();
}
}

View File

@@ -29,7 +29,7 @@ public class UpdateLanguageController : LanguageControllerBase
[HttpPut($"{{{nameof(isoCode)}}}")]
[MapToApiVersion("1.0")]
[ProducesResponseType(typeof(NotFoundResult), StatusCodes.Status404NotFound)]
[ProducesResponseType(StatusCodes.Status404NotFound)]
[ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status400BadRequest)]
[ProducesResponseType(StatusCodes.Status200OK)]
public async Task<IActionResult> Update(string isoCode, LanguageUpdateModel languageUpdateModel)

View File

@@ -25,7 +25,7 @@ public class ByNameSavedSearchLogViewerController : SavedSearchLogViewerControll
/// <returns>The saved log search or not found result.</returns>
[HttpGet("{name}")]
[MapToApiVersion("1.0")]
[ProducesResponseType(typeof(NotFoundResult), StatusCodes.Status404NotFound)]
[ProducesResponseType(StatusCodes.Status404NotFound)]
[ProducesResponseType(typeof(SavedLogSearchViewModel), StatusCodes.Status200OK)]
public async Task<ActionResult<SavedLogSearchViewModel>> ByName(string name)
{

View File

@@ -20,7 +20,7 @@ public class DeleteSavedSearchLogViewerController : SavedSearchLogViewerControll
/// <returns>The result of the deletion.</returns>
[HttpDelete("{name}")]
[MapToApiVersion("1.0")]
[ProducesResponseType(typeof(NotFoundResult), StatusCodes.Status404NotFound)]
[ProducesResponseType(StatusCodes.Status404NotFound)]
[ProducesResponseType(StatusCodes.Status200OK)]
public async Task<IActionResult> Delete(string name)
{

View File

@@ -29,7 +29,7 @@ public class BuildModelsBuilderController : ModelsBuilderControllerBase
}
[HttpPost("build")]
[ProducesResponseType(typeof(CreatedResult), StatusCodes.Status201Created)]
[ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status428PreconditionRequired)]
[MapToApiVersion("1.0")]
public async Task<IActionResult> BuildModels()
@@ -46,7 +46,7 @@ public class BuildModelsBuilderController : ModelsBuilderControllerBase
Type = "Error",
};
return await Task.FromResult(new ObjectResult(problemDetailsModel) { StatusCode = StatusCodes.Status428PreconditionRequired });
return new ObjectResult(problemDetailsModel) { StatusCode = StatusCodes.Status428PreconditionRequired };
}
_modelGenerator.GenerateModels();
@@ -57,6 +57,6 @@ public class BuildModelsBuilderController : ModelsBuilderControllerBase
_mbErrors.Report("Failed to build models.", e);
}
return await Task.FromResult(Created("api/v1/modelsBuilderDashboard", null));
return Ok();
}
}

View File

@@ -21,7 +21,7 @@ public class ByIdRelationController : RelationControllerBase
[HttpGet("{id:int}")]
[MapToApiVersion("1.0")]
[ProducesResponseType(typeof(RelationViewModel), StatusCodes.Status200OK)]
[ProducesResponseType(typeof(NotFoundResult), StatusCodes.Status404NotFound)]
[ProducesResponseType(StatusCodes.Status404NotFound)]
public async Task<ActionResult> ById(int id)
{
IRelation? relation = _relationService.GetById(id);

View File

@@ -59,8 +59,8 @@ public static class BackOfficeAuthBuilderExtensions
{
// Enable the authorization and token endpoints.
options
.SetAuthorizationEndpointUris(Controllers.Security.Paths.BackOfficeApiAuthorizationEndpoint)
.SetTokenEndpointUris(Controllers.Security.Paths.BackOfficeApiTokenEndpoint);
.SetAuthorizationEndpointUris(Controllers.Security.Paths.BackOfficeApiAuthorizationEndpoint.TrimStart('/'))
.SetTokenEndpointUris(Controllers.Security.Paths.BackOfficeApiTokenEndpoint.TrimStart('/'));
// Enable authorization code flow with PKCE
options

View File

@@ -1,6 +1,3 @@
using System.Text.Json;
using System.Text.Json.Serialization;
using System.Text.Json.Serialization.Metadata;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;
using Umbraco.Cms.Core.Composing;
@@ -9,7 +6,6 @@ using Umbraco.Cms.Api.Common.Configuration;
using Umbraco.Cms.Api.Common.DependencyInjection;
using Umbraco.Cms.Api.Management.DependencyInjection;
using Umbraco.Cms.Api.Management.Serialization;
using Umbraco.Cms.Infrastructure.Serialization;
using Umbraco.Cms.Web.Common.ApplicationBuilder;
using Umbraco.New.Cms.Core.Models.Configuration;
@@ -46,6 +42,7 @@ public class ManagementApiComposer : IComposer
services
.ConfigureOptions<ConfigureMvcOptions>()
.ConfigureOptions<ConfigureApiBehaviorOptions>()
.Configure<UmbracoPipelineOptions>(options =>
{
options.AddFilter(new UmbracoPipelineFilter(

File diff suppressed because it is too large Load Diff

View File

@@ -72,6 +72,7 @@ internal sealed class ConfigureUmbracoSwaggerGenOptions : IConfigureOptions<Swag
swaggerGenOptions.CustomSchemaIds(SchemaIdGenerator.Generate);
swaggerGenOptions.SupportNonNullableReferenceTypes();
swaggerGenOptions.OperationFilter<ReponseHeaderOperationFilter>();
swaggerGenOptions.UseOneOfForPolymorphism();
swaggerGenOptions.UseAllOfForInheritance();
swaggerGenOptions.SelectSubTypesUsing(_umbracoJsonTypeInfoResolver.FindSubTypes);

View File

@@ -0,0 +1,36 @@
using Microsoft.AspNetCore.Http;
using Microsoft.OpenApi.Models;
using Swashbuckle.AspNetCore.SwaggerGen;
namespace Umbraco.Cms.Api.Management.OpenApi;
internal class ReponseHeaderOperationFilter : IOperationFilter
{
public void Apply(OpenApiOperation operation, OperationFilterContext context)
{
foreach ((var key, OpenApiResponse? value) in operation.Responses)
{
switch (int.Parse(key))
{
case StatusCodes.Status201Created:
SetHeader(value, "Location", "Location of the newly created resource", "string", "uri");
break;
}
}
}
private void SetHeader(OpenApiResponse value, string headerName, string description, string type, string format)
{
if (value.Headers is null)
{
value.Headers = new Dictionary<string, OpenApiHeader>();
}
value.Headers[headerName] = new OpenApiHeader()
{
Description = description,
Schema = new OpenApiSchema { Description = description, Type = type, Format = format }
};
}
}

View File

@@ -13,8 +13,8 @@
<PackageReference Include="Microsoft.AspNetCore.Mvc.Versioning" Version="5.0.0" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.Versioning.ApiExplorer" Version="5.0.0" />
<PackageReference Include="Microsoft.EntityFrameworkCore.InMemory" Version="7.0.2" />
<PackageReference Include="OpenIddict.AspNetCore" Version="3.1.1" />
<PackageReference Include="OpenIddict.EntityFrameworkCore" Version="3.1.1" />
<PackageReference Include="OpenIddict.AspNetCore" Version="4.0.0" />
<PackageReference Include="OpenIddict.EntityFrameworkCore" Version="4.0.0" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.5.0" />
</ItemGroup>

View File

@@ -18,6 +18,11 @@ public static partial class Constants
/// <remarks>Use this instead of re-creating the string everywhere.</remarks>
public const string RootString = "-1";
/// <summary>
/// The GUID identifier for global system root node.
/// </summary>
public static readonly Guid? RootKey = null;
/// <summary>
/// The integer identifier for content's recycle bin.
/// </summary>

View File

@@ -12,6 +12,6 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="OpenIddict.Abstractions" Version="3.1.1" />
<PackageReference Include="OpenIddict.Abstractions" Version="4.0.0" />
</ItemGroup>
</Project>