From e42c7bd0348585ba0a79fc9ed27a275aaf5f8fb9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?jian=E7=8E=84=E5=86=B0?= Date: Wed, 13 May 2020 16:30:48 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=96=B0=E5=A2=9E=20=E6=8E=A7=E5=88=B6?= =?UTF-8?q?=E5=99=A8=E6=96=87=E6=A1=A3=E6=8E=92=E5=BA=8F=20=E4=BB=A5?= =?UTF-8?q?=E5=8F=8A=20=E6=8E=88=E6=9D=83=E5=AD=98=E5=82=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 2 + samples/Bing.Samples.Api/Startup.cs | 9 +++- .../Bing/Swashbuckle/EnumHandleBase.cs | 2 +- .../Extensions/SwaggerGenExtensions.cs | 26 +++++++++- .../Extensions/SwaggerUIExtensions.cs | 19 +++++++ .../Documents/TagReOrderDocumentFilter.cs | 33 ++++++++++++ .../EnumDescriptionsParameterFilter.cs} | 15 +++--- .../Schemas/EnumDescriptionSchemaFilter.cs | 7 ++- .../Bing/Swashbuckle/Resources/index.html | 52 ++++++++++++++++++- .../Bing/Swashbuckle/TokenStorageParameter.cs | 33 ++++++++++++ 10 files changed, 180 insertions(+), 18 deletions(-) create mode 100644 src/Bing.Extensions.Swashbuckle/Bing/Swashbuckle/Filters/Documents/TagReOrderDocumentFilter.cs rename src/Bing.Extensions.Swashbuckle/Bing/Swashbuckle/Filters/{Documents/EnumDescriptionsDocumentFilter.cs => Parameters/EnumDescriptionsParameterFilter.cs} (58%) create mode 100644 src/Bing.Extensions.Swashbuckle/Bing/Swashbuckle/TokenStorageParameter.cs diff --git a/README.md b/README.md index f17bbe4..ef033de 100644 --- a/README.md +++ b/README.md @@ -21,6 +21,8 @@ Bing.Extensions.Swashbuckle是扩展Swashbuckle.AspNetCore一些常用操作, - 支持显示枚举描述 - 支持Swagger文档授权登录功能 - 支持默认值设置 +- 支持控制器排序 +- 支持Token令牌存储 ## 依赖类库 diff --git a/samples/Bing.Samples.Api/Startup.cs b/samples/Bing.Samples.Api/Startup.cs index 27325d8..35ae4e9 100644 --- a/samples/Bing.Samples.Api/Startup.cs +++ b/samples/Bing.Samples.Api/Startup.cs @@ -2,11 +2,13 @@ using System.Collections.Generic; using System.IO; using Bing.Swashbuckle; +using Bing.Swashbuckle.Filters.Documents; using Bing.Swashbuckle.Filters.Schemas; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Mvc.Controllers; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.PlatformAbstractions; @@ -88,10 +90,12 @@ public IServiceProvider ConfigureServices(IServiceCollection services) //// 显示授权信息 //config.ShowAuthorizeInfo(); - // 显示枚举描述 config.ShowEnumDescription(); + // 控制器排序 + config.OrderByController(); + // 显示Url模式:首字母小写、首字母大写、全小写、全大写、默认 config.ShowUrlMode(); @@ -177,9 +181,10 @@ public void Configure(IApplicationBuilder app, IHostingEnvironment env) config.InjectJavascript("resources/translator"); //config.InjectJavascript("/swagger/resources/export"); config.InjectStylesheet("resources/swagger-common"); - // 使用默认SwaggerUI config.UseDefaultSwaggerUI(); + // 启用Token存储 + config.UseTokenStorage("oauth2"); }; }); app.UseMvc(routes => diff --git a/src/Bing.Extensions.Swashbuckle/Bing/Swashbuckle/EnumHandleBase.cs b/src/Bing.Extensions.Swashbuckle/Bing/Swashbuckle/EnumHandleBase.cs index 0e311c5..26cb8f8 100644 --- a/src/Bing.Extensions.Swashbuckle/Bing/Swashbuckle/EnumHandleBase.cs +++ b/src/Bing.Extensions.Swashbuckle/Bing/Swashbuckle/EnumHandleBase.cs @@ -18,7 +18,7 @@ protected virtual string FormatDescription(Type type) var sb = new StringBuilder(); var result = Enum.GetDescriptions(type); foreach (var item in result) - sb.AppendLine($"{item.Value} = {(string.IsNullOrEmpty(item.Description) ? item.Name : item.Description)}"); + sb.Append($"{item.Value} = {(string.IsNullOrEmpty(item.Description) ? item.Name : item.Description)}{Environment.NewLine}"); return sb.ToString(); } } diff --git a/src/Bing.Extensions.Swashbuckle/Bing/Swashbuckle/Extensions/SwaggerGenExtensions.cs b/src/Bing.Extensions.Swashbuckle/Bing/Swashbuckle/Extensions/SwaggerGenExtensions.cs index ea66cf0..92403f7 100644 --- a/src/Bing.Extensions.Swashbuckle/Bing/Swashbuckle/Extensions/SwaggerGenExtensions.cs +++ b/src/Bing.Extensions.Swashbuckle/Bing/Swashbuckle/Extensions/SwaggerGenExtensions.cs @@ -2,6 +2,7 @@ using Bing.Swashbuckle.Core; using Bing.Swashbuckle.Filters.Documents; using Bing.Swashbuckle.Filters.Operations; +using Bing.Swashbuckle.Filters.Parameters; using Bing.Swashbuckle.Filters.Schemas; using Microsoft.Extensions.DependencyInjection; using Microsoft.OpenApi.Models; @@ -15,18 +16,39 @@ namespace Bing.Swashbuckle /// public static class SwaggerGenExtensions { + #region ShowEnumDescription(显示枚举描述) + /// /// 显示枚举描述 /// /// Swagger生成选项 public static void ShowEnumDescription(this SwaggerGenOptions options) { - if (!options.ParameterFilterDescriptors.Exists(x => x.Type == typeof(EnumDescriptionsDocumentFilter))) - options.ParameterFilter(); + if (!options.ParameterFilterDescriptors.Exists(x => x.Type == typeof(EnumDescriptionsParameterFilter))) + options.ParameterFilter(); if (!options.SchemaFilterDescriptors.Exists(x => x.Type == typeof(EnumDescriptionSchemaFilter))) options.SchemaFilter(); } + #endregion + + #region OrderByController(基于控制器进行排序) + + /// + /// 基于控制器进行排序 + /// + /// Swagger生成选项 + /// 是否降序排序 + public static void OrderByController(this SwaggerGenOptions options, bool orderByDesc = false) + { + if (!options.DocumentFilterDescriptors.Exists(x => x.Type == typeof(TagReOrderDocumentFilter))) + options.DocumentFilter(orderByDesc); + } + + #endregion + + + /// /// 显示文件参数 /// diff --git a/src/Bing.Extensions.Swashbuckle/Bing/Swashbuckle/Extensions/SwaggerUIExtensions.cs b/src/Bing.Extensions.Swashbuckle/Bing/Swashbuckle/Extensions/SwaggerUIExtensions.cs index 3499519..4df8f9b 100644 --- a/src/Bing.Extensions.Swashbuckle/Bing/Swashbuckle/Extensions/SwaggerUIExtensions.cs +++ b/src/Bing.Extensions.Swashbuckle/Bing/Swashbuckle/Extensions/SwaggerUIExtensions.cs @@ -50,6 +50,25 @@ public static void UseCustomSwaggerIndex(this SwaggerUIOptions options) #endregion + #region UseTokenStorage(使用令牌存储) + + /// + /// 使用令牌存储。解决刷新页面导致令牌丢失问题,前提必须使用 方法 + /// + /// SwaggerUI选项 + /// 授权定义。对应于 AddSecurityDefinition 中的 name + /// 缓存类型 + public static void UseTokenStorage(this SwaggerUIOptions options, string securityDefinition, WebCacheType cacheType = WebCacheType.Session) + { + options.ConfigObject.AdditionalItems["token_storage"] = new TokenStorageParameter + { + CacheType = cacheType, + SecurityDefinition = securityDefinition + }; + } + + #endregion + /// /// 添加信息 /// diff --git a/src/Bing.Extensions.Swashbuckle/Bing/Swashbuckle/Filters/Documents/TagReOrderDocumentFilter.cs b/src/Bing.Extensions.Swashbuckle/Bing/Swashbuckle/Filters/Documents/TagReOrderDocumentFilter.cs new file mode 100644 index 0000000..4115361 --- /dev/null +++ b/src/Bing.Extensions.Swashbuckle/Bing/Swashbuckle/Filters/Documents/TagReOrderDocumentFilter.cs @@ -0,0 +1,33 @@ +using System.Linq; +using Microsoft.OpenApi.Models; +using Swashbuckle.AspNetCore.SwaggerGen; + +namespace Bing.Swashbuckle.Filters.Documents +{ + /// + /// 标识重新排序 文档过滤器。用于对控制器进行排序 + /// + internal class TagReOrderDocumentFilter : IDocumentFilter + { + /// + /// 是否降序排序 + /// + private readonly bool _orderByDesc; + + /// + /// 初始化一个类型的实例 + /// + /// 是否降序排序 + public TagReOrderDocumentFilter(bool orderByDesc = false) => _orderByDesc = orderByDesc; + + /// + /// 重写操作处理 + /// + public void Apply(OpenApiDocument swaggerDoc, DocumentFilterContext context) + { + swaggerDoc.Tags = _orderByDesc + ? swaggerDoc.Tags.OrderByDescending(tag => tag.Name).ToList() + : swaggerDoc.Tags.OrderBy(tag => tag.Name).ToList(); + } + } +} diff --git a/src/Bing.Extensions.Swashbuckle/Bing/Swashbuckle/Filters/Documents/EnumDescriptionsDocumentFilter.cs b/src/Bing.Extensions.Swashbuckle/Bing/Swashbuckle/Filters/Parameters/EnumDescriptionsParameterFilter.cs similarity index 58% rename from src/Bing.Extensions.Swashbuckle/Bing/Swashbuckle/Filters/Documents/EnumDescriptionsDocumentFilter.cs rename to src/Bing.Extensions.Swashbuckle/Bing/Swashbuckle/Filters/Parameters/EnumDescriptionsParameterFilter.cs index f8f647a..2207f18 100644 --- a/src/Bing.Extensions.Swashbuckle/Bing/Swashbuckle/Filters/Documents/EnumDescriptionsDocumentFilter.cs +++ b/src/Bing.Extensions.Swashbuckle/Bing/Swashbuckle/Filters/Parameters/EnumDescriptionsParameterFilter.cs @@ -1,12 +1,13 @@ -using Microsoft.OpenApi.Models; +using System; +using Microsoft.OpenApi.Models; using Swashbuckle.AspNetCore.SwaggerGen; -namespace Bing.Swashbuckle.Filters.Documents +namespace Bing.Swashbuckle.Filters.Parameters { /// - /// 枚举描述 文档过滤器。支持Url查询参数 + /// 枚举描述 参数过滤器。支持Url查询参数 /// - internal class EnumDescriptionsDocumentFilter : EnumHandleBase, IParameterFilter + internal class EnumDescriptionsParameterFilter : EnumHandleBase, IParameterFilter { /// /// 重写操作处理 @@ -16,10 +17,8 @@ public void Apply(OpenApiParameter parameter, ParameterFilterContext context) var type = context.ParameterInfo?.ParameterType; if (type == null) return; - if (type.IsEnum) - { - parameter.Description = $"{parameter.Description}\r\n{FormatDescription(type)}"; - } + if (type.IsEnum) + parameter.Description = $"{parameter.Description}{Environment.NewLine}{FormatDescription(type)}"; } } } diff --git a/src/Bing.Extensions.Swashbuckle/Bing/Swashbuckle/Filters/Schemas/EnumDescriptionSchemaFilter.cs b/src/Bing.Extensions.Swashbuckle/Bing/Swashbuckle/Filters/Schemas/EnumDescriptionSchemaFilter.cs index 7cfa45c..90247a4 100644 --- a/src/Bing.Extensions.Swashbuckle/Bing/Swashbuckle/Filters/Schemas/EnumDescriptionSchemaFilter.cs +++ b/src/Bing.Extensions.Swashbuckle/Bing/Swashbuckle/Filters/Schemas/EnumDescriptionSchemaFilter.cs @@ -1,4 +1,5 @@ -using Microsoft.OpenApi.Models; +using System; +using Microsoft.OpenApi.Models; using Swashbuckle.AspNetCore.SwaggerGen; namespace Bing.Swashbuckle.Filters.Schemas @@ -14,9 +15,7 @@ internal class EnumDescriptionSchemaFilter : EnumHandleBase, ISchemaFilter public void Apply(OpenApiSchema schema, SchemaFilterContext context) { if (context.Type.IsEnum) - { - schema.Description = $"{schema.Description}\r\n{FormatDescription(context.Type)}"; - } + schema.Description = $"{schema.Description}{Environment.NewLine}{FormatDescription(context.Type)}"; } } } diff --git a/src/Bing.Extensions.Swashbuckle/Bing/Swashbuckle/Resources/index.html b/src/Bing.Extensions.Swashbuckle/Bing/Swashbuckle/Resources/index.html index c3930e5..9391ff8 100644 --- a/src/Bing.Extensions.Swashbuckle/Bing/Swashbuckle/Resources/index.html +++ b/src/Bing.Extensions.Swashbuckle/Bing/Swashbuckle/Resources/index.html @@ -81,6 +81,10 @@ window.onload = function () { var configObject = JSON.parse('%(ConfigObject)'); var oauthConfigObject = JSON.parse('%(OAuthConfigObject)'); + + console.log('configObject', configObject); + console.log('oauthConfigObject', oauthConfigObject); + // Apply mandatory parameters configObject.dom_id = "#swagger-ui"; configObject.presets = [SwaggerUIBundle.presets.apis, SwaggerUIStandalonePreset]; @@ -98,9 +102,13 @@ if (!configObject.hasOwnProperty("oauth2RedirectUrl")) //configObject.oauth2RedirectUrl = window.location + "oauth2-redirect.html"; // use the built-in default configObject.oauth2RedirectUrl = window.location.href.replace("index.html", "oauth2-redirect.html"); + + // 初始化Token存储 + initTokenStorage(configObject); // Build a system - const ui = SwaggerUIBundle(configObject); + const ui = SwaggerUIBundle(configObject); + window.ui = ui; // Apply OAuth config ui.initOAuth(oauthConfigObject); @@ -142,6 +150,48 @@ document.getElementsByClassName('topbar-wrapper')[0].appendChild(logOutEle) } } + + function initTokenStorage(configObject) { + if(!configObject.token_storage) + return; + configObject.onComplete= () => { + var result = (localStorage.getItem(configObject.token_storage.securityDefinition)) || (sessionStorage.getItem(configObject.token_storage.securityDefinition)); + ui.preauthorizeApiKey(configObject.token_storage.securityDefinition, result); + }; + configObject.requestInterceptor = (req) => { + req.headers["Authorization"] = (localStorage.getItem(configObject.token_storage.securityDefinition)) || (sessionStorage.getItem(configObject.token_storage.securityDefinition)); + return req; + }; + addAuthorizeListener(configObject); + } + + function addAuthorizeListener(configObject) { + var authWrapper = document.querySelector(".scheme-container .auth-wrapper"); + if(authWrapper === undefined || authWrapper === null){ + setTimeout(function(){ + addAuthorizeListener(configObject); + }, 3000); + return; + } + console.log("初始化存储 Token 监听处理"); + authWrapper.addEventListener("click", function(e){ + if(e.type === "click" && e.srcElement.tagName === "BUTTON") { + if(e.srcElement.innerText === "Authorize") { + var result = document.querySelector(".auth-container .wrapper input").value; + console.log(result); + if(configObject.token_storage.cacheType === "Local") + localStorage.setItem(configObject.token_storage.securityDefinition, result); + else + sessionStorage.setItem(configObject.token_storage.securityDefinition, result); + } else if(e.srcElement.innerText === "Logout") { + if(configObject.token_storage.cacheType === "Local") + localStorage.removeItem(configObject.token_storage.securityDefinition); + else + sessionStorage.removeItem(configObject.token_storage.securityDefinition); + } + } + }, false); + } diff --git a/src/Bing.Extensions.Swashbuckle/Bing/Swashbuckle/TokenStorageParameter.cs b/src/Bing.Extensions.Swashbuckle/Bing/Swashbuckle/TokenStorageParameter.cs new file mode 100644 index 0000000..dfd3734 --- /dev/null +++ b/src/Bing.Extensions.Swashbuckle/Bing/Swashbuckle/TokenStorageParameter.cs @@ -0,0 +1,33 @@ +namespace Bing.Swashbuckle +{ + /// + /// 令牌存储参数。用于拦截登录后存储令牌,解决刷新页面导致令牌丢失问题 + /// + internal class TokenStorageParameter + { + /// + /// 授权定义。对应于 AddSecurityDefinition 中的 name + /// + public string SecurityDefinition { get; set; } + + /// + /// 网页缓存类型 + /// + public WebCacheType CacheType { get; set; } + } + + /// + /// 网页缓存方式 + /// + public enum WebCacheType + { + /// + /// 本地存储 + /// + Local, + /// + /// 会话 + /// + Session, + } +}