Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
56 commits
Select commit Hold shift + click to select a range
08b21d1
Merge pull request #855 from microsoft/vnext
baywet May 11, 2022
f918aba
Merge pull request #865 from microsoft/vnext
baywet May 16, 2022
b04aecd
Merge pull request #871 from microsoft/vnext
baywet May 17, 2022
fe8d4fa
Merge pull request #899 from microsoft/vnext
baywet Jun 7, 2022
5fe88e8
Merge pull request #914 from microsoft/vnext
baywet Jun 23, 2022
98877ba
Merge pull request #917 from microsoft/vnext
baywet Jun 23, 2022
6cf490e
Merge pull request #931 from microsoft/vnext
baywet Jul 6, 2022
b2f53ee
Merge pull request #938 from microsoft/vnext
baywet Jul 8, 2022
67a6b07
Merge pull request #947 from microsoft/vnext
andrueastman Jul 19, 2022
35b5282
Merge pull request #958 from microsoft/vnext
darrelmiller Jul 30, 2022
03ff377
Merge pull request #979 from microsoft/vnext
MaggieKimani1 Aug 15, 2022
c382c22
Merge pull request #997 from microsoft/vnext
MaggieKimani1 Sep 2, 2022
ddcdf25
Merge pull request #999 from microsoft/vnext
MaggieKimani1 Sep 2, 2022
512c795
Merge pull request #1002 from microsoft/vnext
baywet Sep 7, 2022
103ea84
Merge pull request #1009 from microsoft/vnext
irvinesunday Sep 12, 2022
f6185b6
Merge pull request #1015 from microsoft/vnext
baywet Sep 19, 2022
e6308a8
Merge pull request #1018 from microsoft/vnext
baywet Sep 20, 2022
5f8a702
Merge pull request #1023 from microsoft/vnext
MaggieKimani1 Sep 26, 2022
d23ad22
Merge pull request #1037 from microsoft/vnext
MaggieKimani1 Oct 6, 2022
1b02c01
Merge pull request #1050 from microsoft/vnext
baywet Oct 25, 2022
656ac9a
Merge pull request #1084 from microsoft/vnext
MaggieKimani1 Nov 21, 2022
40d67ac
Merge pull request #1086 from microsoft/vnext
MaggieKimani1 Nov 21, 2022
0381437
Merge pull request #1100 from microsoft/vnext
baywet Dec 6, 2022
60c11ad
Merge pull request #1120 from microsoft/vnext
baywet Jan 17, 2023
572b303
Merge pull request #1148 from microsoft/vnext
MaggieKimani1 Jan 31, 2023
9c18762
Merge pull request #1153 from microsoft/vnext
baywet Feb 1, 2023
bf7b8cf
Merge pull request #1161 from microsoft/vnext
baywet Feb 13, 2023
e0b36a7
Merge pull request #1170 from microsoft/vnext
MaggieKimani1 Feb 21, 2023
2605650
Merge pull request #1175 from microsoft/vnext
baywet Feb 28, 2023
9155d11
Merge pull request #1181 from microsoft/vnext
MaggieKimani1 Mar 7, 2023
4da5e7a
Merge pull request #1199 from microsoft/vnext
MaggieKimani1 Mar 30, 2023
0975409
Merge pull request #1205 from microsoft/vnext
baywet Apr 5, 2023
14ec838
Merge pull request #1210 from microsoft/vnext
baywet Apr 11, 2023
92e5e07
Merge pull request #1216 from microsoft/vnext
baywet Apr 12, 2023
986917b
Merge pull request #1220 from microsoft/vnext
MaggieKimani1 Apr 17, 2023
d6962c3
Merge pull request #1240 from microsoft/vnext
andrueastman May 3, 2023
27215dd
Merge pull request #1243 from microsoft/vnext
andrueastman May 4, 2023
ffb9bd0
Merge pull request #1279 from microsoft/vnext
MaggieKimani1 Jun 19, 2023
137a456
Merge pull request #1296 from microsoft/vnext
MaggieKimani1 Jul 24, 2023
97c5364
Merge pull request #1324 from microsoft/vnext
baywet Aug 31, 2023
1a39857
Merge pull request #1329 from microsoft/vnext
andrueastman Sep 5, 2023
acd7652
Merge pull request #1335 from microsoft/vnext
baywet Sep 7, 2023
11cfc7d
Merge pull request #1361 from microsoft/vnext
MaggieKimani1 Sep 26, 2023
2ade929
Merge pull request #1393 from microsoft/vnext
andrueastman Oct 5, 2023
1bec222
Merge pull request #1445 from microsoft/vnext
irvinesunday Oct 30, 2023
eeb3013
Merge pull request #1453 from microsoft/vnext
irvinesunday Nov 6, 2023
742df9f
Merge pull request #1456 from microsoft/vnext
MaggieKimani1 Nov 7, 2023
aab3d82
Merge pull request #1461 from microsoft/vnext
irvinesunday Nov 14, 2023
7387007
Merge pull request #1482 from microsoft/vnext
MaggieKimani1 Nov 22, 2023
79f59bf
Merge pull request #1532 from microsoft/vnext
MaggieKimani1 Jan 16, 2024
9a94349
Add ValidationRuleSet.Remove
LucGenetier Jan 21, 2024
01e3a60
Updates following Vincent's comments
LucGenetier Jan 22, 2024
cefbe9f
Updates following Vincent's comments
LucGenetier Jan 21, 2024
724ab3b
Merge branch 'master' of https://github.com/LucGenetier/OpenAPI.NET
LucGenetier Jan 22, 2024
d8419f2
Update
LucGenetier Jan 24, 2024
e2b0aa3
Apply suggestions from code review
baywet Jan 24, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ public static class OpenApiComponentsRules
/// that MUST use keys that match the regular expression: ^[a-zA-Z0-9\.\-_]+$.
/// </summary>
public static ValidationRule<OpenApiComponents> KeyMustBeRegularExpression =>
new(
new(nameof(KeyMustBeRegularExpression),
(context, components) =>
{
ValidateKeys(context, components.Schemas?.Keys, "schemas");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ public static class OpenApiContactRules
/// Email field MUST be email address.
/// </summary>
public static ValidationRule<OpenApiContact> EmailMustBeEmailFormat =>
new(
new(nameof(EmailMustBeEmailFormat),
(context, item) =>
{
context.Enter("email");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ public static class OpenApiDocumentRules
/// The Info field is required.
/// </summary>
public static ValidationRule<OpenApiDocument> OpenApiDocumentFieldIsMissing =>
new(
new(nameof(OpenApiDocumentFieldIsMissing),
(context, item) =>
{
// info
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ public static class OpenApiExtensibleRules
/// Extension name MUST start with "x-".
/// </summary>
public static ValidationRule<IOpenApiExtensible> ExtensionNameMustStartWithXDash =>
new(
new(nameof(ExtensionNameMustStartWithXDash),
(context, item) =>
{
context.Enter("extensions");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ public static class OpenApiExternalDocsRules
/// Validate the field is required.
/// </summary>
public static ValidationRule<OpenApiExternalDocs> UrlIsRequired =>
new(
new(nameof(UrlIsRequired),
(context, item) =>
{
// url
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ public static class OpenApiHeaderRules
/// Validate the data matches with the given data type.
/// </summary>
public static ValidationRule<OpenApiHeader> HeaderMismatchedDataType =>
new(
new(nameof(HeaderMismatchedDataType),
(context, header) =>
{
// example
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ public static class OpenApiInfoRules
/// Validate the field is required.
/// </summary>
public static ValidationRule<OpenApiInfo> InfoRequiredFields =>
new(
new(nameof(InfoRequiredFields),
(context, item) =>
{
// title
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ public static class OpenApiLicenseRules
/// REQUIRED.
/// </summary>
public static ValidationRule<OpenApiLicense> LicenseRequiredFields =>
new(
new(nameof(LicenseRequiredFields),
(context, license) =>
{
context.Enter("name");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ public static class OpenApiMediaTypeRules
/// Validate the data matches with the given data type.
/// </summary>
public static ValidationRule<OpenApiMediaType> MediaTypeMismatchedDataType =>
new(
new(nameof(MediaTypeMismatchedDataType),
(context, mediaType) =>
{
// example
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ public static class OpenApiOAuthFlowRules
/// Validate the field is required.
/// </summary>
public static ValidationRule<OpenApiOAuthFlow> OAuthFlowRequiredFields =>
new(
new(nameof(OAuthFlowRequiredFields),
(context, flow) =>
{
// authorizationUrl
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ public static class OpenApiParameterRules
/// Validate the field is required.
/// </summary>
public static ValidationRule<OpenApiParameter> ParameterRequiredFields =>
new(
new(nameof(ParameterRequiredFields),
(context, item) =>
{
// name
Expand All @@ -43,7 +43,7 @@ public static class OpenApiParameterRules
/// Validate the "required" field is true when "in" is path.
/// </summary>
public static ValidationRule<OpenApiParameter> RequiredMustBeTrueWhenInIsPath =>
new(
new(nameof(RequiredMustBeTrueWhenInIsPath),
(context, item) =>
{
// required
Expand All @@ -62,7 +62,7 @@ public static class OpenApiParameterRules
/// Validate the data matches with the given data type.
/// </summary>
public static ValidationRule<OpenApiParameter> ParameterMismatchedDataType =>
new(
new(nameof(ParameterMismatchedDataType),
(context, parameter) =>
{
// example
Expand Down Expand Up @@ -100,7 +100,7 @@ public static class OpenApiParameterRules
/// Validate that a path parameter should always appear in the path
/// </summary>
public static ValidationRule<OpenApiParameter> PathParameterShouldBeInThePath =>
new(
new(nameof(PathParameterShouldBeInThePath),
(context, parameter) =>
{
if (parameter.In == ParameterLocation.Path &&
Expand Down
4 changes: 2 additions & 2 deletions src/Microsoft.OpenApi/Validations/Rules/OpenApiPathsRules.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ public static class OpenApiPathsRules
/// A relative path to an individual endpoint. The field name MUST begin with a slash.
/// </summary>
public static ValidationRule<OpenApiPaths> PathNameMustBeginWithSlash =>
new(
new(nameof(PathNameMustBeginWithSlash),
(context, item) =>
{
foreach (var pathName in item.Keys)
Expand All @@ -39,7 +39,7 @@ public static class OpenApiPathsRules
/// A relative path to an individual endpoint. The field name MUST begin with a slash.
/// </summary>
public static ValidationRule<OpenApiPaths> PathMustBeUnique =>
new ValidationRule<OpenApiPaths>(
new ValidationRule<OpenApiPaths>(nameof(PathMustBeUnique),
(context, item) =>
{
var hashSet = new HashSet<string>();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ public static class OpenApiResponseRules
/// Validate the field is required.
/// </summary>
public static ValidationRule<OpenApiResponse> ResponseRequiredFields =>
new(
new(nameof(ResponseRequiredFields),
(context, response) =>
{
// description
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.

using System.Linq;
Expand All @@ -17,7 +17,7 @@ public static class OpenApiResponsesRules
/// An OpenAPI operation must contain at least one response
/// </summary>
public static ValidationRule<OpenApiResponses> ResponsesMustContainAtLeastOneResponse =>
new(
new(nameof(ResponsesMustContainAtLeastOneResponse),
(context, responses) =>
{
if (!responses.Keys.Any())
Expand All @@ -31,7 +31,7 @@ public static class OpenApiResponsesRules
/// The response key must either be "default" or an HTTP status code (1xx, 2xx, 3xx, 4xx, 5xx).
/// </summary>
public static ValidationRule<OpenApiResponses> ResponsesMustBeIdentifiedByDefaultOrStatusCode =>
new(
new(nameof(ResponsesMustBeIdentifiedByDefaultOrStatusCode),
(context, responses) =>
{
foreach (var key in responses.Keys)
Expand Down
4 changes: 2 additions & 2 deletions src/Microsoft.OpenApi/Validations/Rules/OpenApiSchemaRules.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ public static class OpenApiSchemaRules
/// Validate the data matches with the given data type.
/// </summary>
public static ValidationRule<OpenApiSchema> SchemaMismatchedDataType =>
new(
new(nameof(SchemaMismatchedDataType),
(context, schema) =>
{
// default
Expand Down Expand Up @@ -60,7 +60,7 @@ public static class OpenApiSchemaRules
/// Validates Schema Discriminator
/// </summary>
public static ValidationRule<OpenApiSchema> ValidateSchemaDiscriminator =>
new(
new(nameof(ValidateSchemaDiscriminator),
(context, schema) =>
{
// discriminator
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ public static class OpenApiServerRules
/// Validate the field is required.
/// </summary>
public static ValidationRule<OpenApiServer> ServerRequiredFields =>
new(
new(nameof(ServerRequiredFields),
(context, server) =>
{
context.Enter("url");
Expand Down
2 changes: 1 addition & 1 deletion src/Microsoft.OpenApi/Validations/Rules/OpenApiTagRules.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ public static class OpenApiTagRules
/// Validate the field is required.
/// </summary>
public static ValidationRule<OpenApiTag> TagRequiredFields =>
new(
new(nameof(TagRequiredFields),
(context, tag) =>
{
context.Enter("name");
Expand Down
28 changes: 25 additions & 3 deletions src/Microsoft.OpenApi/Validations/ValidationRule.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
// Licensed under the MIT license.

using System;
using System.Globalization;
using Microsoft.OpenApi.Exceptions;
using Microsoft.OpenApi.Interfaces;
using Microsoft.OpenApi.Properties;

Expand All @@ -18,12 +18,22 @@ public abstract class ValidationRule
/// </summary>
internal abstract Type ElementType { get; }

/// <summary>
/// Validation rule Name.
/// </summary>
public string Name { get; }

/// <summary>
/// Validate the object.
/// </summary>
/// <param name="context">The context.</param>
/// <param name="item">The object item.</param>
internal abstract void Evaluate(IValidationContext context, object item);

internal ValidationRule(string name)
{
Name = !string.IsNullOrEmpty(name) ? name : throw new ArgumentNullException(nameof(name));
}
}

/// <summary>
Expand All @@ -33,14 +43,26 @@ public abstract class ValidationRule
public class ValidationRule<T> : ValidationRule where T : IOpenApiElement
{
private readonly Action<IValidationContext, T> _validate;

/// <summary>
/// Initializes a new instance of the <see cref="ValidationRule"/> class.
/// </summary>
/// <param name="validate">Action to perform the validation.</param>
[Obsolete("Please use the other constructor and specify a name")]
public ValidationRule(Action<IValidationContext, T> validate)
: this (Guid.NewGuid().ToString("D"), validate)
{
}

/// <summary>
/// Initializes a new instance of the <see cref="ValidationRule"/> class.
/// </summary>
/// <param name="name">Validation rule name.</param>
/// <param name="validate">Action to perform the validation.</param>
public ValidationRule(Action<IValidationContext, T> validate)
public ValidationRule(string name, Action<IValidationContext, T> validate)
: base(name)
{
_validate = Utils.CheckArgumentNull(validate);
_validate = Utils.CheckArgumentNull(validate);
}

internal override Type ElementType
Expand Down
24 changes: 24 additions & 0 deletions src/Microsoft.OpenApi/Validations/ValidationRuleSet.cs
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,30 @@ public void Add(ValidationRule rule)
item.Add(rule);
}

/// <summary>
/// Remove a rule by its name from all types it is used by.
/// </summary>
/// <param name="ruleName">Name of the rule.</param>
public void Remove(string ruleName)
{
foreach (KeyValuePair<Type, IList<ValidationRule>> rule in _rules)
{
_rules[rule.Key] = rule.Value.Where(vr => !vr.Name.Equals(ruleName, StringComparison.Ordinal)).ToList();
}

// Remove types with no rule
_rules = _rules.Where(r => r.Value.Any()).ToDictionary(r => r.Key, r => r.Value);
}

/// <summary>
/// Remove a rule by element type.
/// </summary>
/// <param name="type">Type of the rule.</param>
public void Remove(Type type)
{
_rules.Remove(type);
}

/// <summary>
/// Get the enumerator.
/// </summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1347,7 +1347,7 @@ namespace Microsoft.OpenApi.Validations
}
public abstract class ValidationRule
{
protected ValidationRule() { }
public string Name { get; }
}
public sealed class ValidationRuleSet : System.Collections.Generic.IEnumerable<Microsoft.OpenApi.Validations.ValidationRule>, System.Collections.IEnumerable
{
Expand All @@ -1358,13 +1358,17 @@ namespace Microsoft.OpenApi.Validations
public void Add(Microsoft.OpenApi.Validations.ValidationRule rule) { }
public System.Collections.Generic.IList<Microsoft.OpenApi.Validations.ValidationRule> FindRules(System.Type type) { }
public System.Collections.Generic.IEnumerator<Microsoft.OpenApi.Validations.ValidationRule> GetEnumerator() { }
public void Remove(string ruleName) { }
public void Remove(System.Type type) { }
public static Microsoft.OpenApi.Validations.ValidationRuleSet GetDefaultRuleSet() { }
public static Microsoft.OpenApi.Validations.ValidationRuleSet GetEmptyRuleSet() { }
}
public class ValidationRule<T> : Microsoft.OpenApi.Validations.ValidationRule
where T : Microsoft.OpenApi.Interfaces.IOpenApiElement
{
[System.Obsolete("Please use the other constructor and specify a name")]
public ValidationRule(System.Action<Microsoft.OpenApi.Validations.IValidationContext, T> validate) { }
public ValidationRule(string name, System.Action<Microsoft.OpenApi.Validations.IValidationContext, T> validate) { }
}
}
namespace Microsoft.OpenApi.Validations.Rules
Expand Down
41 changes: 40 additions & 1 deletion test/Microsoft.OpenApi.Tests/Services/OpenApiValidatorTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
using System;
using System.Collections.Generic;
using FluentAssertions;
using Microsoft.OpenApi.Any;
using Microsoft.OpenApi.Interfaces;
using Microsoft.OpenApi.Models;
using Microsoft.OpenApi.Properties;
Expand Down Expand Up @@ -96,7 +97,7 @@ public void ValidateCustomExtension()
var ruleset = ValidationRuleSet.GetDefaultRuleSet();

ruleset.Add(
new ValidationRule<FooExtension>(
new ValidationRule<FooExtension>("FooExtensionRule",
(context, item) =>
{
if (item.Bar == "hey")
Expand Down Expand Up @@ -133,6 +134,44 @@ public void ValidateCustomExtension()
new OpenApiValidatorError("FooExtensionRule", "#/info/x-foo", "Don't say hey")
});
}

[Fact]
public void RemoveRuleByName_Invalid()
{
Assert.Throws<ArgumentNullException>(() => new ValidationRule<IOpenApiAny>(null, (vc, oaa) => { }));
Assert.Throws<ArgumentNullException>(() => new ValidationRule<IOpenApiAny>(string.Empty, (vc, oaa) => { }));
}

[Fact]
public void RemoveRuleByName()
{
var ruleset = ValidationRuleSet.GetDefaultRuleSet();
int expected = ruleset.Rules.Count - 1;
ruleset.Remove("KeyMustBeRegularExpression");

Assert.Equal(expected, ruleset.Rules.Count);

ruleset.Remove("KeyMustBeRegularExpression");
ruleset.Remove("UnknownName");

Assert.Equal(expected, ruleset.Rules.Count);
}

[Fact]
public void RemoveRuleByType()
{
var ruleset = ValidationRuleSet.GetDefaultRuleSet();
int expected = ruleset.Rules.Count - 1;

ruleset.Remove(typeof(OpenApiComponents));

Assert.Equal(expected, ruleset.Rules.Count);

ruleset.Remove(typeof(OpenApiComponents));
ruleset.Remove(typeof(int));

Assert.Equal(expected, ruleset.Rules.Count);
}
}

internal class FooExtension : IOpenApiExtension, IOpenApiElement
Expand Down
Loading