diff --git a/src/Microsoft.Azure.WebJobs.Extensions.OpenApi.Core/SwaggerUI.cs b/src/Microsoft.Azure.WebJobs.Extensions.OpenApi.Core/SwaggerUI.cs index 37788423..ff27e643 100644 --- a/src/Microsoft.Azure.WebJobs.Extensions.OpenApi.Core/SwaggerUI.cs +++ b/src/Microsoft.Azure.WebJobs.Extensions.OpenApi.Core/SwaggerUI.cs @@ -166,12 +166,13 @@ private string Render(string endpoint, OpenApiAuthLevelType authLevel = OpenApiA var swaggerUrl = $"{this._baseUrl.TrimEnd('/')}/{endpoint}"; var queries = this._req.Query.ToDictionary(p => p.Key, p => p.Value); + if (string.IsNullOrEmpty(authKey)) + { + authKey = queries.TryGetValue("code", out var queryCodeValue) ? (string)queryCodeValue : null; + } if (this.IsAuthKeyRequired(authLevel, authKey)) { - if (!queries.ContainsKey("code")) - { - queries.Add("code", new StringValues(authKey)); - } + queries["code"] = new StringValues(authKey); } if (queries.Any()) diff --git a/test/Microsoft.Azure.WebJobs.Extensions.OpenApi.Core.Tests/SwaggerUITests.cs b/test/Microsoft.Azure.WebJobs.Extensions.OpenApi.Core.Tests/SwaggerUITests.cs index 5c2d4869..7b1f006d 100644 --- a/test/Microsoft.Azure.WebJobs.Extensions.OpenApi.Core.Tests/SwaggerUITests.cs +++ b/test/Microsoft.Azure.WebJobs.Extensions.OpenApi.Core.Tests/SwaggerUITests.cs @@ -1,10 +1,15 @@ +using System; using System.Collections.Generic; using System.Reflection; +using System.Threading.Tasks; using FluentAssertions; using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Http.Internal; using Microsoft.Azure.WebJobs.Extensions.OpenApi.Core.Abstractions; +using Microsoft.Azure.WebJobs.Extensions.OpenApi.Core.Enums; +using Microsoft.Extensions.Primitives; using Microsoft.OpenApi.Models; using Microsoft.VisualStudio.TestTools.UnitTesting; @@ -137,5 +142,140 @@ public void Given_NullOptions_When_AddServer_Invoked_Then_It_Should_Return_Swagg (fi.GetValue(ui) as string).Should().Be(expected); } + + + [DataTestMethod] + [DataRow(OpenApiAuthLevelType.Anonymous, null, false, false)] + [DataRow(OpenApiAuthLevelType.Anonymous, "", false, false)] + [DataRow(OpenApiAuthLevelType.Anonymous, "configKey", false, false)] + [DataRow(OpenApiAuthLevelType.User, null, true, false)] + [DataRow(OpenApiAuthLevelType.User, "", true, false)] + [DataRow(OpenApiAuthLevelType.User, "configKey", false, true)] + [DataRow(OpenApiAuthLevelType.Function, null, true, false)] + [DataRow(OpenApiAuthLevelType.Function, "", true, false)] + [DataRow(OpenApiAuthLevelType.Function, "configKey", false, true)] + [DataRow(OpenApiAuthLevelType.System, null, true, false)] + [DataRow(OpenApiAuthLevelType.System, "", true, false)] + [DataRow(OpenApiAuthLevelType.System, "configKey", false, true)] + [DataRow(OpenApiAuthLevelType.Admin, null, true, false)] + [DataRow(OpenApiAuthLevelType.Admin, "", true, false)] + [DataRow(OpenApiAuthLevelType.Admin, "configKey", false, true)] + public void Given_Options_When_IsAuthKeyRequired_Invoked_Then_It_Should_Return_Result( + OpenApiAuthLevelType configuredAuthLevel, string configKey, bool throwsException, bool expected) + { + var ui = new SwaggerUI(); + var method = ui.GetType() + .GetMethod("IsAuthKeyRequired", BindingFlags.Instance | BindingFlags.NonPublic); + + Func action = () => (bool)method.Invoke(ui, new object[] { configuredAuthLevel, configKey }); + + if (throwsException) + { + action.Should().Throw().And.InnerException.Should() + .BeOfType(); + } + else + { + action.Invoke().Should().Be(expected); + } + } + + + [DataTestMethod] + [DataRow(null, OpenApiAuthLevelType.Anonymous, null, null)] + [DataRow(null, OpenApiAuthLevelType.Anonymous, "configKey", null)] + [DataRow(null, OpenApiAuthLevelType.Anonymous, "", null)] + [DataRow("queryKey", OpenApiAuthLevelType.Anonymous, "configKey", "queryKey")] + [DataRow("queryKey", OpenApiAuthLevelType.Anonymous, null, "queryKey")] + [DataRow("queryKey", OpenApiAuthLevelType.Anonymous, "", "queryKey")] + [DataRow("", OpenApiAuthLevelType.Anonymous, null, "")] + [DataRow("", OpenApiAuthLevelType.Anonymous, "configKey", "")] + [DataRow("", OpenApiAuthLevelType.Anonymous, "", "")] + [DataRow(null, OpenApiAuthLevelType.User, null, null, true)] + [DataRow(null, OpenApiAuthLevelType.User, null, "", true)] + [DataRow(null, OpenApiAuthLevelType.User, "configKey", "configKey")] + [DataRow("queryKey", OpenApiAuthLevelType.User, "configKey", "configKey")] + [DataRow("queryKey", OpenApiAuthLevelType.User, null, "queryKey")] + [DataRow("queryKey", OpenApiAuthLevelType.User, "", "queryKey")] + [DataRow("", OpenApiAuthLevelType.User, "configKey", "configKey")] + [DataRow("", OpenApiAuthLevelType.User, null, "",true)] + [DataRow("", OpenApiAuthLevelType.User, "", "",true)] + [DataRow(null, OpenApiAuthLevelType.Function, null, null, true)] + [DataRow(null, OpenApiAuthLevelType.Function, null, "", true)] + [DataRow(null, OpenApiAuthLevelType.Function, "configKey", "configKey")] + [DataRow("queryKey", OpenApiAuthLevelType.Function, "configKey", "configKey")] + [DataRow("queryKey", OpenApiAuthLevelType.Function, null, "queryKey")] + [DataRow("queryKey", OpenApiAuthLevelType.Function, "", "queryKey")] + [DataRow("", OpenApiAuthLevelType.Function, "configKey", "configKey")] + [DataRow("", OpenApiAuthLevelType.Function, null, "",true)] + [DataRow("", OpenApiAuthLevelType.Function, "", "",true)] + [DataRow(null, OpenApiAuthLevelType.System, null, null, true)] + [DataRow(null, OpenApiAuthLevelType.System, null, "", true)] + [DataRow(null, OpenApiAuthLevelType.System, "configKey", "configKey")] + [DataRow("queryKey", OpenApiAuthLevelType.System, "configKey", "configKey")] + [DataRow("queryKey", OpenApiAuthLevelType.System, null, "queryKey")] + [DataRow("queryKey", OpenApiAuthLevelType.System, "", "queryKey")] + [DataRow("", OpenApiAuthLevelType.System, "configKey", "configKey")] + [DataRow("", OpenApiAuthLevelType.System, null, "",true)] + [DataRow("", OpenApiAuthLevelType.System, "", "",true)] + [DataRow(null, OpenApiAuthLevelType.Admin, null, null, true)] + [DataRow(null, OpenApiAuthLevelType.Admin, null, "", true)] + [DataRow(null, OpenApiAuthLevelType.Admin, "configKey", "configKey")] + [DataRow("queryKey", OpenApiAuthLevelType.Admin, "configKey", "configKey")] + [DataRow("queryKey", OpenApiAuthLevelType.Admin, null, "queryKey")] + [DataRow("queryKey", OpenApiAuthLevelType.Admin, "", "queryKey")] + [DataRow("", OpenApiAuthLevelType.Admin, "configKey", "configKey")] + [DataRow("", OpenApiAuthLevelType.Admin, null, "",true)] + [DataRow("", OpenApiAuthLevelType.Admin, "", "",true)] + public async Task Given_AuthKey_Options_When_RenderAsync_Invoked_Then_It_Should_Be_Used_As_Request_Key( + string queryKey, OpenApiAuthLevelType configuredAuthLevel, string configKey, string expectedRequestKey, + bool throwsException = false) + { + var endpoint = "swagger/ui"; + var baseUrl = "https://localhost:7071"; + var ui = new SwaggerUI(); + ui.AddMetadata(new OpenApiInfo()); + var uiType = ui.GetType(); + + //Generate Request Object with query key + var queryDict = new Dictionary(); + if (queryKey != null) + { + queryDict["code"] = queryKey; + } + var req = new Mock(); + req.SetupGet(p => p.Query).Returns(new QueryCollection(queryDict)); + uiType.GetField("_req", BindingFlags.Instance | BindingFlags.NonPublic).SetValue(ui, req.Object); + + //Set BaseUrl + uiType.GetField("_baseUrl", BindingFlags.Instance | BindingFlags.NonPublic).SetValue(ui, baseUrl); + + //Set html string just to contain url placeholder + var swaggerUrlPlaceholder = + uiType.GetField("SwaggerUrlPlaceholder", BindingFlags.Static | BindingFlags.NonPublic) + .GetRawConstantValue() as string; + uiType.GetField("_indexHtml", BindingFlags.Instance | BindingFlags.NonPublic) + .SetValue(ui, swaggerUrlPlaceholder); + + + Func> action = async () => await ui.RenderAsync(endpoint, configuredAuthLevel, configKey); + + if (throwsException) + { + await action.Should().ThrowAsync(); + } + else + { + var result = await action(); + if (expectedRequestKey != null) + { + result.Should().Contain($"code={expectedRequestKey}"); + } + else + { + result.Should().NotContain($"code="); + } + } + } } }