-
Notifications
You must be signed in to change notification settings - Fork 275
Expand file tree
/
Copy pathOpenApiSchemaRules.cs
More file actions
134 lines (126 loc) · 5.79 KB
/
OpenApiSchemaRules.cs
File metadata and controls
134 lines (126 loc) · 5.79 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.
using System.Collections.Generic;
namespace Microsoft.OpenApi
{
using System;
using System.ComponentModel;
using System.Linq;
/// <summary>
/// The validation rules for <see cref="OpenApiSchema"/>.
/// </summary>
[OpenApiRule]
public static class OpenApiSchemaRules
{
/// <summary>
/// Validates Schema Property has value
/// </summary>
public static ValidationRule<IOpenApiSchema> ValidateSchemaPropertyHasValue =>
new(nameof(ValidateSchemaPropertyHasValue),
(context, schema) =>
{
if (schema.Properties is not null)
{
foreach (var property in schema.Properties
.Where(entry => entry.Value is null))
{
context.Enter(property.Key);
context.CreateError(nameof(ValidateSchemaPropertyHasValue),
string.Format(SRResource.Validation_SchemaPropertyObjectRequired,
schema is OpenApiSchemaReference { Reference: not null } schemaReference
? schemaReference.Reference.Id
: string.Empty, property.Key));
context.Exit();
}
}
});
/// <summary>
/// Validates Schema Discriminator
/// </summary>
public static ValidationRule<IOpenApiSchema> ValidateSchemaDiscriminator =>
new(nameof(ValidateSchemaDiscriminator),
(context, schema) =>
{
// discriminator
if (schema is not null && schema.Discriminator != null)
{
var discriminatorName = schema.Discriminator?.PropertyName;
#pragma warning disable CS0618 // Type or member is obsolete
if (!ValidateChildSchemaAgainstDiscriminator(schema, discriminatorName))
{
context.Enter("discriminator");
context.CreateError(nameof(ValidateSchemaDiscriminator),
string.Format(SRResource.Validation_SchemaRequiredFieldListMustContainThePropertySpecifiedInTheDiscriminator,
schema is OpenApiSchemaReference { Reference: not null} schemaReference ? schemaReference.Reference.Id : string.Empty, discriminatorName));
context.Exit();
}
#pragma warning restore CS0618 // Type or member is obsolete
}
});
/// <summary>
/// Validates the property name in the discriminator against the ones present in the children schema
/// </summary>
/// <param name="schema">The parent schema.</param>
/// <param name="discriminatorName">Adds support for polymorphism. The discriminator is an object name that is used to differentiate
/// between other schemas which may satisfy the payload description.</param>
[Obsolete("This method will be made private in future versions.")]
[Browsable(false)]
public static bool ValidateChildSchemaAgainstDiscriminator(IOpenApiSchema schema, string? discriminatorName)
{
if (discriminatorName is not null)
{
if (schema.Required is null || !schema.Required.Contains(discriminatorName))
{
// recursively check nested schema.OneOf, schema.AnyOf or schema.AllOf and their required fields for the discriminator
if (schema.OneOf is { Count: > 0})
{
return TraverseSchemaElements(discriminatorName, schema.OneOf);
}
if (schema.AnyOf is { Count: > 0})
{
return TraverseSchemaElements(discriminatorName, schema.AnyOf);
}
if (schema.AllOf is { Count: > 0})
{
return TraverseSchemaElements(discriminatorName, schema.AllOf);
}
}
else
{
return true;
}
return false;
}
return false;
}
/// <summary>
/// Traverses the schema elements and checks whether the schema contains the discriminator.
/// </summary>
/// <param name="discriminatorName">Adds support for polymorphism. The discriminator is an object name that is used to differentiate
/// between other schemas which may satisfy the payload description.</param>
/// <param name="childSchema">The child schema.</param>
/// <returns></returns>
[Obsolete("This method will be made private in future versions.")]
[Browsable(false)]
public static bool TraverseSchemaElements(string discriminatorName, IList<IOpenApiSchema>? childSchema)
{
if (childSchema is null)
{
return false;
}
foreach (var childItem in childSchema)
{
if ((!childItem.Properties?.ContainsKey(discriminatorName) ?? false) &&
(!childItem.Required?.Contains(discriminatorName) ?? false))
{
return ValidateChildSchemaAgainstDiscriminator(childItem, discriminatorName);
}
else
{
return true;
}
}
return false;
}
}
}