public async Task <IActionResult> Get([FromQuery] string graphVersion   = null,
                                              [FromQuery] string openApiVersion = null,
                                              [FromQuery] OpenApiStyle style    = OpenApiStyle.Plain,
                                              [FromQuery] string format         = null,
                                              [FromQuery] bool forceRefresh     = false)
        {
            try
            {
                OpenApiStyleOptions styleOptions = new OpenApiStyleOptions(style, openApiVersion, graphVersion, format);

                string graphUri = GetVersionUri(styleOptions.GraphVersion);

                if (graphUri == null)
                {
                    return(new BadRequestResult());
                }

                var graphOpenApi = await OpenApiService.GetGraphOpenApiDocumentAsync(graphUri, forceRefresh, styleOptions);

                WriteIndex(Request.Scheme + "://" + Request.Host.Value, styleOptions.GraphVersion, styleOptions.OpenApiVersion, styleOptions.OpenApiFormat,
                           graphOpenApi, Response.Body, styleOptions.Style);

                return(new EmptyResult());
            }
            catch
            {
                return(new BadRequestResult());
            }
        }
        /// <summary>
        /// Update the OpenAPI document based on the style option
        /// </summary>
        /// <param name="style"></param>
        /// <param name="subsetOpenApiDocument"></param>
        /// <returns></returns>
        public static OpenApiDocument ApplyStyle(OpenApiStyleOptions styleOptions, OpenApiDocument subsetOpenApiDocument)
        {
            if (styleOptions.Style == OpenApiStyle.Plain)
            {
                return(subsetOpenApiDocument);
            }

            /* For Powershell and PowerPlatform Styles */

            // Clone doc before making changes
            subsetOpenApiDocument = Clone(subsetOpenApiDocument);

            var anyOfRemover = new AnyOfRemover();
            var walker       = new OpenApiWalker(anyOfRemover);

            walker.Walk(subsetOpenApiDocument);

            if (styleOptions.Style == OpenApiStyle.PowerShell)
            {
                // Format the OperationId for Powershell cmdlet names generation
                var powershellFormatter = new PowershellFormatter();
                walker = new OpenApiWalker(powershellFormatter);
                walker.Walk(subsetOpenApiDocument);

                var version = subsetOpenApiDocument.Info.Version;
                if (!new Regex("v\\d\\.\\d").Match(version).Success)
                {
                    subsetOpenApiDocument.Info.Version = "v1.0-" + version;
                }
            }

            return(subsetOpenApiDocument);
        }
Exemple #3
0
        public void FormatPathFunctionsOfStringDataTypesWithSingleQuotationMarks()
        {
            // Arrange
            string              operationId_1 = "reports.getTeamsUserActivityCounts";
            string              operationId_2 = "reports.getTeamsUserActivityUserDetail-a3f1";
            string              graphVersion  = "beta";
            OpenApiDocument     source        = _source;
            OpenApiStyleOptions styleOptions  = new OpenApiStyleOptions(OpenApiStyle.PowerShell, graphVersion: graphVersion);
            var predicate_1 = OpenApiService.CreatePredicate(operationId_1, null, null, source, false).GetAwaiter().GetResult();
            var predicate_2 = OpenApiService.CreatePredicate(operationId_2, null, null, source, false).GetAwaiter().GetResult();

            // Act
            var subsetOpenApiDocument_1 = OpenApiService.CreateFilteredDocument(source, Title, styleOptions, predicate_1);
            var subsetOpenApiDocument_2 = OpenApiService.CreateFilteredDocument(source, Title, styleOptions, predicate_2);

            // Assert
            Assert.Collection(subsetOpenApiDocument_1.Paths,
                              item =>
            {
                Assert.Equal("/reports/microsoft.graph.getTeamsUserActivityCounts(period='{period}')", item.Key);
            });
            Assert.Collection(subsetOpenApiDocument_2.Paths,
                              item =>
            {
                Assert.Equal("/reports/microsoft.graph.getTeamsUserActivityUserDetail(date={date})", item.Key);
            });
        }
Exemple #4
0
        /// <summary>
        /// Creates an OpenAPI document from a CSDL document.
        /// </summary>
        /// <param name="uri">The file path of the CSDL document location.</param>
        /// <param name="styleOptions">Optional parameter that defines the style
        /// options to be used in formatting the OpenAPI document.</param>
        /// <returns></returns>
        public static OpenApiDocument CreateOpenApiDocument(string uri, OpenApiStyleOptions styleOptions = null)
        {
            if (string.IsNullOrEmpty(uri))
            {
                return(null);
            }

            using StreamReader streamReader = new StreamReader(uri);
            Stream csdl = streamReader.BaseStream;

            var edmModel = CsdlReader.Parse(XElement.Load(csdl).CreateReader());

            var settings = new OpenApiConvertSettings()
            {
                EnableKeyAsSegment            = true,
                EnableOperationId             = true,
                PrefixEntityTypeNameBeforeKey = true,
                TagDepth                 = 2,
                EnablePagination         = styleOptions != null && styleOptions.EnablePagination,
                EnableDiscriminatorValue = styleOptions != null && styleOptions.EnableDiscriminatorValue,
                EnableDerivedTypesReferencesForRequestBody = styleOptions != null && styleOptions.EnableDerivedTypesReferencesForRequestBody,
                EnableDerivedTypesReferencesForResponses   = styleOptions != null && styleOptions.EnableDerivedTypesReferencesForResponses,
                ShowRootPath = styleOptions != null && styleOptions.ShowRootPath
            };
            OpenApiDocument document = edmModel.ConvertToOpenApi(settings);

            document = FixReferences(document);

            return(document);
        }
        public async Task <IActionResult> Post(
            [FromQuery] string operationIds   = null,
            [FromQuery] string tags           = null,
            [FromQuery] string url            = null,
            [FromQuery] string openApiVersion = null,
            [FromQuery] string title          = "Partial Graph API",
            [FromQuery] OpenApiStyle style    = OpenApiStyle.Plain,
            [FromQuery] string format         = null,
            [FromQuery] string graphVersion   = null,
            [FromQuery] bool forceRefresh     = false)
        {
            try
            {
                OpenApiStyleOptions styleOptions = new OpenApiStyleOptions(style, openApiVersion, graphVersion, format);

                string graphUri = GetVersionUri(styleOptions.GraphVersion);

                if (graphUri == null)
                {
                    return(new BadRequestResult());
                }

                OpenApiDocument source = OpenApiService.ConvertCsdlToOpenApi(styleOptions, Request.Body);

                var predicate = await OpenApiService.CreatePredicate(operationIds, tags, url, source, forceRefresh);

                if (predicate == null)
                {
                    return(new BadRequestResult());
                }

                var subsetOpenApiDocument = OpenApiService.CreateFilteredDocument(source, title, styleOptions, predicate);

                subsetOpenApiDocument = OpenApiService.ApplyStyle(styleOptions, subsetOpenApiDocument);

                var stream = OpenApiService.SerializeOpenApiDocument(subsetOpenApiDocument, styleOptions);
                if (styleOptions.OpenApiFormat == "yaml")
                {
                    return(new FileStreamResult(stream, "application/yaml"));
                }
                else
                {
                    return(new FileStreamResult(stream, "application/json"));
                }
            }
            catch (Exception ex)
            {
                return(new BadRequestObjectResult(new ProblemDetails()
                {
                    Detail = ex.Message
                }));
            }
        }
Exemple #6
0
        /// <summary>
        /// Create a representation of the OpenApiDocument to return from an API
        /// </summary>
        /// <param name="subset">OpenAPI document.</param>
        /// <param name="styleOptions">The modal object containing the required styling options.</param>
        /// <returns>A memory stream.</returns>
        public static MemoryStream SerializeOpenApiDocument(OpenApiDocument subset, OpenApiStyleOptions styleOptions)
        {
            var stream = new MemoryStream();
            var sr     = new StreamWriter(stream);
            OpenApiWriterBase writer;

            if (styleOptions.OpenApiFormat == Constants.OpenApiConstants.Format_Yaml)
            {
                if (styleOptions.InlineLocalReferences)
                {
                    writer = new OpenApiYamlWriter(sr,
                                                   new OpenApiWriterSettings {
                        ReferenceInline = ReferenceInlineSetting.InlineLocalReferences
                    });
                }
                else
                {
                    writer = new OpenApiYamlWriter(sr);
                }
            }
            else // json
            {
                if (styleOptions.InlineLocalReferences)
                {
                    writer = new OpenApiJsonWriter(sr,
                                                   new OpenApiWriterSettings {
                        ReferenceInline = ReferenceInlineSetting.InlineLocalReferences
                    });
                }
                else
                {
                    writer = new OpenApiJsonWriter(sr);
                }
            }

            if (styleOptions.OpenApiVersion == Constants.OpenApiConstants.OpenApiVersion_2)
            {
                subset.SerializeAsV2(writer);
            }
            else
            {
                subset.SerializeAsV3(writer);
            }
            sr.Flush();
            stream.Position = 0;
            return(stream);
        }
        public async Task <IActionResult> Get([FromQuery] string graphVersion   = null,
                                              [FromQuery] string openApiVersion = null,
                                              [FromQuery] OpenApiStyle style    = OpenApiStyle.Plain,
                                              [FromQuery] string format         = null,
                                              [FromQuery] bool forceRefresh     = false)
        {
            try
            {
                OpenApiStyleOptions styleOptions = new OpenApiStyleOptions(style, openApiVersion, graphVersion, format);

                string graphUri = GetVersionUri(styleOptions.GraphVersion);

                if (graphUri == null)
                {
                    throw new InvalidOperationException($"Unsupported {nameof(graphVersion)} provided: '{graphVersion}'");
                }

                var graphOpenApi = await OpenApiService.GetGraphOpenApiDocumentAsync(graphUri, forceRefresh);

                WriteIndex(Request.Scheme + "://" + Request.Host.Value, styleOptions.GraphVersion, styleOptions.OpenApiVersion, styleOptions.OpenApiFormat,
                           graphOpenApi, Response.Body, styleOptions.Style);

                return(new EmptyResult());
            }
            catch (InvalidOperationException ex)
            {
                return(new JsonResult(ex.Message)
                {
                    StatusCode = StatusCodes.Status400BadRequest
                });
            }
            catch (ArgumentException ex)
            {
                return(new JsonResult(ex.Message)
                {
                    StatusCode = StatusCodes.Status404NotFound
                });
            }
            catch (Exception ex)
            {
                return(new JsonResult(ex.Message)
                {
                    StatusCode = StatusCodes.Status500InternalServerError
                });
            }
        }
        public async Task <IActionResult> Get(
            [FromQuery] string operationIds   = null,
            [FromQuery] string tags           = null,
            [FromQuery] string url            = null,
            [FromQuery] string openApiVersion = null,
            [FromQuery] string title          = "Partial Graph API",
            [FromQuery] OpenApiStyle style    = OpenApiStyle.Plain,
            [FromQuery] string format         = null,
            [FromQuery] string graphVersion   = null,
            [FromQuery] bool forceRefresh     = false)
        {
            try
            {
                OpenApiStyleOptions styleOptions = new OpenApiStyleOptions(style, openApiVersion, graphVersion, format);

                string graphUri = GetVersionUri(styleOptions.GraphVersion);

                if (graphUri == null)
                {
                    return(new BadRequestResult());
                }

                OpenApiDocument source = await OpenApiService.GetGraphOpenApiDocumentAsync(graphUri, forceRefresh, styleOptions);

                var predicate = await OpenApiService.CreatePredicate(operationIds, tags, url, source, forceRefresh);

                if (predicate == null)
                {
                    return(new BadRequestResult());
                }

                var subsetOpenApiDocument = OpenApiService.CreateFilteredDocument(source, title, styleOptions, predicate);

                subsetOpenApiDocument = OpenApiService.ApplyStyle(styleOptions, subsetOpenApiDocument);

                var stream = OpenApiService.SerializeOpenApiDocument(subsetOpenApiDocument, styleOptions);
                return(new FileStreamResult(stream, "application/json"));
            }
            catch
            {
                return(new BadRequestResult());
            }
        }
        public static OpenApiDocument ConvertCsdlToOpenApi(OpenApiStyleOptions styleOptions, Stream csdl)
        {
            var edmModel = CsdlReader.Parse(XElement.Load(csdl).CreateReader());

            var settings = new OpenApiConvertSettings()
            {
                EnableKeyAsSegment            = true,
                EnableOperationId             = true,
                PrefixEntityTypeNameBeforeKey = true,
                TagDepth                 = 2,
                EnablePagination         = styleOptions != null && styleOptions.EnablePagination,
                EnableDiscriminatorValue = styleOptions != null && styleOptions.EnableDiscriminatorValue,
                EnableDerivedTypesReferencesForRequestBody = styleOptions != null && styleOptions.EnableDerivedTypesReferencesForRequestBody,
                EnableDerivedTypesReferencesForResponses   = styleOptions != null && styleOptions.EnableDerivedTypesReferencesForResponses,
                ShowRootPath = styleOptions != null && styleOptions.ShowRootPath,
                ShowLinks    = styleOptions != null && styleOptions.ShowLinks
            };
            OpenApiDocument document = edmModel.ConvertToOpenApi(settings);

            document = FixReferences(document);
            return(document);
        }
        public async Task <IActionResult> Post(
            [FromQuery] string operationIds   = null,
            [FromQuery] string tags           = null,
            [FromQuery] string url            = null,
            [FromQuery] string openApiVersion = null,
            [FromQuery] string title          = "Partial Graph API",
            [FromQuery] OpenApiStyle style    = OpenApiStyle.Plain,
            [FromQuery] string format         = null,
            [FromQuery] string graphVersion   = null,
            [FromQuery] bool forceRefresh     = false)
        {
            try
            {
                OpenApiStyleOptions styleOptions = new OpenApiStyleOptions(style, openApiVersion, graphVersion, format);

                string graphUri = GetVersionUri(styleOptions.GraphVersion);

                if (graphUri == null)
                {
                    throw new InvalidOperationException($"Unsupported {nameof(graphVersion)} provided: '{graphVersion}'");
                }

                OpenApiDocument source = OpenApiService.ConvertCsdlToOpenApi(Request.Body);

                var predicate = await OpenApiService.CreatePredicate(operationIds, tags, url, source, forceRefresh);

                var subsetOpenApiDocument = OpenApiService.CreateFilteredDocument(source, title, styleOptions.GraphVersion, predicate);

                subsetOpenApiDocument = OpenApiService.ApplyStyle(styleOptions.Style, subsetOpenApiDocument);

                var stream = OpenApiService.SerializeOpenApiDocument(subsetOpenApiDocument, styleOptions);

                if (styleOptions.OpenApiFormat == "yaml")
                {
                    return(new FileStreamResult(stream, "text/yaml"));
                }
                else
                {
                    return(new FileStreamResult(stream, "application/json"));
                }
            }
            catch (InvalidOperationException ex)
            {
                return(new JsonResult(ex.Message)
                {
                    StatusCode = StatusCodes.Status400BadRequest
                });
            }
            catch (ArgumentException ex)
            {
                return(new JsonResult(ex.Message)
                {
                    StatusCode = StatusCodes.Status404NotFound
                });
            }
            catch (Exception ex)
            {
                return(new JsonResult(ex.Message)
                {
                    StatusCode = StatusCodes.Status500InternalServerError
                });
            }
        }
        /// <summary>
        /// Create partial document based on provided predicate
        /// </summary>
        public static OpenApiDocument CreateFilteredDocument(OpenApiDocument source, string title, OpenApiStyleOptions styleOptions, Func <OpenApiOperation, bool> predicate)
        {
            var subset = new OpenApiDocument
            {
                Info = new OpenApiInfo()
                {
                    Title   = title,
                    Version = styleOptions.GraphVersion
                },

                Components = new OpenApiComponents()
            };
            var aadv2Scheme = new OpenApiSecurityScheme()
            {
                Type  = SecuritySchemeType.OAuth2,
                Flows = new OpenApiOAuthFlows()
                {
                    AuthorizationCode = new OpenApiOAuthFlow()
                    {
                        AuthorizationUrl = new Uri(Constants.GraphConstants.GraphAuthorizationUrl),
                        TokenUrl         = new Uri(Constants.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(Constants.GraphConstants.GraphUrl, styleOptions.GraphVersion)
            });

            var results = FindOperations(source, predicate);

            foreach (var result in results)
            {
                OpenApiPathItem pathItem;
                string          pathKey = FormatPathFunctions(result.CurrentKeys.Path, result.Operation.Parameters);

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

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

            if (subset.Paths == null)
            {
                throw new ArgumentNullException("No paths returned.");
            }

            if (styleOptions.Style == OpenApiStyle.GEAutocomplete)
            {
                // Content property and its schema $refs are unnecessary for autocomplete
                RemoveContent(subset);
            }

            CopyReferences(subset);

            return(subset);
        }
        private static async Task <OpenApiDocument> CreateOpenApiDocumentAsync(Uri csdlHref, OpenApiStyleOptions styleOptions = null)
        {
            var httpClient = CreateHttpClient();

            Stream csdl = await httpClient.GetStreamAsync(csdlHref.OriginalString);

            OpenApiDocument document = ConvertCsdlToOpenApi(styleOptions, csdl);

            return(document);
        }
        /// <summary>
        /// Get OpenApiDocument version of Microsoft Graph based on CSDL document
        /// </summary>
        /// <param name="graphUri">The uri of the Microsoft Graph metadata doc.</param>
        /// <param name="forceRefresh">Don't read from in-memory cache.</param>
        /// <param name="styleOptions">Optional modal object containing the required styling options.</param>
        /// <returns>Instance of an OpenApiDocument</returns>
        public static async Task <OpenApiDocument> GetGraphOpenApiDocumentAsync(string graphUri, bool forceRefresh, OpenApiStyleOptions styleOptions = null)
        {
            var csdlHref = new Uri(graphUri);

            if (!forceRefresh && _OpenApiDocuments.TryGetValue(csdlHref, out OpenApiDocument doc))
            {
                return(doc);
            }

            OpenApiDocument source = await CreateOpenApiDocumentAsync(csdlHref, styleOptions);

            _OpenApiDocuments[csdlHref] = source;
            return(source);
        }