mirror of
https://github.com/scm-manager/scm-manager.git
synced 2025-11-13 08:55:44 +01:00
Create openapi docs for me endpoint and changesets
This commit is contained in:
@@ -1,8 +1,9 @@
|
|||||||
package sonia.scm.api.v2.resources;
|
package sonia.scm.api.v2.resources;
|
||||||
|
|
||||||
import com.webcohesion.enunciate.metadata.rs.ResponseCode;
|
import io.swagger.v3.oas.annotations.Operation;
|
||||||
import com.webcohesion.enunciate.metadata.rs.StatusCodes;
|
import io.swagger.v3.oas.annotations.media.Content;
|
||||||
import com.webcohesion.enunciate.metadata.rs.TypeHint;
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import io.swagger.v3.oas.annotations.responses.ApiResponse;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import sonia.scm.PageResult;
|
import sonia.scm.PageResult;
|
||||||
import sonia.scm.repository.Changeset;
|
import sonia.scm.repository.Changeset;
|
||||||
@@ -42,17 +43,82 @@ public class ChangesetRootResource {
|
|||||||
this.changesetToChangesetDtoMapper = changesetToChangesetDtoMapper;
|
this.changesetToChangesetDtoMapper = changesetToChangesetDtoMapper;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@GET
|
||||||
|
@Path("{id}")
|
||||||
|
@Produces(VndMediaType.CHANGESET)
|
||||||
|
@Operation(summary = "Collection of changesets", description = "Returns a collection of changesets.", tags = "Repository")
|
||||||
|
@ApiResponse(
|
||||||
|
responseCode = "200",
|
||||||
|
description = "success",
|
||||||
|
content = @Content(
|
||||||
|
mediaType = VndMediaType.CHANGESET,
|
||||||
|
schema = @Schema(implementation = ChangesetDto.class)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
@ApiResponse(responseCode = "401", description = "not authenticated / invalid credentials")
|
||||||
|
@ApiResponse(responseCode = "403", description = "not authorized, the current user has no privileges to read the changeset")
|
||||||
|
@ApiResponse(
|
||||||
|
responseCode = "404",
|
||||||
|
description = "not found, no changeset with the specified id is available in the repository",
|
||||||
|
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, @PathParam("id") String id) throws IOException {
|
||||||
|
try (RepositoryService repositoryService = serviceFactory.create(new NamespaceAndName(namespace, name))) {
|
||||||
|
Repository repository = repositoryService.getRepository();
|
||||||
|
RepositoryPermissions.read(repository).check();
|
||||||
|
ChangesetPagingResult changesets = repositoryService.getLogCommand()
|
||||||
|
.setStartChangeset(id)
|
||||||
|
.setEndChangeset(id)
|
||||||
|
.getChangesets();
|
||||||
|
if (changesets != null && changesets.getChangesets() != null && !changesets.getChangesets().isEmpty()) {
|
||||||
|
Optional<Changeset> changeset = changesets.getChangesets().stream().filter(ch -> ch.getId().equals(id)).findFirst();
|
||||||
|
if (!changeset.isPresent()) {
|
||||||
|
return Response.status(Response.Status.NOT_FOUND).build();
|
||||||
|
}
|
||||||
|
return Response.ok(changesetToChangesetDtoMapper.map(changeset.get(), repository)).build();
|
||||||
|
} else {
|
||||||
|
return Response.status(Response.Status.NOT_FOUND).build();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@GET
|
@GET
|
||||||
@Path("")
|
@Path("")
|
||||||
@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 changeset"),
|
|
||||||
@ResponseCode(code = 404, condition = "not found, no changesets available in the repository"),
|
|
||||||
@ResponseCode(code = 500, condition = "internal server error")
|
|
||||||
})
|
|
||||||
@Produces(VndMediaType.CHANGESET_COLLECTION)
|
@Produces(VndMediaType.CHANGESET_COLLECTION)
|
||||||
@TypeHint(CollectionDto.class)
|
@Operation(summary = "Specific changeset", description = "Returns a specific changeset.", tags = "Repository")
|
||||||
|
@ApiResponse(
|
||||||
|
responseCode = "200",
|
||||||
|
description = "success",
|
||||||
|
content = @Content(
|
||||||
|
mediaType = VndMediaType.CHANGESET_COLLECTION,
|
||||||
|
schema = @Schema(implementation = CollectionDto.class)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
@ApiResponse(responseCode = "401", description = "not authenticated / invalid credentials")
|
||||||
|
@ApiResponse(responseCode = "403", description = "not authorized, the current user has no privileges to read the changeset")
|
||||||
|
@ApiResponse(
|
||||||
|
responseCode = "404",
|
||||||
|
description = "not found, no changesets available in the repository",
|
||||||
|
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 getAll(@PathParam("namespace") String namespace, @PathParam("name") String name, @DefaultValue("0") @QueryParam("page") int page,
|
public Response getAll(@PathParam("namespace") String namespace, @PathParam("name") String name, @DefaultValue("0") @QueryParam("page") int page,
|
||||||
@DefaultValue("10") @QueryParam("pageSize") int pageSize) throws IOException {
|
@DefaultValue("10") @QueryParam("pageSize") int pageSize) throws IOException {
|
||||||
try (RepositoryService repositoryService = serviceFactory.create(new NamespaceAndName(namespace, name))) {
|
try (RepositoryService repositoryService = serviceFactory.create(new NamespaceAndName(namespace, name))) {
|
||||||
@@ -75,35 +141,4 @@ public class ChangesetRootResource {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@GET
|
|
||||||
@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 changeset"),
|
|
||||||
@ResponseCode(code = 404, condition = "not found, no changeset with the specified id is available in the repository"),
|
|
||||||
@ResponseCode(code = 500, condition = "internal server error")
|
|
||||||
})
|
|
||||||
@Produces(VndMediaType.CHANGESET)
|
|
||||||
@TypeHint(ChangesetDto.class)
|
|
||||||
@Path("{id}")
|
|
||||||
public Response get(@PathParam("namespace") String namespace, @PathParam("name") String name, @PathParam("id") String id) throws IOException {
|
|
||||||
try (RepositoryService repositoryService = serviceFactory.create(new NamespaceAndName(namespace, name))) {
|
|
||||||
Repository repository = repositoryService.getRepository();
|
|
||||||
RepositoryPermissions.read(repository).check();
|
|
||||||
ChangesetPagingResult changesets = repositoryService.getLogCommand()
|
|
||||||
.setStartChangeset(id)
|
|
||||||
.setEndChangeset(id)
|
|
||||||
.getChangesets();
|
|
||||||
if (changesets != null && changesets.getChangesets() != null && !changesets.getChangesets().isEmpty()) {
|
|
||||||
Optional<Changeset> changeset = changesets.getChangesets().stream().filter(ch -> ch.getId().equals(id)).findFirst();
|
|
||||||
if (!changeset.isPresent()) {
|
|
||||||
return Response.status(Response.Status.NOT_FOUND).build();
|
|
||||||
}
|
|
||||||
return Response.ok(changesetToChangesetDtoMapper.map(changeset.get(), repository)).build();
|
|
||||||
} else {
|
|
||||||
return Response.status(Response.Status.NOT_FOUND).build();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
package sonia.scm.api.v2.resources;
|
package sonia.scm.api.v2.resources;
|
||||||
|
|
||||||
import com.webcohesion.enunciate.metadata.rs.ResponseCode;
|
import io.swagger.v3.oas.annotations.Operation;
|
||||||
import com.webcohesion.enunciate.metadata.rs.StatusCodes;
|
import io.swagger.v3.oas.annotations.media.Content;
|
||||||
import com.webcohesion.enunciate.metadata.rs.TypeHint;
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import io.swagger.v3.oas.annotations.responses.ApiResponse;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import sonia.scm.PageResult;
|
import sonia.scm.PageResult;
|
||||||
import sonia.scm.repository.Changeset;
|
import sonia.scm.repository.Changeset;
|
||||||
@@ -54,15 +55,32 @@ public class FileHistoryRootResource {
|
|||||||
*/
|
*/
|
||||||
@GET
|
@GET
|
||||||
@Path("{revision}/{path: .*}")
|
@Path("{revision}/{path: .*}")
|
||||||
@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 changeset"),
|
|
||||||
@ResponseCode(code = 404, condition = "not found, no changesets available in the repository"),
|
|
||||||
@ResponseCode(code = 500, condition = "internal server error")
|
|
||||||
})
|
|
||||||
@Produces(VndMediaType.CHANGESET_COLLECTION)
|
@Produces(VndMediaType.CHANGESET_COLLECTION)
|
||||||
@TypeHint(CollectionDto.class)
|
@Operation(summary = "Changesets to given file", description = "Get all changesets related to the given file starting with the given revision.", tags = "Repository")
|
||||||
|
@ApiResponse(
|
||||||
|
responseCode = "200",
|
||||||
|
description = "success",
|
||||||
|
content = @Content(
|
||||||
|
mediaType = VndMediaType.CHANGESET_COLLECTION,
|
||||||
|
schema = @Schema(implementation = CollectionDto.class)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
@ApiResponse(responseCode = "401", description = "not authenticated / invalid credentials")
|
||||||
|
@ApiResponse(responseCode = "403", description = "not authorized, the current user has no privileges to read the changeset")
|
||||||
|
@ApiResponse(
|
||||||
|
responseCode = "404",
|
||||||
|
description = "not found, no changesets available in the repository",
|
||||||
|
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 getAll(@PathParam("namespace") String namespace, @PathParam("name") String name,
|
public Response getAll(@PathParam("namespace") String namespace, @PathParam("name") String name,
|
||||||
@PathParam("revision") String revision,
|
@PathParam("revision") String revision,
|
||||||
@PathParam("path") String path,
|
@PathParam("path") String path,
|
||||||
|
|||||||
@@ -3,6 +3,12 @@ package sonia.scm.api.v2.resources;
|
|||||||
import com.webcohesion.enunciate.metadata.rs.ResponseCode;
|
import com.webcohesion.enunciate.metadata.rs.ResponseCode;
|
||||||
import com.webcohesion.enunciate.metadata.rs.StatusCodes;
|
import com.webcohesion.enunciate.metadata.rs.StatusCodes;
|
||||||
import com.webcohesion.enunciate.metadata.rs.TypeHint;
|
import com.webcohesion.enunciate.metadata.rs.TypeHint;
|
||||||
|
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 org.apache.shiro.authc.credential.PasswordService;
|
import org.apache.shiro.authc.credential.PasswordService;
|
||||||
import sonia.scm.user.UserManager;
|
import sonia.scm.user.UserManager;
|
||||||
import sonia.scm.web.VndMediaType;
|
import sonia.scm.web.VndMediaType;
|
||||||
@@ -23,11 +29,13 @@ import javax.ws.rs.core.UriInfo;
|
|||||||
/**
|
/**
|
||||||
* RESTful Web Service Resource to get currently logged in users.
|
* RESTful Web Service Resource to get currently logged in users.
|
||||||
*/
|
*/
|
||||||
|
@OpenAPIDefinition(tags = {
|
||||||
|
@Tag(name = "Me", description = "Me related endpoints")
|
||||||
|
})
|
||||||
@Path(MeResource.ME_PATH_V2)
|
@Path(MeResource.ME_PATH_V2)
|
||||||
public class MeResource {
|
public class MeResource {
|
||||||
|
|
||||||
static final String ME_PATH_V2 = "v2/me/";
|
static final String ME_PATH_V2 = "v2/me/";
|
||||||
|
|
||||||
private final MeDtoFactory meDtoFactory;
|
private final MeDtoFactory meDtoFactory;
|
||||||
private final UserManager userManager;
|
private final UserManager userManager;
|
||||||
private final PasswordService passwordService;
|
private final PasswordService passwordService;
|
||||||
@@ -45,12 +53,23 @@ public class MeResource {
|
|||||||
@GET
|
@GET
|
||||||
@Path("")
|
@Path("")
|
||||||
@Produces(VndMediaType.ME)
|
@Produces(VndMediaType.ME)
|
||||||
@TypeHint(MeDto.class)
|
@Operation(summary = "Current user", description = "Returns the currently logged in user or a 401 if user is not logged in.", tags = "Me")
|
||||||
@StatusCodes({
|
@ApiResponse(
|
||||||
@ResponseCode(code = 200, condition = "success"),
|
responseCode = "200",
|
||||||
@ResponseCode(code = 401, condition = "not authenticated / invalid credentials"),
|
description = "success",
|
||||||
@ResponseCode(code = 500, condition = "internal server error")
|
content = @Content(
|
||||||
})
|
mediaType = VndMediaType.ME,
|
||||||
|
schema = @Schema(implementation = MeDto.class)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
@ApiResponse(responseCode = "401", description = "not authenticated / invalid credentials")
|
||||||
|
@ApiResponse(
|
||||||
|
responseCode = "500",
|
||||||
|
description = "internal server error",
|
||||||
|
content = @Content(
|
||||||
|
mediaType = VndMediaType.ERROR_TYPE,
|
||||||
|
schema = @Schema(implementation = ErrorDto.class)
|
||||||
|
))
|
||||||
public Response get(@Context Request request, @Context UriInfo uriInfo) {
|
public Response get(@Context Request request, @Context UriInfo uriInfo) {
|
||||||
return Response.ok(meDtoFactory.create()).build();
|
return Response.ok(meDtoFactory.create()).build();
|
||||||
}
|
}
|
||||||
@@ -60,13 +79,17 @@ public class MeResource {
|
|||||||
*/
|
*/
|
||||||
@PUT
|
@PUT
|
||||||
@Path("password")
|
@Path("password")
|
||||||
@StatusCodes({
|
|
||||||
@ResponseCode(code = 204, condition = "update success"),
|
|
||||||
@ResponseCode(code = 401, condition = "not authenticated / invalid credentials"),
|
|
||||||
@ResponseCode(code = 500, condition = "internal server error")
|
|
||||||
})
|
|
||||||
@TypeHint(TypeHint.NO_CONTENT.class)
|
|
||||||
@Consumes(VndMediaType.PASSWORD_CHANGE)
|
@Consumes(VndMediaType.PASSWORD_CHANGE)
|
||||||
|
@Operation(summary = "Change password", description = "Change password of the current user.", tags = "Me")
|
||||||
|
@ApiResponse(responseCode = "204", description = "update success")
|
||||||
|
@ApiResponse(responseCode = "401", description = "not authenticated / invalid credentials")
|
||||||
|
@ApiResponse(
|
||||||
|
responseCode = "500",
|
||||||
|
description = "internal server error",
|
||||||
|
content = @Content(
|
||||||
|
mediaType = VndMediaType.ERROR_TYPE,
|
||||||
|
schema = @Schema(implementation = ErrorDto.class)
|
||||||
|
))
|
||||||
public Response changePassword(@Valid PasswordChangeDto passwordChange) {
|
public Response changePassword(@Valid PasswordChangeDto passwordChange) {
|
||||||
userManager.changePasswordForLoggedInUser(
|
userManager.changePasswordForLoggedInUser(
|
||||||
passwordService.encryptPassword(passwordChange.getOldPassword()),
|
passwordService.encryptPassword(passwordChange.getOldPassword()),
|
||||||
|
|||||||
Reference in New Issue
Block a user