From 8fb463c26ab257f9b0aac19b53d5667a4f8c84e6 Mon Sep 17 00:00:00 2001 From: Eduard Heimbuch Date: Wed, 19 Feb 2020 13:51:43 +0100 Subject: [PATCH] update rest resource annotations --- .../v2/resources/AvailablePluginResource.java | 27 +++-- .../v2/resources/InstalledPluginResource.java | 108 ++++++++++++++---- .../v2/resources/PendingPluginResource.java | 75 +++++++++--- .../api/v2/resources/PluginRootResource.java | 6 + 4 files changed, 168 insertions(+), 48 deletions(-) diff --git a/scm-webapp/src/main/java/sonia/scm/api/v2/resources/AvailablePluginResource.java b/scm-webapp/src/main/java/sonia/scm/api/v2/resources/AvailablePluginResource.java index 8cce1018d9..bbd9444f01 100644 --- a/scm-webapp/src/main/java/sonia/scm/api/v2/resources/AvailablePluginResource.java +++ b/scm-webapp/src/main/java/sonia/scm/api/v2/resources/AvailablePluginResource.java @@ -1,12 +1,10 @@ package sonia.scm.api.v2.resources; import de.otto.edison.hal.HalRepresentation; -import io.swagger.v3.oas.annotations.OpenAPIDefinition; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.media.Content; import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.responses.ApiResponse; -import io.swagger.v3.oas.annotations.tags.Tag; import sonia.scm.plugin.AvailablePlugin; import sonia.scm.plugin.InstalledPlugin; import sonia.scm.plugin.PluginManager; @@ -28,9 +26,6 @@ import java.util.stream.Collectors; import static sonia.scm.ContextEntry.ContextBuilder.entity; import static sonia.scm.NotFoundException.notFound; -@OpenAPIDefinition(tags = { - @Tag(name = "Available plugin", description = "Available plugin related endpoints") -}) public class AvailablePluginResource { private final PluginDtoCollectionMapper collectionMapper; @@ -51,13 +46,17 @@ public class AvailablePluginResource { */ @GET @Path("") - @Operation(summary = "Find all available plugins", description = "Returns a collection of available plugins.", tags = "Available plugin") + @Operation( + summary = "Find all available plugins", + description = "Returns a collection of available plugins.", + tags = "Plugin Management" + ) @ApiResponse( responseCode = "200", description = "success", content = @Content( mediaType = VndMediaType.PLUGIN_COLLECTION, - schema = @Schema(implementation = HalRepresentation.class) + schema = @Schema(implementation = CollectionDto.class) ) ) @ApiResponse(responseCode = "401", description = "not authenticated / invalid credentials") @@ -89,7 +88,12 @@ public class AvailablePluginResource { */ @GET @Path("/{name}") - @Operation(summary = "Find single available plugin", description = "Returns an available plugins.", tags = "Available plugin") + @Produces(VndMediaType.PLUGIN) + @Operation( + summary = "Find single available plugin", + description = "Returns an available plugins.", + tags = "Plugin Management" + ) @ApiResponse( responseCode = "200", description = "success", @@ -109,7 +113,6 @@ public class AvailablePluginResource { schema = @Schema(implementation = ErrorDto.class) ) ) - @Produces(VndMediaType.PLUGIN) public Response getAvailablePlugin(@PathParam("name") String name) { PluginPermissions.read().check(); Optional plugin = pluginManager.getAvailable(name); @@ -128,7 +131,11 @@ public class AvailablePluginResource { */ @POST @Path("/{name}/install") - @Operation(summary = "Triggers plugin installation", description = "Put single plugin in installation queue. Plugin will be installed after restart.", tags = "Available plugin") + @Operation( + summary = "Triggers plugin installation", + description = "Put single plugin in installation queue. Plugin will be installed after restart.", + tags = "Plugin Management" + ) @ApiResponse(responseCode = "200", description = "success") @ApiResponse(responseCode = "401", description = "not authenticated / invalid credentials") @ApiResponse(responseCode = "403", description = "not authorized, the current user does not have the \"plugin:manage\" privilege") diff --git a/scm-webapp/src/main/java/sonia/scm/api/v2/resources/InstalledPluginResource.java b/scm-webapp/src/main/java/sonia/scm/api/v2/resources/InstalledPluginResource.java index eff83aee77..c74f88a185 100644 --- a/scm-webapp/src/main/java/sonia/scm/api/v2/resources/InstalledPluginResource.java +++ b/scm-webapp/src/main/java/sonia/scm/api/v2/resources/InstalledPluginResource.java @@ -2,7 +2,11 @@ package sonia.scm.api.v2.resources; import com.webcohesion.enunciate.metadata.rs.ResponseCode; import com.webcohesion.enunciate.metadata.rs.StatusCodes; -import com.webcohesion.enunciate.metadata.rs.TypeHint; +import de.otto.edison.hal.HalRepresentation; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.responses.ApiResponse; import sonia.scm.plugin.AvailablePlugin; import sonia.scm.plugin.InstalledPlugin; import sonia.scm.plugin.PluginManager; @@ -43,12 +47,30 @@ public class InstalledPluginResource { */ @GET @Path("") - @StatusCodes({ - @ResponseCode(code = 200, condition = "success"), - @ResponseCode(code = 500, condition = "internal server error") - }) - @TypeHint(CollectionDto.class) @Produces(VndMediaType.PLUGIN_COLLECTION) + @Operation( + summary = "Find all installed plugins", + description = "Returns a collection of installed plugins.", + tags = "Plugin Management" + ) + @ApiResponse( + responseCode = "200", + description = "success", + content = @Content( + mediaType = VndMediaType.PLUGIN_COLLECTION, + schema = @Schema(implementation = HalRepresentation.class) + ) + ) + @ApiResponse(responseCode = "401", description = "not authenticated / invalid credentials") + @ApiResponse(responseCode = "403", description = "not authorized, the current user does not have the \"plugin:read\" privilege") + @ApiResponse( + responseCode = "500", + description = "internal server error", + content = @Content( + mediaType = VndMediaType.ERROR_TYPE, + schema = @Schema(implementation = ErrorDto.class) + ) + ) public Response getInstalledPlugins() { PluginPermissions.read().check(); List plugins = pluginManager.getInstalled(); @@ -61,11 +83,22 @@ public class InstalledPluginResource { */ @POST @Path("/update") - @StatusCodes({ - @ResponseCode(code = 200, condition = "success"), - @ResponseCode(code = 500, condition = "internal server error") - }) - @TypeHint(CollectionDto.class) + @Operation( + summary = "Update all installed plugins", + description = "Updates all installed plugins to the latest compatible version.", + tags = "Plugin Management" + ) + @ApiResponse(responseCode = "200", description = "success") + @ApiResponse(responseCode = "401", description = "not authenticated / invalid credentials") + @ApiResponse(responseCode = "403", description = "not authorized, the current user does not have the \"plugin:manage\" privilege") + @ApiResponse( + responseCode = "500", + description = "internal server error", + content = @Content( + mediaType = VndMediaType.ERROR_TYPE, + schema = @Schema(implementation = ErrorDto.class) + ) + ) public Response updateAll() { pluginManager.updateAll(); return Response.ok().build(); @@ -75,18 +108,35 @@ public class InstalledPluginResource { * Returns the installed plugin with the given id. * * @param name name of plugin - * * @return installed plugin with specified id */ @GET @Path("/{name}") - @StatusCodes({ - @ResponseCode(code = 200, condition = "success"), - @ResponseCode(code = 404, condition = "not found"), - @ResponseCode(code = 500, condition = "internal server error") - }) - @TypeHint(PluginDto.class) @Produces(VndMediaType.PLUGIN) + @Operation( + summary = "Get installed plugin by name", + description = "Returns the installed plugin with the given id", + tags = "Plugin Management" + ) + @ApiResponse( + responseCode = "200", + description = "success", + content = @Content( + mediaType = VndMediaType.PLUGIN, + schema = @Schema(implementation = PluginDto.class) + ) + ) + @ApiResponse(responseCode = "401", description = "not authenticated / invalid credentials") + @ApiResponse(responseCode = "403", description = "not authorized, the current user does not have the \"plugin:read\" privilege") + @ApiResponse(responseCode = "404", description = "not found, plugin by given id could not be found") + @ApiResponse( + responseCode = "500", + description = "internal server error", + content = @Content( + mediaType = VndMediaType.ERROR_TYPE, + schema = @Schema(implementation = ErrorDto.class) + ) + ) public Response getInstalledPlugin(@PathParam("name") String name) { PluginPermissions.read().check(); Optional pluginDto = pluginManager.getInstalled(name); @@ -100,17 +150,29 @@ public class InstalledPluginResource { /** * Triggers plugin uninstall. + * * @param name plugin name * @return HTTP Status. */ @POST @Path("/{name}/uninstall") - @StatusCodes({ - @ResponseCode(code = 200, condition = "success"), - @ResponseCode(code = 500, condition = "internal server error") - }) + @Operation( + summary = "Uninstall plugin", + description = "Add plugin uninstall to pending queue. The plugin will be removed on restart.", + tags = "Plugin Management" + ) + @ApiResponse(responseCode = "200", description = "success") + @ApiResponse(responseCode = "401", description = "not authenticated / invalid credentials") + @ApiResponse(responseCode = "403", description = "not authorized, the current user does not have the \"plugin:manage\" privilege") + @ApiResponse( + responseCode = "500", + description = "internal server error", + content = @Content( + mediaType = VndMediaType.ERROR_TYPE, + schema = @Schema(implementation = ErrorDto.class) + ) + ) public Response uninstallPlugin(@PathParam("name") String name, @QueryParam("restart") boolean restartAfterInstallation) { - PluginPermissions.manage().check(); pluginManager.uninstall(name, restartAfterInstallation); return Response.ok().build(); } diff --git a/scm-webapp/src/main/java/sonia/scm/api/v2/resources/PendingPluginResource.java b/scm-webapp/src/main/java/sonia/scm/api/v2/resources/PendingPluginResource.java index 7d4663829e..be8bed9729 100644 --- a/scm-webapp/src/main/java/sonia/scm/api/v2/resources/PendingPluginResource.java +++ b/scm-webapp/src/main/java/sonia/scm/api/v2/resources/PendingPluginResource.java @@ -1,10 +1,12 @@ package sonia.scm.api.v2.resources; -import com.webcohesion.enunciate.metadata.rs.ResponseCode; -import com.webcohesion.enunciate.metadata.rs.StatusCodes; import de.otto.edison.hal.Embedded; import de.otto.edison.hal.HalRepresentation; import de.otto.edison.hal.Links; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.responses.ApiResponse; import sonia.scm.plugin.AvailablePlugin; import sonia.scm.plugin.InstalledPlugin; import sonia.scm.plugin.PluginManager; @@ -40,11 +42,30 @@ public class PendingPluginResource { @GET @Path("") - @StatusCodes({ - @ResponseCode(code = 200, condition = "success"), - @ResponseCode(code = 500, condition = "internal server error") - }) @Produces(VndMediaType.PLUGIN_COLLECTION) + @Operation( + summary = "Find all pending plugins", + description = "Returns a collection of pending plugins.", + tags = "Plugin Management" + ) + @ApiResponse( + responseCode = "200", + description = "success", + content = @Content( + mediaType = VndMediaType.PLUGIN_COLLECTION, + schema = @Schema(implementation = CollectionDto.class) + ) + ) + @ApiResponse(responseCode = "401", description = "not authenticated / invalid credentials") + @ApiResponse(responseCode = "403", description = "not authorized, the current user does not have the \"plugin:read\" privilege") + @ApiResponse( + responseCode = "500", + description = "internal server error", + content = @Content( + mediaType = VndMediaType.ERROR_TYPE, + schema = @Schema(implementation = ErrorDto.class) + ) + ) public Response getPending() { List pending = pluginManager .getAvailable() @@ -71,7 +92,7 @@ public class PendingPluginResource { if ( PluginPermissions.manage().isPermitted() && - (!installDtos.isEmpty() || !updateDtos.isEmpty() || !uninstallDtos.isEmpty()) + (!installDtos.isEmpty() || !updateDtos.isEmpty() || !uninstallDtos.isEmpty()) ) { linksBuilder.single(link("execute", resourceLinks.pendingPluginCollection().executePending())); linksBuilder.single(link("cancel", resourceLinks.pendingPluginCollection().cancelPending())); @@ -103,10 +124,22 @@ public class PendingPluginResource { @POST @Path("/execute") - @StatusCodes({ - @ResponseCode(code = 200, condition = "success"), - @ResponseCode(code = 500, condition = "internal server error") - }) + @Operation( + summary = "Execute pending", + description = "Executes all pending plugin changes. The server will be restarted on this action.", + tags = "Plugin Management" + ) + @ApiResponse(responseCode = "200", description = "success") + @ApiResponse(responseCode = "401", description = "not authenticated / invalid credentials") + @ApiResponse(responseCode = "403", description = "not authorized, the current user does not have the \"plugin:manage\" privilege") + @ApiResponse( + responseCode = "500", + description = "internal server error", + content = @Content( + mediaType = VndMediaType.ERROR_TYPE, + schema = @Schema(implementation = ErrorDto.class) + ) + ) public Response executePending() { pluginManager.executePendingAndRestart(); return Response.ok().build(); @@ -114,10 +147,22 @@ public class PendingPluginResource { @POST @Path("/cancel") - @StatusCodes({ - @ResponseCode(code = 200, condition = "success"), - @ResponseCode(code = 500, condition = "internal server error") - }) + @Operation( + summary = "Cancel pending", + description = "Cancels all pending plugin changes and clear the pending queue.", + tags = "Plugin Management" + ) + @ApiResponse(responseCode = "200", description = "success") + @ApiResponse(responseCode = "401", description = "not authenticated / invalid credentials") + @ApiResponse(responseCode = "403", description = "not authorized, the current user does not have the \"plugin:manage\" privilege") + @ApiResponse( + responseCode = "500", + description = "internal server error", + content = @Content( + mediaType = VndMediaType.ERROR_TYPE, + schema = @Schema(implementation = ErrorDto.class) + ) + ) public Response cancelPending() { pluginManager.cancelPending(); return Response.ok().build(); diff --git a/scm-webapp/src/main/java/sonia/scm/api/v2/resources/PluginRootResource.java b/scm-webapp/src/main/java/sonia/scm/api/v2/resources/PluginRootResource.java index 14abbe73d8..3b1613d1c0 100644 --- a/scm-webapp/src/main/java/sonia/scm/api/v2/resources/PluginRootResource.java +++ b/scm-webapp/src/main/java/sonia/scm/api/v2/resources/PluginRootResource.java @@ -1,9 +1,15 @@ package sonia.scm.api.v2.resources; +import io.swagger.v3.oas.annotations.OpenAPIDefinition; +import io.swagger.v3.oas.annotations.tags.Tag; + import javax.inject.Inject; import javax.inject.Provider; import javax.ws.rs.Path; +@OpenAPIDefinition(tags = { + @Tag(name = "Plugin Management", description = "Plugin management related endpoints") +}) @Path("v2/plugins") public class PluginRootResource {