Files
KArtSell.Aegis/docs/Design/kbx-foundation-v36/backend/Shared/Contracts/KbxApiContractSwaggerExtensions.cs
T

79 lines
3.4 KiB
C#

using System.Text.RegularExpressions;
using Microsoft.OpenApi.Any;
using Microsoft.OpenApi.Models;
using Shared.Contracts.Generated;
using Shared.Problems;
using Swashbuckle.AspNetCore.SwaggerGen;
namespace Shared.Contracts;
public static class KbxApiContractSwaggerExtensions
{
public static void AddKbxApiContracts(this SwaggerGenOptions options)
{
options.OperationFilter<KbxApiContractOperationFilter>();
options.OperationFilter<KbxProblemOpenApiOperationFilter>();
}
}
public sealed class KbxApiContractOperationFilter : IOperationFilter
{
public void Apply(OpenApiOperation operation, OperationFilterContext context)
{
var method = context.ApiDescription.HttpMethod?.ToUpperInvariant();
var relative = "/" + (context.ApiDescription.RelativePath ?? string.Empty).TrimStart('/');
var normalized = Normalize(relative);
var contract = KbxApiCatalog.All.FirstOrDefault(x =>
x.Method == method && Normalize(x.Path) == normalized);
if (contract is null) return;
operation.OperationId = contract.Id;
operation.Extensions["x-kbx-permission"] = new OpenApiString(contract.Permission ?? string.Empty);
operation.Extensions["x-kbx-idempotency"] = new OpenApiString(contract.Idempotency);
operation.Extensions["x-kbx-kind"] = new OpenApiString(contract.Kind);
}
private static string Normalize(string value) =>
Regex.Replace(value, @"\{([^}:]+):[^}]+\}", "{$1}").ToLowerInvariant();
}
public sealed class KbxProblemOpenApiOperationFilter : IOperationFilter
{
public void Apply(OpenApiOperation operation, OperationFilterContext context)
{
var problem = new OpenApiSchema
{
OneOf = new List<OpenApiSchema>
{
context.SchemaGenerator.GenerateSchema(typeof(KbxValidationProblem), context.SchemaRepository),
context.SchemaGenerator.GenerateSchema(typeof(KbxBusinessProblem), context.SchemaRepository),
context.SchemaGenerator.GenerateSchema(typeof(KbxConflictProblem), context.SchemaRepository),
context.SchemaGenerator.GenerateSchema(typeof(KbxPermissionProblem), context.SchemaRepository),
context.SchemaGenerator.GenerateSchema(typeof(KbxNotFoundProblem), context.SchemaRepository),
context.SchemaGenerator.GenerateSchema(typeof(KbxIntegrationProblem), context.SchemaRepository),
context.SchemaGenerator.GenerateSchema(typeof(KbxSystemProblem), context.SchemaRepository),
}
};
Add(operation, "400", "Validation problem", problem);
Add(operation, "403", "Permission problem", problem);
Add(operation, "404", "Not found problem", problem);
Add(operation, "409", "Conflict or business rule problem", problem);
Add(operation, "422", "Business rule problem", problem);
Add(operation, "500", "System problem", problem);
}
private static void Add(OpenApiOperation operation, string status, string description, OpenApiSchema schema)
{
if (operation.Responses.ContainsKey(status)) return;
operation.Responses[status] = new OpenApiResponse
{
Description = description,
Content = new Dictionary<string, OpenApiMediaType>
{
["application/json"] = new() { Schema = schema }
}
};
}
}