From 668c6d4c85d7b405e4f5f1ba54884a9dc2a65130 Mon Sep 17 00:00:00 2001 From: Waldek Mastykarz Date: Fri, 8 May 2026 14:33:27 +0200 Subject: [PATCH] Updates dependencies --- DevProxy.Abstractions/Data/MSGraphDb.cs | 11 +- .../DevProxy.Abstractions.csproj | 2 +- DevProxy.Abstractions/packages.lock.json | 22 +-- DevProxy.Plugins/DevProxy.Plugins.csproj | 6 +- .../Extensions/ApiCenterExtensions.cs | 14 +- .../Extensions/OpenApiDocumentExtensions.cs | 52 ++++-- .../Generation/ApiCenterOnboardingPlugin.cs | 10 +- .../Generation/OpenApiSpecGeneratorPlugin.cs | 176 +++++++++++------- DevProxy.Plugins/Models/ApiCenterModels.cs | 2 +- .../ApiCenterMinimalPermissionsPlugin.cs | 4 +- .../ApiCenterProductionVersionPlugin.cs | 2 +- .../MinimalPermissionsGuidancePlugin.cs | 6 +- .../Reporting/MinimalPermissionsPlugin.cs | 6 +- DevProxy.Plugins/packages.lock.json | 70 +++---- DevProxy/DevProxy.csproj | 7 +- DevProxy/packages.lock.json | 103 +++++----- 16 files changed, 253 insertions(+), 240 deletions(-) diff --git a/DevProxy.Abstractions/Data/MSGraphDb.cs b/DevProxy.Abstractions/Data/MSGraphDb.cs index eaced4e8..4d17c59d 100644 --- a/DevProxy.Abstractions/Data/MSGraphDb.cs +++ b/DevProxy.Abstractions/Data/MSGraphDb.cs @@ -5,8 +5,7 @@ using DevProxy.Abstractions.Utils; using Microsoft.Data.Sqlite; using Microsoft.Extensions.Logging; -using Microsoft.OpenApi.Models; -using Microsoft.OpenApi.Readers; +using Microsoft.OpenApi; using System.Net; using System.Net.Http.Headers; @@ -153,7 +152,7 @@ private async Task FillDataAsync(CancellationToken cancellationToken) _logger.LogTrace("Endpoint {GraphVersion}{Key}...", graphVersion, path.Key); // Get the GET operation for this path - var getOperation = path.Value.Operations.FirstOrDefault(o => o.Key == OperationType.Get).Value; + var getOperation = path.Value.Operations?.FirstOrDefault(o => o.Key == HttpMethod.Get).Value; if (getOperation == null) { _logger.LogTrace("No GET operation found for {GraphVersion}{Key}", graphVersion, path.Key); @@ -161,7 +160,7 @@ private async Task FillDataAsync(CancellationToken cancellationToken) } // Check if the GET operation has a $select parameter - var hasSelect = getOperation.Parameters.Any(p => p.Name == "$select"); + var hasSelect = getOperation.Parameters?.Any(p => p.Name == "$select") == true; _logger.LogTrace("Inserting endpoint {GraphVersion}{Key} with hasSelect={HasSelect}...", graphVersion, path.Key, hasSelect); pathParam.Value = path.Key; @@ -275,8 +274,8 @@ private async Task LoadOpenAPIFilesAsync(string folder, CancellationToken cancel try { await using var fileStream = file.OpenRead(); - var openApiDocument = await new OpenApiStreamReader().ReadAsync(fileStream, cancellationToken); - _openApiDocuments[version] = openApiDocument.OpenApiDocument; + var readResult = await OpenApiDocument.LoadAsync(fileStream, "yaml", cancellationToken: cancellationToken); + _openApiDocuments[version] = readResult.Document!; _logger.LogDebug("Added OpenAPI file {FilePath} for {Version}", filePath, version); } diff --git a/DevProxy.Abstractions/DevProxy.Abstractions.csproj b/DevProxy.Abstractions/DevProxy.Abstractions.csproj index 9c64b88f..0858c3cd 100644 --- a/DevProxy.Abstractions/DevProxy.Abstractions.csproj +++ b/DevProxy.Abstractions/DevProxy.Abstractions.csproj @@ -19,7 +19,7 @@ - + diff --git a/DevProxy.Abstractions/packages.lock.json b/DevProxy.Abstractions/packages.lock.json index 6cddadd2..a1e448e3 100644 --- a/DevProxy.Abstractions/packages.lock.json +++ b/DevProxy.Abstractions/packages.lock.json @@ -64,15 +64,11 @@ "Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.7" } }, - "Microsoft.OpenApi.Readers": { + "Microsoft.OpenApi": { "type": "Direct", - "requested": "[1.6.29, )", - "resolved": "1.6.29", - "contentHash": "GYtIRq1iUO6zwnrUa63ELQHHSgMXRAxkXhtSyOKvH8tVPXql0HOjPTgJv7ZzGuzEzCIDZNujKUjrfi+36xxDSg==", - "dependencies": { - "Microsoft.OpenApi": "1.6.29", - "SharpYaml": "2.1.1" - } + "requested": "[3.5.3, )", + "resolved": "3.5.3", + "contentHash": "V/PpjnjbnKsLTy0Bp3euE3l9vAJff/ZgaaOclKLZh6aGkmkWix008MidGVORHlbYfpu7pRMdvo5bGwbiDMFyxg==" }, "Newtonsoft.Json.Schema": { "type": "Direct", @@ -275,21 +271,11 @@ "resolved": "10.0.7", "contentHash": "D5M0Jr551iTgwkZMN9rm0pSkgNLj5quUWQUmQPMZh7k/bnvZTnXRGfE2KuvXf1EEjt/ofD9yw9IumpgdP9QCnw==" }, - "Microsoft.OpenApi": { - "type": "Transitive", - "resolved": "1.6.29", - "contentHash": "mLoYWWwRP3C7Iier4dDzepq0kw1Tpdlh+B6KZ1SNcgq/tWI8aC41WYvIsJpsAS4UG1IV4c0AAnZs8qCPobzBkQ==" - }, "Newtonsoft.Json": { "type": "Transitive", "resolved": "13.0.3", "contentHash": "HrC5BXdl00IP9zeV+0Z848QWPAoCr9P3bDEZguI+gkLcBKAOxix/tLEAAHC+UvDNPv4a2d18lOReHMOagPa+zQ==" }, - "SharpYaml": { - "type": "Transitive", - "resolved": "2.1.1", - "contentHash": "BISoFuW2AwZYXxrZGaBnedo21BvrdgC4kkWd6QYrOdhOGSsZB0RSqcBw09l9caUE1g3sykJoRfSbtSzZS6tYig==" - }, "SQLitePCLRaw.bundle_e_sqlite3": { "type": "Transitive", "resolved": "2.1.11", diff --git a/DevProxy.Plugins/DevProxy.Plugins.csproj b/DevProxy.Plugins/DevProxy.Plugins.csproj index 8fffbe75..214dcfd4 100644 --- a/DevProxy.Plugins/DevProxy.Plugins.csproj +++ b/DevProxy.Plugins/DevProxy.Plugins.csproj @@ -32,11 +32,11 @@ false runtime - + false runtime - + false runtime @@ -56,7 +56,7 @@ false runtime - + false runtime diff --git a/DevProxy.Plugins/Extensions/ApiCenterExtensions.cs b/DevProxy.Plugins/Extensions/ApiCenterExtensions.cs index 979b6fa2..4c2bbddc 100644 --- a/DevProxy.Plugins/Extensions/ApiCenterExtensions.cs +++ b/DevProxy.Plugins/Extensions/ApiCenterExtensions.cs @@ -5,7 +5,7 @@ using DevProxy.Abstractions.Proxy; using DevProxy.Plugins.ApiCenter; using Microsoft.Extensions.Logging; -using Microsoft.OpenApi.Readers; +using Microsoft.OpenApi; using System.Diagnostics; #pragma warning disable IDE0130 @@ -115,7 +115,7 @@ internal static async Task> GetApiDefinitionsB continue; } - if (!definition.Definition.Servers.Any()) + if (definition.Definition.Servers is null || !definition.Definition.Servers.Any()) { logger.LogDebug("No servers found for API definition {DefinitionId}", definition.Id); continue; @@ -123,7 +123,10 @@ internal static async Task> GetApiDefinitionsB foreach (var server in definition.Definition.Servers) { - apiDefinitions[server.Url] = definition; + if (server.Url is not null) + { + apiDefinitions[server.Url] = definition; + } } } } @@ -153,7 +156,7 @@ internal static IEnumerable GetUrls(this Api api) d.Properties?.Server?.RuntimeUri ?? []) ?? []; var urlsFromVersions = api.Versions?.SelectMany(v => v.Definitions?.SelectMany(d => - d.Definition?.Servers.Select(s => s.Url) ?? []) ?? []) ?? []; + d.Definition?.Servers?.Select(s => s.Url).Where(u => u is not null).Cast() ?? []) ?? []) ?? []; return new HashSet([.. urlsFromDeployments, .. urlsFromVersions]); } @@ -282,7 +285,8 @@ internal static async Task LoadOpenApiDefinitionAsync(this ApiDefinition apiDefi try { - apiDefinition.Definition = new OpenApiStringReader().Read(exportResult.Value, out _); + var readResult = OpenApiDocument.Parse(exportResult.Value ?? "", null); + apiDefinition.Definition = readResult.Document; } catch (Exception ex) { diff --git a/DevProxy.Plugins/Extensions/OpenApiDocumentExtensions.cs b/DevProxy.Plugins/Extensions/OpenApiDocumentExtensions.cs index 8adfc6c7..0677769c 100644 --- a/DevProxy.Plugins/Extensions/OpenApiDocumentExtensions.cs +++ b/DevProxy.Plugins/Extensions/OpenApiDocumentExtensions.cs @@ -10,7 +10,7 @@ using System.Text.RegularExpressions; #pragma warning disable IDE0130 -namespace Microsoft.OpenApi.Models; +namespace Microsoft.OpenApi; #pragma warning restore IDE0130 static class OpenApiDocumentExtensions @@ -20,7 +20,7 @@ public static ApiPermissionsInfo CheckMinimalPermissions(this OpenApiDocument op { if (logger.IsEnabled(LogLevel.Information)) { - logger.LogInformation("Checking minimal permissions for API {ApiName}...", openApiDocument.Servers.First().Url); + logger.LogInformation("Checking minimal permissions for API {ApiName}...", openApiDocument.Servers?.First().Url); } var tokenPermissions = new List(); @@ -62,7 +62,19 @@ public static ApiPermissionsInfo CheckMinimalPermissions(this OpenApiDocument op } // get allowed scopes for the operation - if (!Enum.TryParse(method, true, out var operationType)) + var httpMethod = method.ToUpperInvariant() switch + { + "GET" => HttpMethod.Get, + "PUT" => HttpMethod.Put, + "POST" => HttpMethod.Post, + "DELETE" => HttpMethod.Delete, + "OPTIONS" => HttpMethod.Options, + "HEAD" => HttpMethod.Head, + "PATCH" => HttpMethod.Patch, + "TRACE" => HttpMethod.Trace, + _ => null + }; + if (httpMethod is null) { errors.Add(new() { @@ -83,7 +95,7 @@ public static ApiPermissionsInfo CheckMinimalPermissions(this OpenApiDocument op continue; } - if (!pathItem.Value.Value.Operations.TryGetValue(operationType, out var operation)) + if (pathItem.Value.Value.Operations?.TryGetValue(httpMethod, out var operation) != true) { errors.Add(new() { @@ -93,7 +105,7 @@ public static ApiPermissionsInfo CheckMinimalPermissions(this OpenApiDocument op continue; } - var scopes = operation.GetEffectiveScopes(openApiDocument, logger, schemeName); + var scopes = operation!.GetEffectiveScopes(openApiDocument, logger, schemeName); if (scopes.Length != 0) { operationsAndScopes[$"{method} {pathItem.Value.Key}"] = scopes; @@ -101,7 +113,7 @@ public static ApiPermissionsInfo CheckMinimalPermissions(this OpenApiDocument op operationsFromRequests.Add(new() { - Method = operationType.ToString().ToUpperInvariant(), + Method = httpMethod.Method.ToUpperInvariant(), OriginalUrl = url, TokenizedUrl = pathItem.Value.Key }); @@ -126,13 +138,13 @@ [.. operationsFromRequests return permissionsInfo; } - public static KeyValuePair? FindMatchingPathItem(this OpenApiDocument openApiDocument, string requestUrl, ILogger logger) + public static KeyValuePair? FindMatchingPathItem(this OpenApiDocument openApiDocument, string requestUrl, ILogger logger) { - foreach (var server in openApiDocument.Servers) + foreach (var server in openApiDocument.Servers ?? []) { logger.LogDebug("Checking server URL {ServerUrl}...", server.Url); - if (!UrlMatchesServerUrl(requestUrl, server.Url)) + if (server.Url is null || !UrlMatchesServerUrl(requestUrl, server.Url)) { logger.LogDebug("Request URL {RequestUrl} does not match server URL {ServerUrl}", requestUrl, server.Url); continue; @@ -193,8 +205,8 @@ [.. operationsFromRequests public static string[] GetEffectiveScopes(this OpenApiOperation operation, OpenApiDocument openApiDocument, ILogger logger, string? schemeName) { - var oauth2Scheme = openApiDocument.GetOAuth2Schemes(schemeName).FirstOrDefault(); - if (oauth2Scheme is null) + var oauth2Entry = openApiDocument.GetOAuth2Schemes(schemeName).FirstOrDefault(); + if (oauth2Entry.Value is null) { if (string.IsNullOrWhiteSpace(schemeName)) { @@ -207,12 +219,14 @@ public static string[] GetEffectiveScopes(this OpenApiOperation operation, OpenA return []; } + var schemeRef = new OpenApiSecuritySchemeReference(oauth2Entry.Key, openApiDocument); + var globalScopes = Array.Empty(); - var globalOAuth2Requirement = openApiDocument.SecurityRequirements - .FirstOrDefault(req => req.ContainsKey(oauth2Scheme)); + var globalOAuth2Requirement = openApiDocument.Security? + .FirstOrDefault(req => req.ContainsKey(schemeRef)); if (globalOAuth2Requirement is not null) { - globalScopes = [.. globalOAuth2Requirement[oauth2Scheme]]; + globalScopes = [.. globalOAuth2Requirement[schemeRef]]; } if (operation.Security is null) @@ -222,8 +236,8 @@ public static string[] GetEffectiveScopes(this OpenApiOperation operation, OpenA } var operationOAuth2Requirement = operation.Security - .Where(req => req.ContainsKey(oauth2Scheme)) - .SelectMany(req => req[oauth2Scheme]); + .Where(req => req.ContainsKey(schemeRef)) + .SelectMany(req => req[schemeRef]); if (operationOAuth2Requirement is not null) { return [.. operationOAuth2Requirement]; @@ -232,13 +246,13 @@ public static string[] GetEffectiveScopes(this OpenApiOperation operation, OpenA return []; } - public static OpenApiSecurityScheme[] GetOAuth2Schemes(this OpenApiDocument openApiDocument, string? schemeName) + public static KeyValuePair[] GetOAuth2Schemes(this OpenApiDocument openApiDocument, string? schemeName) { - var schemes = openApiDocument.Components.SecuritySchemes + var schemes = openApiDocument.Components?.SecuritySchemes? .Where(s => s.Value.Type == SecuritySchemeType.OAuth2 && (string.IsNullOrWhiteSpace(schemeName) || string.Equals(schemeName, s.Key, StringComparison.Ordinal))); - return [.. schemes.Select(s => s.Value)]; + return [.. schemes ?? []]; } private static bool UrlMatchesServerUrl(string absoluteUrl, string serverUrl) diff --git a/DevProxy.Plugins/Generation/ApiCenterOnboardingPlugin.cs b/DevProxy.Plugins/Generation/ApiCenterOnboardingPlugin.cs index d0c146e6..ed6dbcbd 100644 --- a/DevProxy.Plugins/Generation/ApiCenterOnboardingPlugin.cs +++ b/DevProxy.Plugins/Generation/ApiCenterOnboardingPlugin.cs @@ -10,7 +10,7 @@ using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; -using Microsoft.OpenApi.Models; +using Microsoft.OpenApi; using System.Diagnostics; namespace DevProxy.Plugins.Generation; @@ -157,9 +157,9 @@ public override async Task AfterRecordingStopAsync(RecordingArgs e, Cancellation continue; } - var operation = pathItem.Value.Value.Operations.FirstOrDefault(x => - x.Key.ToString().Equals(method, StringComparison.OrdinalIgnoreCase)).Value; - if (operation is null) + var operation = pathItem.Value.Value.Operations?.FirstOrDefault(x => + x.Key.Method.Equals(method, StringComparison.OrdinalIgnoreCase)); + if (operation is null || operation.Value.Value is null) { Logger.LogDebug("No matching operation found for {Method} {Url}. Adding new API...", method, url); newApis.Add(new(method, url)); @@ -170,7 +170,7 @@ public override async Task AfterRecordingStopAsync(RecordingArgs e, Cancellation { MethodAndUrl = $"{method} {url}", ApiDefinitionId = apiDefinition.Id, - OperationId = operation.OperationId + OperationId = operation.Value.Value.OperationId ?? "" }); } diff --git a/DevProxy.Plugins/Generation/OpenApiSpecGeneratorPlugin.cs b/DevProxy.Plugins/Generation/OpenApiSpecGeneratorPlugin.cs index f43d6429..4c395609 100644 --- a/DevProxy.Plugins/Generation/OpenApiSpecGeneratorPlugin.cs +++ b/DevProxy.Plugins/Generation/OpenApiSpecGeneratorPlugin.cs @@ -9,11 +9,7 @@ using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Logging; using Microsoft.OpenApi; -using Microsoft.OpenApi.Any; -using Microsoft.OpenApi.Extensions; -using Microsoft.OpenApi.Interfaces; -using Microsoft.OpenApi.Models; -using Microsoft.OpenApi.Writers; +using System.Text.Json.Nodes; using System.Collections.Specialized; using System.Globalization; using System.Text.Json; @@ -40,7 +36,9 @@ public enum SpecVersion { #pragma warning disable CA1707 v2_0, - v3_0 + v3_0, + v3_1, + v3_2 #pragma warning restore CA1707 } @@ -120,6 +118,11 @@ request.Context.Session is null || { var pathItem = GetOpenApiPathItem(request.Context.Session); var parametrizedPath = ParametrizePath(pathItem, request.Context.Session.HttpClient.Request.RequestUri); + if (pathItem.Operations is null) + { + Logger.LogDebug("No operations found for request {MethodAndUrlString}. Skipping...", methodAndUrlString); + continue; + } var operationInfo = pathItem.Operations.First(); operationInfo.Value.OperationId = await GetOperationIdAsync( operationInfo.Key.ToString(), @@ -145,21 +148,33 @@ request.Context.Session is null || var generatedOpenApiSpecs = new Dictionary(); foreach (var openApiDoc in openApiDocs) { + if (openApiDoc.Servers is null || !openApiDoc.Servers.Any()) + { + Logger.LogDebug("OpenAPI doc has no servers. Skipping..."); + continue; + } var server = openApiDoc.Servers.First(); + if (string.IsNullOrEmpty(server.Url)) + { + Logger.LogDebug("Server URL is null or empty. Skipping..."); + continue; + } var fileName = GetFileNameFromServerUrl(server.Url, Configuration.SpecFormat); var openApiSpecVersion = Configuration.SpecVersion switch { SpecVersion.v2_0 => OpenApiSpecVersion.OpenApi2_0, SpecVersion.v3_0 => OpenApiSpecVersion.OpenApi3_0, + SpecVersion.v3_1 => OpenApiSpecVersion.OpenApi3_1, + SpecVersion.v3_2 => OpenApiSpecVersion.OpenApi3_2, _ => OpenApiSpecVersion.OpenApi3_0 }; var docString = Configuration.SpecFormat switch { - SpecFormat.Json => openApiDoc.SerializeAsJson(openApiSpecVersion), - SpecFormat.Yaml => openApiDoc.SerializeAsYaml(openApiSpecVersion), - _ => openApiDoc.SerializeAsJson(openApiSpecVersion) + SpecFormat.Json => await openApiDoc.SerializeAsJsonAsync(openApiSpecVersion, cancellationToken), + SpecFormat.Yaml => await openApiDoc.SerializeAsYamlAsync(openApiSpecVersion, cancellationToken), + _ => await openApiDoc.SerializeAsJsonAsync(openApiSpecVersion, cancellationToken) }; Logger.LogDebug(" Writing OpenAPI spec to {FileName}...", fileName); @@ -218,14 +233,14 @@ private OpenApiPathItem GetOpenApiPathItem(SessionEventArgs session) var method = request.Method?.ToUpperInvariant() switch { - "DELETE" => OperationType.Delete, - "GET" => OperationType.Get, - "HEAD" => OperationType.Head, - "OPTIONS" => OperationType.Options, - "PATCH" => OperationType.Patch, - "POST" => OperationType.Post, - "PUT" => OperationType.Put, - "TRACE" => OperationType.Trace, + "DELETE" => HttpMethod.Delete, + "GET" => HttpMethod.Get, + "HEAD" => HttpMethod.Head, + "OPTIONS" => HttpMethod.Options, + "PATCH" => HttpMethod.Patch, + "POST" => HttpMethod.Post, + "PUT" => HttpMethod.Put, + "TRACE" => HttpMethod.Trace, _ => throw new NotSupportedException($"Method {request.Method} is not supported") }; var operation = new OpenApiOperation @@ -240,7 +255,7 @@ private OpenApiPathItem GetOpenApiPathItem(SessionEventArgs session) SetRequestBody(operation, request); SetResponseFromSession(operation, response); - path.Operations.Add(method, operation); + path.Operations?.Add(method, operation); return path; } @@ -260,13 +275,13 @@ private void SetRequestBody(OpenApiOperation operation, Request request) } Logger.LogDebug(" Processing request body..."); - operation.RequestBody = new() + operation.RequestBody = new OpenApiRequestBody { - Content = new Dictionary + Content = new Dictionary { { GetMediaType(request.ContentType), - new() + new OpenApiMediaType { Schema = GetSchemaFromBody(GetMediaType(request.ContentType), request.BodyString) } @@ -300,12 +315,12 @@ private void SetParametersFromRequestHeaders(OpenApiOperation operation, HeaderC continue; } - operation.Parameters.Add(new() + operation.Parameters?.Add(new OpenApiParameter() { Name = header.Name, In = ParameterLocation.Header, Required = false, - Schema = new() { Type = "string" } + Schema = new OpenApiSchema() { Type = JsonSchemaType.String } }); Logger.LogDebug(" Added header {HeaderName}", header.Name); } @@ -334,11 +349,11 @@ private void SetParametersFromQueryString(OpenApiOperation operation, NameValueC Name = key, In = ParameterLocation.Query, Required = isRequired, - Schema = new() { Type = "string" } + Schema = new OpenApiSchema() { Type = JsonSchemaType.String } }; SetParameterDefault(parameter, value); - operation.Parameters.Add(parameter); + operation.Parameters?.Add(parameter); Logger.LogDebug(" Added query string parameter {ParameterKey}", key); } } @@ -349,7 +364,10 @@ private static void SetParameterDefault(OpenApiParameter parameter, object? valu { return; } - parameter.Schema.Default = new OpenApiString(value.ToString()); + if (parameter.Schema is OpenApiSchema schema) + { + schema.Default = JsonValue.Create(value.ToString()); + } } private void SetResponseFromSession(OpenApiOperation operation, Response response) @@ -371,7 +389,7 @@ private void SetResponseFromSession(OpenApiOperation operation, Response respons { Logger.LogDebug(" Response has body"); - openApiResponse.Content.Add(GetMediaType(response.ContentType), new() + openApiResponse.Content?.Add(GetMediaType(response.ContentType), new OpenApiMediaType() { Schema = GetSchemaFromBody(GetMediaType(response.ContentType), response.BodyString) }); @@ -400,15 +418,15 @@ private void SetResponseFromSession(OpenApiOperation operation, Response respons continue; } - if (openApiResponse.Headers.ContainsKey(header.Name)) + if (openApiResponse.Headers?.ContainsKey(header.Name) == true) { Logger.LogDebug(" Header {HeaderName} already exists in response", header.Name); continue; } - openApiResponse.Headers.Add(header.Name, new() + openApiResponse.Headers?.Add(header.Name, new OpenApiHeader() { - Schema = new() { Type = "string" } + Schema = new OpenApiSchema() { Type = JsonSchemaType.String } }); Logger.LogDebug(" Added header {HeaderName}", header.Name); } @@ -418,7 +436,7 @@ private void SetResponseFromSession(OpenApiOperation operation, Response respons Logger.LogDebug(" Response doesn't have headers"); } - operation.Responses.Add(responseCode, openApiResponse); + operation.Responses?.Add(responseCode, openApiResponse); } private OpenApiSchema? GetSchemaFromBody(string? contentType, string body) @@ -437,7 +455,7 @@ private void SetResponseFromSession(OpenApiOperation operation, Response respons Logger.LogDebug(" Ignoring response types"); return new() { - Type = "string" + Type = JsonSchemaType.String }; } @@ -450,7 +468,7 @@ private void SetResponseFromSession(OpenApiOperation operation, Response respons private void AddOrMergePathItem(List openApiDocs, OpenApiPathItem pathItem, Uri requestUri, string parametrizedPath) { var serverUrl = requestUri.GetLeftPart(UriPartial.Authority); - var openApiDoc = openApiDocs.FirstOrDefault(d => d.Servers.Any(s => s.Url == serverUrl)); + var openApiDoc = openApiDocs.FirstOrDefault(d => d.Servers?.Any(s => s.Url == serverUrl) == true); if (openApiDoc is null) { @@ -491,31 +509,34 @@ private void AddOrMergePathItem(List openApiDocs, OpenApiPathIt } Logger.LogDebug(" Merging path {ParametrizedPath} into OpenAPI spec...", parametrizedPath); - var operation = pathItem.Operations.First(); - AddOrMergeOperation(value, operation.Key, operation.Value); + var operation = pathItem.Operations?.First(); + if (operation is not null) + { + AddOrMergeOperation((OpenApiPathItem)value, operation.Value.Key, operation.Value.Value); + } } - private void AddOrMergeOperation(OpenApiPathItem pathItem, OperationType operationType, OpenApiOperation apiOperation) + private void AddOrMergeOperation(OpenApiPathItem pathItem, HttpMethod httpMethod, OpenApiOperation apiOperation) { - if (!pathItem.Operations.TryGetValue(operationType, out var value)) + if (pathItem.Operations?.TryGetValue(httpMethod, out var value) != true) { - Logger.LogDebug(" Adding operation {OperationType} to path...", operationType); + Logger.LogDebug(" Adding operation {OperationType} to path...", httpMethod); - pathItem.AddOperation(operationType, apiOperation); + pathItem.AddOperation(httpMethod, apiOperation); // since we've just added the operation, we're done return; } - Logger.LogDebug(" Merging operation {OperationType} into path...", operationType); + Logger.LogDebug(" Merging operation {OperationType} into path...", httpMethod); - var operation = value; + var operation = value!; AddOrMergeParameters(operation, apiOperation.Parameters); - AddOrMergeRequestBody(operation, apiOperation.RequestBody); + AddOrMergeRequestBody(operation, (OpenApiRequestBody?)apiOperation.RequestBody); AddOrMergeResponse(operation, apiOperation.Responses); } - private void AddOrMergeParameters(OpenApiOperation operation, IList parameters) + private void AddOrMergeParameters(OpenApiOperation operation, IList? parameters) { if (parameters is null || !parameters.Any()) { @@ -527,11 +548,11 @@ private void AddOrMergeParameters(OpenApiOperation operation, IList p.Name == parameter.Name && p.In == parameter.In); + var paramFromOperation = operation.Parameters?.FirstOrDefault(p => p.Name == parameter.Name && p.In == parameter.In); if (paramFromOperation is null) { Logger.LogDebug(" Adding parameter {ParameterName} to operation...", parameter.Name); - operation.Parameters.Add(parameter); + operation.Parameters?.Add(parameter); continue; } @@ -540,7 +561,7 @@ private void AddOrMergeParameters(OpenApiOperation operation, IList() + }; + } + operation.RequestBody.Content!.Add(requestBody.Content.FirstOrDefault()); // since we've just added the request body, we're done return; } @@ -611,7 +643,7 @@ private void AddOrMergeRequestBody(OpenApiOperation operation, OpenApiRequestBod MergeSchema(bodyFromOperation.Schema, requestBody.Content.FirstOrDefault().Value.Schema); } - private void AddOrMergeResponse(OpenApiOperation operation, OpenApiResponses apiResponses) + private void AddOrMergeResponse(OpenApiOperation operation, OpenApiResponses? apiResponses) { if (apiResponses is null) { @@ -622,31 +654,39 @@ private void AddOrMergeResponse(OpenApiOperation operation, OpenApiResponses api var apiResponseInfo = apiResponses.FirstOrDefault(); var apiResponseStatusCode = apiResponseInfo.Key; var apiResponse = apiResponseInfo.Value; - _ = operation.Responses.TryGetValue(apiResponseStatusCode, out var responseFromOperation); + IOpenApiResponse? responseFromOperation = null; + if (operation.Responses is not null) + { + _ = operation.Responses.TryGetValue(apiResponseStatusCode, out responseFromOperation); + } if (responseFromOperation is null) { Logger.LogDebug(" Adding response {ApiResponseStatusCode} to operation...", apiResponseStatusCode); - operation.Responses.Add(apiResponseStatusCode, apiResponse); + operation.Responses?.Add(apiResponseStatusCode, apiResponse); // since we've just added the response, we're done return; } - if (!apiResponse.Content.Any()) + if (apiResponse.Content is null || !apiResponse.Content.Any()) { Logger.LogDebug(" No response content to process"); return; } var apiResponseContentType = apiResponse.Content.First().Key; - _ = responseFromOperation.Content.TryGetValue(apiResponseContentType, out var contentFromOperation); + IOpenApiMediaType? contentFromOperation = null; + if (responseFromOperation.Content is not null) + { + _ = responseFromOperation.Content.TryGetValue(apiResponseContentType, out contentFromOperation); + } if (contentFromOperation is null) { Logger.LogDebug(" Adding response {ApiResponseContentType} to {ApiResponseStatusCode} to response...", apiResponseContentType, apiResponseStatusCode); - responseFromOperation.Content.Add(apiResponse.Content.First()); + responseFromOperation.Content?.Add(apiResponse.Content.First()); // since we've just added the content, we're done return; } @@ -680,12 +720,12 @@ private static string ParametrizePath(OpenApiPathItem pathItem, Uri requestUri) var parameterName = $"{previousSegment}-id"; segments[i] = $"{{{parameterName}}}{(requestUri.Segments[i].EndsWith('/') ? "/" : "")}"; - pathItem.Parameters.Add(new() + pathItem.Parameters?.Add(new OpenApiParameter { Name = parameterName, In = ParameterLocation.Path, Required = true, - Schema = new() { Type = "string" } + Schema = new OpenApiSchema { Type = JsonSchemaType.String } }); } else @@ -759,7 +799,7 @@ private static OpenApiSchema GetSchemaFromJsonString(string jsonString) { return new() { - Type = "object" + Type = JsonSchemaType.Object }; } } @@ -773,26 +813,26 @@ private static OpenApiSchema GetSchemaFromJsonElement(JsonElement jsonElement) #pragma warning restore IDE0010 { case JsonValueKind.String: - schema.Type = "string"; + schema.Type = JsonSchemaType.String; break; case JsonValueKind.Number: - schema.Type = "number"; + schema.Type = JsonSchemaType.Number; break; case JsonValueKind.True: case JsonValueKind.False: - schema.Type = "boolean"; + schema.Type = JsonSchemaType.Boolean; break; case JsonValueKind.Object: - schema.Type = "object"; + schema.Type = JsonSchemaType.Object; schema.Properties = jsonElement.EnumerateObject() - .ToDictionary(p => p.Name, p => GetSchemaFromJsonElement(p.Value)); + .ToDictionary(p => p.Name, p => (IOpenApiSchema)GetSchemaFromJsonElement(p.Value)); break; case JsonValueKind.Array: - schema.Type = "array"; + schema.Type = JsonSchemaType.Array; schema.Items = GetSchemaFromJsonElement(jsonElement.EnumerateArray().FirstOrDefault()); break; default: - schema.Type = "object"; + schema.Type = JsonSchemaType.Object; break; } diff --git a/DevProxy.Plugins/Models/ApiCenterModels.cs b/DevProxy.Plugins/Models/ApiCenterModels.cs index d2d3248b..0680258e 100644 --- a/DevProxy.Plugins/Models/ApiCenterModels.cs +++ b/DevProxy.Plugins/Models/ApiCenterModels.cs @@ -2,7 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -using Microsoft.OpenApi.Models; +using Microsoft.OpenApi; #pragma warning disable IDE0130 namespace DevProxy.Plugins.Models.ApiCenter; diff --git a/DevProxy.Plugins/Reporting/ApiCenterMinimalPermissionsPlugin.cs b/DevProxy.Plugins/Reporting/ApiCenterMinimalPermissionsPlugin.cs index cf212be1..a0ddb148 100644 --- a/DevProxy.Plugins/Reporting/ApiCenterMinimalPermissionsPlugin.cs +++ b/DevProxy.Plugins/Reporting/ApiCenterMinimalPermissionsPlugin.cs @@ -11,7 +11,7 @@ using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; -using Microsoft.OpenApi.Models; +using Microsoft.OpenApi; using System.Diagnostics; namespace DevProxy.Plugins.Reporting; @@ -253,7 +253,7 @@ private ApiPermissionsInfo CheckMinimalPermissions(IEnumerable reque { if (Logger.IsEnabled(LogLevel.Information)) { - Logger.LogInformation("Checking minimal permissions for API {ApiName}...", apiDefinition.Definition!.Servers.First().Url); + Logger.LogInformation("Checking minimal permissions for API {ApiName}...", apiDefinition.Definition!.Servers?.First().Url); } return apiDefinition.Definition!.CheckMinimalPermissions(requests, Logger, Configuration.SchemeName); diff --git a/DevProxy.Plugins/Reporting/ApiCenterProductionVersionPlugin.cs b/DevProxy.Plugins/Reporting/ApiCenterProductionVersionPlugin.cs index dabcb5c1..58368e80 100644 --- a/DevProxy.Plugins/Reporting/ApiCenterProductionVersionPlugin.cs +++ b/DevProxy.Plugins/Reporting/ApiCenterProductionVersionPlugin.cs @@ -152,7 +152,7 @@ public override async Task AfterRecordingStopAsync(RecordingArgs e, Cancellation continue; } - if (!definitionFromApiCenter.Definition.Servers.Any()) + if (definitionFromApiCenter.Definition.Servers is null || !definitionFromApiCenter.Definition.Servers.Any()) { Logger.LogDebug("No servers found for API definition {DefinitionId}", definitionFromApiCenter.Id); continue; diff --git a/DevProxy.Plugins/Reporting/MinimalPermissionsGuidancePlugin.cs b/DevProxy.Plugins/Reporting/MinimalPermissionsGuidancePlugin.cs index 090f831c..168d9257 100644 --- a/DevProxy.Plugins/Reporting/MinimalPermissionsGuidancePlugin.cs +++ b/DevProxy.Plugins/Reporting/MinimalPermissionsGuidancePlugin.cs @@ -8,8 +8,7 @@ using DevProxy.Plugins.Models; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Logging; -using Microsoft.OpenApi.Models; -using Microsoft.OpenApi.Readers; +using Microsoft.OpenApi; namespace DevProxy.Plugins.Reporting; @@ -256,7 +255,8 @@ private async Task> LoadApiSpecsAsync(string var fileContents = await File.ReadAllTextAsync(file, cancellationToken); fileContents = ProxyUtils.ReplaceVariables(fileContents, ProxyConfiguration.Env, v => $"{{{v}}}"); - var apiDefinition = new OpenApiStringReader().Read(fileContents, out _); + var readResult = OpenApiDocument.Parse(fileContents, null); + var apiDefinition = readResult.Document; if (apiDefinition is null) { continue; diff --git a/DevProxy.Plugins/Reporting/MinimalPermissionsPlugin.cs b/DevProxy.Plugins/Reporting/MinimalPermissionsPlugin.cs index 9e1dfbfe..1cad5fe1 100644 --- a/DevProxy.Plugins/Reporting/MinimalPermissionsPlugin.cs +++ b/DevProxy.Plugins/Reporting/MinimalPermissionsPlugin.cs @@ -8,8 +8,7 @@ using DevProxy.Plugins.Models; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Logging; -using Microsoft.OpenApi.Models; -using Microsoft.OpenApi.Readers; +using Microsoft.OpenApi; using System.Text.RegularExpressions; namespace DevProxy.Plugins.Reporting; @@ -191,7 +190,8 @@ private async Task> LoadApiSpecsAsync(string var fileContents = await File.ReadAllTextAsync(file, cancellationToken); fileContents = ProxyUtils.ReplaceVariables(fileContents, ProxyConfiguration.Env, v => $"{{{v}}}"); - var apiDefinition = new OpenApiStringReader().Read(fileContents, out _); + var readResult = OpenApiDocument.Parse(fileContents, null); + var apiDefinition = readResult.Document; if (apiDefinition is null) { continue; diff --git a/DevProxy.Plugins/packages.lock.json b/DevProxy.Plugins/packages.lock.json index cc45a04b..f78155e5 100644 --- a/DevProxy.Plugins/packages.lock.json +++ b/DevProxy.Plugins/packages.lock.json @@ -44,19 +44,19 @@ }, "Microsoft.IdentityModel.Protocols.OpenIdConnect": { "type": "Direct", - "requested": "[8.17.0, )", - "resolved": "8.17.0", - "contentHash": "8DuZM96o2epBioyp56Q+H8bdGwO8FnU4nQMa0c6pboe9+monH9PZGY+CHKmsdw90ObJ5OXtiKG1TWuLbJp2VvQ==", + "requested": "[8.18.0, )", + "resolved": "8.18.0", + "contentHash": "suO9qM+gTjIMmHiEwZFitx1Z0BROQwTT3BYJJCDM/+djBAolhXHVpZzTzIFAxkjgakJRNCRlZi9ecZ2g68Pn5w==", "dependencies": { - "Microsoft.IdentityModel.Protocols": "8.17.0", - "System.IdentityModel.Tokens.Jwt": "8.17.0" + "Microsoft.IdentityModel.Protocols": "8.18.0", + "System.IdentityModel.Tokens.Jwt": "8.18.0" } }, "Microsoft.OpenApi": { "type": "Direct", - "requested": "[1.6.29, )", - "resolved": "1.6.29", - "contentHash": "mLoYWWwRP3C7Iier4dDzepq0kw1Tpdlh+B6KZ1SNcgq/tWI8aC41WYvIsJpsAS4UG1IV4c0AAnZs8qCPobzBkQ==" + "requested": "[3.5.3, )", + "resolved": "3.5.3", + "contentHash": "V/PpjnjbnKsLTy0Bp3euE3l9vAJff/ZgaaOclKLZh6aGkmkWix008MidGVORHlbYfpu7pRMdvo5bGwbiDMFyxg==" }, "Newtonsoft.Json": { "type": "Direct", @@ -92,12 +92,12 @@ }, "System.IdentityModel.Tokens.Jwt": { "type": "Direct", - "requested": "[8.17.0, )", - "resolved": "8.17.0", - "contentHash": "nKikRYheDeSaXA3wGr2otwaiRFygBa25m+hc7MEomZVIEWZvKVqd8wgP9yn+8QpLRGgw//dUs4LErGx9gtVmAA==", + "requested": "[8.18.0, )", + "resolved": "8.18.0", + "contentHash": "JxKlBca3/eXeH4koAGjEXOwrBdtwyDXwHXdYT5TQunp64TcVBl4wBCfmlGwhSG017Q/Qrz24leLxV6v2eknnJg==", "dependencies": { - "Microsoft.IdentityModel.JsonWebTokens": "8.17.0", - "Microsoft.IdentityModel.Tokens": "8.17.0" + "Microsoft.IdentityModel.JsonWebTokens": "8.18.0", + "Microsoft.IdentityModel.Tokens": "8.18.0" } }, "Unobtanium.Web.Proxy": { @@ -388,49 +388,40 @@ }, "Microsoft.IdentityModel.Abstractions": { "type": "Transitive", - "resolved": "8.17.0", - "contentHash": "6NrxQGcZg6IunkN8K2F0UVMavNpfCjbjjjON7PYcL8FwI8aULKUreiHsRX/yaA8j3XsTJnQKUYpoQk5gBjULZw==" + "resolved": "8.18.0", + "contentHash": "8VUcDy66uw1GUC/ytyRJAUgGxydPu2rLtUbUAiniCHd5SMB/01Q28XgqFyxIqb3srz6HWTgSsZdDbkdVJr3LXQ==" }, "Microsoft.IdentityModel.JsonWebTokens": { "type": "Transitive", - "resolved": "8.17.0", - "contentHash": "JbFZ3OVwtvqcqgBL0cIkhRYbIP7u9GIUYLOgbNqLWtBtZY8tGDpdGyXMzUVX0gVHq1ovuHsKZrkVv+ziHEnBHw==", + "resolved": "8.18.0", + "contentHash": "ZUMJt3r1zOi67AVSfnh3u9hg9KCq06roOIX5gs7FqsucSZ/VTsI89DI9h2gHyU0xOtj/qVZV2ugWS6JlLMTwHQ==", "dependencies": { - "Microsoft.IdentityModel.Tokens": "8.17.0" + "Microsoft.IdentityModel.Tokens": "8.18.0" } }, "Microsoft.IdentityModel.Logging": { "type": "Transitive", - "resolved": "8.17.0", - "contentHash": "w1vjfri0BWqW7RkSZY3ZsqekNfIJJg5BQSFs2j+a+pCXOVrkezmJcn74pT3djwjXJh71577C6wJQgNc2UPz30w==", + "resolved": "8.18.0", + "contentHash": "c2l/VEtW1XI/ifcu49xzDwgrZZ0a0aX/TwCPC7mEHFQk/KixDgtSdjB5eDhYyCO38GJiRUjeRTz9aWCy1t55ww==", "dependencies": { - "Microsoft.IdentityModel.Abstractions": "8.17.0" + "Microsoft.IdentityModel.Abstractions": "8.18.0" } }, "Microsoft.IdentityModel.Protocols": { "type": "Transitive", - "resolved": "8.17.0", - "contentHash": "TYbO2KMvWvu8bxbEDCgzggNckCGjwr6NxFf2VYW7PpmCRbsoMNNgVYlCiRvy748t6gj5MJ8v/jcqWrcLMg6PaQ==", + "resolved": "8.18.0", + "contentHash": "kKimlJy4j5m9ZkX/RTp12+gvxzM+QU5H3h7zzdroTt0v10/7AQsHG4tqi3ixvNjx5PPY0JnbpBsNXC/Xb1+sgQ==", "dependencies": { - "Microsoft.IdentityModel.Tokens": "8.17.0" + "Microsoft.IdentityModel.Tokens": "8.18.0" } }, "Microsoft.IdentityModel.Tokens": { "type": "Transitive", - "resolved": "8.17.0", - "contentHash": "teaW35URIV2x78Tzk+dVJiC4M62/9mQoSEoDjDGoEZmcQa3H2rE+XQpm9Tmdo9KK1Lcrnve4zoyLavl69kCFGg==", + "resolved": "8.18.0", + "contentHash": "c6ksXXFj5oPPsl8pfsui5zv8Gs7uxrGetXCTc1p7k7Nue/C8iBMtAVgtRrH7Esqe596QWD7KS3exKYY1FJG2iw==", "dependencies": { "Microsoft.Extensions.Logging.Abstractions": "8.0.0", - "Microsoft.IdentityModel.Logging": "8.17.0" - } - }, - "Microsoft.OpenApi.Readers": { - "type": "Transitive", - "resolved": "1.6.29", - "contentHash": "GYtIRq1iUO6zwnrUa63ELQHHSgMXRAxkXhtSyOKvH8tVPXql0HOjPTgJv7ZzGuzEzCIDZNujKUjrfi+36xxDSg==", - "dependencies": { - "Microsoft.OpenApi": "1.6.29", - "SharpYaml": "2.1.1" + "Microsoft.IdentityModel.Logging": "8.18.0" } }, "Newtonsoft.Json.Schema": { @@ -460,11 +451,6 @@ "resolved": "7.1.0", "contentHash": "8paijHmWYO7zxSRNLlbDzzaFT7By827wIgdOrAg9q64+XasUYK8RCT3Y4mbISxeQ3iNdaK7wGeDmT2GWRtqRBQ==" }, - "SharpYaml": { - "type": "Transitive", - "resolved": "2.1.1", - "contentHash": "BISoFuW2AwZYXxrZGaBnedo21BvrdgC4kkWd6QYrOdhOGSsZB0RSqcBw09l9caUE1g3sykJoRfSbtSzZS6tYig==" - }, "SQLitePCLRaw.bundle_e_sqlite3": { "type": "Transitive", "resolved": "2.1.11", @@ -527,7 +513,7 @@ "Microsoft.Extensions.Configuration.Binder": "[10.0.7, )", "Microsoft.Extensions.Configuration.Json": "[10.0.7, )", "Microsoft.Extensions.Logging.Abstractions": "[10.0.7, )", - "Microsoft.OpenApi.Readers": "[1.6.29, )", + "Microsoft.OpenApi": "[3.5.3, )", "Newtonsoft.Json.Schema": "[4.0.1, )", "Scriban": "[7.1.0, )", "System.CommandLine": "[2.0.7, )", diff --git a/DevProxy/DevProxy.csproj b/DevProxy/DevProxy.csproj index a75ea783..3ec31dc2 100644 --- a/DevProxy/DevProxy.csproj +++ b/DevProxy/DevProxy.csproj @@ -34,15 +34,14 @@ - - + - + - + diff --git a/DevProxy/packages.lock.json b/DevProxy/packages.lock.json index 82e0a831..30b76abf 100644 --- a/DevProxy/packages.lock.json +++ b/DevProxy/packages.lock.json @@ -25,22 +25,12 @@ }, "Microsoft.IdentityModel.Protocols.OpenIdConnect": { "type": "Direct", - "requested": "[8.17.0, )", - "resolved": "8.17.0", - "contentHash": "8DuZM96o2epBioyp56Q+H8bdGwO8FnU4nQMa0c6pboe9+monH9PZGY+CHKmsdw90ObJ5OXtiKG1TWuLbJp2VvQ==", + "requested": "[8.18.0, )", + "resolved": "8.18.0", + "contentHash": "suO9qM+gTjIMmHiEwZFitx1Z0BROQwTT3BYJJCDM/+djBAolhXHVpZzTzIFAxkjgakJRNCRlZi9ecZ2g68Pn5w==", "dependencies": { - "Microsoft.IdentityModel.Protocols": "8.17.0", - "System.IdentityModel.Tokens.Jwt": "8.17.0" - } - }, - "Microsoft.OpenApi.Readers": { - "type": "Direct", - "requested": "[1.6.29, )", - "resolved": "1.6.29", - "contentHash": "GYtIRq1iUO6zwnrUa63ELQHHSgMXRAxkXhtSyOKvH8tVPXql0HOjPTgJv7ZzGuzEzCIDZNujKUjrfi+36xxDSg==", - "dependencies": { - "Microsoft.OpenApi": "1.6.29", - "SharpYaml": "2.1.1" + "Microsoft.IdentityModel.Protocols": "8.18.0", + "System.IdentityModel.Tokens.Jwt": "8.18.0" } }, "Microsoft.VisualStudio.Threading": { @@ -80,14 +70,14 @@ }, "Swashbuckle.AspNetCore": { "type": "Direct", - "requested": "[8.1.1, )", - "resolved": "8.1.1", - "contentHash": "HJHexmU0PiYevgTLvKjYkxEtclF2w4O7iTd3Ef3p6KeT0kcYLpkFVgCw6glpGS57h8769anv8G+NFi9Kge+/yw==", + "requested": "[10.1.7, )", + "resolved": "10.1.7", + "contentHash": "vgef8DPT411JU5JjHiDbr0WOxsIVuAvegPGtqmm4Na4JRl/264dfBJcGkiPHsAr5P+Vda+qN1rZKRtBl1rF9aA==", "dependencies": { - "Microsoft.Extensions.ApiDescription.Server": "6.0.5", - "Swashbuckle.AspNetCore.Swagger": "8.1.1", - "Swashbuckle.AspNetCore.SwaggerGen": "8.1.1", - "Swashbuckle.AspNetCore.SwaggerUI": "8.1.1" + "Microsoft.Extensions.ApiDescription.Server": "10.0.0", + "Swashbuckle.AspNetCore.Swagger": "10.1.7", + "Swashbuckle.AspNetCore.SwaggerGen": "10.1.7", + "Swashbuckle.AspNetCore.SwaggerUI": "10.1.7" } }, "System.CommandLine": { @@ -98,12 +88,12 @@ }, "System.IdentityModel.Tokens.Jwt": { "type": "Direct", - "requested": "[8.17.0, )", - "resolved": "8.17.0", - "contentHash": "nKikRYheDeSaXA3wGr2otwaiRFygBa25m+hc7MEomZVIEWZvKVqd8wgP9yn+8QpLRGgw//dUs4LErGx9gtVmAA==", + "requested": "[8.18.0, )", + "resolved": "8.18.0", + "contentHash": "JxKlBca3/eXeH4koAGjEXOwrBdtwyDXwHXdYT5TQunp64TcVBl4wBCfmlGwhSG017Q/Qrz24leLxV6v2eknnJg==", "dependencies": { - "Microsoft.IdentityModel.JsonWebTokens": "8.17.0", - "Microsoft.IdentityModel.Tokens": "8.17.0" + "Microsoft.IdentityModel.JsonWebTokens": "8.18.0", + "Microsoft.IdentityModel.Tokens": "8.18.0" } }, "Unobtanium.Web.Proxy": { @@ -190,8 +180,8 @@ }, "Microsoft.Extensions.ApiDescription.Server": { "type": "Transitive", - "resolved": "6.0.5", - "contentHash": "Ckb5EDBUNJdFWyajfXzUIMRkhf52fHZOQuuZg/oiu8y7zDCVwD0iHhew6MnThjHmevanpxL3f5ci2TtHQEN6bw==" + "resolved": "10.0.0", + "contentHash": "NCWCGiwRwje8773yzPQhvucYnnfeR+ZoB1VRIrIMp4uaeUNw7jvEPHij3HIbwCDuNCrNcphA00KSAR9yD9qmbg==" }, "Microsoft.Extensions.DependencyModel": { "type": "Transitive", @@ -217,45 +207,45 @@ }, "Microsoft.IdentityModel.Abstractions": { "type": "Transitive", - "resolved": "8.17.0", - "contentHash": "6NrxQGcZg6IunkN8K2F0UVMavNpfCjbjjjON7PYcL8FwI8aULKUreiHsRX/yaA8j3XsTJnQKUYpoQk5gBjULZw==" + "resolved": "8.18.0", + "contentHash": "8VUcDy66uw1GUC/ytyRJAUgGxydPu2rLtUbUAiniCHd5SMB/01Q28XgqFyxIqb3srz6HWTgSsZdDbkdVJr3LXQ==" }, "Microsoft.IdentityModel.JsonWebTokens": { "type": "Transitive", - "resolved": "8.17.0", - "contentHash": "JbFZ3OVwtvqcqgBL0cIkhRYbIP7u9GIUYLOgbNqLWtBtZY8tGDpdGyXMzUVX0gVHq1ovuHsKZrkVv+ziHEnBHw==", + "resolved": "8.18.0", + "contentHash": "ZUMJt3r1zOi67AVSfnh3u9hg9KCq06roOIX5gs7FqsucSZ/VTsI89DI9h2gHyU0xOtj/qVZV2ugWS6JlLMTwHQ==", "dependencies": { - "Microsoft.IdentityModel.Tokens": "8.17.0" + "Microsoft.IdentityModel.Tokens": "8.18.0" } }, "Microsoft.IdentityModel.Logging": { "type": "Transitive", - "resolved": "8.17.0", - "contentHash": "w1vjfri0BWqW7RkSZY3ZsqekNfIJJg5BQSFs2j+a+pCXOVrkezmJcn74pT3djwjXJh71577C6wJQgNc2UPz30w==", + "resolved": "8.18.0", + "contentHash": "c2l/VEtW1XI/ifcu49xzDwgrZZ0a0aX/TwCPC7mEHFQk/KixDgtSdjB5eDhYyCO38GJiRUjeRTz9aWCy1t55ww==", "dependencies": { - "Microsoft.IdentityModel.Abstractions": "8.17.0" + "Microsoft.IdentityModel.Abstractions": "8.18.0" } }, "Microsoft.IdentityModel.Protocols": { "type": "Transitive", - "resolved": "8.17.0", - "contentHash": "TYbO2KMvWvu8bxbEDCgzggNckCGjwr6NxFf2VYW7PpmCRbsoMNNgVYlCiRvy748t6gj5MJ8v/jcqWrcLMg6PaQ==", + "resolved": "8.18.0", + "contentHash": "kKimlJy4j5m9ZkX/RTp12+gvxzM+QU5H3h7zzdroTt0v10/7AQsHG4tqi3ixvNjx5PPY0JnbpBsNXC/Xb1+sgQ==", "dependencies": { - "Microsoft.IdentityModel.Tokens": "8.17.0" + "Microsoft.IdentityModel.Tokens": "8.18.0" } }, "Microsoft.IdentityModel.Tokens": { "type": "Transitive", - "resolved": "8.17.0", - "contentHash": "teaW35URIV2x78Tzk+dVJiC4M62/9mQoSEoDjDGoEZmcQa3H2rE+XQpm9Tmdo9KK1Lcrnve4zoyLavl69kCFGg==", + "resolved": "8.18.0", + "contentHash": "c6ksXXFj5oPPsl8pfsui5zv8Gs7uxrGetXCTc1p7k7Nue/C8iBMtAVgtRrH7Esqe596QWD7KS3exKYY1FJG2iw==", "dependencies": { - "Microsoft.IdentityModel.Logging": "8.17.0" + "Microsoft.IdentityModel.Logging": "8.18.0" } }, "Microsoft.OpenApi": { "type": "Transitive", - "resolved": "1.6.29", - "contentHash": "mLoYWWwRP3C7Iier4dDzepq0kw1Tpdlh+B6KZ1SNcgq/tWI8aC41WYvIsJpsAS4UG1IV4c0AAnZs8qCPobzBkQ==" + "resolved": "3.5.3", + "contentHash": "V/PpjnjbnKsLTy0Bp3euE3l9vAJff/ZgaaOclKLZh6aGkmkWix008MidGVORHlbYfpu7pRMdvo5bGwbiDMFyxg==" }, "Microsoft.VisualStudio.Threading.Analyzers": { "type": "Transitive", @@ -301,11 +291,6 @@ "resolved": "7.1.0", "contentHash": "8paijHmWYO7zxSRNLlbDzzaFT7By827wIgdOrAg9q64+XasUYK8RCT3Y4mbISxeQ3iNdaK7wGeDmT2GWRtqRBQ==" }, - "SharpYaml": { - "type": "Transitive", - "resolved": "2.1.1", - "contentHash": "BISoFuW2AwZYXxrZGaBnedo21BvrdgC4kkWd6QYrOdhOGSsZB0RSqcBw09l9caUE1g3sykJoRfSbtSzZS6tYig==" - }, "SQLitePCLRaw.bundle_e_sqlite3": { "type": "Transitive", "resolved": "2.1.11", @@ -335,24 +320,24 @@ }, "Swashbuckle.AspNetCore.Swagger": { "type": "Transitive", - "resolved": "8.1.1", - "contentHash": "h+8D5jQtnl6X4f2hJQwf0Khj0SnCQANzirCELjXJ6quJ4C1aNNCvJrAsQ+4fOKAMqJkvW48cKj79ftG+YoGcRg==", + "resolved": "10.1.7", + "contentHash": "EjLibt/d/QuRv170GoihTbcPUpgzSFm2WKHhnGJFZQ03JYzfuitsM79azaAR8NBwRunU7yScSX6HRE5JUlrEMQ==", "dependencies": { - "Microsoft.OpenApi": "1.6.23" + "Microsoft.OpenApi": "2.4.1" } }, "Swashbuckle.AspNetCore.SwaggerGen": { "type": "Transitive", - "resolved": "8.1.1", - "contentHash": "2EuPzXSNleOOzYvziERWRLnk1Oz9i0Z1PimaUFy1SasBqeV/rG+eMfwFAMtTaf4W6gvVOzRcUCNRHvpBIIzr+A==", + "resolved": "10.1.7", + "contentHash": "PuubO9BjvNn6U3D9kLpuWKY1JtziWw7SsGBq0age1E50uQjQ8Fzl8s0EwzrLfANqYJNgDnJi9l7N1QxcGVB2Zw==", "dependencies": { - "Swashbuckle.AspNetCore.Swagger": "8.1.1" + "Swashbuckle.AspNetCore.Swagger": "10.1.7" } }, "Swashbuckle.AspNetCore.SwaggerUI": { "type": "Transitive", - "resolved": "8.1.1", - "contentHash": "GDLX/MpK4oa2nYC1N/zN2UidQTtVKLPF6gkdEmGb0RITEwpJG9Gu8olKqPYnKqVeFn44JZoCS0M2LGRKXP8B/A==" + "resolved": "10.1.7", + "contentHash": "iJo3ODyUb/M8Vm8AH1r9y9iAba0w95xsCn3zFVl96ISRHbTDWxi+l7oFVCZqUEdjd97B8VMDPnMliWAdomR8uw==" }, "System.ClientModel": { "type": "Transitive", @@ -382,7 +367,7 @@ "dependencies": { "Markdig": "[1.1.3, )", "Microsoft.EntityFrameworkCore.Sqlite": "[10.0.7, )", - "Microsoft.OpenApi.Readers": "[1.6.29, )", + "Microsoft.OpenApi": "[3.5.3, )", "Newtonsoft.Json.Schema": "[4.0.1, )", "Scriban": "[7.1.0, )", "System.CommandLine": "[2.0.7, )",