diff --git a/CHANGELOG.md b/CHANGELOG.md
index f1b8346..462ebcc 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -8,6 +8,10 @@
These are the changes to each version that has been released on the [nuget](https://www.nuget.org/packages/Unchase.Swashbuckle.AspNetCore.Extensions/).
+## v2.2.0 `(2020-02-28)`
+
+- [x] Add feature: remove Paths and Definitions from OpenApi documentation for specific controller action without accepted roles
+
## v2.1.6 `(2020-02-21)`
- [x] Fix bug: replace `
` tag to `{Envirinment.NewLine}{Envirinment.NewLine}` for enum descriptions
diff --git a/README.md b/README.md
index 1ec84b0..7447528 100644
--- a/README.md
+++ b/README.md
@@ -108,7 +108,7 @@ public void ConfigureServices(IServiceCollection services)
}
```
-2. **Hide Paths and Defenitions from OpenApi documentation** without accepted roles in OpenApi document:
+2. **Hide Paths and Definitions from OpenApi documentation** without accepted roles:
- In the _ConfigureServices_ method of _Startup.cs_, inside your `AddSwaggerGen` call, enable `HidePathsAndDefinitionsByRolesDocumentFilter` document filter:
```csharp
@@ -127,6 +127,28 @@ public void ConfigureServices(IServiceCollection services)
}
```
+- Since [v2.2.0](https://github.com/unchase/Unchase.Swashbuckle.AspNetCore.Extensions/releases/tag/v2.2.0) you can hide Paths and Definitions from OpenApi documentation for specific controller action without accepted roles like this:
+
+```csharp
+// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
+public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
+{
+ //...
+
+ // enable middleware to serve generated Swagger as a JSON endpoint.
+ app.UseSwagger(c =>
+ {
+ c.PreSerializeFilters.Add((openApiDoc, httpRequest) =>
+ {
+ // remove Paths and Components from OpenApi documentation for specific controller action without accepted roles
+ openApiDoc.RemovePathsAndComponentsWithoutAcceptedRolesFor(controller => nameof(controller.SomeAction), new List {"AcceptedRole"});
+ });
+ });
+
+ //...
+}
+```
+
3. **Append action count into the SwaggetTag's descriptions in OpenApi document**:
- In the _ConfigureServices_ method of _Startup.cs_, inside your `AddSwaggerGen` call, enable `AppendActionCountToTagSummaryDocumentFilter` document filter:
diff --git a/appveyor.yml b/appveyor.yml
index 440bbf0..216a1b3 100644
--- a/appveyor.yml
+++ b/appveyor.yml
@@ -1,4 +1,4 @@
-version: 2.1.{build}
+version: 2.2.{build}
pull_requests:
do_not_increment_build_number: true
skip_tags: true
diff --git a/src/Unchase.Swashbuckle.AspNetCore.Extensions/Extensions/EnumTypeExtensions.cs b/src/Unchase.Swashbuckle.AspNetCore.Extensions/Extensions/EnumTypeExtensions.cs
index 76b3dc7..eb6b8dc 100644
--- a/src/Unchase.Swashbuckle.AspNetCore.Extensions/Extensions/EnumTypeExtensions.cs
+++ b/src/Unchase.Swashbuckle.AspNetCore.Extensions/Extensions/EnumTypeExtensions.cs
@@ -57,8 +57,8 @@ internal static string AddEnumValuesDescription(this OpenApiSchema schema, bool
if (!schema.Extensions.ContainsKey("x-enumDescriptions"))
continue;
- var xenumDescriptions = (OpenApiArray)schema.Extensions["x-enumDescriptions"];
- if (xenumDescriptions?.Count == schema.Enum.Count)
+ var xEnumDescriptions = (OpenApiArray)schema.Extensions["x-enumDescriptions"];
+ if (xEnumDescriptions?.Count == schema.Enum.Count)
{
var description = ((OpenApiString)((OpenApiArray)schema.Extensions["x-enumDescriptions"])[i]).Value;
sb.Append($" ({description})");
diff --git a/src/Unchase.Swashbuckle.AspNetCore.Extensions/Extensions/OpenApiDocumentExtensions.cs b/src/Unchase.Swashbuckle.AspNetCore.Extensions/Extensions/OpenApiDocumentExtensions.cs
new file mode 100644
index 0000000..322b254
--- /dev/null
+++ b/src/Unchase.Swashbuckle.AspNetCore.Extensions/Extensions/OpenApiDocumentExtensions.cs
@@ -0,0 +1,42 @@
+using System;
+using System.Collections.Generic;
+using System.Reflection;
+using Microsoft.AspNetCore.Mvc;
+using Microsoft.OpenApi.Models;
+using Unchase.Swashbuckle.AspNetCore.Extensions.Factories;
+using Unchase.Swashbuckle.AspNetCore.Extensions.Filters;
+
+namespace Unchase.Swashbuckle.AspNetCore.Extensions.Extensions
+{
+ ///
+ /// Extension methods for .
+ ///
+ public static class OpenApiDocumentExtensions
+ {
+ ///
+ /// Remove Paths and Components from OpenApi documentation without accepted roles.
+ ///
+ /// .
+ /// Action name selector.
+ /// Collection of accepted roles.
+ ///
+ /// Returns .
+ ///
+ public static OpenApiDocument RemovePathsAndComponentsWithoutAcceptedRolesFor(this OpenApiDocument openApiDoc, Func actionNameSelector,
+ IReadOnlyList acceptedRoles) where TController : class, new()
+ {
+ var actionDescriptor = ApiDescriptionFactory.Create(actionNameSelector, typeof(TController).GetCustomAttribute().Template)?.ActionDescriptor;
+ if (actionDescriptor != null)
+ {
+ var paths = new Dictionary
+ {
+ { ((Microsoft.AspNetCore.Mvc.Controllers.ControllerActionDescriptor)actionDescriptor).MethodInfo, actionDescriptor.AttributeRouteInfo.Template }
+ };
+
+ HidePathsAndDefinitionsByRolesDocumentFilter.RemovePathsAndComponents(openApiDoc, paths, openApiDoc.Components.Schemas, acceptedRoles);
+ }
+
+ return openApiDoc;
+ }
+ }
+}
diff --git a/src/Unchase.Swashbuckle.AspNetCore.Extensions/Extensions/SwaggerGenOptionsExtensions.cs b/src/Unchase.Swashbuckle.AspNetCore.Extensions/Extensions/SwaggerGenOptionsExtensions.cs
index 338948c..8d8f4c3 100644
--- a/src/Unchase.Swashbuckle.AspNetCore.Extensions/Extensions/SwaggerGenOptionsExtensions.cs
+++ b/src/Unchase.Swashbuckle.AspNetCore.Extensions/Extensions/SwaggerGenOptionsExtensions.cs
@@ -6,6 +6,9 @@
namespace Unchase.Swashbuckle.AspNetCore.Extensions.Extensions
{
+ ///
+ /// Extension methods for .
+ ///
public static class SwaggerGenOptionsExtensions
{
#region Extensions
diff --git a/src/Unchase.Swashbuckle.AspNetCore.Extensions/Factories/ApiDescriptionFactory.cs b/src/Unchase.Swashbuckle.AspNetCore.Extensions/Factories/ApiDescriptionFactory.cs
new file mode 100644
index 0000000..44cac4c
--- /dev/null
+++ b/src/Unchase.Swashbuckle.AspNetCore.Extensions/Factories/ApiDescriptionFactory.cs
@@ -0,0 +1,193 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Reflection;
+using Microsoft.AspNetCore.Mvc;
+using Microsoft.AspNetCore.Mvc.Abstractions;
+using Microsoft.AspNetCore.Mvc.ApiExplorer;
+using Microsoft.AspNetCore.Mvc.Controllers;
+using Microsoft.AspNetCore.Mvc.Routing;
+
+namespace Unchase.Swashbuckle.AspNetCore.Extensions.Factories
+{
+ ///
+ /// factory.
+ ///
+ internal static class ApiDescriptionFactory
+ {
+ ///
+ /// Create .
+ ///
+ /// Type of Controller.
+ /// Controller action name.
+ /// Group name.
+ /// Http method.
+ /// Relative path.
+ /// Collection of .
+ /// Collection of .
+ /// Collection of .
+ ///
+ /// Returns .
+ ///
+ internal static ApiDescription Create(
+ Type controllerType,
+ string actionName,
+ string groupName = null,
+ string httpMethod = null,
+ string relativePath = null,
+ IEnumerable parameterDescriptions = null,
+ IEnumerable supportedRequestFormats = null,
+ IEnumerable supportedResponseTypes = null)
+ {
+ var methodInfo = controllerType.GetMethod(actionName);
+
+ if (methodInfo == null)
+ return null;
+
+ var actionDescriptor = CreateActionDescriptor(methodInfo);
+
+ var routAttr = controllerType.GetCustomAttributes().OfType().LastOrDefault();
+
+ if (string.IsNullOrWhiteSpace(actionDescriptor.AttributeRouteInfo.Template))
+ return null;
+ //throw new InvalidOperationException($"HttpMethod attribute of \"{methodInfo.Name}\" action in \"{controllerType.Name}\" controller must have a template specified.");
+
+ if (routAttr != null && !string.IsNullOrWhiteSpace(routAttr.Template))
+ {
+ var template = routAttr.Template;
+ actionDescriptor.AttributeRouteInfo.Template = template + "/" + actionDescriptor.AttributeRouteInfo.Template;
+ }
+
+ foreach (var routeValue in actionDescriptor.RouteValues)
+ {
+ actionDescriptor.AttributeRouteInfo.Template =
+ actionDescriptor.AttributeRouteInfo.Template.Replace($"[{routeValue.Key}]", routeValue.Value);
+ }
+
+ httpMethod = httpMethod ?? methodInfo?.GetCustomAttributes().OfType().FirstOrDefault()?.HttpMethods?.FirstOrDefault();
+
+ var apiDescription = new ApiDescription
+ {
+ ActionDescriptor = actionDescriptor,
+ GroupName = groupName,
+ HttpMethod = httpMethod,
+ RelativePath = relativePath,
+ };
+
+ if (parameterDescriptions != null)
+ {
+ foreach (var parameter in parameterDescriptions)
+ {
+ // If the provided action has a matching parameter - use it to assign ParameterDescriptor & ModelMetadata
+ var controllerParameterDescriptor = actionDescriptor.Parameters
+ .OfType()
+ .FirstOrDefault(parameterDescriptor => parameterDescriptor.Name == parameter.Name);
+
+ if (controllerParameterDescriptor != null)
+ {
+ parameter.ParameterDescriptor = controllerParameterDescriptor;
+ parameter.ModelMetadata = ModelMetadataFactory.CreateForParameter(controllerParameterDescriptor.ParameterInfo);
+ }
+
+ apiDescription.ParameterDescriptions.Add(parameter);
+ }
+ }
+
+ if (supportedRequestFormats != null)
+ {
+ foreach (var requestFormat in supportedRequestFormats)
+ {
+ apiDescription.SupportedRequestFormats.Add(requestFormat);
+ }
+ }
+
+ if (supportedResponseTypes != null)
+ {
+ foreach (var responseType in supportedResponseTypes)
+ {
+ // If the provided action has a return value AND the response status is 2XX - use it to assign ModelMetadata
+ if (methodInfo?.ReturnType != null && responseType.StatusCode / 100 == 2)
+ {
+ responseType.ModelMetadata = ModelMetadataFactory.CreateForType(methodInfo.ReturnType);
+ }
+
+ apiDescription.SupportedResponseTypes.Add(responseType);
+ }
+ }
+
+ return apiDescription;
+ }
+
+ ///
+ /// Create .
+ ///
+ /// Type of Controller.
+ /// Action name selector.
+ /// Group name.
+ /// Http method.
+ /// Relative path.
+ /// Collection of .
+ /// Collection of .
+ /// Collection of .
+ ///
+ /// Returns .
+ ///
+ internal static ApiDescription Create(
+ Func actionNameSelector,
+ string groupName = null,
+ string httpMethod = null,
+ string relativePath = null,
+ IEnumerable parameterDescriptions = null,
+ IEnumerable supportedRequestFormats = null,
+ IEnumerable supportedResponseTypes = null)
+ where TController : new()
+ {
+ return Create(
+ typeof(TController),
+ actionNameSelector(new TController()),
+ groupName,
+ httpMethod,
+ relativePath,
+ parameterDescriptions,
+ supportedRequestFormats,
+ supportedResponseTypes
+ );
+ }
+
+ private static ActionDescriptor CreateActionDescriptor(MethodInfo methodInfo)
+ {
+ var httpMethodAttribute = methodInfo.GetCustomAttribute();
+ var attributeRouteInfo = (httpMethodAttribute != null)
+ ? new AttributeRouteInfo { Template = httpMethodAttribute.Template, Name = httpMethodAttribute.Name }
+ : null;
+
+ var parameterDescriptors = methodInfo.GetParameters()
+ .Select(CreateParameterDescriptor)
+ .ToList();
+
+ var routeValues = new Dictionary
+ {
+ ["controller"] = methodInfo.DeclaringType?.Name.Replace("Controller", string.Empty)
+ };
+
+ return new ControllerActionDescriptor
+ {
+ AttributeRouteInfo = attributeRouteInfo,
+ ControllerTypeInfo = methodInfo.DeclaringType.GetTypeInfo(),
+ MethodInfo = methodInfo,
+ Parameters = parameterDescriptors,
+ RouteValues = routeValues
+ };
+ }
+
+ private static ParameterDescriptor CreateParameterDescriptor(ParameterInfo parameterInfo)
+ {
+ return new ControllerParameterDescriptor
+ {
+ Name = parameterInfo.Name,
+ ParameterInfo = parameterInfo,
+ ParameterType = parameterInfo.ParameterType,
+ };
+ }
+ }
+}
diff --git a/src/Unchase.Swashbuckle.AspNetCore.Extensions/Factories/ModelMetadataFactory.cs b/src/Unchase.Swashbuckle.AspNetCore.Extensions/Factories/ModelMetadataFactory.cs
new file mode 100644
index 0000000..74e6493
--- /dev/null
+++ b/src/Unchase.Swashbuckle.AspNetCore.Extensions/Factories/ModelMetadataFactory.cs
@@ -0,0 +1,25 @@
+using System;
+using System.Reflection;
+using Microsoft.AspNetCore.Mvc.ModelBinding;
+
+namespace Unchase.Swashbuckle.AspNetCore.Extensions.Factories
+{
+ public static class ModelMetadataFactory
+ {
+ public static ModelMetadata CreateForType(Type type)
+ {
+ return new EmptyModelMetadataProvider().GetMetadataForType(type);
+ }
+
+ public static ModelMetadata CreateForProperty(Type containingType, string propertyName)
+ {
+ return new EmptyModelMetadataProvider().GetMetadataForProperty(containingType, propertyName);
+ }
+
+ public static ModelMetadata CreateForParameter(ParameterInfo parameter)
+ {
+ return new EmptyModelMetadataProvider().GetMetadataForParameter(parameter);
+ }
+
+ }
+}
diff --git a/src/Unchase.Swashbuckle.AspNetCore.Extensions/Filters/ChangeResponseByHttpStatusCodeDocumentFilter.cs b/src/Unchase.Swashbuckle.AspNetCore.Extensions/Filters/ChangeResponseByHttpStatusCodeDocumentFilter.cs
index 4c61527..c873c6c 100644
--- a/src/Unchase.Swashbuckle.AspNetCore.Extensions/Filters/ChangeResponseByHttpStatusCodeDocumentFilter.cs
+++ b/src/Unchase.Swashbuckle.AspNetCore.Extensions/Filters/ChangeResponseByHttpStatusCodeDocumentFilter.cs
@@ -34,13 +34,13 @@ internal class ChangeResponseByHttpStatusCodeDocumentFilter : IDocumentFilter
{
#region Fileds
- private int _httpStatusCode;
+ private readonly int _httpStatusCode;
- private string _responseDescription;
+ private readonly string _responseDescription;
- private ResponseExampleOptions _responseExampleOption;
+ private readonly ResponseExampleOptions _responseExampleOption;
- private T _responseExample;
+ private readonly T _responseExample;
#endregion
diff --git a/src/Unchase.Swashbuckle.AspNetCore.Extensions/Filters/HidePathsAndDefinitionsByRolesDocumentFilter.cs b/src/Unchase.Swashbuckle.AspNetCore.Extensions/Filters/HidePathsAndDefinitionsByRolesDocumentFilter.cs
index 44166b8..6093c7a 100644
--- a/src/Unchase.Swashbuckle.AspNetCore.Extensions/Filters/HidePathsAndDefinitionsByRolesDocumentFilter.cs
+++ b/src/Unchase.Swashbuckle.AspNetCore.Extensions/Filters/HidePathsAndDefinitionsByRolesDocumentFilter.cs
@@ -4,11 +4,12 @@
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
+using Microsoft.AspNetCore.Mvc.Controllers;
namespace Unchase.Swashbuckle.AspNetCore.Extensions.Filters
{
///
- /// Filter for removing Paths and Defenitions from OpenApi documentation without accepted roles.
+ /// Filter for removing Paths and Components from OpenApi documentation without accepted roles.
///
public class HidePathsAndDefinitionsByRolesDocumentFilter : IDocumentFilter
{
@@ -33,7 +34,9 @@ public HidePathsAndDefinitionsByRolesDocumentFilter(IEnumerable accepted
#region Methods
- private List GetRequiredDefinitions(DocumentFilterContext context, OpenApiReference reference)
+ #region GetRequiredDefinitions
+
+ private static List GetRequiredDefinitions(IDictionary schemas, OpenApiReference reference)
{
var result = new List();
@@ -44,7 +47,7 @@ private List GetRequiredDefinitions(DocumentFilterContext context, OpenA
result.Add(reference.Id);
}
- var responseSchema = context.SchemaRepository.Schemas[reference?.Id];
+ var responseSchema = schemas[reference?.Id];
if (responseSchema != null)
{
if (responseSchema.Properties?.Count > 0)
@@ -54,16 +57,16 @@ private List GetRequiredDefinitions(DocumentFilterContext context, OpenA
if (schemaProperty.Value?.Reference?.Id != null)
{
result.Add(schemaProperty.Value?.Reference?.Id);
- var responseSchemaPropertySchema = context.SchemaRepository.Schemas[schemaProperty.Value?.Reference?.Id];
+ var responseSchemaPropertySchema = schemas[schemaProperty.Value?.Reference?.Id];
if (responseSchemaPropertySchema?.Reference != null)
{
- result.AddRange(GetRequiredDefinitions(context, responseSchemaPropertySchema.Reference));
+ result.AddRange(GetRequiredDefinitions(schemas, responseSchemaPropertySchema.Reference));
if (responseSchemaPropertySchema.Items?.Reference?.Id != null)
{
- var itemsSchema = context.SchemaRepository.Schemas[responseSchemaPropertySchema.Items?.Reference?.Id];
+ var itemsSchema = schemas[responseSchemaPropertySchema.Items?.Reference?.Id];
if (itemsSchema?.Reference?.Id != null)
{
- result.AddRange(GetRequiredDefinitions(context, itemsSchema.Reference));
+ result.AddRange(GetRequiredDefinitions(schemas, itemsSchema.Reference));
}
}
}
@@ -72,10 +75,10 @@ private List GetRequiredDefinitions(DocumentFilterContext context, OpenA
if (schemaProperty.Value?.Items?.Reference?.Id != null)
{
result.Add(schemaProperty.Value?.Items?.Reference?.Id);
- var itemsSchema = context.SchemaRepository.Schemas[schemaProperty.Value?.Items?.Reference?.Id];
+ var itemsSchema = schemas[schemaProperty.Value?.Items?.Reference?.Id];
if (itemsSchema?.Reference?.Id != null)
{
- result.AddRange(GetRequiredDefinitions(context, itemsSchema.Reference));
+ result.AddRange(GetRequiredDefinitions(schemas, itemsSchema.Reference));
}
if (itemsSchema?.Properties?.Count > 0)
@@ -93,7 +96,7 @@ private List GetRequiredDefinitions(DocumentFilterContext context, OpenA
{
if (itemsSchemaPropertyAllOf?.Reference?.Id != null)
{
- result.AddRange(GetRequiredDefinitions(context, itemsSchemaPropertyAllOf?.Reference));
+ result.AddRange(GetRequiredDefinitions(schemas, itemsSchemaPropertyAllOf?.Reference));
}
}
}
@@ -107,7 +110,7 @@ private List GetRequiredDefinitions(DocumentFilterContext context, OpenA
{
if (schemaPropertyAllOf?.Reference?.Id != null)
{
- result.AddRange(GetRequiredDefinitions(context, schemaPropertyAllOf.Reference));
+ result.AddRange(GetRequiredDefinitions(schemas, schemaPropertyAllOf.Reference));
}
}
}
@@ -117,10 +120,10 @@ private List GetRequiredDefinitions(DocumentFilterContext context, OpenA
if (responseSchema?.Items?.Reference?.Id != null)
{
result.Add(responseSchema?.Items?.Reference?.Id);
- var itemsSchema = context.SchemaRepository.Schemas[responseSchema?.Items?.Reference?.Id];
+ var itemsSchema = schemas[responseSchema?.Items?.Reference?.Id];
if (itemsSchema?.Reference?.Id != null)
{
- result.AddRange(GetRequiredDefinitions(context, itemsSchema?.Reference));
+ result.AddRange(GetRequiredDefinitions(schemas, itemsSchema?.Reference));
}
}
}
@@ -131,36 +134,34 @@ private List GetRequiredDefinitions(DocumentFilterContext context, OpenA
return result;
}
+ #endregion
+
+ #region RemovePathsAndComponents
+
///
- /// Apply filter.
+ /// Remove Paths and Components from OpenApi documentation without accepted roles.
///
/// .
- /// .
- public void Apply(OpenApiDocument openApiDoc, DocumentFilterContext context)
+ /// Dictionary of openApi paths with keys.
+ /// Dictionary with openApi schemas with schame name keys.
+ /// Collection of accepted roles.
+ internal static void RemovePathsAndComponents(OpenApiDocument openApiDoc, IDictionary paths, IDictionary schemas, IReadOnlyList acceptedRoles)
{
- if (!this._acceptedRoles.Any())
- return;
-
var keysForRemove = new List();
- var refsForProbablyRemove = new List();
var requiredRefs = new List();
#region Remove Paths
- foreach (var apiDescriptionActioDescription in context.ApiDescriptions.Select(ad => ad.ActionDescriptor))
+ foreach (var path in paths)
{
- var methodInfo = ((Microsoft.AspNetCore.Mvc.Controllers.ControllerActionDescriptor)apiDescriptionActioDescription).MethodInfo;
- var authorizeAttributes = methodInfo.GetCustomAttributes(false);
- if (authorizeAttributes != null)
+ var authorizeAttributes = path.Key.GetCustomAttributes(false);
+ foreach (var authorizeAttribute in authorizeAttributes)
{
- foreach (var authorizeAttribute in authorizeAttributes)
+ var authorizeAttributeRoles = authorizeAttribute?.Roles?.Split(',').Select(r => r.Trim()).ToList();
+ var intersect = authorizeAttributeRoles?.Intersect(acceptedRoles);
+ if (intersect == null || !intersect.Any())
{
- var authorizeAttributeRoles = authorizeAttribute?.Roles?.Split(',').Select(r => r.Trim()).ToList();
- var intersect = authorizeAttributeRoles?.Intersect(this._acceptedRoles);
- if (intersect == null || !intersect.Any())
- {
- keysForRemove.Add($"/{apiDescriptionActioDescription.AttributeRouteInfo.Template}");
- }
+ keysForRemove.Add($"/{path.Value}");
}
}
}
@@ -172,16 +173,16 @@ public void Apply(OpenApiDocument openApiDoc, DocumentFilterContext context)
#endregion
- #region Remove components
+ #region Remove Components
- foreach (var operation in openApiDoc.Paths?.Where(p => p.Value?.Operations != null).SelectMany(p => p.Value?.Operations))
+ foreach (var operation in openApiDoc?.Paths?.Where(p => p.Value?.Operations != null)?.SelectMany(p => p.Value?.Operations))
{
if (operation.Value?.Responses != null)
foreach (var response in operation.Value?.Responses)
{
if (response.Value?.Reference?.Id != null && !requiredRefs.Contains(response.Value?.Reference?.Id))
{
- requiredRefs.AddRange(GetRequiredDefinitions(context, response.Value?.Reference));
+ requiredRefs.AddRange(GetRequiredDefinitions(schemas, response.Value?.Reference));
requiredRefs = requiredRefs.Distinct().ToList();
}
@@ -189,7 +190,7 @@ public void Apply(OpenApiDocument openApiDoc, DocumentFilterContext context)
{
if (responseContentSchema?.Reference?.Id != null && !requiredRefs.Contains(responseContentSchema?.Reference?.Id))
{
- requiredRefs.AddRange(GetRequiredDefinitions(context, responseContentSchema?.Reference));
+ requiredRefs.AddRange(GetRequiredDefinitions(schemas, responseContentSchema?.Reference));
requiredRefs = requiredRefs.Distinct().ToList();
}
}
@@ -199,7 +200,7 @@ public void Apply(OpenApiDocument openApiDoc, DocumentFilterContext context)
{
if (parameter?.Schema?.Reference?.Id != null && !requiredRefs.Contains(parameter.Schema.Reference.Id))
{
- requiredRefs.AddRange(GetRequiredDefinitions(context, parameter.Schema.Reference));
+ requiredRefs.AddRange(GetRequiredDefinitions(schemas, parameter.Schema.Reference));
requiredRefs = requiredRefs.Distinct().ToList();
}
@@ -207,7 +208,7 @@ public void Apply(OpenApiDocument openApiDoc, DocumentFilterContext context)
{
if (parameterContentSchema?.Reference?.Id != null && !requiredRefs.Contains(parameterContentSchema?.Reference?.Id))
{
- requiredRefs.AddRange(GetRequiredDefinitions(context, parameterContentSchema?.Reference));
+ requiredRefs.AddRange(GetRequiredDefinitions(schemas, parameterContentSchema?.Reference));
requiredRefs = requiredRefs.Distinct().ToList();
}
}
@@ -249,9 +250,9 @@ public void Apply(OpenApiDocument openApiDoc, DocumentFilterContext context)
{
if (tagsDict[tag] == 0)
{
- var seaggerTag = openApiDoc.Tags.FirstOrDefault(t => t.Name == tag);
- if (seaggerTag != null)
- openApiDoc.Tags.Remove(seaggerTag);
+ var swaggerTag = openApiDoc.Tags.FirstOrDefault(t => t.Name == tag);
+ if (swaggerTag != null)
+ openApiDoc.Tags.Remove(swaggerTag);
}
}
@@ -259,5 +260,33 @@ public void Apply(OpenApiDocument openApiDoc, DocumentFilterContext context)
}
#endregion
+
+ #region Apply
+
+ ///
+ /// Apply filter.
+ ///
+ /// .
+ /// .
+ public void Apply(OpenApiDocument openApiDoc, DocumentFilterContext context)
+ {
+ if (!this._acceptedRoles.Any())
+ return;
+
+ var apiDescriptions = context.ApiDescriptions;
+ var schemas = context.SchemaRepository.Schemas;
+
+ var paths = new Dictionary();
+ foreach (var actionDescriptor in apiDescriptions.Select(ad => ad.ActionDescriptor))
+ {
+ paths.Add(((ControllerActionDescriptor)actionDescriptor).MethodInfo, actionDescriptor.AttributeRouteInfo.Template);
+ }
+
+ RemovePathsAndComponents(openApiDoc, paths, schemas, this._acceptedRoles.ToList());
+ }
+
+ #endregion
+
+ #endregion
}
}
diff --git a/src/Unchase.Swashbuckle.AspNetCore.Extensions/Filters/XEnumNamesParameterFilter.cs b/src/Unchase.Swashbuckle.AspNetCore.Extensions/Filters/XEnumNamesParameterFilter.cs
index c36662c..0550e24 100644
--- a/src/Unchase.Swashbuckle.AspNetCore.Extensions/Filters/XEnumNamesParameterFilter.cs
+++ b/src/Unchase.Swashbuckle.AspNetCore.Extensions/Filters/XEnumNamesParameterFilter.cs
@@ -12,7 +12,7 @@ public class XEnumNamesParameterFilter : IParameterFilter
{
#region Fields
- private bool _includeXEnumDescriptions;
+ private readonly bool _includeXEnumDescriptions;
#endregion
diff --git a/src/Unchase.Swashbuckle.AspNetCore.Extensions/Filters/XEnumNamesSchemaFilter.cs b/src/Unchase.Swashbuckle.AspNetCore.Extensions/Filters/XEnumNamesSchemaFilter.cs
index b309349..b84f083 100644
--- a/src/Unchase.Swashbuckle.AspNetCore.Extensions/Filters/XEnumNamesSchemaFilter.cs
+++ b/src/Unchase.Swashbuckle.AspNetCore.Extensions/Filters/XEnumNamesSchemaFilter.cs
@@ -13,7 +13,7 @@ public class XEnumNamesSchemaFilter : ISchemaFilter
{
#region Fields
- private bool _includeXEnumDescriptions;
+ private readonly bool _includeXEnumDescriptions;
#endregion
diff --git a/src/Unchase.Swashbuckle.AspNetCore.Extensions/Unchase.Swashbuckle.AspNetCore.Extensions.csproj b/src/Unchase.Swashbuckle.AspNetCore.Extensions/Unchase.Swashbuckle.AspNetCore.Extensions.csproj
index d555fb5..4884ce9 100644
--- a/src/Unchase.Swashbuckle.AspNetCore.Extensions/Unchase.Swashbuckle.AspNetCore.Extensions.csproj
+++ b/src/Unchase.Swashbuckle.AspNetCore.Extensions/Unchase.Swashbuckle.AspNetCore.Extensions.csproj
@@ -14,9 +14,9 @@
7.3
https://github.com/unchase/Unchase.Swashbuckle.AspNetCore.Extensions/blob/master/assets/icon.png?raw=true
- 2.1.6
- 2.1.6.0
- 2.1.6.0
+ 2.2.0
+ 2.2.0.0
+ 2.2.0.0
false
Unchase.Swashbuckle.AspNetCore.Extensions.xml
diff --git a/src/Unchase.Swashbuckle.AspNetCore.Extensions/Unchase.Swashbuckle.AspNetCore.Extensions.xml b/src/Unchase.Swashbuckle.AspNetCore.Extensions/Unchase.Swashbuckle.AspNetCore.Extensions.xml
index 89da3b6..d154045 100644
--- a/src/Unchase.Swashbuckle.AspNetCore.Extensions/Unchase.Swashbuckle.AspNetCore.Extensions.xml
+++ b/src/Unchase.Swashbuckle.AspNetCore.Extensions/Unchase.Swashbuckle.AspNetCore.Extensions.xml
@@ -4,6 +4,27 @@
Unchase.Swashbuckle.AspNetCore.Extensions
+
+
+ Extension methods for .
+
+
+
+
+ Remove Paths and Components from OpenApi documentation without accepted roles.
+
+ .
+ Action name selector.
+ Collection of accepted roles.
+
+ Returns .
+
+
+
+
+ Extension methods for .
+
+
Change all responses by specific http status codes in OpenApi document.
@@ -42,6 +63,43 @@
Returns .
+
+
+ factory.
+
+
+
+
+ Create .
+
+ Type of Controller.
+ Controller action name.
+ Group name.
+ Http method.
+ Relative path.
+ Collection of .
+ Collection of .
+ Collection of .
+
+ Returns .
+
+
+
+
+ Create .
+
+ Type of Controller.
+ Action name selector.
+ Group name.
+ Http method.
+ Relative path.
+ Collection of .
+ Collection of .
+ Collection of .
+
+ Returns .
+
+
Options for response example.
@@ -86,7 +144,7 @@
- Filter for removing Paths and Defenitions from OpenApi documentation without accepted roles.
+ Filter for removing Paths and Components from OpenApi documentation without accepted roles.
@@ -95,6 +153,15 @@
+
+
+ Remove Paths and Components from OpenApi documentation without accepted roles.
+
+ .
+ Dictionary of openApi paths with keys.
+ Dictionary with openApi schemas with schame name keys.
+ Collection of accepted roles.
+
Apply filter.
diff --git a/test/WebApi3.1-Swashbuckle/Controllers/HidedController.cs b/test/WebApi3.1-Swashbuckle/Controllers/HidedController.cs
index 67d6b05..8bfa1b5 100644
--- a/test/WebApi3.1-Swashbuckle/Controllers/HidedController.cs
+++ b/test/WebApi3.1-Swashbuckle/Controllers/HidedController.cs
@@ -16,7 +16,7 @@ public class HidedController : ControllerBase
///
/// Hided action.
///
- [HttpGet()]
+ [HttpGet("HidedAction")]
[Authorize(Roles = "NotAcceptedRole")]
public IActionResult HidedAction()
{
diff --git a/test/WebApi3.1-Swashbuckle/Startup.cs b/test/WebApi3.1-Swashbuckle/Startup.cs
index 680eb36..3e79c8d 100644
--- a/test/WebApi3.1-Swashbuckle/Startup.cs
+++ b/test/WebApi3.1-Swashbuckle/Startup.cs
@@ -11,6 +11,7 @@
using TodoApi.Models;
using Unchase.Swashbuckle.AspNetCore.Extensions.Extensions;
using Unchase.Swashbuckle.AspNetCore.Extensions.Filters;
+using WebApi3._1_Swashbuckle.Controllers;
using WebApi3._1_Swashbuckle.Models;
namespace WebApi3._1_Swashbuckle
@@ -47,7 +48,7 @@ public void ConfigureServices(IServiceCollection services)
#region HidePathsAndDefinitionsByRolesDocumentFilter
- // remove Paths and Defenitions from OpenApi documentation without accepted roles
+ // remove Paths and Components from OpenApi documentation without accepted roles
options.DocumentFilter(new List { "AcceptedRole" });
#endregion
@@ -105,8 +106,15 @@ public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
app.UseDeveloperExceptionPage();
}
- // Enable middleware to serve generated Swagger as a JSON endpoint.
- app.UseSwagger();
+ // enable middleware to serve generated Swagger as a JSON endpoint.
+ app.UseSwagger(c =>
+ {
+ c.PreSerializeFilters.Add((openApiDoc, httpRequest) =>
+ {
+ // remove Paths and Components from OpenApi documentation for specific controller action without accepted roles
+ openApiDoc.RemovePathsAndComponentsWithoutAcceptedRolesFor(controller => nameof(controller.HidedAction), new List {"AcceptedRole"});
+ });
+ });
// Enable middleware to serve swagger-ui (HTML, JS, CSS, etc.),
// specifying the Swagger JSON endpoint.