/// <summary>
        /// Verifies whether an LRO PUT operation returns response models for
        /// 200/201 status codes
        /// </summary>
        /// <param name="definitions"></param>
        /// <param name="context"></param>
        /// <returns></returns>
        public override IEnumerable <ValidationMessage> GetValidationMessages(Dictionary <string, Dictionary <string, Operation> > paths, RuleContext context)
        {
            var serviceDefinition = (ServiceDefinition)context.Root;

            foreach (var path in paths)
            {
                var lroPutOps = path.Value.Where(val => val.Key.ToLower().Equals("put")).Select(val => val.Value);
                foreach (var op in lroPutOps)
                {
                    if (op.Responses == null)
                    {
                        // if put operation has no response model, let some other validation rule handle the violation
                        continue;
                    }
                    foreach (var resp in op.Responses)
                    {
                        if (resp.Key == "200" || resp.Key == "201")
                        {
                            var modelRef = resp.Value?.Schema?.Reference ?? string.Empty;
                            if (!serviceDefinition.Definitions.ContainsKey(modelRef.StripDefinitionPath()))
                            {
                                var violatingVerb = ValidationUtilities.GetOperationIdVerb(op.OperationId, path);
                                yield return(new ValidationMessage(new FileObjectPath(context.File, context.Path.AppendProperty(path.Key).AppendProperty(violatingVerb).AppendProperty("responses").AppendProperty(resp.Key)),
                                                                   this, op.OperationId, resp.Key));
                            }
                        }
                    }
                }
            }
        }
示例#2
0
        // Verifies if a tracked resource has a corresponding PATCH operation
        public override IEnumerable <ValidationMessage> GetValidationMessages(Dictionary <string, Dictionary <string, Operation> > paths, RuleContext context)
        {
            var serviceDefinition = context.Root;
            var ops           = ValidationUtilities.GetOperationsByRequestMethod("put", serviceDefinition);
            var putRespModels = ops.Select(op => (op.Responses?.ContainsKey("200") != true) ? null : op.Responses["200"].Schema?.Reference?.StripDefinitionPath());

            putRespModels = putRespModels.Where(modelName => !string.IsNullOrEmpty(modelName));
            var xmsResModels    = ValidationUtilities.GetXmsAzureResourceModels(serviceDefinition.Definitions);
            var violatingModels = putRespModels.Where(respModel => !ValidationUtilities.EnumerateModelHierarchy(respModel, serviceDefinition.Definitions).Intersect(xmsResModels).Any());

            foreach (var model in violatingModels)
            {
                var violatingOp     = ops.Where(op => (op.Responses?.ContainsKey("200") == true) && op.Responses["200"]?.Schema?.Reference?.StripDefinitionPath() == model).First();
                var violatingPath   = ValidationUtilities.GetOperationIdPath(violatingOp.OperationId, paths);
                var violatingOpVerb = ValidationUtilities.GetOperationIdVerb(violatingOp.OperationId, violatingPath);
                yield return(new ValidationMessage(new FileObjectPath(context.File, context.Path.AppendProperty(violatingPath.Key).AppendProperty(violatingOpVerb)), this, violatingOp.OperationId, model));
            }
        }
示例#3
0
        /// Verifies if a PUT operation request and response schemas match
        public override IEnumerable <ValidationMessage> GetValidationMessages(Dictionary <string, Dictionary <string, Operation> > paths, RuleContext context)
        {
            var serviceDefinition = (ServiceDefinition)context.Root;
            var ops = ValidationUtilities.GetOperationsByRequestMethod("put", serviceDefinition);

            foreach (var op in ops)
            {
                // if PUT operation does not have any request parameters, skip, let some other validation rule handle it
                // if no 200 response exists, skip, let some other validation rule handle empty PUT response operations
                if (op.Parameters?.Any() != true || op.Responses?.ContainsKey("200") != true || serviceDefinition.Definitions?.Any() != true)
                {
                    continue;
                }

                // look for the request body schema in the operation parameters section as well as the global parameters section
                string reqBodySchema = null;
                if (op.Parameters.Any(p => p.In == ParameterLocation.Body))
                {
                    reqBodySchema = op.Parameters.First(p => p.In == ParameterLocation.Body).Schema?.Reference?.StripDefinitionPath();
                }
                else
                {
                    var opGlobalParams = op.Parameters.Where(p => serviceDefinition.Parameters.ContainsKey(p.Reference?.StripParameterPath() ?? ""));
                    if (opGlobalParams.Any())
                    {
                        reqBodySchema = opGlobalParams.FirstOrDefault(p => p.In == ParameterLocation.Body)?.Schema?.Reference?.StripDefinitionPath();
                    }
                }

                // if no body parameters were found, skip, let some other validation handle an empty body put operation
                if (string.IsNullOrEmpty(reqBodySchema) || !serviceDefinition.Definitions.ContainsKey(reqBodySchema))
                {
                    continue;
                }
                var respModel = op.Responses["200"]?.Schema?.Reference?.StripDefinitionPath() ?? string.Empty;
                // if the 200 response schema does not match the request body parameter schema, flag violation
                if (respModel != reqBodySchema)
                {
                    var violatingPath   = ValidationUtilities.GetOperationIdPath(op.OperationId, paths);
                    var violatingOpVerb = ValidationUtilities.GetOperationIdVerb(op.OperationId, violatingPath);
                    yield return(new ValidationMessage(new FileObjectPath(context.File, context.Path.AppendProperty(violatingPath.Key).AppendProperty(violatingOpVerb)), this, op.OperationId, reqBodySchema, respModel));
                }
            }
        }