//   [Fact]
        public void ParseVeryLargeSwaggerPaths()
        {
            var opsTerm = new VocabTerm<Operation>();

            var pathTerm = new VocabTerm<Path>();
            pathTerm.MapAnyObject<Operation>(opsTerm, (s, p) =>
            {
                return s.AddOperation(p, Guid.NewGuid().ToString());
            });

            var pathsTerm = new VocabTerm<OpenApiDocument>("paths");

            pathsTerm.MapAnyObject<Path>(pathTerm, (s, p) =>
            {
                return s.AddPath(p);
            });

            var rootTerm = new VocabTerm<OpenApiDocument>();
            rootTerm.MapObject<OpenApiDocument>(pathsTerm, (s) =>
            {
                return s;
            });

            var swaggerDoc = new OpenApiDocument();
            var sw = new Stopwatch();
            using (var stream = File.OpenRead(@"C:\Users\Darrel\Documents\Swagger\WebSites.json"))
            {

                sw.Start();

                JsonStreamingParser.ParseStream(stream, swaggerDoc, rootTerm);
                sw.Stop();
            };

            _output.WriteLine(swaggerDoc.Paths.Count.ToString());
            _output.WriteLine("That took : " + sw.ElapsedMilliseconds);

        }
Example #2
0
 public void Apply(OpenApiDocument swaggerDoc, DocumentFilterContext context)
 {
     var path  = swaggerDoc.Paths.Where(x => x.Key.Contains("Values")).First().Value;
     var param = path.Operations.Where(x => x.Key.Equals("Post")).First().Value;
     //param.Extensions.Add("x-code-samples", new OpenApiExtension { "123456" });
 }
Example #3
0
        static void Main(string[] args)
        {
            if (args.Length == 0)
            {
                Console.WriteLine("Please enter a solution prefix");
            }
            else
            {
                solutionPrefix = args[0];
            }

            bool generatePaths = false;

            if (args.Length > 1)
            {
                if (args[1] == "generatePaths")
                {
                    generatePaths = true;
                }
            }

            // Feature flags

            // True if we use the Autorest Odata extension
            bool enableOdataExtension = false;

            // True if we get metadata from Dynamics
            bool getMetadata = true;

            // True if we use strings instead of guids primary keys.
            bool useStringForGuid = true;

            bool disableCustomErrorClass = true;

            List <string> defsToKeep = new List <string>();

            // start by getting secrets.
            var builder = new ConfigurationBuilder()
                          .AddEnvironmentVariables();

            builder.AddUserSecrets <Program>();
            var    Configuration = builder.Build();
            string csdl;

            // get the metadata.
            if (getMetadata)
            {
                csdl = GetDynamicsMetadata(Configuration);
                File.WriteAllText("dynamics-metadata.xml", csdl);
            }
            else
            {
                csdl = File.ReadAllText("dynamics-metadata.xml");
            }

            // fix the csdl.

            csdl = csdl.Replace("ConcurrencyMode=\"Fixed\"", "");

            IEdmModel model = CsdlReader.Parse(XElement.Parse(csdl).CreateReader());

            // fix dates.

            /*
             * OpenApiTarget target = OpenApiTarget.Json;
             * OpenApiWriterSettings settings = new OpenApiWriterSettings
             * {
             *  BaseUri = new Uri(Configuration["DYNAMICS_ODATA_URI"])
             * };
             */

            string swagger = null;

            OpenApiConvertSettings openApiSettings = new OpenApiConvertSettings
            {
                // configuration
            };
            OpenApiDocument swaggerDocument = model.ConvertToOpenApi(openApiSettings);

            if (generatePaths)
            {
                List <string> paths = new List <string>();
                foreach (var path in swaggerDocument.Paths)
                {
                    string subPath = path.Key.Substring(path.Key.LastIndexOf("/") + 1);
                    if (subPath.Contains("("))
                    {
                        subPath = subPath.Substring(0, subPath.IndexOf("("));
                    }

                    string pathSample = path.Key.Substring(1, subPath.Length);
                    if (pathSample != subPath)
                    {
                        paths.Add(path.Key);
                    }
                }
                File.WriteAllText("paths-excluded.json", JsonConvert.SerializeObject(paths));
            }
            else
            {
                List <string> itemsToRemove = new List <string>();
                if (File.Exists("paths-excluded.json"))
                {
                    string pathsExcluded = File.ReadAllText("paths-excluded.json");
                    itemsToRemove = JsonConvert.DeserializeObject <List <string> >(pathsExcluded);
                }


                List <string> allops = new List <string>();

                // fix the operationIds.
                foreach (var path in swaggerDocument.Paths)
                {
                    if (itemsToRemove.Contains(path.Key))
                    {
                        continue;
                    }
                    if (path.Key.Contains("transactioncurrencyid"))
                    {
                        itemsToRemove.Add(path.Key);
                        continue;
                    }
                    if (path.Key.Contains("scheduledprocessexecution"))
                    {
                        itemsToRemove.Add(path.Key);
                        continue;
                    }

                    // determine if this is a get by key, or a get by key with additional .
                    string subPath = "";

                    string temp = path.Key.Substring(path.Key.LastIndexOf("/") + 1);
                    if (temp.Contains("("))
                    {
                        temp = temp.Substring(0, temp.IndexOf("("));
                        string pathSample = path.Key.Substring(1, temp.Length);
                        if (pathSample != temp)
                        {
                            subPath = temp;
                        }

                        subPath += "ByKey";
                    }

                    OpenApiTag firstTag = null; // operation.Value.Tags.FirstOrDefault();


                    if (firstTag == null)
                    {
                        firstTag = new OpenApiTag()
                        {
                            Name = temp
                        };
                    }

                    string prefix        = "Unknown";
                    string firstTagLower = "";

                    if (firstTag != null)
                    {
                        bool ok2Delete = true;
                        firstTagLower = firstTag.Name.ToLower();

                        if (firstTagLower.Equals("contacts") ||
                            firstTagLower.Equals("accounts") ||
                            firstTagLower.Equals("invoices") ||
                            firstTagLower.Equals("incidents") ||
                            firstTagLower.Equals("sharepointsites") ||
                            firstTagLower.Equals("savedqueries") ||
                            firstTagLower.Equals("sharepointdocumentlocations"))
                        {
                            ok2Delete = false;
                        }


                        if (!firstTagLower.StartsWith("msdyn") && !firstTagLower.StartsWith("abs_") && firstTagLower.IndexOf(solutionPrefix) != -1)
                        {
                            //Console.Out.WriteLine($"NOT ok to delete {firstTagLower}");
                            ok2Delete = false;
                        }

                        if (ok2Delete)
                        {
                            //Console.Out.WriteLine($"ok to delete {firstTagLower}");
                            if (!itemsToRemove.Contains(path.Key))
                            {
                                itemsToRemove.Add(path.Key);
                            }
                            continue;
                        }

                        if (!allops.Contains(firstTag.Name))
                        {
                            allops.Add(firstTag.Name);
                        }
                        prefix = firstTagLower;
                        // Capitalize the first character.

                        if (prefix.Length > 0 && prefix.Length > solutionPrefix.Length)
                        {
                            if (prefix.ToUpper().Substring(0, solutionPrefix.Length) == solutionPrefix.ToUpper())
                            {
                                prefix = prefix.Substring(solutionPrefix.Length);
                            }
                            prefix = prefix.Substring(0, 1).ToUpper() + prefix.Substring(1);
                        }
                        // remove any underscores.
                        prefix = prefix.Replace("_", "");
                    }

                    foreach (var operation in path.Value.Operations)
                    {
                        if (!firstTagLower.StartsWith("msdyn") && !firstTagLower.StartsWith("abs_") && firstTagLower.IndexOf(solutionPrefix) != -1)
                        {
                            firstTagLower = firstTagLower.Replace($"{solutionPrefix}_", "");
                            firstTagLower = firstTagLower.Replace(solutionPrefix, "");
                            operation.Value.Tags.Clear();
                            operation.Value.Tags.Add(new OpenApiTag()
                            {
                                Name = firstTagLower
                            });
                        }

                        string suffix = "";


                        switch (operation.Key)
                        {
                        case OperationType.Post:
                            suffix = "Create";
                            // for creates we also want to add a header parameter to ensure we get the new object back.
                            OpenApiParameter swaggerParameter = new OpenApiParameter()
                            {
                                Schema = new OpenApiSchema()
                                {
                                    Type = "string", Default = new OpenApiString("return=representation")
                                },
                                Name        = "Prefer",
                                Description = "Required in order for the service to return a JSON representation of the object.",
                                In          = ParameterLocation.Header
                            };
                            operation.Value.Parameters.Add(swaggerParameter);
                            break;

                        case OperationType.Patch:
                            suffix = "Update";
                            if (subPath == "ByKey")
                            {
                                subPath = "";
                            }
                            break;

                        case OperationType.Put:
                            suffix = "Put";
                            if (subPath == "ByKey")
                            {
                                subPath = "";
                            }
                            break;

                        case OperationType.Delete:
                            suffix = "Delete";
                            if (subPath == "ByKey")
                            {
                                subPath = "";
                            }
                            break;

                        case OperationType.Get:
                            suffix = "Get";
                            break;
                        }

                        if (suffix.Length >= solutionPrefix.Length && suffix.ToUpper().Substring(0, solutionPrefix.Length) == solutionPrefix.ToUpper())
                        {
                            suffix = suffix.Substring(solutionPrefix.Length);
                        }

                        operation.Value.OperationId = prefix + "_" + suffix;

                        if (!firstTag.Name.Contains(subPath))
                        {
                            operation.Value.OperationId += subPath;
                        }

                        string operationDef = null;
                        // adjustments to response

                        foreach (var response in operation.Value.Responses)
                        {
                            var val = response.Value;
                            if (response.Key == "default")
                            {
                                if (string.IsNullOrEmpty(response.Value.Description))
                                {
                                    response.Value.Description = "OData Error";
                                }
                                ;

                                if (disableCustomErrorClass && response.Value.Reference != null)
                                {
                                    response.Value.Reference = null;
                                }
                            }

                            if (val != null)
                            {
                                bool hasValue = false;
                                foreach (var schema in val.Content)
                                {
                                    foreach (var property in schema.Value.Schema.Properties)
                                    {
                                        if (property.Key.Equals("value"))
                                        {
                                            hasValue = true;
                                            break;
                                        }
                                    }
                                    if (hasValue)
                                    {
                                        var    newSchema = schema.Value.Schema.Properties["value"];
                                        string resultName;
                                        string itemName;

                                        if (newSchema.Type == "array")
                                        {
                                            itemName     = newSchema.Items.Reference.Id;
                                            operationDef = itemName;
                                            resultName   = $"{itemName}Collection";
                                        }
                                        else
                                        {
                                            itemName   = "!ERR";
                                            resultName = "!ERR";
                                        }



                                        if (!swaggerDocument.Components.Schemas.ContainsKey(resultName))
                                        {
                                            // move the inline schema to defs.
                                            swaggerDocument.Components.Schemas.Add(resultName, schema.Value.Schema);

                                            //var newSchema = swaggerDocument.Components.Schemas[resultName].Properties["value"];
                                            if (newSchema.Type == "array")
                                            {
                                                newSchema.Items = new OpenApiSchema()
                                                {
                                                    Reference = new OpenApiReference()
                                                    {
                                                        Id = itemName, Type = ReferenceType.Schema
                                                    }, Type = "none"
                                                };
                                                AddSubItems(swaggerDocument, defsToKeep, itemName);
                                            }
                                            AddSubItems(swaggerDocument, defsToKeep, resultName);
                                        }

                                        schema.Value.Schema = new OpenApiSchema {
                                            Reference = new OpenApiReference()
                                            {
                                                Id = resultName, Type = ReferenceType.Schema
                                            }, Type = "none"
                                        };
                                        // val.Reference = new OpenApiReference() { Id = resultName, Type = ReferenceType.Schema, ExternalResource = null };
                                    }
                                    else
                                    {
                                        if (schema.Value.Schema.Reference != null)
                                        {
                                            operationDef = schema.Value.Schema.Reference.Id;
                                            AddSubItems(swaggerDocument, defsToKeep, operationDef);
                                        }
                                    }
                                }
                            }
                        }



                        // adjustments to operation parameters
                        if (enableOdataExtension)
                        {
                            string[] oDataParameters = { "top", "skip", "search", "filter", "count", "$orderby", "$select", "$expand" };

                            List <OpenApiParameter> parametersToRemove = new List <OpenApiParameter>();

                            foreach (var oDataParameter in oDataParameters)
                            {
                                foreach (var parameter in operation.Value.Parameters)
                                {
                                    if (parameter.Name == oDataParameter)
                                    {
                                        parametersToRemove.Add(parameter);
                                    }

                                    if (parameter.Reference != null && parameter.Reference.Id == oDataParameter)
                                    {
                                        parametersToRemove.Add(parameter);
                                    }
                                }
                            }
                            foreach (var parameter in parametersToRemove)
                            {
                                operation.Value.Parameters.Remove(parameter);
                            }
                        }


                        operation.Value.Extensions.Clear();


                        if (operationDef != null && enableOdataExtension)
                        {
                            operation.Value.Extensions.Add("x-ms-odata", new OpenApiString($"#/definitions/{operationDef}"));
                            AddSubItems(swaggerDocument, defsToKeep, operationDef);
                        }

                        foreach (var parameter in operation.Value.Parameters)
                        {
                            if (parameter.Reference != null)
                            {
                                if (parameter.Reference.Id == "top" || parameter.Reference.Id == "skip")
                                {
                                    parameter.Name      = $"${parameter.Reference.Id}";
                                    parameter.Reference = null;
                                    parameter.In        = ParameterLocation.Query;
                                    parameter.Schema    = new OpenApiSchema()
                                    {
                                        Type = "integer"
                                    };
                                }
                                else if (parameter.Reference.Id == "search" || parameter.Reference.Id == "filter")
                                {
                                    parameter.Name      = $"${parameter.Reference.Id}";
                                    parameter.Reference = null;
                                    parameter.In        = ParameterLocation.Query;
                                    parameter.Schema    = new OpenApiSchema()
                                    {
                                        Type = "string"
                                    };
                                }
                                else if (parameter.Reference.Id == "count")
                                {
                                    parameter.Name      = $"${parameter.Reference.Id}";
                                    parameter.Reference = null;
                                    parameter.In        = ParameterLocation.Query;
                                    parameter.Schema    = new OpenApiSchema()
                                    {
                                        Type = "boolean"
                                    };
                                }
                            }
                            else
                            {
                                string name = parameter.Name;
                                if (name == null)
                                {
                                    name = parameter.Name;
                                }

                                if (name != null)
                                {
                                    if (name == "$top" || name == "$skip")
                                    {
                                        parameter.In        = ParameterLocation.Query;
                                        parameter.Reference = null;
                                        parameter.Schema    = new OpenApiSchema()
                                        {
                                            Type = "integer"
                                        };
                                    }
                                    if (name == "$search" || name == "$filter")
                                    {
                                        parameter.In        = ParameterLocation.Query;
                                        parameter.Reference = null;
                                        parameter.Schema    = new OpenApiSchema()
                                        {
                                            Type = "string"
                                        };
                                    }
                                    if (name == "$orderby" || name == "$select" || name == "$expand")
                                    {
                                        parameter.In        = ParameterLocation.Query;
                                        parameter.Reference = null;
                                        parameter.Schema    = new OpenApiSchema()
                                        {
                                            Type  = "array",
                                            Items = new OpenApiSchema()
                                            {
                                                Type = "string"
                                            }
                                        };
                                        parameter.Extensions.Add("collectionFormat", new OpenApiString("csv"));
                                    }
                                    if (name == "$count")
                                    {
                                        parameter.In        = ParameterLocation.Query;
                                        parameter.Reference = null;
                                        parameter.Schema    = new OpenApiSchema()
                                        {
                                            Type = "boolean"
                                        };
                                    }
                                    if (name == "If-Match")
                                    {
                                        parameter.Reference = null;
                                        parameter.Schema    = new OpenApiSchema()
                                        {
                                            Type = "string"
                                        };
                                    }

                                    if (parameter.Extensions != null && parameter.Extensions.ContainsKey("x-ms-docs-key-type"))
                                    {
                                        parameter.Extensions.Remove("x-ms-docs-key-type");
                                    }

                                    if (string.IsNullOrEmpty(parameter.Name))
                                    {
                                        parameter.Name = name;
                                    }
                                }
                            }

                            // get rid of style if it exists.
                            if (parameter.Style != ParameterStyle.Simple)
                            {
                                parameter.Style = ParameterStyle.Simple;
                            }

                            // get rid of guid type if it exists

                            if (parameter.Schema?.Format != null && useStringForGuid && parameter.Schema.Format == "uuid")
                            {
                                parameter.Schema.Format  = null;
                                parameter.Schema.Pattern = null;
                            }

                            // may need to clear unique items here.

                            // align the schema if it exists.
                            if (parameter.Schema != null && parameter.Schema.Items != null)
                            {
                                var schema = parameter.Schema;
                                if (schema.Type == "array" && parameter.Style == null)
                                {
                                    // may be a good idea to set collectionFormat to csv here.  It is also set below.

                                    parameter.Style = ParameterStyle.Simple;
                                }
                            }
                        }
                    }
                }

                foreach (var opDelete in itemsToRemove)
                {
                    swaggerDocument.Paths.Remove(opDelete);
                }

                foreach (var path in swaggerDocument.Paths)
                {
                    foreach (var value in path.Value.Operations)
                    {
                        foreach (var response in value.Value.Responses)
                        {
                            if (response.Value.Reference != null)
                            {
                                var schema = response.Value.Reference;
                                if (!string.IsNullOrEmpty(schema.Id) && (schema.Type.Value.GetDisplayName() == "array" || schema.Type.Value.GetDisplayName() == "object"))
                                {
                                    string title = schema.Id;
                                    AddSubItems(swaggerDocument, defsToKeep, title);
                                }
                            }
                        }
                        foreach (var parameter in value.Value.Parameters)
                        {
                            if (parameter.Schema != null && parameter.Schema.Reference != null)
                            {
                                var schema = parameter.Schema.Reference;
                                if (!string.IsNullOrEmpty(schema.Id) && (schema.Type.Value.GetDisplayName() == "array" || schema.Type.Value.GetDisplayName() == "object"))
                                {
                                    AddSubItems(swaggerDocument, defsToKeep, schema.Id);
                                }
                            }
                        }
                    }
                }



                // reverse the items to keep.

                List <string> defsToRemove = new List <string>();


                foreach (var definition in swaggerDocument.Components.Schemas)
                {
                    if (
                        !definition.Key.Contains("odata.error") &&
                        !definition.Key.Contains("crmbaseentity") &&
                        !definition.Key.ToLower().Contains("optionmetadata") &&
                        !defsToKeep.Contains(definition.Key))
                    {
                        defsToRemove.Add(definition.Key);
                    }
                }

                foreach (string defToRemove in defsToRemove)
                {
                    //Console.Out.WriteLine($"Remove: {defToRemove}");
                    if (!string.IsNullOrEmpty(defToRemove) && swaggerDocument.Components.Schemas.ContainsKey(defToRemove))
                    {
                        swaggerDocument.Components.Schemas.Remove(defToRemove);
                    }
                }

                /*
                 * List<string> responsesToRemove = new List<string>();
                 *
                 *
                 * foreach (string responseToRemove in responsesToRemove)
                 * {
                 *  Console.Out.WriteLine($"Remove Response: {responseToRemove}");
                 *
                 *  if (!string.IsNullOrEmpty(responseToRemove) && swaggerDocument.Components.Responses.ContainsKey(responseToRemove))
                 *  {
                 *      swaggerDocument.Components.Responses.Remove(responseToRemove);
                 *  }
                 *
                 *
                 * }
                 *
                 */

                /*
                 * Cleanup definitions.
                 */

                foreach (var definition in swaggerDocument.Components.Schemas)
                {
                    if (definition.Value.Description == null)
                    {
                        definition.Value.Description = definition.Key;
                    }


                    // consolidate AllOf
                    if (definition.Value.AllOf != null && definition.Value.Type == null)
                    {
                        definition.Value.Type = "object";
                    }

                    var dictionary = new Dictionary <string, OpenApiSchema>();
                    MergeSubItems(dictionary, definition.Value);
                    definition.Value.Properties = dictionary;
                    if (definition.Value.AllOf != null)
                    {
                        definition.Value.AllOf.Clear();
                    }

                    // Clear out the example if it exists

                    if (definition.Value.Example != null)
                    {
                        definition.Value.Example = null;
                    }

                    /*
                     * if (definition.Value.Title != null)
                     * {
                     *  definition.Value.Title = null;
                     * }
                     *
                     * if (definition.Value.Enum != null)
                     * {
                     *  definition.Value.Enum.Clear();
                     * }
                     */

                    if (definition.Value != null && definition.Value.Properties != null)
                    {
                        foreach (var property in definition.Value.Properties)
                        {
                            // convert all dates to datetimeoffset.
                            // special handling of the Dynamics "DATE (YYYY-MM-DD)" fields will need to be done with extensions.
                            if (property.Value.Format != null && property.Value.Format == "date")
                            {
                                property.Value.Format = "date-time";
                            }
                            if (property.Value.Type == null)
                            {
                                property.Value.Type = "string";
                            }

                            // fix for doubles
                            if (property.Value != null && property.Value.Format != null && property.Value.Format.Equals("double"))
                            {
                                property.Value.Format = "decimal";
                                property.Value.Type   = "number";
                            }
                            if (property.Key.Equals("totalamount"))
                            {
                                property.Value.Type   = "number";
                                property.Value.Format = "decimal";
                            }

                            if (property.Key.Equals("versionnumber"))
                            {
                                // clear oneof.
                                if (property.Value.OneOf != null)
                                {
                                    property.Value.OneOf.Clear();
                                }

                                // force to string.
                                property.Value.Type = "string";
                            }

                            if (property.Value.Minimum != null)
                            {
                                property.Value.Minimum = null;
                            }
                            if (property.Value.Maximum != null)
                            {
                                property.Value.Maximum = null;
                            }
                            if (property.Value.Pattern != null)
                            {
                                property.Value.Pattern = null;
                            }


                            if (property.Value.Format != null && property.Value.Format == "uuid" && useStringForGuid)
                            {
                                property.Value.Format = null;
                            }
                        }
                    }
                }


                // remove extra tags.
                swaggerDocument.Tags.Clear();

                // cleanup parameters.
                //swaggerDocument.Components.Parameters.Clear();


                //**************************************

                // fix for "odata.error.main" - innererror property.

                swaggerDocument.Components.Schemas["odata.error.main"].Properties.Remove("innererror");

                // fix for two entities that have links to everything else - this causes massive spikes in memory consumption.

                swaggerDocument.Components.Schemas.Remove("Microsoft.Dynamics.CRM.transactioncurrency");
                swaggerDocument.Components.Schemas.Remove("Microsoft.Dynamics.CRM.syncerror");

                Dictionary <string, OpenApiSchema> props = new Dictionary <string, OpenApiSchema>();
                props.Add("nil", new OpenApiSchema()
                {
                    Type = "string"
                });
                swaggerDocument.Components.Schemas.Add("Microsoft.Dynamics.CRM.transactioncurrency", new OpenApiSchema()
                {
                    Properties = props
                });
                swaggerDocument.Components.Schemas.Add("Microsoft.Dynamics.CRM.syncerror", new OpenApiSchema()
                {
                    Properties = props
                });


                // swagger = swaggerDocument.SerializeAsJson(OpenApiSpecVersion.OpenApi3_0); // ToJson(SchemaType.Swagger2);
                swagger = swaggerDocument.SerializeAsJson(OpenApiSpecVersion.OpenApi2_0);
            }

            File.WriteAllText("dynamics-swagger.json", swagger);
        }
        public static IServiceCollection AddYardarm(this IServiceCollection services, YardarmGenerationSettings settings, OpenApiDocument document)
        {
            services.AddDefaultEnrichers();

            // Generators
            services
            .AddTransient <IReferenceGenerator, NuGetReferenceGenerator>()
            .AddTransient <ISyntaxTreeGenerator, AssemblyInfoGenerator>()
            .AddTransient <ISyntaxTreeGenerator, ClientGenerator>()
            .AddTransient <ISyntaxTreeGenerator, SchemaGenerator>()
            .AddTransient <ISyntaxTreeGenerator, SecuritySchemeGenerator>()
            .AddTransient <ISyntaxTreeGenerator, RequestBodyGenerator>()
            .AddTransient <ISyntaxTreeGenerator, ResponseGenerator>()
            .AddTransient <ISyntaxTreeGenerator, ResponseSetGenerator>()
            .AddTransient <ISyntaxTreeGenerator, RequestGenerator>()
            .AddTransient <ISyntaxTreeGenerator, TagGenerator>()
            .AddTransient <IDependencyGenerator, StandardDependencyGenerator>();

            services.TryAddSingleton <ITypeGeneratorRegistry, TypeGeneratorRegistry>();
            services.TryAdd(new ServiceDescriptor(typeof(ITypeGeneratorRegistry <>), typeof(TypeGeneratorRegistry <>), ServiceLifetime.Singleton));
            services.TryAddSingleton <ITypeGeneratorFactory <OpenApiSchema>, DefaultSchemaGeneratorFactory>();

            services.TryAddSingleton <ITypeGeneratorFactory <OpenApiSecurityScheme>, SecuritySchemeTypeGeneratorFactory>();
            services.TryAddSingleton <ITypeGeneratorFactory <OpenApiRequestBody>, RequestBodyTypeGeneratorFactory>();
            services.TryAddSingleton <ITypeGeneratorFactory <OpenApiResponse>, ResponseTypeGeneratorFactory>();
            services.TryAddSingleton <ITypeGeneratorFactory <OpenApiResponses>, ResponseSetTypeGeneratorFactory>();
            services.TryAddSingleton <ITypeGeneratorFactory <OpenApiOperation>, RequestTypeGeneratorFactory>();
            services.TryAddSingleton <ITypeGeneratorFactory <OpenApiTag>, TagTypeGeneratorFactory>();
            services.TryAddSingleton <ITypeGeneratorFactory <OpenApiUnknownResponse>, UnknownResponseTypeGeneratorFactory>();
            services.TryAddSingleton <IAddHeadersMethodGenerator, AddHeadersMethodGenerator>();
            services.TryAddSingleton <IBuildContentMethodGenerator, BuildContentMethodGenerator>();
            services.TryAddSingleton <IBuildRequestMethodGenerator, BuildRequestMethodGenerator>();
            services.TryAddSingleton <IBuildUriMethodGenerator, BuildUriMethodGenerator>();
            services.TryAddSingleton <IGetBodyMethodGenerator, GetBodyMethodGenerator>();
            services.TryAddSingleton <IOperationMethodGenerator, OperationMethodGenerator>();
            services.TryAddSingleton <IMediaTypeSelector, JsonMediaTypeSelector>();

            services.TryAddSingleton <IPackageSpecGenerator, DefaultPackageSpecGenerator>();
            services.TryAddSingleton(serviceProvider => serviceProvider.GetRequiredService <IPackageSpecGenerator>().Generate());

            // Names
            services.TryAddSingleton <CamelCaseNameFormatter>();
            services.TryAddSingleton <PascalCaseNameFormatter>();
            services.TryAddSingleton <INameFormatterSelector, DefaultNameFormatterSelector>();
            services.TryAddSingleton <IElementTypeNameProvider, DefaultElementTypeNameProvider>();
            services.TryAddSingleton <INamespaceProvider, DefaultNamespaceProvider>();
            services.TryAddSingleton <IHttpResponseCodeNameProvider, HttpResponseCodeNameProvider>();
            services.TryAddSingleton <IRootNamespace, RootNamespace>();
            services.TryAddSingleton <IAuthenticationNamespace, AuthenticationNamespace>();
            services.TryAddSingleton <IRequestsNamespace, RequestsNamespace>();
            services.TryAddSingleton <IResponsesNamespace, ResponsesNamespace>();
            services.TryAddSingleton <ISerializationNamespace, SerializationNamespace>();

            // Other
            services
            .AddLogging()
            .AddSingleton <GenerationContext>()
            .AddSingleton(settings)
            .AddSingleton(document)
            .AddTransient <NuGetPacker>();

            services.TryAddSingleton <IOpenApiElementRegistry, OpenApiElementRegistry>();

            return(services);
        }
Example #5
0
        /// <summary>
        /// Create predicate function based on passed query parameters
        /// </summary>
        /// <param name="operationIds">Comma delimited list of operationIds or * for all operations.</param>
        /// <param name="tags">Comma delimited list of tags or a single regex.</param>
        /// <param name="url">Url path to match with Operation Ids.</param>
        /// <param name="graphVersion">Version of Microsoft Graph.</param>
        /// <param name="forceRefresh">Don't read from in-memory cache.</param>
        /// <returns>A predicate</returns>
        public static async Task <Func <OpenApiOperation, bool> > CreatePredicate(string operationIds, string tags, string url,
                                                                                  OpenApiDocument source, bool forceRefresh = false)
        {
            if (url != null && (operationIds != null || tags != null))
            {
                throw new InvalidOperationException("Cannot filter by url and either operationIds and tags at the same time.");
            }
            else if (operationIds != null && tags != null)
            {
                throw new InvalidOperationException("Cannot filter by operationIds and tags at the same time.");
            }

            Func <OpenApiOperation, bool> predicate;

            if (operationIds != null)
            {
                if (operationIds == "*")
                {
                    predicate = (o) => true;  // All operations
                }
                else
                {
                    var operationIdsArray = operationIds.Split(',');
                    predicate = (o) => operationIdsArray.Contains(o.OperationId);
                }
            }
            else if (tags != null)
            {
                var tagsArray = tags.Split(',');
                if (tagsArray.Length == 1)
                {
                    var regex = new Regex(tagsArray[0]);

                    predicate = (o) => o.Tags.Any(t => regex.IsMatch(t.Name));
                }
                else
                {
                    predicate = (o) => o.Tags.Any(t => tagsArray.Contains(t.Name));
                }
            }
            else if (url != null)
            {
                /* Extract the respective Operation Id(s) that match the provided url path */

                if (!_openApiOperationsTable.Any() || forceRefresh)
                {
                    _uriTemplateTable       = new UriTemplateMatcher();
                    _openApiOperationsTable = new Dictionary <int, OpenApiOperation[]>();

                    await PopulateReferenceTablesAync(source);
                }

                url = url.Replace('-', '_');

                TemplateMatch resultMatch = _uriTemplateTable.Match(new Uri(url.ToLower(), UriKind.RelativeOrAbsolute));

                if (resultMatch == null)
                {
                    throw new ArgumentException("The url supplied could not be found.");
                }

                /* Fetch the corresponding Operations Id(s) for the matched url */

                OpenApiOperation[] openApiOps        = _openApiOperationsTable[int.Parse(resultMatch.Key)];
                string[]           operationIdsArray = openApiOps.Select(x => x.OperationId).ToArray();

                predicate = (o) => operationIdsArray.Contains(o.OperationId);
            }
            else
            {
                throw new InvalidOperationException("Either operationIds, tags or url need to be specified.");
            }

            return(predicate);
        }
Example #6
0
        public void GetPathsByBasePathSegmentName(int expectedCount, string basePathSegmentName, OpenApiDocument openApiDocument)
        {
            // Act
            var actual = openApiDocument.GetPathsByBasePathSegmentName(basePathSegmentName);

            // Assert
            Assert.NotNull(actual);
            Assert.Equal(expectedCount, actual.Count);
        }
Example #7
0
 /// <summary>
 /// Validate if a resource has at least one 4xx and a 500 response.
 /// Supressions: Rule,Path,Operation,ResponseCode
 /// </summary>
 public ResponseWithout4xxAnd500Rule(OpenApiDocument contract,
                                     Supressions supressions, IOptions <RuleSettings> ruleSettings, OpenApiDocumentCache cache) : base(contract, supressions,
                                                                                                                                       ruleSettings, cache, ruleName, Severity.Warning)
 {
 }
Example #8
0
        /// <summary>
        /// Walks through the <see cref="OpenApiDocument"/> and validates each element.
        /// </summary>
        /// <param name="doc"></param>
        public void Walk(OpenApiDocument doc)
        {
            _visitor.Visit(doc);
            _visitor.Visit(doc.Info);
            _visitor.Visit(doc.Servers);

            if (doc.Servers != null)
            {
                foreach (var server in doc.Servers)
                {
                    _visitor.Visit(server);
                    foreach (var variable in server.Variables.Values)
                    {
                        _visitor.Visit(variable);
                    }
                }
            }

            _visitor.Visit(doc.Paths);
            foreach (var pathItem in doc.Paths.Values)
            {
                _visitor.Visit(pathItem);
                _visitor.Visit(pathItem.Operations);
                foreach (var operation in pathItem.Operations.Values)
                {
                    _visitor.Visit(operation);
                    if (operation.Parameters != null)
                    {
                        _visitor.Visit(operation.Parameters);
                        foreach (var parameter in operation.Parameters)
                        {
                            _visitor.Visit(parameter);
                        }
                    }

                    if (operation.RequestBody != null)
                    {
                        _visitor.Visit(operation.RequestBody);

                        if (operation.RequestBody.Content != null)
                        {
                            WalkContent(operation.RequestBody.Content);
                        }
                    }

                    if (operation.Responses != null)
                    {
                        _visitor.Visit(operation.Responses);

                        foreach (var response in operation.Responses.Values)
                        {
                            _visitor.Visit(response);
                            WalkContent(response.Content);

                            if (response.Links != null)
                            {
                                _visitor.Visit(response.Links);
                                foreach (var link in response.Links.Values)
                                {
                                    _visitor.Visit(link);
                                }
                            }
                        }
                    }
                }
            }
        }
 public void Apply(OpenApiDocument model, DocumentFilterContext context)
 {
     Filter(model, context);
 }
Example #10
0
        /// <summary>
        /// Reads the stream input and parses it into an Open API document.
        /// </summary>
        /// <param name="input">Stream containing OpenAPI description to parse.</param>
        /// <param name="diagnostic">Returns diagnostic object containing errors detected during parsing</param>
        /// <returns>Instance of newly created OpenApiDocument</returns>
        public OpenApiDocument Read(Stream input, out OpenApiDiagnostic diagnostic)
        {
            ParsingContext context;
            YamlDocument   yamlDocument;

            diagnostic = new OpenApiDiagnostic();

            // Parse the YAML/JSON
            try
            {
                yamlDocument = LoadYamlDocument(input);
            }
            catch (SyntaxErrorException ex)
            {
                diagnostic.Errors.Add(new OpenApiReaderError(ex));
                return(new OpenApiDocument());
            }

            context = new ParsingContext
            {
                ExtensionParsers = _settings.ExtensionParsers
            };

            OpenApiDocument document = null;

            try
            {
                // Parse the OpenAPI Document
                document = context.Parse(yamlDocument, diagnostic);

                // Resolve References if requested
                switch (_settings.ReferenceResolution)
                {
                case ReferenceResolutionSetting.ResolveAllReferences:
                    throw new ArgumentException(Properties.SRResource.CannotResolveRemoteReferencesSynchronously);

                case ReferenceResolutionSetting.ResolveLocalReferences:
                    var resolver = new OpenApiReferenceResolver(document);
                    var walker   = new OpenApiWalker(resolver);
                    walker.Walk(document);
                    foreach (var item in resolver.Errors)
                    {
                        diagnostic.Errors.Add(item);
                    }
                    break;

                case ReferenceResolutionSetting.DoNotResolveReferences:
                    break;
                }
            }
            catch (OpenApiException ex)
            {
                diagnostic.Errors.Add(new OpenApiError(ex));
            }

            // Validate the document
            var errors = document.Validate(_settings.RuleSet);

            foreach (var item in errors)
            {
                diagnostic.Errors.Add(item);
            }

            return(document);
        }
Example #11
0
        public void When_parent_parameters_have_same_kind_then_they_are_included()
        {
            //// Arrange
            var swagger  = @"{
  ""swagger"" : ""2.0"",
  ""info"" : {
    ""version"" : ""1.0.2"",
    ""title"" : ""Test API""
  },
  ""host"" : ""localhost:8080"",
  ""basePath"" : ""/"",
  ""tags"" : [ {
    ""name"" : ""api""
  } ],
  ""schemes"" : [ ""http"" ],
  ""paths"" : {
     ""/removeElement"" : {

""parameters"": [
                {
                ""name"": ""SecureToken"",
                    ""in"": ""header"",
                    ""description"": ""cookie"",
                    ""required"": true,
                    ""type"": ""string""
                }
            ],

      ""delete"" : {
        ""tags"" : [ ""api"" ],
        ""summary"" : ""Removes elements"",
        ""description"" : ""Removes elements"",
        ""operationId"" : ""removeElement"",
        ""consumes"" : [ ""application/json"" ],
        ""produces"" : [ ""application/json"" ],
        ""parameters"" : [ {
          ""name"" : ""X-User"",
          ""in"" : ""header"",
          ""description"" : ""User identifier"",
          ""required"" : true,
          ""type"" : ""string""
        }, {
          ""name"" : ""elementId"",
          ""in"" : ""query"",
          ""description"" : ""The ids of existing elements that should be removed"",
          ""required"" : false,
          ""type"" : ""array"",
          ""items"" : {
            ""type"" : ""integer"",
            ""format"" : ""int64""
          },
        } ],
        ""responses"" : {
          ""default"" : {
            ""description"" : ""successful operation""
          }
        }
      }
    }
  },
    ""definitions"" : { }
}
";
            var document = OpenApiDocument.FromJsonAsync(swagger).Result;

            //// Act
            var generator = new CSharpClientGenerator(document, new CSharpClientGeneratorSettings());
            var code      = generator.GenerateFile();

            //// Assert
            Assert.Contains("RemoveElementAsync(string x_User, System.Collections.Generic.IEnumerable<long> elementId, string secureToken)", code);
        }
Example #12
0
        public void Deep_object_properties_are_correctly_named()
        {
            //// Arrange
            var swagger = @"{
   'openapi' : '3.0',
   'info' : {
      'version' : '1.0.2',
       'title' : 'Test API'
   },
   'paths': {
      '/journeys': {
         'get': {
            'tags': [
               'CheckIn'
            ],
            'summary': 'Retrieve journeys',
            'operationId': 'retrieveJourneys',
            'description': '',
            'parameters': [
                {
                   'name': 'lastName',
                   'in': 'query',
                   'schema': { 'type': 'string' }
                },
                {
                   'name': 'eTicketNumber',
                   'in': 'query',
                   'schema': { 'type': 'string' }
                },
                {
                   'name': 'options',
                   'in': 'query',
                   'style': 'deepObject',
                   'explode': true,
                   'schema': { '$ref': '#/components/schemas/Options' }
                }
            ],
            'responses': {}
         }
      }
   },
   'components':{
      'schemas': {
         'Options': {
            'type':'object',
            'properties': {
               'optionalOrder.id': {
                  'schema': { 'type': 'string' }
               },
               'optionalFrequentFlyerCard.id':{
                  'schema': { 'type': 'string' }
               },
               'optionalDepartureDate':{
                  'schema': { 'type': 'string' }
               },
               'optionalOriginLocationCode':{
                  'schema': { 'type': 'string' }
               }
            }
         }
      }
   }
}";

            var document = OpenApiDocument.FromJsonAsync(swagger, "", SchemaType.OpenApi3).Result;

            //// Act
            var generator = new CSharpClientGenerator(document, new CSharpClientGeneratorSettings());
            var code      = generator.GenerateFile();

            //// Assert
            Assert.Contains("options[optionalOrder.id]=", code);
            Assert.Contains("options.OptionalOrderId", code);
        }
Example #13
0
        public void When_swagger_contains_optional_parameters_then_they_are_rendered_in_CSharp()
        {
            //// Arrange
            var swagger = @"{
   ""paths"":{
      ""/journeys"":{
         ""get"":{
            ""tags"":[
               ""CheckIn""
            ],
            ""summary"":""Retrieve journeys"",
            ""operationId"":""retrieveJourneys"",
            ""description"":"""",
            ""parameters"":[
               {
                  ""$ref"":""#/parameters/lastName""
               },
               {
                  ""$ref"":""#/parameters/optionalOrderId""
               },
               {
                  ""$ref"":""#/parameters/eTicketNumber""
               },
               {
                  ""$ref"":""#/parameters/optionalFrequentFlyerCardId""
               },
               {
                  ""$ref"":""#/parameters/optionalDepartureDate""
               },
               {
                  ""$ref"":""#/parameters/optionalOriginLocationCode""
               }
            ],
            ""responses"": {}
         }
      }
   },
   ""parameters"":{
      ""lastName"":{
         ""name"":""lastName"",
         ""type"":""string"",
         ""required"":true
      },
      ""optionalOrderId"":{
         ""name"":""optionalOrderId"",
         ""type"":""string"",
         ""required"":false
      },
      ""eTicketNumber"":{
         ""name"":""eTicketNumber"",
         ""type"":""string"",
         ""required"":false
      },
      ""optionalFrequentFlyerCardId"":{
         ""name"":""optionalFrequentFlyerCardId"",
         ""type"":""string"",
         ""required"":false
      },
      ""optionalDepartureDate"":{
         ""name"":""optionalDepartureDate"",
         ""type"":""string"",
         ""required"":false
      },
      ""optionalOriginLocationCode"":{
         ""name"":""optionalOriginLocationCode"",
         ""type"":""string"",
         ""required"":false
      }
   }
}";

            var document = OpenApiDocument.FromJsonAsync(swagger).Result;

            //// Act
            var generator = new CSharpClientGenerator(document, new CSharpClientGeneratorSettings());
            var code      = generator.GenerateFile();

            //// Assert
            Assert.Contains("lastName", code);
            Assert.Contains("optionalOrderId", code);
        }
Example #14
0
        public ContentResult GetV1OpenApi()
        {
            OpenApiDocument document = CreateDocument("v1");

            return(CreateContent(document));
        }
Example #15
0
        /// <inheritdoc />
        public void Apply(OpenApiDocument swaggerDoc, DocumentFilterContext context)
        {
            if (swaggerDoc == null)
            {
                throw new ArgumentNullException(nameof(swaggerDoc));
            }
            if (context == null)
            {
                throw new ArgumentNullException(nameof(context));
            }

            swaggerDoc.Components.Parameters.Add(ApiHeaders.InstanceIdHeader, new OpenApiParameter
            {
                In          = ParameterLocation.Header,
                Name        = ApiHeaders.InstanceIdHeader,
                Description = "The instance ID being accessed",
                Required    = true,
                Style       = ParameterStyle.Simple,
                Schema      = new OpenApiSchema
                {
                    Type = "integer"
                }
            });

            var productHeaderSchema = new OpenApiSchema
            {
                Type   = "string",
                Format = "productheader"
            };

            swaggerDoc.Components.Parameters.Add(ApiHeaders.ApiVersionHeader, new OpenApiParameter
            {
                In          = ParameterLocation.Header,
                Name        = ApiHeaders.ApiVersionHeader,
                Description = "The API version being used in the form \"Tgstation.Server.Api/[API version]\"",
                Required    = true,
                Style       = ParameterStyle.Simple,
                Example     = new OpenApiString($"Tgstation.Server.Api/{ApiHeaders.Version}"),
                Schema      = productHeaderSchema
            });

            swaggerDoc.Components.Parameters.Add(HeaderNames.UserAgent, new OpenApiParameter
            {
                In          = ParameterLocation.Header,
                Name        = HeaderNames.UserAgent,
                Description = "The user agent of the calling client.",
                Required    = true,
                Style       = ParameterStyle.Simple,
                Example     = new OpenApiString("Your-user-agent/1.0.0.0"),
                Schema      = productHeaderSchema
            });

            string bridgeOperationPath = null;

            foreach (var path in swaggerDoc.Paths)
            {
                foreach (var operation in path.Value.Operations.Select(x => x.Value))
                {
                    if (operation.OperationId.Equals("BridgeController.Process", StringComparison.Ordinal))
                    {
                        bridgeOperationPath = path.Key;
                        continue;
                    }

                    operation.Parameters.Add(new OpenApiParameter
                    {
                        Reference = new OpenApiReference
                        {
                            Type = ReferenceType.Parameter,
                            Id   = ApiHeaders.ApiVersionHeader
                        },
                    });

                    operation.Parameters.Add(new OpenApiParameter
                    {
                        Reference = new OpenApiReference
                        {
                            Type = ReferenceType.Parameter,
                            Id   = HeaderNames.UserAgent
                        }
                    });
                }
            }

            swaggerDoc.Paths.Remove(bridgeOperationPath);

            AddDefaultResponses(swaggerDoc);
        }
Example #16
0
        public void ParseCompleteSwagger()
        {

            var vocab = OpenApiVocab.Create();
            
            var stream = this.GetType().Assembly
                .GetManifestResourceStream(this.GetType(), "forecast.io.swagger.json");

            var swaggerDoc = new OpenApiDocument();

            JsonStreamingParser.ParseStream(stream, swaggerDoc, vocab);

            Assert.Equal("2.0", swaggerDoc.Version);
            Assert.Equal(1, swaggerDoc.Schemes.Count);
            Assert.Equal("https", swaggerDoc.Schemes.First());

            Assert.Equal(1, swaggerDoc.Paths.Count );
            Assert.Equal(swaggerDoc.Paths.Keys.First(), "/forecast/{apiKey}/{latitude},{longitude}");
            var path = swaggerDoc.Paths.Values.First();
            Assert.Equal(1, path.Operations.Count);
            var operation = path.Operations.Values.First();
            Assert.Equal("Forecast", operation.Id);

            Assert.False(String.IsNullOrEmpty(swaggerDoc.Info.Description));
            Assert.False(String.IsNullOrEmpty(swaggerDoc.Info.Title));
            Assert.True(String.IsNullOrEmpty(swaggerDoc.Info.Version));
            

        }
Example #17
0
        static void AddDefaultResponses(OpenApiDocument document)
        {
            var errorMessageContent = new Dictionary <string, OpenApiMediaType>
            {
                {
                    ApiHeaders.ApplicationJson,
                    new OpenApiMediaType
                    {
                        Schema = new OpenApiSchema
                        {
                            Reference = new OpenApiReference
                            {
                                Id   = nameof(ErrorMessage),
                                Type = ReferenceType.Schema
                            }
                        }
                    }
                }
            };

            void AddDefaultResponse(HttpStatusCode code, OpenApiResponse concrete)
            {
                string responseKey = $"{(int)code}";

                document.Components.Responses.Add(responseKey, concrete);

                var referenceResponse = new OpenApiResponse
                {
                    Reference = new OpenApiReference
                    {
                        Type = ReferenceType.Response,
                        Id   = responseKey
                    }
                };

                foreach (var operation in document.Paths.SelectMany(path => path.Value.Operations))
                {
                    operation.Value.Responses.TryAdd(responseKey, referenceResponse);
                }
            }

            AddDefaultResponse(HttpStatusCode.BadRequest, new OpenApiResponse
            {
                Description = "A badly formatted request was made. See error message for details.",
                Content     = errorMessageContent,
            });

            AddDefaultResponse(HttpStatusCode.Unauthorized, new OpenApiResponse
            {
                Description = "No/invalid token provided."
            });

            AddDefaultResponse(HttpStatusCode.Forbidden, new OpenApiResponse
            {
                Description = "User lacks sufficient permissions for the operation."
            });

            AddDefaultResponse(HttpStatusCode.Conflict, new OpenApiResponse
            {
                Description = "A data integrity check failed while performing the operation. See error message for details.",
                Content     = errorMessageContent
            });

            AddDefaultResponse(HttpStatusCode.InternalServerError, new OpenApiResponse
            {
                Description = "The server encountered an unhandled error. See error message for details.",
                Content     = errorMessageContent
            });

            AddDefaultResponse(HttpStatusCode.ServiceUnavailable, new OpenApiResponse
            {
                Description = "The server may be starting up or shutting down."
            });

            AddDefaultResponse(HttpStatusCode.NotImplemented, new OpenApiResponse
            {
                Description = "This operation requires POSIX system identites to be implemented. See https://github.com/tgstation/tgstation-server/issues/709",
                Content     = errorMessageContent
            });
        }
Example #18
0
        /// <summary>
        /// 生成内容
        /// </summary>
        /// <param name="document">对象</param>
        /// <param name="content">内容</param>
        /// <returns></returns>
        internal static string GeneratorContent(OpenApiDocument document, string content)
        {
            var result = Engine.Razor.RunCompile(content, "api", typeof(OpenApiDocument), document);

            return(result);
        }
        /// <summary>
        /// Add the default error responses to a given <paramref name="document"/>.
        /// </summary>
        /// <param name="document">The <see cref="OpenApiDocument"/> to augment.</param>
        static void AddDefaultResponses(OpenApiDocument document)
        {
            var errorMessageContent = new Dictionary <string, OpenApiMediaType>
            {
                {
                    MediaTypeNames.Application.Json,
                    new OpenApiMediaType
                    {
                        Schema = new OpenApiSchema
                        {
                            Reference = new OpenApiReference
                            {
                                Id   = nameof(ErrorMessageResponse),
                                Type = ReferenceType.Schema,
                            },
                        },
                    }
                },
            };

            void AddDefaultResponse(HttpStatusCode code, OpenApiResponse concrete)
            {
                string responseKey = $"{(int)code}";

                document.Components.Responses.Add(responseKey, concrete);

                var referenceResponse = new OpenApiResponse
                {
                    Reference = new OpenApiReference
                    {
                        Type = ReferenceType.Response,
                        Id   = responseKey,
                    },
                };

                foreach (var operation in document.Paths.SelectMany(path => path.Value.Operations))
                {
                    operation.Value.Responses.TryAdd(responseKey, referenceResponse);
                }
            }

            AddDefaultResponse(HttpStatusCode.BadRequest, new OpenApiResponse
            {
                Description = "A badly formatted request was made. See error message for details.",
                Content     = errorMessageContent,
            });

            AddDefaultResponse(HttpStatusCode.Unauthorized, new OpenApiResponse
            {
                Description = "Invalid Authentication header.",
            });

            AddDefaultResponse(HttpStatusCode.Forbidden, new OpenApiResponse
            {
                Description = "User lacks sufficient permissions for the operation.",
            });

            AddDefaultResponse(HttpStatusCode.Conflict, new OpenApiResponse
            {
                Description = "A data integrity check failed while performing the operation. See error message for details.",
                Content     = errorMessageContent,
            });

            AddDefaultResponse(HttpStatusCode.NotAcceptable, new OpenApiResponse
            {
                Description = $"Invalid Accept header, TGS requires `{HeaderNames.Accept}: {MediaTypeNames.Application.Json}`.",
                Content     = errorMessageContent,
            });

            AddDefaultResponse(HttpStatusCode.InternalServerError, new OpenApiResponse
            {
                Description = ErrorCode.InternalServerError.Describe(),
                Content     = errorMessageContent,
            });

            AddDefaultResponse(HttpStatusCode.ServiceUnavailable, new OpenApiResponse
            {
                Description = "The server may be starting up or shutting down.",
            });

            AddDefaultResponse(HttpStatusCode.NotImplemented, new OpenApiResponse
            {
                Description = ErrorCode.RequiresPosixSystemIdentity.Describe(),
                Content     = errorMessageContent,
            });
        }
        /// <summary>
        /// Compares two <see cref="OpenApiDocument"/>s and returns a list of differences.
        /// </summary>
        public static List <OpenApiDifference> Compare(OpenApiDocument source, OpenApiDocument target)
        {
            var diffs = new List <OpenApiDifference>();

            return(diffs);
        }
 public void Apply(OpenApiDocument swaggerDoc, DocumentFilterContext context)
 {
     swaggerDoc.Extensions.Add("X-foo", new OpenApiString("bar"));
     swaggerDoc.Extensions.Add("X-docName", new OpenApiString(context.DocumentName));
 }
Example #22
0
 /// <summary>
 /// Remove Paths and Components from OpenApi documentation without accepted roles.
 /// </summary>
 /// <param name="openApiDoc"><see cref="OpenApiDocument"/>.</param>
 /// <param name="paths">Dictionary of openApi paths with <see cref="MethodInfo"/> keys.</param>
 /// <param name="schemas">Dictionary with openApi schemas with scheme name keys.</param>
 /// <param name="acceptedRoles">Collection of accepted roles.</param>
 internal static void RemovePathsAndComponents(
     OpenApiDocument openApiDoc,
     IDictionary <(MethodInfo ActionMethodInfo, Type ControllerType), string> paths,
 /// <summary>
 /// Visits <see cref="OpenApiDocument"/>
 /// </summary>
 public virtual void Visit(OpenApiDocument doc)
 {
 }
        /// <summary>
        /// Create partial document based on provided predicate
        /// </summary>
        public static OpenApiDocument CreateFilteredDocument(OpenApiDocument source, string title, string graphVersion, Func <OpenApiOperation, bool> predicate)
        {
            var subset = new OpenApiDocument
            {
                Info = new OpenApiInfo()
                {
                    Title   = title,
                    Version = graphVersion
                },

                Components = new OpenApiComponents()
            };
            var aadv2Scheme = new OpenApiSecurityScheme()
            {
                Type  = SecuritySchemeType.OAuth2,
                Flows = new OpenApiOAuthFlows()
                {
                    AuthorizationCode = new OpenApiOAuthFlow()
                    {
                        AuthorizationUrl = new Uri(GraphConstants.GraphAuthorizationUrl),
                        TokenUrl         = new Uri(GraphConstants.GraphTokenUrl)
                    }
                },
                Reference = new OpenApiReference()
                {
                    Id = "azureaadv2", Type = ReferenceType.SecurityScheme
                },
                UnresolvedReference = false
            };

            subset.Components.SecuritySchemes.Add("azureaadv2", aadv2Scheme);

            subset.SecurityRequirements.Add(new OpenApiSecurityRequirement()
            {
                { aadv2Scheme, new string[] { } }
            });

            subset.Servers.Add(new OpenApiServer()
            {
                Description = "Core", Url = string.Format(GraphConstants.GraphUrl, graphVersion)
            });

            var results = FindOperations(source, predicate);

            foreach (var result in results)
            {
                OpenApiPathItem pathItem;

                if (subset.Paths == null)
                {
                    subset.Paths = new OpenApiPaths();
                    pathItem     = new OpenApiPathItem();
                    subset.Paths.Add(result.CurrentKeys.Path, pathItem);
                }
                else
                {
                    if (!subset.Paths.TryGetValue(result.CurrentKeys.Path, out pathItem))
                    {
                        pathItem = new OpenApiPathItem();
                        subset.Paths.Add(result.CurrentKeys.Path, pathItem);
                    }
                }

                pathItem.Operations.Add((OperationType)result.CurrentKeys.Operation, result.Operation);
            }

            CopyReferences(subset);

            return(subset);
        }
Example #25
0
 public OpenApiValidatorHandler(OpenApiDocument openApiDocument, HttpMessageHandler innerHandler)
     : base(innerHandler)
 {
     _openApiDocument = openApiDocument;
 }
        public static OpenApiDocument CreateFilteredDocument(string title, string version, OpenApiDocument source, Func <OpenApiOperation, bool> predicate)
        {
            var subset = new OpenApiDocument
            {
                Info = new OpenApiInfo()
                {
                    Title   = title,
                    Version = version
                },

                Components = new OpenApiComponents()
            };
            var aadv2Scheme = new OpenApiSecurityScheme()
            {
                Type  = SecuritySchemeType.OAuth2,
                Flows = new OpenApiOAuthFlows()
                {
                    AuthorizationCode = new OpenApiOAuthFlow()
                    {
                        AuthorizationUrl = new Uri("https://login.microsoftonline.com/common/oauth2/v2.0/authorize"),
                        TokenUrl         = new Uri("https://login.microsoftonline.com/common/oauth2/v2.0/token")
                    }
                },
                Reference = new OpenApiReference()
                {
                    Id = "azureaadv2", Type = ReferenceType.SecurityScheme
                },
                UnresolvedReference = false
            };

            subset.Components.SecuritySchemes.Add("azureaadv2", aadv2Scheme);

            subset.SecurityRequirements.Add(new OpenApiSecurityRequirement()
            {
                { aadv2Scheme, new string[] { } }
            });

            subset.Servers.Add(new OpenApiServer()
            {
                Description = "Core", Url = "https://graph.microsoft.com/v1.0/"
            });

            var operationObjects = new List <OpenApiOperation>();
            var results          = FindOperations(source, predicate);

            foreach (var result in results)
            {
                OpenApiPathItem pathItem = null;
                if (subset.Paths == null)
                {
                    subset.Paths = new OpenApiPaths();
                    pathItem     = new OpenApiPathItem();
                    subset.Paths.Add(result.CurrentKeys.Path, pathItem);
                }
                else
                {
                    if (!subset.Paths.TryGetValue(result.CurrentKeys.Path, out pathItem))
                    {
                        pathItem = new OpenApiPathItem();
                        subset.Paths.Add(result.CurrentKeys.Path, pathItem);
                    }
                }

                pathItem.Operations.Add((OperationType)result.CurrentKeys.Operation, result.Operation);
            }
            return(subset);
        }
Example #27
0
 public OpenApiValidatorHandler(OpenApiDocument openApiDocument)
     : this(openApiDocument, new HttpClientHandler())
 {
 }
Example #28
0
        private List <Type> GenerateForControllers(
            OpenApiDocument document,
            IGrouping <Type, Tuple <ApiDescription, ControllerActionDescriptor> >[] apiGroups,
            OpenApiSchemaResolver schemaResolver)
        {
            var usedControllerTypes = new List <Type>();
            var swaggerGenerator    = new OpenApiDocumentGenerator(Settings, schemaResolver);

            var allOperations = new List <Tuple <OpenApiOperationDescription, ApiDescription, MethodInfo> >();

            foreach (var controllerApiDescriptionGroup in apiGroups)
            {
                var controllerType = controllerApiDescriptionGroup.Key;

                var hasIgnoreAttribute = controllerType.GetTypeInfo()
                                         .GetCustomAttributes()
                                         .GetAssignableToTypeName("SwaggerIgnoreAttribute", TypeNameStyle.Name)
                                         .Any();

                if (!hasIgnoreAttribute)
                {
                    var operations = new List <Tuple <OpenApiOperationDescription, ApiDescription, MethodInfo> >();
                    foreach (var item in controllerApiDescriptionGroup)
                    {
                        var apiDescription = item.Item1;
                        var method         = item.Item2.MethodInfo;

                        var actionHasIgnoreAttribute = method.GetCustomAttributes().GetAssignableToTypeName("SwaggerIgnoreAttribute", TypeNameStyle.Name).Any();
                        if (actionHasIgnoreAttribute)
                        {
                            continue;
                        }

                        var path = apiDescription.RelativePath;
                        if (!path.StartsWith("/", StringComparison.Ordinal))
                        {
                            path = "/" + path;
                        }

                        var controllerActionDescriptor = (ControllerActionDescriptor)apiDescription.ActionDescriptor;
                        var httpMethod = apiDescription.HttpMethod?.ToLowerInvariant() ?? OpenApiOperationMethod.Get;

                        var operationDescription = new OpenApiOperationDescription
                        {
                            Path      = path,
                            Method    = httpMethod,
                            Operation = new OpenApiOperation
                            {
                                IsDeprecated = IsOperationDeprecated(item.Item1, controllerActionDescriptor, method),
                                OperationId  = GetOperationId(document, controllerActionDescriptor, method),
                                Consumes     = apiDescription.SupportedRequestFormats
                                               .Select(f => f.MediaType)
                                               .Distinct()
                                               .ToList(),
                                Produces = apiDescription.SupportedResponseTypes
                                           .SelectMany(t => t.ApiResponseFormats.Select(f => f.MediaType))
                                           .Distinct()
                                           .ToList()
                            }
                        };

                        operations.Add(new Tuple <OpenApiOperationDescription, ApiDescription, MethodInfo>(operationDescription, apiDescription, method));
                    }

                    var addedOperations = AddOperationDescriptionsToDocument(document, controllerType, operations, swaggerGenerator, schemaResolver);
                    if (addedOperations.Any())
                    {
                        usedControllerTypes.Add(controllerApiDescriptionGroup.Key);
                    }

                    allOperations.AddRange(addedOperations);
                }
            }

            UpdateConsumesAndProduces(document, allOperations);
            return(usedControllerTypes);
        }
Example #29
0
 private static TypeScriptClientGenerator CreateGenerator(OpenApiDocument document)
 {
     return(new TypeScriptClientGenerator(document, SettingsFactory.TpeScripGeneratorSettings));
 }
Example #30
0
        public ContentResult GetOpenApi()
        {
            OpenApiDocument document = CreateDocument(string.Empty);

            return(CreateContent(document));
        }
 private static string GetSanitizeTitle(this OpenApiDocument document)
 => RemoveCharacters(
     document.Info.Title,
     "Swagger", " ", ".", "-");
Example #32
0
        public ContentResult GetV2OpenApi(string data)
        {
            OpenApiDocument document = CreateDocument("v2{data}");

            return(CreateContent(document));
        }
Example #33
0
        public void ParseSwaggerPaths()
        {

            var opsTerm = new VocabTerm<Operation>();

            var pathTerm = new VocabTerm<Path>();
            pathTerm.MapAnyObject<Operation>(opsTerm, (s, p) => {
                return s.AddOperation(p, Guid.NewGuid().ToString());
            });

            var pathsTerm = new VocabTerm<OpenApiDocument>("paths");

            pathsTerm.MapAnyObject<Path>(pathTerm,(s,p) => {
                return s.AddPath(p);
            });

            var rootTerm = new VocabTerm<OpenApiDocument>();
            rootTerm.MapObject<OpenApiDocument>(pathsTerm, (s) =>
             {
                 return s;
             });



            var stream = this.GetType().Assembly
     .GetManifestResourceStream(this.GetType(), "forecast.io.swagger.json");

            var swaggerDoc = new OpenApiDocument();

            JsonStreamingParser.ParseStream(stream, swaggerDoc, rootTerm);

            Assert.Equal(1, swaggerDoc.Paths.Count);
            Assert.Equal(1, swaggerDoc.Paths.First().Value.Operations.Count());
        }