Skip to content

Commit 55eec16

Browse files
Derich367Simon Schneider
and
Simon Schneider
authored
override function key from query if set in parameters, allow function key to be set from query (#383)
Co-authored-by: Simon Schneider <[email protected]>
1 parent 355386f commit 55eec16

File tree

2 files changed

+145
-4
lines changed

2 files changed

+145
-4
lines changed

src/Microsoft.Azure.WebJobs.Extensions.OpenApi.Core/SwaggerUI.cs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -166,12 +166,13 @@ private string Render(string endpoint, OpenApiAuthLevelType authLevel = OpenApiA
166166
var swaggerUrl = $"{this._baseUrl.TrimEnd('/')}/{endpoint}";
167167

168168
var queries = this._req.Query.ToDictionary(p => p.Key, p => p.Value);
169+
if (string.IsNullOrEmpty(authKey))
170+
{
171+
authKey = queries.TryGetValue("code", out var queryCodeValue) ? (string)queryCodeValue : null;
172+
}
169173
if (this.IsAuthKeyRequired(authLevel, authKey))
170174
{
171-
if (!queries.ContainsKey("code"))
172-
{
173-
queries.Add("code", new StringValues(authKey));
174-
}
175+
queries["code"] = new StringValues(authKey);
175176
}
176177

177178
if (queries.Any())

test/Microsoft.Azure.WebJobs.Extensions.OpenApi.Core.Tests/SwaggerUITests.cs

Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,15 @@
1+
using System;
12
using System.Collections.Generic;
23
using System.Reflection;
4+
using System.Threading.Tasks;
35

46
using FluentAssertions;
57

68
using Microsoft.AspNetCore.Http;
9+
using Microsoft.AspNetCore.Http.Internal;
710
using Microsoft.Azure.WebJobs.Extensions.OpenApi.Core.Abstractions;
11+
using Microsoft.Azure.WebJobs.Extensions.OpenApi.Core.Enums;
12+
using Microsoft.Extensions.Primitives;
813
using Microsoft.OpenApi.Models;
914
using Microsoft.VisualStudio.TestTools.UnitTesting;
1015

@@ -137,5 +142,140 @@ public void Given_NullOptions_When_AddServer_Invoked_Then_It_Should_Return_Swagg
137142

138143
(fi.GetValue(ui) as string).Should().Be(expected);
139144
}
145+
146+
147+
[DataTestMethod]
148+
[DataRow(OpenApiAuthLevelType.Anonymous, null, false, false)]
149+
[DataRow(OpenApiAuthLevelType.Anonymous, "", false, false)]
150+
[DataRow(OpenApiAuthLevelType.Anonymous, "configKey", false, false)]
151+
[DataRow(OpenApiAuthLevelType.User, null, true, false)]
152+
[DataRow(OpenApiAuthLevelType.User, "", true, false)]
153+
[DataRow(OpenApiAuthLevelType.User, "configKey", false, true)]
154+
[DataRow(OpenApiAuthLevelType.Function, null, true, false)]
155+
[DataRow(OpenApiAuthLevelType.Function, "", true, false)]
156+
[DataRow(OpenApiAuthLevelType.Function, "configKey", false, true)]
157+
[DataRow(OpenApiAuthLevelType.System, null, true, false)]
158+
[DataRow(OpenApiAuthLevelType.System, "", true, false)]
159+
[DataRow(OpenApiAuthLevelType.System, "configKey", false, true)]
160+
[DataRow(OpenApiAuthLevelType.Admin, null, true, false)]
161+
[DataRow(OpenApiAuthLevelType.Admin, "", true, false)]
162+
[DataRow(OpenApiAuthLevelType.Admin, "configKey", false, true)]
163+
public void Given_Options_When_IsAuthKeyRequired_Invoked_Then_It_Should_Return_Result(
164+
OpenApiAuthLevelType configuredAuthLevel, string configKey, bool throwsException, bool expected)
165+
{
166+
var ui = new SwaggerUI();
167+
var method = ui.GetType()
168+
.GetMethod("IsAuthKeyRequired", BindingFlags.Instance | BindingFlags.NonPublic);
169+
170+
Func<bool> action = () => (bool)method.Invoke(ui, new object[] { configuredAuthLevel, configKey });
171+
172+
if (throwsException)
173+
{
174+
action.Should().Throw<TargetInvocationException>().And.InnerException.Should()
175+
.BeOfType<InvalidOperationException>();
176+
}
177+
else
178+
{
179+
action.Invoke().Should().Be(expected);
180+
}
181+
}
182+
183+
184+
[DataTestMethod]
185+
[DataRow(null, OpenApiAuthLevelType.Anonymous, null, null)]
186+
[DataRow(null, OpenApiAuthLevelType.Anonymous, "configKey", null)]
187+
[DataRow(null, OpenApiAuthLevelType.Anonymous, "", null)]
188+
[DataRow("queryKey", OpenApiAuthLevelType.Anonymous, "configKey", "queryKey")]
189+
[DataRow("queryKey", OpenApiAuthLevelType.Anonymous, null, "queryKey")]
190+
[DataRow("queryKey", OpenApiAuthLevelType.Anonymous, "", "queryKey")]
191+
[DataRow("", OpenApiAuthLevelType.Anonymous, null, "")]
192+
[DataRow("", OpenApiAuthLevelType.Anonymous, "configKey", "")]
193+
[DataRow("", OpenApiAuthLevelType.Anonymous, "", "")]
194+
[DataRow(null, OpenApiAuthLevelType.User, null, null, true)]
195+
[DataRow(null, OpenApiAuthLevelType.User, null, "", true)]
196+
[DataRow(null, OpenApiAuthLevelType.User, "configKey", "configKey")]
197+
[DataRow("queryKey", OpenApiAuthLevelType.User, "configKey", "configKey")]
198+
[DataRow("queryKey", OpenApiAuthLevelType.User, null, "queryKey")]
199+
[DataRow("queryKey", OpenApiAuthLevelType.User, "", "queryKey")]
200+
[DataRow("", OpenApiAuthLevelType.User, "configKey", "configKey")]
201+
[DataRow("", OpenApiAuthLevelType.User, null, "",true)]
202+
[DataRow("", OpenApiAuthLevelType.User, "", "",true)]
203+
[DataRow(null, OpenApiAuthLevelType.Function, null, null, true)]
204+
[DataRow(null, OpenApiAuthLevelType.Function, null, "", true)]
205+
[DataRow(null, OpenApiAuthLevelType.Function, "configKey", "configKey")]
206+
[DataRow("queryKey", OpenApiAuthLevelType.Function, "configKey", "configKey")]
207+
[DataRow("queryKey", OpenApiAuthLevelType.Function, null, "queryKey")]
208+
[DataRow("queryKey", OpenApiAuthLevelType.Function, "", "queryKey")]
209+
[DataRow("", OpenApiAuthLevelType.Function, "configKey", "configKey")]
210+
[DataRow("", OpenApiAuthLevelType.Function, null, "",true)]
211+
[DataRow("", OpenApiAuthLevelType.Function, "", "",true)]
212+
[DataRow(null, OpenApiAuthLevelType.System, null, null, true)]
213+
[DataRow(null, OpenApiAuthLevelType.System, null, "", true)]
214+
[DataRow(null, OpenApiAuthLevelType.System, "configKey", "configKey")]
215+
[DataRow("queryKey", OpenApiAuthLevelType.System, "configKey", "configKey")]
216+
[DataRow("queryKey", OpenApiAuthLevelType.System, null, "queryKey")]
217+
[DataRow("queryKey", OpenApiAuthLevelType.System, "", "queryKey")]
218+
[DataRow("", OpenApiAuthLevelType.System, "configKey", "configKey")]
219+
[DataRow("", OpenApiAuthLevelType.System, null, "",true)]
220+
[DataRow("", OpenApiAuthLevelType.System, "", "",true)]
221+
[DataRow(null, OpenApiAuthLevelType.Admin, null, null, true)]
222+
[DataRow(null, OpenApiAuthLevelType.Admin, null, "", true)]
223+
[DataRow(null, OpenApiAuthLevelType.Admin, "configKey", "configKey")]
224+
[DataRow("queryKey", OpenApiAuthLevelType.Admin, "configKey", "configKey")]
225+
[DataRow("queryKey", OpenApiAuthLevelType.Admin, null, "queryKey")]
226+
[DataRow("queryKey", OpenApiAuthLevelType.Admin, "", "queryKey")]
227+
[DataRow("", OpenApiAuthLevelType.Admin, "configKey", "configKey")]
228+
[DataRow("", OpenApiAuthLevelType.Admin, null, "",true)]
229+
[DataRow("", OpenApiAuthLevelType.Admin, "", "",true)]
230+
public async Task Given_AuthKey_Options_When_RenderAsync_Invoked_Then_It_Should_Be_Used_As_Request_Key(
231+
string queryKey, OpenApiAuthLevelType configuredAuthLevel, string configKey, string expectedRequestKey,
232+
bool throwsException = false)
233+
{
234+
var endpoint = "swagger/ui";
235+
var baseUrl = "https://localhost:7071";
236+
var ui = new SwaggerUI();
237+
ui.AddMetadata(new OpenApiInfo());
238+
var uiType = ui.GetType();
239+
240+
//Generate Request Object with query key
241+
var queryDict = new Dictionary<string, StringValues>();
242+
if (queryKey != null)
243+
{
244+
queryDict["code"] = queryKey;
245+
}
246+
var req = new Mock<IHttpRequestDataObject>();
247+
req.SetupGet(p => p.Query).Returns(new QueryCollection(queryDict));
248+
uiType.GetField("_req", BindingFlags.Instance | BindingFlags.NonPublic).SetValue(ui, req.Object);
249+
250+
//Set BaseUrl
251+
uiType.GetField("_baseUrl", BindingFlags.Instance | BindingFlags.NonPublic).SetValue(ui, baseUrl);
252+
253+
//Set html string just to contain url placeholder
254+
var swaggerUrlPlaceholder =
255+
uiType.GetField("SwaggerUrlPlaceholder", BindingFlags.Static | BindingFlags.NonPublic)
256+
.GetRawConstantValue() as string;
257+
uiType.GetField("_indexHtml", BindingFlags.Instance | BindingFlags.NonPublic)
258+
.SetValue(ui, swaggerUrlPlaceholder);
259+
260+
261+
Func<Task<string>> action = async () => await ui.RenderAsync(endpoint, configuredAuthLevel, configKey);
262+
263+
if (throwsException)
264+
{
265+
await action.Should().ThrowAsync<InvalidOperationException>();
266+
}
267+
else
268+
{
269+
var result = await action();
270+
if (expectedRequestKey != null)
271+
{
272+
result.Should().Contain($"code={expectedRequestKey}");
273+
}
274+
else
275+
{
276+
result.Should().NotContain($"code=");
277+
}
278+
}
279+
}
140280
}
141281
}

0 commit comments

Comments
 (0)