diff --git a/API/Controller/Device/Pair.cs b/API/Controller/Device/Pair.cs index 3f3bf01b..d8d79fa1 100644 --- a/API/Controller/Device/Pair.cs +++ b/API/Controller/Device/Pair.cs @@ -22,11 +22,34 @@ public sealed partial class DeviceController [AllowAnonymous] [MapToApiVersion("1")] [HttpGet("pair/{pairCode}", Name = "Pair")] - [HttpGet("~/{version:apiVersion}/pair/{pairCode}", Name = "Pair_DEPRECATED")] // Backwards compatibility + [EndpointName("PairDeviceByCode")] [EnableRateLimiting("auth")] [ProducesResponseType>(StatusCodes.Status200OK, MediaTypeNames.Application.Json)] [ProducesResponseType(StatusCodes.Status404NotFound, MediaTypeNames.Application.ProblemJson)] // PairCodeNotFound public async Task Pair([FromRoute] string pairCode) + { + return await PairInternal(pairCode); + } + + /// + /// Pair a device with a pair code. + /// + /// The pair code to pair with. + /// Successfully assigned LCG node + /// No such pair code exists + [AllowAnonymous] + [MapToApiVersion("1")] + [HttpGet("~/{version:apiVersion}/pair/{pairCode}", Name = "PairDeviceByCode_DEPRECATED")] // Backwards compatibility + [EndpointName("PairDeviceByCode_DEPRECATED")] + [EnableRateLimiting("auth")] + [ProducesResponseType>(StatusCodes.Status200OK, MediaTypeNames.Application.Json)] + [ProducesResponseType(StatusCodes.Status404NotFound, MediaTypeNames.Application.ProblemJson)] // PairCodeNotFound + public async Task PairDeprecated([FromRoute] string pairCode) + { + return await PairInternal(pairCode); + } + + public async Task PairInternal([FromRoute] string pairCode) { var devicePairs = _redis.RedisCollection(); diff --git a/Common/OpenAPI/DocumentDefaults.cs b/Common/OpenAPI/DocumentDefaults.cs index 54764ce6..ada54816 100644 --- a/Common/OpenAPI/DocumentDefaults.cs +++ b/Common/OpenAPI/DocumentDefaults.cs @@ -13,7 +13,7 @@ public static Func(this WebApplicationBuil options.OpenApiVersion = OpenApiSpecVersion.OpenApi3_1; options.AddDocumentTransformer(DocumentDefaults.GetDocumentTransformer( version: description.ApiVersion.ToString())); + options.CreateSchemaReferenceId = (type) => + { + var defaultName = type.Type.Name; + var cleanName = defaultName + .Replace("[]", "Array") + .Replace("`1", "Of") + .Replace("`2", "OfTwo"); + return cleanName; + }; + options.AddOperationTransformer((operation, context, cancellationToken) => + { + var actionDescriptor = context.Description.ActionDescriptor; + + // Use endpoint name if available + var endpointName = actionDescriptor.EndpointMetadata + .OfType() + .FirstOrDefault()?.EndpointName; + + if (!string.IsNullOrEmpty(endpointName)) + { + operation.OperationId = endpointName; + return Task.CompletedTask; + } + + // For controllers + var controller = actionDescriptor.RouteValues.TryGetValue("controller", out var ctrl) ? ctrl : null; + var action = actionDescriptor.RouteValues.TryGetValue("action", out var act) ? act : null; + + if (!string.IsNullOrEmpty(controller) && !string.IsNullOrEmpty(action)) + { + operation.OperationId = $"{controller}{action}"; + } + + return Task.CompletedTask; + }); }); } }