/// <summary>
 /// Validate if a resource has an id property on response.
 /// Supressions: Rule,Path,Operation,ResponseCode
 /// </summary>
 public IdPropertyResponseRule(OpenApiDocument contract,
                               Supressions supressions, IOptions <RuleSettings> ruleSettings, OpenApiDocumentCache cache) : base(contract, supressions,
                                                                                                                                 ruleSettings, cache, ruleName, Severity.Warning)
 {
     idPropertyName = ruleSettings.Value.IdPropertyResponse.IdPropertyName;
 }
示例#2
0
        private protected override void ExecuteRuleLogic()
        {
            if (!string.IsNullOrEmpty(Contract.Info.Description) &&
                !Contract.Info.Description.BeginsUpperAndFinishesWithPeriod())
            {
                listResult.Add(
                    new ResultItem(this, $"info.description:{Contract.Info.Description}"));
            }

            foreach (KeyValuePair <string, OpenApiPathItem> path in Contract.Paths.Where(path =>
                                                                                         !Supressions.IsSupressed(ruleName, path.Key)))
            {
                if (
                    !string.IsNullOrEmpty(path.Value.Description) &&
                    !path.Value.Description.BeginsUpperAndFinishesWithPeriod()
                    ||
                    !string.IsNullOrEmpty(path.Value.Summary) &&
                    !path.Value.Summary.BeginsUpperAndFinishesWithPeriod()
                    )
                {
                    listResult.Add(
                        new ResultItem(this, path: path.Key));
                }

                foreach (var parameter in Contract.GetAllParameters().Where(x => x.Path == path.Key))
                {
                    if (Supressions.IsSupressed(ruleName, path.Key, parameter.Method))
                    {
                        continue;
                    }

                    if (Supressions.IsSupressed(ruleName, path.Key, parameter.Method, parameter.Name))
                    {
                        continue;
                    }

                    if (!string.IsNullOrEmpty(parameter.OpenApiParameter.Description) &&
                        !parameter.OpenApiParameter.Description.BeginsUpperAndFinishesWithPeriod())
                    {
                        listResult.Add(new ResultItem(this, parameter.ResultLocation()));
                    }
                }

                foreach (KeyValuePair <OperationType, OpenApiOperation> operation in path.Value.Operations)
                {
                    foreach (KeyValuePair <string, OpenApiResponse> response in operation.Value.Responses)
                    {
                        if (Supressions.IsSupressed(ruleName, path.Key,
                                                    Convert.ToString(operation.Key.ToString().ToLowerInvariant()), string.Empty,
                                                    response.Key))
                        {
                            continue;
                        }

                        //Usually, response description only have the response code and description without punctuation.
                        //Ex: 200 Ok

                        foreach (KeyValuePair <string, OpenApiMediaType> content in response.Value.Content)
                        {
                            if (content.Value.Schema != null)
                            {
                                foreach (KeyValuePair <string, OpenApiSchema> firstLevelproperty in content.Value.Schema
                                         .Properties)
                                {
                                    //fist level: data, pagination, etc.
                                    //second level: resource properties first level.
                                    listResult.TryAddEmptiableRange(
                                        CheckInnerPropertyDescription(path.Key, operation.Key.ToString().ToLower(),
                                                                      response.Key, content.Key, firstLevelproperty.Key,
                                                                      firstLevelproperty.Value.Properties)
                                        );
                                }
                            }
                        }
                    }
                }
            }
        }
示例#3
0
 /// <summary>
 /// Try to test if the base URL parts togheter compose a valid URL.
 /// Supressions: Rule
 /// </summary>
 public BaseUrlRule(OpenApiDocument contract, Supressions supressions,
                    IOptions <RuleSettings> ruleSettings, OpenApiDocumentCache cache) :
     base(contract, supressions, ruleSettings, cache, ruleName, Severity.Error)
 {
 }
示例#4
0
 /// <summary>
 /// Validates if 200 or 206 HTTP Status codes are wrongly with empty content as answer.
 /// Supressions: Rule,Path,Operation,ResponseCode
 /// </summary>
 public Empty200Rule(OpenApiDocument contract, Supressions supressions,
                     IOptions <RuleSettings> ruleSettings, OpenApiDocumentCache cache) :
     base(contract, supressions, ruleSettings, cache, ruleName, Severity.Warning)
 {
     this.cache = cache;
 }
示例#5
0
 /// <summary>
 /// Validates if descriptions or summaries have some quality level, as begining with upper letter and finishing with period.
 /// Supressions: Rule,Path,Operation,parameter,ResponseCode,PropertyFull
 /// </summary>
 public DescriptionQualityRule(OpenApiDocument contract,
                               Supressions supressions, IOptions <RuleSettings> ruleSettings, OpenApiDocumentCache cache) :
     base(contract, supressions, ruleSettings, cache, ruleName, Severity.Information)
 {
 }
示例#6
0
 /// <summary>
 /// Validate if paths have names that represents CRUD actions.
 /// Supressions: Rule,Path
 /// </summary>
 public PathWithCrudNamesRule(OpenApiDocument contract, Supressions supressions,
                              IOptions <RuleSettings> ruleSettings, OpenApiDocumentCache cache) :
     base(contract, supressions, ruleSettings, cache, ruleName, Severity.Warning)
 {
     wordsToAvoid = ruleSettings.Value.PathWithCrudNames.WordsToAvoid.Split(',');
 }
示例#7
0
 /// <summary>
 /// Validate if a resource that returns some 3XX answers has Location header.
 /// Supressions: Rule,Path,Operation,ResponseCode
 /// </summary>
 public Http3xxWithoutLocationHeaderRule(OpenApiDocument contract,
                                         Supressions supressions, IOptions <RuleSettings> ruleSettings, OpenApiDocumentCache cache) : base(contract, supressions,
                                                                                                                                           ruleSettings, cache, ruleName, Severity.Warning)
 {
     this.cache = cache;
 }
        private protected override void ExecuteRuleLogic()
        {
            var parameters = Contract.GetAllParameters();

            //Search for parameters in query, path or header with examples that value is likelihood date and the format attribute is not date or date-time.
            foreach (OpenApiDocumentExtensions.Parameter parameter in parameters)
            {
                if (Supressions.IsSupressed(ruleName, parameter.Path))
                {
                    continue;
                }

                if (Supressions.IsSupressed(ruleName, parameter.Path, parameter.Method))
                {
                    continue;
                }

                if (Supressions.IsSupressed(ruleName, parameter.Path, parameter.Method, parameter.Name))
                {
                    continue;
                }

                //Parameters in query, path or header
                if (parameter.OpenApiParameter.Example != null && parameter.OpenApiParameter.Examples?.Count > 0 &&
                    parameter.OpenApiParameter.Schema.Type.ToLower() == "string")
                {
                    if (parameter.OpenApiParameter.Example is OpenApiString exApiString &&
                        DateTime.TryParse(exApiString.Value, out _) &&
                        parameter.OpenApiParameter.Schema.Format != "date" &&
                        parameter.OpenApiParameter.Schema.Format != "date-time")
                    {
                        listResult.Add(new ResultItem(this)
                        {
                            Value = parameter.ResultLocation()
                        });
                    }

                    foreach (KeyValuePair <string, OpenApiExample> example in parameter.OpenApiParameter.Examples)
                    {
                        if (parameter.OpenApiParameter.Schema?.Type?.ToLower() == "string" &&
                            example.Value.Value is OpenApiString apiString &&
                            DateTime.TryParse(apiString.Value, out _) &&
                            parameter.OpenApiParameter.Schema.Format != "date" &&
                            parameter.OpenApiParameter.Schema.Format != "date-time")
                        {
                            listResult.Add(new ResultItem(this)
                            {
                                Value = parameter.ResultLocation()
                            });
                        }
                    }
                }
            }

            //Search for properties in request and response bodies with examples that value is likelihood date and the format is not date or date-time.
            var propertiesWithLikelyNumericExample =
                Contract.GetAllBodyProperties(RuleSettings, Cache)
                .Where(property =>
                       property.OpenApiSchemaObject?.Type?.ToLower() == "string" &&
                       property.Example is OpenApiString apiString &&
                       DateTime.TryParse(apiString.Value, out _) &&
                       property.OpenApiSchemaObject.Format != "date" &&
                       property.OpenApiSchemaObject.Format != "date-time"
                       )
                .ToList();

            foreach (var property in propertiesWithLikelyNumericExample)
            {
                if (Supressions.IsSupressed(ruleName, property.Path, property.Operation.ToLowerInvariant(),
                                            property.FullName,
                                            property.ResponseCode))
                {
                    continue;
                }

                listResult.Add(new ResultItem(this)
                {
                    Value = property.ResultLocation()
                });
            }
        }
 /// <summary>
 /// Validates if parameters or attributes have examples indicating that the content is likely date type and the format is not date or date-time.
 /// Supressions: Rule,Path,Operation,ResponseCode,Content,PropertyFull
 /// </summary>
 public DateWithoutFormatRule(OpenApiDocument contract,
                              Supressions supressions,
                              IOptions <RuleSettings> ruleSettings, OpenApiDocumentCache cache)
     : base(contract, supressions, ruleSettings, cache, ruleName, Severity.Hint)
 {
 }
示例#10
0
 /// <summary>
 /// Validate the properties case type.
 /// Supressions: Rule,Path,Operation,ResponseCode,PropertyFull
 /// </summary>
 public NestingDepthRule(OpenApiDocument contract, Supressions supressions,
                         IOptions <RuleSettings> ruleSettings, OpenApiDocumentCache cache)
     : base(contract, supressions, ruleSettings, cache, ruleName, Severity.Warning)
 {
     maxDepth = ruleSettings.Value.NestingDepth.Depth;
 }