diff --git a/scm-webapp/pom.xml b/scm-webapp/pom.xml index 924e176024..4520700dbc 100644 --- a/scm-webapp/pom.xml +++ b/scm-webapp/pom.xml @@ -426,6 +426,13 @@ provided + + io.swagger.core.v3 + swagger-annotations + 2.1.1 + provided + + @@ -471,6 +478,50 @@ + + io.openapitools.swagger + swagger-maven-plugin + 2.1.2 + + + sonia.scm.api.v2.resources + + ${basedir}/target/openapi/META-INF/scm + openapi + JSON,YAML + true + + + + http://localhost:8081/scm/api + local endpoint url + + + + SCM-Manager REST-API + ${project.version} + + scmmanager@googlegroups.com + SCM-Manager + https://scm-manager.org + + + http://www.opensource.org/licenses/bsd-license.php + BSD + + + src/main/doc/openapi.md + + + + + + generate + + + + + sonia.scm.maven smp-maven-plugin @@ -511,9 +562,15 @@ org.apache.maven.plugins maven-war-plugin - 2.2 + 3.1.0 true + + + target/openapi + WEB-INF/classes + + diff --git a/scm-webapp/src/main/doc/openapi.md b/scm-webapp/src/main/doc/openapi.md new file mode 100644 index 0000000000..c014899c30 --- /dev/null +++ b/scm-webapp/src/main/doc/openapi.md @@ -0,0 +1,3 @@ +# openapi docs from code + +describe hateoas diff --git a/scm-webapp/src/main/java/sonia/scm/api/v2/resources/AuthenticationResource.java b/scm-webapp/src/main/java/sonia/scm/api/v2/resources/AuthenticationResource.java index deab53a708..3bb37b99d4 100644 --- a/scm-webapp/src/main/java/sonia/scm/api/v2/resources/AuthenticationResource.java +++ b/scm-webapp/src/main/java/sonia/scm/api/v2/resources/AuthenticationResource.java @@ -3,6 +3,10 @@ package sonia.scm.api.v2.resources; import com.google.inject.Inject; import com.webcohesion.enunciate.metadata.rs.ResponseCode; import com.webcohesion.enunciate.metadata.rs.StatusCodes; +import io.swagger.v3.oas.annotations.enums.SecuritySchemeIn; +import io.swagger.v3.oas.annotations.enums.SecuritySchemeType; +import io.swagger.v3.oas.annotations.security.SecurityScheme; +import io.swagger.v3.oas.annotations.security.SecuritySchemes; import org.apache.shiro.SecurityUtils; import org.apache.shiro.authc.AuthenticationException; import org.apache.shiro.subject.Subject; @@ -19,6 +23,22 @@ import javax.ws.rs.core.Response; import java.net.URI; import java.util.Optional; +@SecuritySchemes({ + @SecurityScheme( + name = "Basic Authentication", + description = "HTTP Basic authentication with username and password", + scheme = "Basic", + type = SecuritySchemeType.HTTP + ), + @SecurityScheme( + name = "Bearer Token Authentication", + in = SecuritySchemeIn.HEADER, + paramName = "Authorization", + scheme = "Bearer", + bearerFormat = "JWT", + type = SecuritySchemeType.APIKEY + ) +}) @Path(AuthenticationResource.PATH) @AllowAnonymousAccess public class AuthenticationResource { diff --git a/scm-webapp/src/main/java/sonia/scm/api/v2/resources/RepositoryResource.java b/scm-webapp/src/main/java/sonia/scm/api/v2/resources/RepositoryResource.java index 2294dc600e..ebae9e53e9 100644 --- a/scm-webapp/src/main/java/sonia/scm/api/v2/resources/RepositoryResource.java +++ b/scm-webapp/src/main/java/sonia/scm/api/v2/resources/RepositoryResource.java @@ -3,6 +3,10 @@ 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 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.repository.NamespaceAndName; import sonia.scm.repository.Repository; import sonia.scm.repository.RepositoryManager; @@ -87,14 +91,39 @@ public class RepositoryResource { @GET @Path("") @Produces(VndMediaType.REPOSITORY) - @TypeHint(RepositoryDto.class) - @StatusCodes({ - @ResponseCode(code = 200, condition = "success"), - @ResponseCode(code = 401, condition = "not authenticated / invalid credentials"), - @ResponseCode(code = 403, condition = "not authorized, the current user has no privileges to read the repository"), - @ResponseCode(code = 404, condition = "not found, no repository with the specified name available in the namespace"), - @ResponseCode(code = 500, condition = "internal server error") - }) + @Operation(summary = "Returns a single repository", description = "Returns the repository for the given namespace and name.", tags = "Repository") + @ApiResponse( + responseCode = "200", + description = "success", + content = @Content( + mediaType = VndMediaType.REPOSITORY, + schema = @Schema(implementation = RepositoryDto.class) + ) + ) + @ApiResponse( + responseCode = "401", + description = "not authenticated / invalid credentials" + ) + @ApiResponse( + responseCode = "403", + description = "not authorized, the current user has no privileges to read the repository" + ) + @ApiResponse( + responseCode = "404", + description = "not found, no repository with the specified name available in the namespace", + content = @Content( + mediaType = VndMediaType.ERROR_TYPE, + schema = @Schema(implementation = ErrorDto.class) + ) + ) + @ApiResponse( + responseCode = "500", + description = "internal server error", + content = @Content( + mediaType = VndMediaType.ERROR_TYPE, + schema = @Schema(implementation = ErrorDto.class) + ) + ) public Response get(@PathParam("namespace") String namespace, @PathParam("name") String name){ return adapter.get(loadBy(namespace, name), repositoryToDtoMapper::map); } @@ -168,7 +197,7 @@ public class RepositoryResource { } @Path("branches/") - public BranchRootResource branches(@PathParam("namespace") String namespace, @PathParam("name") String name) { + public BranchRootResource branches() { return branchRootResource.get(); } diff --git a/scm-webapp/src/main/java/sonia/scm/api/v2/resources/RepositoryRootResource.java b/scm-webapp/src/main/java/sonia/scm/api/v2/resources/RepositoryRootResource.java index a7a6365c37..7b8c1120e1 100644 --- a/scm-webapp/src/main/java/sonia/scm/api/v2/resources/RepositoryRootResource.java +++ b/scm-webapp/src/main/java/sonia/scm/api/v2/resources/RepositoryRootResource.java @@ -1,12 +1,20 @@ 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; /** - * RESTful Web Service Resource to manage repositories. + * RESTful Web Service Resource to manage repositories. */ +@OpenAPIDefinition( + tags = { + @Tag(name = "Repository", description = "Repository related endpoints") + } +) @Path(RepositoryRootResource.REPOSITORIES_PATH_V2) public class RepositoryRootResource { static final String REPOSITORIES_PATH_V2 = "v2/repositories/";