Skip to content

Commit d2e4111

Browse files
committed
fix: failing unit tests for security scheme references in security requirements
Signed-off-by: Vincent Biret <[email protected]>
1 parent 837f000 commit d2e4111

File tree

8 files changed

+45
-79
lines changed

8 files changed

+45
-79
lines changed

src/Microsoft.OpenApi/Models/OpenApiSecurityRequirement.cs

Lines changed: 23 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
using System;
55
using System.Collections.Generic;
6+
using System.Linq;
67
using Microsoft.OpenApi.Interfaces;
78
using Microsoft.OpenApi.Models.Interfaces;
89
using Microsoft.OpenApi.Models.References;
@@ -18,7 +19,7 @@ namespace Microsoft.OpenApi.Models
1819
/// then the value is a list of scope names required for the execution.
1920
/// For other security scheme types, the array MUST be empty.
2021
/// </summary>
21-
public class OpenApiSecurityRequirement : Dictionary<IOpenApiSecurityScheme, IList<string>>,
22+
public class OpenApiSecurityRequirement : Dictionary<OpenApiSecuritySchemeReference, IList<string>>,
2223
IOpenApiSerializable
2324
{
2425
/// <summary>
@@ -36,40 +37,42 @@ public OpenApiSecurityRequirement()
3637
/// </summary>
3738
public void SerializeAsV31(IOpenApiWriter writer)
3839
{
39-
SerializeInternal(writer, (writer, element) => element.SerializeAsV31(writer));
40+
SerializeInternal(writer, (w, s) => w.WritePropertyName(s.Reference.ReferenceV3));
4041
}
4142

4243
/// <summary>
4344
/// Serialize <see cref="OpenApiSecurityRequirement"/> to Open Api v3.0
4445
/// </summary>
4546
public void SerializeAsV3(IOpenApiWriter writer)
4647
{
47-
SerializeInternal(writer, (writer, element) => element.SerializeAsV3(writer));
48+
SerializeInternal(writer, (w, s) => w.WritePropertyName(s.Reference.ReferenceV3));
4849
}
4950

5051
/// <summary>
5152
/// Serialize <see cref="OpenApiSecurityRequirement"/>
5253
/// </summary>
53-
private void SerializeInternal(IOpenApiWriter writer, Action<IOpenApiWriter, IOpenApiSerializable> callback)
54+
private void SerializeInternal(IOpenApiWriter writer, Action<IOpenApiWriter, OpenApiSecuritySchemeReference> callback)
5455
{
55-
Utils.CheckArgumentNull(writer);;
56+
Utils.CheckArgumentNull(writer);
57+
58+
// Reaching this point means the reference to a specific OpenApiSecurityScheme fails.
59+
// We are not able to serialize this SecurityScheme/Scopes key value pair since we do not know what
60+
// string to output.
61+
var validPairs = this.Where(static p => p.Key?.Target is not null).ToArray();
62+
63+
if (validPairs.Length == 0)
64+
{
65+
return;
66+
}
5667

5768
writer.WriteStartObject();
5869

59-
foreach (var securitySchemeAndScopesValuePair in this)
70+
foreach (var securitySchemeAndScopesValuePair in validPairs)
6071
{
6172
var securityScheme = securitySchemeAndScopesValuePair.Key;
6273
var scopes = securitySchemeAndScopesValuePair.Value;
6374

64-
if (securityScheme is not OpenApiSecuritySchemeReference schemeReference || schemeReference.Reference is null)
65-
{
66-
// Reaching this point means the reference to a specific OpenApiSecurityScheme fails.
67-
// We are not able to serialize this SecurityScheme/Scopes key value pair since we do not know what
68-
// string to output.
69-
continue;
70-
}
71-
72-
writer.WritePropertyName(schemeReference.Reference.ReferenceV3);
75+
callback(writer, securityScheme);
7376

7477
writer.WriteStartArray();
7578

@@ -89,48 +92,19 @@ private void SerializeInternal(IOpenApiWriter writer, Action<IOpenApiWriter, IOp
8992
/// </summary>
9093
public void SerializeAsV2(IOpenApiWriter writer)
9194
{
92-
Utils.CheckArgumentNull(writer);;
93-
94-
writer.WriteStartObject();
95-
96-
foreach (var securitySchemeAndScopesValuePair in this)
97-
{
98-
var securityScheme = securitySchemeAndScopesValuePair.Key;
99-
var scopes = securitySchemeAndScopesValuePair.Value;
100-
101-
if (securityScheme is not OpenApiSecuritySchemeReference schemeReference || schemeReference.Reference is null)
102-
{
103-
// Reaching this point means the reference to a specific OpenApiSecurityScheme fails.
104-
// We are not able to serialize this SecurityScheme/Scopes key value pair since we do not know what
105-
// string to output.
106-
continue;
107-
}
108-
109-
securityScheme.SerializeAsV2(writer);
110-
111-
writer.WriteStartArray();
112-
113-
foreach (var scope in scopes)
114-
{
115-
writer.WriteValue(scope);
116-
}
117-
118-
writer.WriteEndArray();
119-
}
120-
121-
writer.WriteEndObject();
95+
SerializeInternal(writer, (w, s) => s.SerializeAsV2(w));
12296
}
12397

12498
/// <summary>
12599
/// Comparer for OpenApiSecurityScheme that only considers the Id in the Reference
126100
/// (i.e. the string that will actually be displayed in the written document)
127101
/// </summary>
128-
private sealed class OpenApiSecuritySchemeReferenceEqualityComparer : IEqualityComparer<IOpenApiSecurityScheme>
102+
private sealed class OpenApiSecuritySchemeReferenceEqualityComparer : IEqualityComparer<OpenApiSecuritySchemeReference>
129103
{
130104
/// <summary>
131105
/// Determines whether the specified objects are equal.
132106
/// </summary>
133-
public bool Equals(IOpenApiSecurityScheme x, IOpenApiSecurityScheme y)
107+
public bool Equals(OpenApiSecuritySchemeReference x, OpenApiSecuritySchemeReference y)
134108
{
135109
if (x == null && y == null)
136110
{
@@ -148,17 +122,13 @@ public bool Equals(IOpenApiSecurityScheme x, IOpenApiSecurityScheme y)
148122
/// <summary>
149123
/// Returns a hash code for the specified object.
150124
/// </summary>
151-
public int GetHashCode(IOpenApiSecurityScheme obj)
125+
public int GetHashCode(OpenApiSecuritySchemeReference obj)
152126
{
153127
if (obj is null)
154128
{
155129
return 0;
156130
}
157-
else if (obj is OpenApiSecuritySchemeReference reference)
158-
{
159-
return string.IsNullOrEmpty(reference?.Reference?.Id) ? 0 : reference.Reference.Id.GetHashCode();
160-
}
161-
return obj.GetHashCode();
131+
return string.IsNullOrEmpty(obj?.Reference?.Id) ? 0 : obj.Reference.Id.GetHashCode();
162132
}
163133
}
164134
}

src/Microsoft.OpenApi/Models/References/BaseOpenApiReferenceHolder.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ public T Target
1616
{
1717
get
1818
{
19-
_target ??= Reference.HostDocument.ResolveReferenceTo<T>(Reference);
19+
_target ??= Reference.HostDocument?.ResolveReferenceTo<T>(Reference);
2020
return _target;
2121
}
2222
}

src/Microsoft.OpenApi/Reader/V2/OpenApiSecurityRequirementDeserializer.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ public static OpenApiSecurityRequirement LoadSecurityRequirement(ParseNode node,
4343
return securityRequirement;
4444
}
4545

46-
private static IOpenApiSecurityScheme LoadSecuritySchemeByReference(
46+
private static OpenApiSecuritySchemeReference LoadSecuritySchemeByReference(
4747
OpenApiDocument openApiDocument,
4848
string schemeName)
4949
{

src/Microsoft.OpenApi/Reader/V3/OpenApiSecurityRequirementDeserializer.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ public static OpenApiSecurityRequirement LoadSecurityRequirement(ParseNode node,
4040
return securityRequirement;
4141
}
4242

43-
private static IOpenApiSecurityScheme LoadSecuritySchemeByReference(
43+
private static OpenApiSecuritySchemeReference LoadSecuritySchemeByReference(
4444
OpenApiDocument openApiDocument,
4545
string schemeName)
4646
{

src/Microsoft.OpenApi/Reader/V31/OpenApiSecurityRequirementDeserializer.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ public static OpenApiSecurityRequirement LoadSecurityRequirement(ParseNode node,
4040
return securityRequirement;
4141
}
4242

43-
private static IOpenApiSecurityScheme LoadSecuritySchemeByReference(string schemeName, OpenApiDocument hostDocument)
43+
private static OpenApiSecuritySchemeReference LoadSecuritySchemeByReference(string schemeName, OpenApiDocument hostDocument)
4444
{
4545
return new OpenApiSecuritySchemeReference(schemeName, hostDocument);
4646
}

test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiDocumentTests.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -889,8 +889,8 @@ public async Task ParseModifiedPetStoreDocumentWithTagAndSecurityShouldSucceed()
889889
{
890890
new OpenApiSecurityRequirement
891891
{
892-
[securityScheme1] = new List<string>(),
893-
[securityScheme2] = new List<string>
892+
[new OpenApiSecuritySchemeReference(securityScheme1, "securitySchemeName1")] = new List<string>(),
893+
[new OpenApiSecuritySchemeReference(securityScheme2, "securitySchemeName2")] = new List<string>
894894
{
895895
"scope1",
896896
"scope2"
@@ -1035,8 +1035,8 @@ public async Task ParseModifiedPetStoreDocumentWithTagAndSecurityShouldSucceed()
10351035
{
10361036
new OpenApiSecurityRequirement
10371037
{
1038-
[securityScheme1] = new List<string>(),
1039-
[securityScheme2] = new List<string>
1038+
[new OpenApiSecuritySchemeReference(securityScheme1, "securitySchemeName1")] = new List<string>(),
1039+
[new OpenApiSecuritySchemeReference(securityScheme2, "securitySchemeName2")] = new List<string>
10401040
{
10411041
"scope1",
10421042
"scope2",

test/Microsoft.OpenApi.Tests/Models/OpenApiOperationTests.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -181,8 +181,8 @@ public class OpenApiOperationTests
181181
{
182182
new()
183183
{
184-
[new OpenApiSecuritySchemeReference("securitySchemeId1", hostDocument: null)] = new List<string>(),
185-
[new OpenApiSecuritySchemeReference("securitySchemeId2", hostDocument: null)] = new List<string>
184+
[new OpenApiSecuritySchemeReference(new OpenApiSecurityScheme(), "securitySchemeId1")] = new List<string>(),
185+
[new OpenApiSecuritySchemeReference(new OpenApiSecurityScheme(), "securitySchemeId2")] = new List<string>
186186
{
187187
"scopeName1",
188188
"scopeName2"

test/Microsoft.OpenApi.Tests/Models/OpenApiSecurityRequirementTests.cs

Lines changed: 12 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -25,49 +25,45 @@ public class OpenApiSecurityRequirementTests
2525
new()
2626
{
2727
[
28-
new OpenApiSecuritySchemeReference("scheme1", hostDocument: null)
28+
new OpenApiSecuritySchemeReference(new OpenApiSecurityScheme(), "scheme1")
2929
] = new List<string>
3030
{
3131
"scope1",
3232
"scope2",
3333
"scope3",
3434
},
3535
[
36-
new OpenApiSecuritySchemeReference("scheme2", hostDocument: null)
36+
new OpenApiSecuritySchemeReference(new OpenApiSecurityScheme(), "scheme2")
3737
] = new List<string>
3838
{
3939
"scope4",
4040
"scope5",
4141
},
4242
[
43-
new OpenApiSecuritySchemeReference("scheme3", hostDocument: null)
43+
new OpenApiSecuritySchemeReference(new OpenApiSecurityScheme(), "scheme3")
4444
] = new List<string>()
4545
};
4646

4747
public static OpenApiSecurityRequirement SecurityRequirementWithUnreferencedSecurityScheme =
4848
new()
4949
{
5050
[
51-
new OpenApiSecuritySchemeReference("scheme1", hostDocument: null)
51+
new OpenApiSecuritySchemeReference(new OpenApiSecurityScheme(), "scheme1")
5252
] = new List<string>
5353
{
5454
"scope1",
5555
"scope2",
5656
"scope3",
5757
},
5858
[
59-
new OpenApiSecurityScheme()
60-
{
61-
// This security scheme is unreferenced, so this key value pair cannot be serialized.
62-
Name = "brokenUnreferencedScheme"
63-
}
59+
new OpenApiSecuritySchemeReference("brokenUnreferencedScheme", hostDocument: null)
6460
] = new List<string>
6561
{
6662
"scope4",
6763
"scope5",
6864
},
6965
[
70-
new OpenApiSecuritySchemeReference("scheme3", hostDocument: null)
66+
new OpenApiSecuritySchemeReference(new OpenApiSecurityScheme(), "scheme3")
7167
] = new List<string>()
7268
};
7369

@@ -246,13 +242,13 @@ public void SchemesShouldConsiderOnlyReferenceIdForEquality()
246242
};
247243

248244
// Act
249-
securityRequirement.Add(securityScheme1, new List<string>());
250-
securityRequirement.Add(securityScheme2, new List<string> { "scope1", "scope2" });
245+
securityRequirement.Add(new OpenApiSecuritySchemeReference(securityScheme1, "securityScheme1"), new List<string>());
246+
securityRequirement.Add(new OpenApiSecuritySchemeReference(securityScheme2, "securityScheme2"), new List<string> { "scope1", "scope2" });
251247

252248
var addSecurityScheme1Duplicate = () =>
253-
securityRequirement.Add(securityScheme1Duplicate, new List<string>());
249+
securityRequirement.Add(new OpenApiSecuritySchemeReference(securityScheme1Duplicate, "securityScheme1"), new List<string>());
254250
var addSecurityScheme1WithDifferentProperties = () =>
255-
securityRequirement.Add(securityScheme1WithDifferentProperties, new List<string>());
251+
securityRequirement.Add(new OpenApiSecuritySchemeReference(securityScheme1WithDifferentProperties, "securityScheme1"), new List<string>());
256252

257253
// Assert
258254
// Only the first two should be added successfully since the latter two are duplicates of securityScheme1.
@@ -267,8 +263,8 @@ public void SchemesShouldConsiderOnlyReferenceIdForEquality()
267263
{
268264
// This should work with any security scheme object
269265
// as long as Reference.Id os securityScheme1
270-
[securityScheme1WithDifferentProperties] = new List<string>(),
271-
[securityScheme2] = new List<string> { "scope1", "scope2" },
266+
[new OpenApiSecuritySchemeReference(securityScheme1WithDifferentProperties, "securityScheme1")] = new List<string>(),
267+
[new OpenApiSecuritySchemeReference(securityScheme2, "securityScheme2")] = new List<string> { "scope1", "scope2" },
272268
});
273269
}
274270
}

0 commit comments

Comments
 (0)