NejCommon.NET/Controllers/IApiDescriptionVisibilitySchemaFilter.cs
honzapatCZ 77a536ee79 init
2024-09-02 17:30:42 +02:00

118 lines
4.8 KiB
C#

using System;
using System.Linq;
using Microsoft.AspNetCore.Mvc.ApiExplorer;
using Microsoft.OpenApi.Models;
using Swashbuckle.AspNetCore.SwaggerGen;
namespace NejCommon.Controllers
{
public class IApiDescriptionVisibilitySchemaFilter : ISchemaFilter
{
List<OpenApiSchema> schemas = new List<OpenApiSchema>();
public void Apply(OpenApiSchema schema, SchemaFilterContext context)
{
RemoveSchemas(context);
//Get the .net type of the schema
var type = context.Type;
//Get attributes that imlement IApiDescriptionVisibilityProvider interface
var attributes = type.GetCustomAttributes(typeof(IApiDescriptionVisibilityProvider), true).Select(a => a as IApiDescriptionVisibilityProvider);
//If there are no attributes, then return
if (!attributes.Any())
return;
var ignore = attributes.Any(a => a.IgnoreApi);
//If the schema is ignored, then remove it from the schema repository
if (!ignore)
return;
schemas.Add(schema);
RemoveSchemas(context);
}
public void RemoveSchemas(SchemaFilterContext context)
{
foreach (var schema in schemas)
{
var key = context.SchemaRepository.Schemas.FirstOrDefault(k => k.Value == schema).Key;
if (string.IsNullOrWhiteSpace(key))
continue;
//Console.WriteLine($"Removing schema {key}");
context.SchemaRepository.Schemas.Remove(key);
}
}
}
public class OrphanedFilter : IDocumentFilter
{
public void Apply(OpenApiDocument swaggerDoc, DocumentFilterContext context)
{
// Add all paths parameters, bodies, responses and query parameters to a list
var ops = swaggerDoc.Paths.SelectMany(p => p.Value.Operations).ToList();
var Parameters = ops
.SelectMany(o => o.Value.Parameters)
.Select(x => x.Schema).ToList();
var requst = ops
.Select(o => o.Value.RequestBody)
.Where(c => c != null)
.SelectMany(x => x.Content)
.Select(c => c.Value.Schema).ToList();
var res = ops
.SelectMany(o => o.Value.Responses)
.SelectMany(r => r.Value.Content)
.Select(c => c.Value.Schema).ToList();
var usedSchemas = Parameters.Union(requst).Union(res).Distinct();
/*
Console.WriteLine($"Used schemas: {string.Join(", ", swaggerDoc.Components.Parameters)}");
var usedSchemas = swaggerDoc.Components.Parameters.Select(x => x.Value.Schema).
Union(swaggerDoc.Components.RequestBodies.Select(x => x.Value.Content).SelectMany(x => x.Values).Select(x => x.Schema)).
Union(swaggerDoc.Components.Responses.Select(x => x.Value.Content).SelectMany(x => x.Values).Select(x => x.Schema)).
Distinct();
*/
var schemas = usedSchemas.ToList();
var currentSchemas = new Dictionary<string, OpenApiSchema>();
foreach(var sch in schemas){
ExpandSchemas(context.SchemaRepository, currentSchemas, sch);
}
//Console.WriteLine($"Used schemas: {string.Join(", ", currentSchemas.Keys)}");
var orphanedSchemas = swaggerDoc.Components.Schemas.Where(x => !currentSchemas.ContainsKey(x.Key)).ToDictionary(x => x.Key, x => x.Value);
//Console.WriteLine($"Unused schemas: {string.Join(", ", orphanedSchemas.Keys)}");
swaggerDoc.Components.Schemas = swaggerDoc.Components.Schemas.Where(x => currentSchemas.ContainsKey(x.Key)).ToDictionary(x => x.Key, x => x.Value);
}
public static void ExpandSchemas(SchemaRepository repo, Dictionary<string, OpenApiSchema> currentSchemas, OpenApiSchema schemaToExpand)
{
if(schemaToExpand == null)
return;
if(schemaToExpand.Type == "array")
schemaToExpand = schemaToExpand.Items;
var selfRef = schemaToExpand.Reference?.Id;
var properties = schemaToExpand.Properties.Values.ToList();
if(selfRef != null && !currentSchemas.ContainsKey(selfRef) && repo.Schemas.ContainsKey(selfRef))
{
var sch = repo.Schemas[selfRef];
currentSchemas.Add(selfRef, sch);
ExpandSchemas(repo, currentSchemas, sch);
}
foreach(var sch in properties)
{
ExpandSchemas(repo, currentSchemas, sch);
}
}
}
}