public async Task <IActionResult> Get( [FromQuery] string operationIds = null, [FromQuery] string tags = null, [FromQuery] string openApiVersion = "2", [FromQuery] string title = "Partial Graph API", [FromQuery] OpenApiStyle style = OpenApiStyle.Plain, [FromQuery] string format = "yaml", [FromQuery] string graphVersion = "v1.0", [FromQuery] bool forceRefresh = false) { var predicate = OpenApiService.CreatePredicate(operationIds, tags); if (predicate == null) { return(new BadRequestResult()); } OpenApiDocument source = await OpenApiService.GetGraphOpenApiDocument(graphVersion, forceRefresh); var subsetOpenApiDocument = OpenApiService.CreateFilteredDocument(source, title, graphVersion, predicate); subsetOpenApiDocument = OpenApiService.ApplyStyle(style, subsetOpenApiDocument); var stream = OpenApiService.SerializeOpenApiDocument(subsetOpenApiDocument, openApiVersion, format); return(new FileStreamResult(stream, "application/json")); }
/// <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(OpenApiStyle style, OpenApiDocument subsetOpenApiDocument) { if (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 (style == OpenApiStyle.PowerShell) { // Format the OperationId for Powershell cmdlet names generation var operationIdFormatter = new OperationIdPowershellFormatter(); walker = new OpenApiWalker(operationIdFormatter); 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); }
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()); } }
private void WriteIndex(string baseUrl, string graphVersion, string openApiVersion, string format, OpenApiDocument graphOpenApi, Stream stream, OpenApiStyle style) { var sw = new StreamWriter(stream); var indexSearch = new OpenApiOperationIndex(); var walker = new OpenApiWalker(indexSearch); walker.Walk(graphOpenApi); sw.AutoFlush = true; sw.WriteLine("<head>"); sw.WriteLine("<link rel='stylesheet' href='./stylesheet.css' />"); sw.WriteLine("</head>"); sw.WriteLine("<h1># OpenAPI Operations for Microsoft Graph</h1>"); sw.WriteLine("<b/>"); sw.WriteLine("<ul>"); foreach (var item in indexSearch.Index) { var target = $"{baseUrl}/openapi?tags={item.Key.Name}&openApiVersion={openApiVersion}&graphVersion={graphVersion}&format={format}&style={style}"; sw.WriteLine($"<li>{item.Key.Name} [<a href='{target}'>OpenApi</a>] [<a href='/swagger/index.html#url={target}'>Swagger UI</a>]</li>"); sw.WriteLine("<ul>"); foreach (var op in item.Value) { sw.WriteLine($"<li>{op.OperationId} [<a href='../../openapi?operationIds={op.OperationId}&openApiVersion={openApiVersion}&graphVersion={graphVersion}" + $"&format={format}&style={style}'>OpenAPI</a>]</li>"); } sw.WriteLine("</ul>"); } sw.WriteLine("</ul>"); sw.Dispose(); }
public OpenApiStyleOptions(OpenApiStyle style, string openApiVersion = null, string graphVersion = null, string openApiFormat = null) { Style = style; OpenApiVersion = openApiVersion; GraphVersion = graphVersion; OpenApiFormat = openApiFormat; SetStyleOptions(); }
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 })); } }
/// <summary> /// Update the OpenAPI document based on the style option /// </summary> /// <param name="style">The OpenApiStyle value.</param> /// <param name="subsetOpenApiDocument">The subset of an OpenAPI document.</param> /// <returns>An OpenAPI doc with the respective style applied.</returns> public static OpenApiDocument ApplyStyle(OpenApiStyle style, OpenApiDocument subsetOpenApiDocument) { if (style == OpenApiStyle.GEAutocomplete) { // Clone doc before making changes subsetOpenApiDocument = Clone(subsetOpenApiDocument); // The Content property and its schema $refs are unnecessary for autocomplete RemoveContent(subsetOpenApiDocument); } else if (style == OpenApiStyle.PowerShell || style == OpenApiStyle.PowerPlatform) { /* For Powershell and PowerPlatform Styles */ // Clone doc before making changes subsetOpenApiDocument = Clone(subsetOpenApiDocument); // Remove AnyOf var anyOfRemover = new AnyOfRemover(); var walker = new OpenApiWalker(anyOfRemover); walker.Walk(subsetOpenApiDocument); if (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; } // Remove the root path to make AutoREST happy subsetOpenApiDocument.Paths.Remove("/"); // Temp. fix - Escape the # character from description in // 'microsoft.graph.networkInterface' schema EscapePoundCharacter(subsetOpenApiDocument.Components); } } if (subsetOpenApiDocument.Paths == null || !subsetOpenApiDocument.Paths.Any()) { throw new ArgumentException("No paths found for the supplied parameters."); } return(subsetOpenApiDocument); }
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 void RemoveOperationDescriptionsInCreateFilteredDocument(OpenApiStyle style) { // Arrange var predicate = _openApiService.CreatePredicate(operationIds: null, tags: null, url: "/users/{user-id}/messages/{message-id}", source: _graphMockSource, graphVersion: GraphVersion); var subsetOpenApiDocument = _openApiService.CreateFilteredDocument(_graphMockSource, Title, GraphVersion, predicate); // Act subsetOpenApiDocument = _openApiService.ApplyStyle(style, subsetOpenApiDocument); var description = subsetOpenApiDocument.Paths .FirstOrDefault().Value .Operations[OperationType.Get] .Description; // Assert Assert.Null(description); }
public IActionResult Get(string version = "v1.0", [FromQuery] string operationIds = null, [FromQuery] string tags = null, [FromQuery] string openApiVersion = "2", [FromQuery] string title = "Partial Graph API", [FromQuery] OpenApiStyle style = OpenApiStyle.Plain, [FromQuery] string format = "yaml") { OpenApiDocument graphOpenApi = null; switch (version) { case "v1.0": graphOpenApi = FilterOpenApiService.GetGraphOpenApiV1(); break; case "beta": graphOpenApi = FilterOpenApiService.GetGraphOpenApiBeta(); break; default: return(new NotFoundResult()); } if (operationIds != null && tags != null) { return(new BadRequestResult()); } Func <OpenApiOperation, bool> predicate = null; 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(','); predicate = (o) => o.Tags.Any(t => tagsArray.Contains(t.Name)); } else { return(new NotFoundResult()); } var subsetOpenApiDocument = FilterOpenApiService.CreateFilteredDocument(title, version, graphOpenApi, predicate); FilterOpenApiService.CopyReferences(graphOpenApi, subsetOpenApiDocument); if (style == OpenApiStyle.PowerPlatform || style == OpenApiStyle.Powershell) { // Clone doc before making changes subsetOpenApiDocument = Clone(subsetOpenApiDocument); var anyOfRemover = new AnyOfRemover(); var walker = new OpenApiWalker(anyOfRemover); walker.Walk(subsetOpenApiDocument); } return(CreateResult(openApiVersion, subsetOpenApiDocument, format)); }
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 }); } }
public void ReturnStyledOpenApiDocumentInApplyStyleForAllOpenApiStyles(OpenApiStyle style, string url, OperationType operationType, string expectedOperationId = null) { // Arrange OpenApiDocument source = _graphBetaSource; // Act var predicate = OpenApiService.CreatePredicate(operationIds: null, tags: null, url: url, source: source) .GetAwaiter().GetResult(); var subsetOpenApiDocument = OpenApiService.CreateFilteredDocument(source, Title, GraphVersion, predicate); subsetOpenApiDocument = OpenApiService.ApplyStyle(style, subsetOpenApiDocument); // Assert if (style == OpenApiStyle.GEAutocomplete || style == OpenApiStyle.Plain) { var content = subsetOpenApiDocument.Paths[url] .Operations[operationType] .Responses["200"] .Content; Assert.Single(subsetOpenApiDocument.Paths); if (style == OpenApiStyle.GEAutocomplete) { Assert.Empty(content); } else // Plain { Assert.NotEmpty(content); } } else // PowerShell || PowerPlatform { if (operationType == OperationType.Post) { var anyOf = subsetOpenApiDocument.Paths[url] .Operations[operationType] .Responses["200"] .Content["application/json"] .Schema .AnyOf; Assert.Null(anyOf); } if (style == OpenApiStyle.PowerShell) { if (operationType == OperationType.Post) { var newOperationId = subsetOpenApiDocument.Paths[url] .Operations[operationType] .OperationId; Assert.Equal(expectedOperationId, newOperationId); } else if (operationType == OperationType.Patch) { var newOperationId = subsetOpenApiDocument.Paths[url] .Operations[operationType] .OperationId; Assert.Equal(expectedOperationId, newOperationId); } else if (operationType == OperationType.Put) { var newOperationId = subsetOpenApiDocument.Paths[url] .Operations[operationType] .OperationId; Assert.Equal(expectedOperationId, newOperationId); } } } }
/// <summary> /// Create a representation of the OpenApiDocument to return from an API /// </summary> /// <param name="subset">OpenAPI document</param> /// <param name="openApiVersion"></param> /// <param name="format">The format of the OpenAPI doc.</param> /// <param name="style">The styling preference of the OpenAPI doc.</param> /// <returns></returns> public static MemoryStream SerializeOpenApiDocument(OpenApiDocument subset, string openApiVersion, string format, OpenApiStyle style) { var stream = new MemoryStream(); var sr = new StreamWriter(stream); OpenApiWriterBase writer; if (format == "yaml") { if (style == OpenApiStyle.PowerPlatform) { writer = new OpenApiYamlWriter(sr, new OpenApiWriterSettings { ReferenceInline = ReferenceInlineSetting.InlineLocalReferences }); } else { writer = new OpenApiYamlWriter(sr); } } else { if (style == OpenApiStyle.PowerPlatform) { writer = new OpenApiJsonWriter(sr, new OpenApiWriterSettings { ReferenceInline = ReferenceInlineSetting.InlineLocalReferences }); } else { writer = new OpenApiJsonWriter(sr); } } if (openApiVersion == "2") { subset.SerializeAsV2(writer); } else { subset.SerializeAsV3(writer); } sr.Flush(); stream.Position = 0; return(stream); }
public void SetExplodePropertyToFalseInParametersWithStyleEqualsFormForAllStyles(OpenApiStyle style) { // Act var predicate = _openApiService.CreatePredicate(operationIds: null, tags: null, url: "/users/{user-id}/messages/{message-id}", source: _graphMockSource, graphVersion: GraphVersion); var subsetOpenApiDocument = _openApiService.CreateFilteredDocument(_graphMockSource, Title, GraphVersion, predicate); subsetOpenApiDocument = _openApiService.ApplyStyle(style, subsetOpenApiDocument); var parameter = subsetOpenApiDocument.Paths .FirstOrDefault().Value .Operations.FirstOrDefault().Value .Parameters.First(s => s.Name.Equals("$select")); // Assert Assert.False(parameter.Explode); }