diff --git a/hawkbit-rest/hawkbit-ddi-api/src/main/java/org/eclipse/hawkbit/ddi/rest/api/DdiRootControllerRestApi.java b/hawkbit-rest/hawkbit-ddi-api/src/main/java/org/eclipse/hawkbit/ddi/rest/api/DdiRootControllerRestApi.java index 3c2202817..7bc84394e 100644 --- a/hawkbit-rest/hawkbit-ddi-api/src/main/java/org/eclipse/hawkbit/ddi/rest/api/DdiRootControllerRestApi.java +++ b/hawkbit-rest/hawkbit-ddi-api/src/main/java/org/eclipse/hawkbit/ddi/rest/api/DdiRootControllerRestApi.java @@ -126,6 +126,17 @@ public interface DdiRootControllerRestApi { * {@link HttpStatus#OK} or in case of partial download * {@link HttpStatus#PARTIAL_CONTENT}. */ + @Operation(summary = "Artifact download", description = "Handles GET DdiArtifact download request. This could be full or partial (as specified by RFC7233 (Range Requests)) download request.") + @ApiResponses(value = { + @ApiResponse(responseCode = "200", description = "Successfully retrieved"), + @ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters", content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))), + @ApiResponse(responseCode = "401", description = "The request requires user authentication.", content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))), + @ApiResponse(responseCode = "403", description = "Insufficient permissions, entity is not allowed to be changed (i.e. read-only) or data volume restriction applies.", content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))), + @ApiResponse(responseCode = "404", description = "Target or Module not found", content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))), + @ApiResponse(responseCode = "405", description = "The http request method is not allowed on the resource.", content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))), + @ApiResponse(responseCode = "406", description = "In case accept header is specified and not application/json.", content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))), + @ApiResponse(responseCode = "429", description = "Too many requests. The server will refuse further attempts and the client has to wait another second.", content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))) + }) @GetMapping(value = DdiRestConstants.BASE_V1_REQUEST_MAPPING + "/{controllerId}/softwaremodules/{softwareModuleId}/artifacts/{fileName}") ResponseEntity downloadArtifact(@PathVariable("tenant") final String tenant, @@ -148,6 +159,17 @@ public interface DdiRootControllerRestApi { * @return {@link ResponseEntity} with status {@link HttpStatus#OK} if * successful */ + @Operation(summary = "MD5 checksum download", description = "Handles GET {@link DdiArtifact} MD5 checksum file download request.") + @ApiResponses(value = { + @ApiResponse(responseCode = "200", description = "Successfully retrieved"), + @ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters", content = @Content(mediaType = "application/json", schema = @Schema(implementation = ExceptionInfo.class))), + @ApiResponse(responseCode = "401", description = "The request requires user authentication.", content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))), + @ApiResponse(responseCode = "403", description = "Insufficient permissions, entity is not allowed to be changed (i.e. read-only) or data volume restriction applies.", content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))), + @ApiResponse(responseCode = "404", description = "Target or Module not found", content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))), + @ApiResponse(responseCode = "405", description = "The http request method is not allowed on the resource.", content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))), + @ApiResponse(responseCode = "406", description = "In case accept header is specified and not application/json.", content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))), + @ApiResponse(responseCode = "429", description = "Too many requests. The server will refuse further attempts and the client has to wait another second.", content = @Content(mediaType = "application/json", schema = @Schema(hidden = true))) + }) @GetMapping(value = DdiRestConstants.BASE_V1_REQUEST_MAPPING + "/{controllerId}/softwaremodules/{softwareModuleId}/artifacts/{fileName}" + DdiRestConstants.ARTIFACT_MD5_DWNL_SUFFIX, produces = MediaType.TEXT_PLAIN_VALUE) diff --git a/hawkbit-rest/hawkbit-rest-core/src/main/java/org/eclipse/hawkbit/rest/OpenApiConfiguration.java b/hawkbit-rest/hawkbit-rest-core/src/main/java/org/eclipse/hawkbit/rest/OpenApiConfiguration.java index d92361c14..764480905 100644 --- a/hawkbit-rest/hawkbit-rest-core/src/main/java/org/eclipse/hawkbit/rest/OpenApiConfiguration.java +++ b/hawkbit-rest/hawkbit-rest-core/src/main/java/org/eclipse/hawkbit/rest/OpenApiConfiguration.java @@ -12,35 +12,29 @@ package org.eclipse.hawkbit.rest; import io.swagger.v3.oas.models.Components; import io.swagger.v3.oas.models.OpenAPI; import io.swagger.v3.oas.models.info.Info; -import io.swagger.v3.oas.models.security.OAuthFlow; -import io.swagger.v3.oas.models.security.OAuthFlows; -import io.swagger.v3.oas.models.security.Scopes; import io.swagger.v3.oas.models.security.SecurityRequirement; import io.swagger.v3.oas.models.security.SecurityScheme; import org.springdoc.core.GroupedOpenApi; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +@Configuration public class OpenApiConfiguration { private static final String DESCRIPTION = """ - The Management API is a RESTful API that enables to perform Create/Read/Update/Delete operations for provisioning targets - (i.e. devices) and repository content (i.e. software). Based on the Management API you can manage and monitor software update - operations via HTTP/HTTPS. The Management API supports JSON payload with hypermedia as well as filtering, sorting and paging. - Furthermore the Management API provides permission based access control and standard roles as well as custom role creation. - The API is protected and needs authentication and authorization based on the security concept. + Eclipse hawkBit™ is a domain-independent back-end framework for rolling out software updates to constrained edge devices as well as more powerful controllers and gateways connected to IP based networking infrastructure. """; @Bean public OpenAPI customOpenApi() { - final String apiTitle = "hawkBit Management REST API"; + final String apiTitle = "hawkBit REST APIs"; final String basiAuthSecSchemeName = "basicAuth"; - final String oauth2SecSchemeName = "OAuth2"; final String bearerAuthenticationSchemeName = "Bearer Authentication"; return new OpenAPI() .addSecurityItem(new SecurityRequirement().addList(basiAuthSecSchemeName)) - .addSecurityItem(new SecurityRequirement().addList(oauth2SecSchemeName)) .addSecurityItem(new SecurityRequirement().addList(bearerAuthenticationSchemeName)) .components( new Components() @@ -51,18 +45,6 @@ public class OpenApiConfiguration { .in(SecurityScheme.In.HEADER) .scheme("basic") ) - .addSecuritySchemes(oauth2SecSchemeName, - new SecurityScheme() - .name(oauth2SecSchemeName) - .type(SecurityScheme.Type.OAUTH2) - .flows(new OAuthFlows().authorizationCode(new OAuthFlow() - .authorizationUrl("${spring.security.oauth2.client.provider.suite.authorization-uri}") - .tokenUrl("${spring.security.oauth2.client.provider.suite.token-uri}") - .refreshUrl("${spring.security.oauth2.client.provider.suite.token-uri}") - .scopes(new Scopes() - .addString("openid", "openid") - .addString("offline_access", "offline_access")))) - ) .addSecuritySchemes(bearerAuthenticationSchemeName, new SecurityScheme() .name(bearerAuthenticationSchemeName) @@ -73,6 +55,10 @@ public class OpenApiConfiguration { } @Bean + @ConditionalOnProperty( + value="hawkbit.server.swagger.mgmt.api.group.enabled", + havingValue = "true", + matchIfMissing = true) public GroupedOpenApi mgmtApi() { return GroupedOpenApi.builder() .group("Management API") @@ -81,6 +67,10 @@ public class OpenApiConfiguration { } @Bean + @ConditionalOnProperty( + value="hawkbit.server.swagger.ddi.api.group.enabled", + havingValue = "true", + matchIfMissing = true) public GroupedOpenApi ddiApi() { return GroupedOpenApi.builder() .group("Direct Device Integration API")