diff --git a/hawkbit-mgmt/hawkbit-mgmt-resource-deprecated/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/deprecated/DeprecatedMgmtRestApi.java b/hawkbit-mgmt/hawkbit-mgmt-resource-deprecated/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/deprecated/DeprecatedMgmtRestApi.java index 66e2663e2..cf13b90f7 100644 --- a/hawkbit-mgmt/hawkbit-mgmt-resource-deprecated/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/deprecated/DeprecatedMgmtRestApi.java +++ b/hawkbit-mgmt/hawkbit-mgmt-resource-deprecated/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/deprecated/DeprecatedMgmtRestApi.java @@ -12,6 +12,8 @@ package org.eclipse.hawkbit.mgmt.rest.resource.deprecated; import java.util.List; import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.extensions.Extension; +import io.swagger.v3.oas.annotations.extensions.ExtensionProperty; import io.swagger.v3.oas.annotations.media.Content; import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.responses.ApiResponse; @@ -24,6 +26,7 @@ import org.eclipse.hawkbit.mgmt.rest.resource.deprecated.json.model.MgmtAssigned import org.eclipse.hawkbit.mgmt.rest.resource.deprecated.json.model.MgmtAssignedTargetRequestBody; import org.eclipse.hawkbit.mgmt.rest.resource.deprecated.json.model.MgmtDistributionSetTagAssigmentResult; import org.eclipse.hawkbit.mgmt.rest.resource.deprecated.json.model.MgmtTargetTagAssigmentResult; +import org.eclipse.hawkbit.rest.OpenApiConfiguration; import org.eclipse.hawkbit.rest.json.model.ExceptionInfo; import org.springframework.hateoas.MediaTypes; import org.springframework.http.MediaType; @@ -37,7 +40,8 @@ import org.springframework.web.bind.annotation.RequestBody; */ // no request mapping specified here to avoid CVE-2021-22044 in Feign client @Deprecated(forRemoval = true) -@Tag(name = "Deprecated Management API", description = "Deprecated REST operations.") +@Tag(name = "Deprecated operations", description = "Deprecated REST operations.", + extensions = @Extension(name = OpenApiConfiguration.X_HAWKBIT, properties = @ExtensionProperty(name = "order", value = "2147483647"))) public interface DeprecatedMgmtRestApi { /** diff --git a/hawkbit-mgmt/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtOpenApiConfiguration.java b/hawkbit-mgmt/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtOpenApiConfiguration.java index 188090532..ef596f18f 100644 --- a/hawkbit-mgmt/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtOpenApiConfiguration.java +++ b/hawkbit-mgmt/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtOpenApiConfiguration.java @@ -57,7 +57,8 @@ public class MgmtOpenApiConfiguration { .type(SecurityScheme.Type.HTTP) .in(SecurityScheme.In.HEADER) .bearerFormat("JWT") - .scheme("bearer")))) + .scheme("bearer"))) + .tags(OpenApiConfiguration.sort(openApi.getTags()))) .build(); } } \ No newline at end of file diff --git a/hawkbit-rest-core/src/main/java/org/eclipse/hawkbit/rest/OpenApiConfiguration.java b/hawkbit-rest-core/src/main/java/org/eclipse/hawkbit/rest/OpenApiConfiguration.java index 52d3c1943..67d9cba79 100644 --- a/hawkbit-rest-core/src/main/java/org/eclipse/hawkbit/rest/OpenApiConfiguration.java +++ b/hawkbit-rest-core/src/main/java/org/eclipse/hawkbit/rest/OpenApiConfiguration.java @@ -9,8 +9,14 @@ */ package org.eclipse.hawkbit.rest; +import java.util.Comparator; +import java.util.List; +import java.util.Map; +import java.util.Optional; + import io.swagger.v3.oas.models.OpenAPI; import io.swagger.v3.oas.models.info.Info; +import io.swagger.v3.oas.models.tags.Tag; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -24,6 +30,9 @@ public class OpenApiConfiguration { public static final String HAWKBIT_SERVER_SWAGGER_ENABLED = "hawkbit.server.swagger.enabled"; + public static final String X_HAWKBIT = "x-hawkbit"; + public static final String ORDER = "order"; + private static final String API_TITLE = "hawkBit REST APIs"; private static final String API_VERSION = "v1"; private static final String DESCRIPTION = """ @@ -34,4 +43,34 @@ public class OpenApiConfiguration { public OpenAPI openApi() { return new OpenAPI().info(new Info().title(API_TITLE).version(API_VERSION).description(DESCRIPTION)); } + + public static List sort(final List tags) { + tags.sort(TAG_COMPARATOR); + return tags; + } + + private static final Comparator TAG_COMPARATOR = new Comparator<>() { + + @Override + public int compare(final Tag o1, final Tag o2) { + final int o1Order = order(o1); + final int o2Order = order(o2); + if (o1Order == o2Order) { + return o1.getName().compareTo(o2.getName()); + } else { + return Integer.compare(o1Order, o2Order); + } + } + + private static int order(final Tag tag) { + return Optional.ofNullable(tag.getExtensions()) + .map(extensions -> extensions.get(X_HAWKBIT)) + .filter(extension -> Map.class.isAssignableFrom(extension.getClass())) + .map(Map.class::cast) + .map(propertiesMap -> propertiesMap.get(ORDER)) + .map(String.class::cast) + .map(Integer::parseInt) + .orElse(0); + } + }; } \ No newline at end of file