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); }
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); }); }
/// <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 })); } }
/// <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); }