Skip to content

Commit 7316184

Browse files
committed
Init implementation for the Open API validation
1 parent bdba12d commit 7316184

24 files changed

+1025
-0
lines changed

src/Microsoft.OpenApi/Properties/SRResource.Designer.cs

Lines changed: 18 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/Microsoft.OpenApi/Properties/SRResource.resx

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -177,4 +177,10 @@
177177
<data name="SourceExpressionHasInvalidFormat" xml:space="preserve">
178178
<value>The source expression '{0}' has invalid format.</value>
179179
</data>
180+
<data name="Validation_PathItemMustBeginWithSlash" xml:space="preserve">
181+
<value>The path item name '{0}' MUST begin with a slash.</value>
182+
</data>
183+
<data name="Validation_StringMustBeEmailAddress" xml:space="preserve">
184+
<value>The string '{0}' MUST be in the format of an email address.</value>
185+
</data>
180186
</root>
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
// ------------------------------------------------------------
2+
// Copyright (c) Microsoft Corporation. All rights reserved.
3+
// Licensed under the MIT License (MIT). See LICENSE in the repo root for license information.
4+
// ------------------------------------------------------------
5+
6+
using System.Collections.Generic;
7+
using System.Linq;
8+
using Microsoft.OpenApi.Interfaces;
9+
using Microsoft.OpenApi.Validations.Rules;
10+
11+
namespace Microsoft.OpenApi.Validations
12+
{
13+
/// <summary>
14+
/// The public APIs to validate the Open API element.
15+
/// </summary>
16+
public static class OpenApiElementValidator
17+
{
18+
/// <summary>
19+
/// Validate the Open API element.
20+
/// </summary>
21+
/// <typeparam name="T">The Open API element type.</typeparam>
22+
/// <param name="element">The Open API element.</param>
23+
/// <returns>True means no errors, otherwise with errors.</returns>
24+
public static bool Validate<T>(this T element) where T : IOpenApiElement
25+
{
26+
IEnumerable<ValidationError> errors;
27+
return element.Validate(out errors);
28+
}
29+
30+
/// <summary>
31+
/// Validate the Open API element.
32+
/// </summary>
33+
/// <typeparam name="T">The Open API element type.</typeparam>
34+
/// <param name="element">The Open API element.</param>
35+
/// <param name="errors">The output errors.</param>
36+
/// <returns>True means no errors, otherwise with errors.</returns>
37+
public static bool Validate<T>(this T element, out IEnumerable<ValidationError> errors)
38+
where T : IOpenApiElement
39+
{
40+
ValidationRuleSet ruleSet = ValidationRuleSet.DefaultRuleSet;
41+
return element.Validate(ruleSet, out errors);
42+
}
43+
44+
/// <summary>
45+
/// Validate the Open API element.
46+
/// </summary>
47+
/// <typeparam name="T">The Open API element type.</typeparam>
48+
/// <param name="element">The Open API element.</param>
49+
/// <param name="ruleSet">The input rule set.</param>
50+
/// <param name="errors">The output errors.</param>
51+
/// <returns>True means no errors, otherwise with errors.</returns>
52+
public static bool Validate<T>(this T element, ValidationRuleSet ruleSet, out IEnumerable<ValidationError> errors)
53+
where T : IOpenApiElement
54+
{
55+
errors = null;
56+
if (element == null)
57+
{
58+
return true;
59+
}
60+
61+
if (ruleSet == null)
62+
{
63+
ruleSet = ValidationRuleSet.DefaultRuleSet;
64+
}
65+
66+
ValidationContext context = new ValidationContext(ruleSet);
67+
68+
context.Validate(element);
69+
70+
errors = context.Errors;
71+
72+
return !errors.Any();
73+
}
74+
}
75+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
// ------------------------------------------------------------
2+
// Copyright (c) Microsoft Corporation. All rights reserved.
3+
// Licensed under the MIT License (MIT). See LICENSE in the repo root for license information.
4+
// ------------------------------------------------------------
5+
6+
using Microsoft.OpenApi.Models;
7+
8+
namespace Microsoft.OpenApi.Validations.Rules
9+
{
10+
/// <summary>
11+
/// The validation rules for <see cref="OpenApiComponents"/>.
12+
/// </summary>
13+
public static class OpenApiComponentsRules
14+
{
15+
}
16+
}
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
// ------------------------------------------------------------
2+
// Copyright (c) Microsoft Corporation. All rights reserved.
3+
// Licensed under the MIT License (MIT). See LICENSE in the repo root for license information.
4+
// ------------------------------------------------------------
5+
6+
using System;
7+
using Microsoft.OpenApi.Models;
8+
using Microsoft.OpenApi.Properties;
9+
10+
namespace Microsoft.OpenApi.Validations.Rules
11+
{
12+
/// <summary>
13+
/// The validation rules for <see cref="OpenApiContact"/>.
14+
/// </summary>
15+
internal static class OpenApiContactRules
16+
{
17+
/// <summary>
18+
/// Email field MUST be email address.
19+
/// </summary>
20+
public static readonly ValidationRule<OpenApiContact> EmailMustBeEmailFormat =
21+
new ValidationRule<OpenApiContact>(
22+
(context, item) =>
23+
{
24+
context.Push("email");
25+
if (item != null && item.Email != null)
26+
{
27+
if (!item.Email.IsEmailAddress())
28+
{
29+
ValidationError error = new ValidationError(ErrorReason.EmailFormat, context.PathString,
30+
String.Format(SRResource.Validation_StringMustBeEmailAddress, item.Email));
31+
context.AddError(error);
32+
}
33+
}
34+
context.Pop();
35+
});
36+
37+
/// <summary>
38+
/// Url field MUST be url format.
39+
/// </summary>
40+
public static readonly ValidationRule<OpenApiContact> UrlMustBeUrlFormat =
41+
new ValidationRule<OpenApiContact>(
42+
(context, item) =>
43+
{
44+
context.Push("url");
45+
if (item != null && item.Url != null)
46+
{
47+
// TODO:
48+
}
49+
context.Pop();
50+
});
51+
}
52+
}
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
// ------------------------------------------------------------
2+
// Copyright (c) Microsoft Corporation. All rights reserved.
3+
// Licensed under the MIT License (MIT). See LICENSE in the repo root for license information.
4+
// ------------------------------------------------------------
5+
6+
using Microsoft.OpenApi.Models;
7+
8+
namespace Microsoft.OpenApi.Validations.Rules
9+
{
10+
/// <summary>
11+
/// The validation rules for <see cref="OpenApiDocument"/>.
12+
/// </summary>
13+
internal static class OpenApiDocumentRules
14+
{
15+
/// <summary>
16+
/// The Info field is required.
17+
/// </summary>
18+
public static readonly ValidationRule<OpenApiDocument> InfoIsRequired =
19+
new ValidationRule<OpenApiDocument>(
20+
(context, item) =>
21+
{
22+
if (item.Info == null)
23+
{
24+
//context.AddError();
25+
}
26+
});
27+
28+
/// <summary>
29+
/// The Paths field is required.
30+
/// </summary>
31+
public static readonly ValidationRule<OpenApiDocument> PathsIsRequired =
32+
new ValidationRule<OpenApiDocument>(
33+
(context, item) =>
34+
{
35+
if (item.Paths == null)
36+
{
37+
//context.AddError();
38+
}
39+
});
40+
}
41+
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
// ------------------------------------------------------------
2+
// Copyright (c) Microsoft Corporation. All rights reserved.
3+
// Licensed under the MIT License (MIT). See LICENSE in the repo root for license information.
4+
// ------------------------------------------------------------
5+
6+
using Microsoft.OpenApi.Interfaces;
7+
8+
namespace Microsoft.OpenApi.Validations.Rules
9+
{
10+
/// <summary>
11+
/// The validation rules for <see cref="IOpenApiExtensible"/>.
12+
/// </summary>
13+
public static class OpenApiExtensibleRules
14+
{
15+
/// <summary>
16+
/// Extension name MUST start with "x-".
17+
/// </summary>
18+
private static readonly ValidationRule<IOpenApiExtensible> ExtensionNameMustStartWithXDollar =
19+
new ValidationRule<IOpenApiExtensible>(
20+
(context, item) =>
21+
{
22+
foreach (var extensible in item.Extensions)
23+
{
24+
25+
}
26+
});
27+
}
28+
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
// ------------------------------------------------------------
2+
// Copyright (c) Microsoft Corporation. All rights reserved.
3+
// Licensed under the MIT License (MIT). See LICENSE in the repo root for license information.
4+
// ------------------------------------------------------------
5+
6+
using System;
7+
using Microsoft.OpenApi.Models;
8+
9+
namespace Microsoft.OpenApi.Validations.Rules
10+
{
11+
/// <summary>
12+
/// The validation rules for <see cref="OpenApiInfo"/>.
13+
/// </summary>
14+
internal static class OpenApiInfoRules
15+
{
16+
/// <summary>
17+
/// The title of the application is required.
18+
/// </summary>
19+
public static readonly ValidationRule<OpenApiInfo> TitleIsRequired =
20+
new ValidationRule<OpenApiInfo>(
21+
(context, item) =>
22+
{
23+
if (String.IsNullOrEmpty(item.Title))
24+
{
25+
// add error.
26+
}
27+
});
28+
29+
// add more rule.
30+
}
31+
}
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
// ------------------------------------------------------------
2+
// Copyright (c) Microsoft Corporation. All rights reserved.
3+
// Licensed under the MIT License (MIT). See LICENSE in the repo root for license information.
4+
// ------------------------------------------------------------
5+
6+
using Microsoft.OpenApi.Models;
7+
using Microsoft.OpenApi.Properties;
8+
9+
namespace Microsoft.OpenApi.Validations.Rules
10+
{
11+
/// <summary>
12+
/// The validation rules for <see cref="OpenApiPaths"/>.
13+
/// </summary>
14+
public static class OpenApiPathsRules
15+
{
16+
/// <summary>
17+
/// A relative path to an individual endpoint. The field name MUST begin with a slash.
18+
/// </summary>
19+
public static readonly ValidationRule<OpenApiPaths> PathNameMustBeginWithSlash =
20+
new ValidationRule<OpenApiPaths>(
21+
(context, item) =>
22+
{
23+
foreach (var pathName in item.Keys)
24+
{
25+
context.Push(pathName);
26+
27+
if (string.IsNullOrEmpty(pathName))
28+
{
29+
// Add the error message
30+
// context.Add(...);
31+
}
32+
33+
if (!pathName.StartsWith("/"))
34+
{
35+
ValidationError error = new ValidationError(ErrorReason.Format, context.PathString,
36+
string.Format(SRResource.Validation_PathItemMustBeginWithSlash, pathName));
37+
context.AddError(error);
38+
}
39+
40+
context.Pop();
41+
}
42+
});
43+
44+
// add more rules
45+
}
46+
}
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
// ------------------------------------------------------------
2+
// Copyright (c) Microsoft Corporation. All rights reserved.
3+
// Licensed under the MIT License (MIT). See LICENSE in the repo root for license information.
4+
// ------------------------------------------------------------
5+
6+
using System;
7+
8+
namespace Microsoft.OpenApi.Validations.Rules
9+
{
10+
internal static class RuleHelpers
11+
{
12+
/// <summary>
13+
/// Input string must be in the format of an email address
14+
/// </summary>
15+
/// <param name="input">The input string.</param>
16+
/// <returns></returns>
17+
public static bool IsEmailAddress(this string input)
18+
{
19+
if (String.IsNullOrEmpty(input))
20+
{
21+
return false;
22+
}
23+
24+
var splits = input.Split('@');
25+
if (splits.Length != 2)
26+
{
27+
return false;
28+
}
29+
30+
if (String.IsNullOrEmpty(splits[0]) || String.IsNullOrEmpty(splits[1]))
31+
{
32+
return false;
33+
}
34+
35+
// Add more rules.
36+
37+
return true;
38+
}
39+
}
40+
}

0 commit comments

Comments
 (0)