mirror of
https://github.com/scm-manager/scm-manager.git
synced 2025-11-12 16:35:45 +01:00
Polishing during review.
Extends REST API docs, straightens naming, cleans up dependencies, clears warnings, does a bit of formatting, etc.
This commit is contained in:
@@ -405,19 +405,6 @@
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<!-- Validation -->
|
||||
|
||||
<dependency>
|
||||
<groupId>javax.validation</groupId>
|
||||
<artifactId>validation-api</artifactId>
|
||||
<version>2.0.1.Final</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.hibernate</groupId>
|
||||
<artifactId>hibernate-validator</artifactId>
|
||||
<version>6.0.10.Final</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
@@ -871,7 +858,7 @@
|
||||
<dependency>
|
||||
<groupId>com.webcohesion.enunciate</groupId>
|
||||
<artifactId>enunciate-top</artifactId>
|
||||
<version>2.9.1</version>
|
||||
<version>${enunciate.version}</version>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>com.webcohesion.enunciate</groupId>
|
||||
@@ -879,6 +866,11 @@
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.webcohesion.enunciate</groupId>
|
||||
<artifactId>enunciate-lombok</artifactId>
|
||||
<version>${enunciate.version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</plugin>
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@ import static java.util.Optional.ofNullable;
|
||||
* the {@link JsonNode} tree.</p>
|
||||
*/
|
||||
@Provider
|
||||
@Priority(FilterPriorities.FIELD_FILTER)
|
||||
@Priority(ResponseFilterPriorities.FIELD_FILTER)
|
||||
public class FieldContainerResponseFilter implements ContainerResponseFilter {
|
||||
|
||||
private static final String PARAMETER_FIELDS = "fields";
|
||||
|
||||
@@ -11,12 +11,12 @@ import java.util.Map;
|
||||
|
||||
import static java.util.Arrays.stream;
|
||||
|
||||
public final class JsonFilters {
|
||||
final class JsonFilters {
|
||||
|
||||
private JsonFilters() {
|
||||
}
|
||||
|
||||
public static void filterByFields(JsonNode root, Collection<String> filterExpressions) {
|
||||
static void filterByFields(JsonNode root, Collection<String> filterExpressions) {
|
||||
createJsonFilterNode(filterExpressions).filterNode(root);
|
||||
}
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@ import java.util.Set;
|
||||
* and processes all registered plugins for the {@link JsonEnricher} extension point.
|
||||
*/
|
||||
@Provider
|
||||
@Priority(FilterPriorities.JSON_MARSHALLING)
|
||||
@Priority(ResponseFilterPriorities.JSON_MARSHALLING)
|
||||
public class JsonMarshallingResponseFilter implements ContainerResponseFilter {
|
||||
|
||||
private final ObjectMapper objectMapper;
|
||||
|
||||
@@ -5,16 +5,17 @@ import javax.ws.rs.Priorities;
|
||||
|
||||
/**
|
||||
* A collection of filter priorities used by custom {@link javax.ws.rs.container.ContainerResponseFilter}s.
|
||||
* Higher number means earlier execution in the response filter chain.
|
||||
*/
|
||||
final class FilterPriorities {
|
||||
final class ResponseFilterPriorities {
|
||||
|
||||
/**
|
||||
* Other filters depend on already marshalled {@link com.fasterxml.jackson.databind.JsonNode} trees. Thus, JSON
|
||||
* marshalling has to happen before those filters
|
||||
*/
|
||||
static final int JSON_MARSHALLING = Priorities.USER + 1000;
|
||||
static final int FIELD_FILTER = JSON_MARSHALLING - 1000;
|
||||
static final int FIELD_FILTER = Priorities.USER;
|
||||
|
||||
private FilterPriorities() {
|
||||
private ResponseFilterPriorities() {
|
||||
}
|
||||
}
|
||||
@@ -16,10 +16,8 @@ import static de.otto.edison.hal.Links.linkingTo;
|
||||
import static sonia.scm.api.v2.resources.ResourceLinks.group;
|
||||
import static sonia.scm.api.v2.resources.ResourceLinks.user;
|
||||
|
||||
/**
|
||||
* Mapstruct does not support parameterized (i.e. non-default) constructors. Thus, we need to use field injection.
|
||||
*/
|
||||
@java.lang.SuppressWarnings("squid:S3306")
|
||||
// Mapstruct does not support parameterized (i.e. non-default) constructors. Thus, we need to use field injection.
|
||||
@SuppressWarnings("squid:S3306")
|
||||
@Mapper
|
||||
public abstract class GroupToGroupDtoMapper extends BaseMapper<Group, GroupDto> {
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* This class is used to create links for JAX-RS resources. Create a new instance specifying all resource classes used
|
||||
* to process the request. Than for each of these classes call <code>builder.method(...).parameters(...)</code> for each
|
||||
* to process the request. Then for each of these classes call <code>builder.method(...).parameters(...)</code> for each
|
||||
* of these classes consecutively. The builder itself is immutable, so that each instance is reusable and you get a new
|
||||
* builder for each method.
|
||||
*
|
||||
|
||||
@@ -4,13 +4,16 @@ import de.otto.edison.hal.HalRepresentation;
|
||||
import de.otto.edison.hal.Links;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
@Data @NoArgsConstructor @AllArgsConstructor
|
||||
@NoArgsConstructor @AllArgsConstructor
|
||||
@Data @EqualsAndHashCode(callSuper = false)
|
||||
public class MemberDto extends HalRepresentation {
|
||||
private String name;
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("squid:S1185") // We want to have this method available in this package
|
||||
protected HalRepresentation add(Links links) {
|
||||
return super.add(links);
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ package sonia.scm.api.v2.resources;
|
||||
|
||||
import com.webcohesion.enunciate.metadata.rs.ResponseCode;
|
||||
import com.webcohesion.enunciate.metadata.rs.ResponseHeader;
|
||||
import com.webcohesion.enunciate.metadata.rs.ResponseHeaders;
|
||||
import com.webcohesion.enunciate.metadata.rs.StatusCodes;
|
||||
import com.webcohesion.enunciate.metadata.rs.TypeHint;
|
||||
import sonia.scm.PageResult;
|
||||
@@ -31,12 +32,14 @@ import static sonia.scm.api.v2.resources.ResourceLinks.user;
|
||||
|
||||
@Produces(VndMediaType.USER_COLLECTION)
|
||||
public class UserCollectionResource extends AbstractManagerResource<User, UserException> {
|
||||
public static final int DEFAULT_PAGE_SIZE = 10;
|
||||
|
||||
private static final int DEFAULT_PAGE_SIZE = 10;
|
||||
private final UserDtoToUserMapper dtoToUserMapper;
|
||||
private final UserCollectionToDtoMapper userCollectionToDtoMapper;
|
||||
|
||||
@Inject
|
||||
public UserCollectionResource(UserManager manager, UserDtoToUserMapper dtoToUserMapper, UserCollectionToDtoMapper userCollectionToDtoMapper) {
|
||||
public UserCollectionResource(UserManager manager, UserDtoToUserMapper dtoToUserMapper,
|
||||
UserCollectionToDtoMapper userCollectionToDtoMapper) {
|
||||
super(manager);
|
||||
this.dtoToUserMapper = dtoToUserMapper;
|
||||
this.userCollectionToDtoMapper = userCollectionToDtoMapper;
|
||||
@@ -44,50 +47,52 @@ public class UserCollectionResource extends AbstractManagerResource<User, UserEx
|
||||
|
||||
/**
|
||||
* Returns all users for a given page number with a given page size (default page size is {@value DEFAULT_PAGE_SIZE}).
|
||||
* <strong>Note:</strong> This method requires admin privileges.
|
||||
*
|
||||
* <strong>Note:</strong> This method requires "user" privileges.
|
||||
*
|
||||
* @param request the current request
|
||||
* @param page the number of the requested page
|
||||
* @param pageSize the page size (default page size is {@value DEFAULT_PAGE_SIZE})
|
||||
* @param sortby sort parameter
|
||||
* @param desc sort direction desc or aesc
|
||||
* @return
|
||||
* @param sortBy sort parameter
|
||||
* @param desc sort direction desc or asc
|
||||
*/
|
||||
@GET
|
||||
@Path("")
|
||||
@TypeHint(UserDto[].class)
|
||||
@StatusCodes({
|
||||
@ResponseCode(code = 200, condition = "success"),
|
||||
@ResponseCode(code = 403, condition = "forbidden, the current user has no admin privileges"),
|
||||
@ResponseCode(code = 403, condition = "forbidden, the current user does not have the \"user\" privilege"),
|
||||
@ResponseCode(code = 500, condition = "internal server error")
|
||||
})
|
||||
@Override
|
||||
public Response getAll(@Context Request request,
|
||||
@DefaultValue("0") @QueryParam("page") int page,
|
||||
@DefaultValue("" + DEFAULT_PAGE_SIZE) @QueryParam("pageSize") int pageSize,
|
||||
@QueryParam("sortby") String sortby,
|
||||
@DefaultValue("false")
|
||||
@QueryParam("desc") boolean desc) {
|
||||
PageResult<User> pageResult = fetchPage(sortby, desc, page, pageSize);
|
||||
@QueryParam("sortby") String sortBy,
|
||||
@DefaultValue("false") @QueryParam("desc") boolean desc) {
|
||||
|
||||
PageResult<User> pageResult = fetchPage(sortBy, desc, page, pageSize);
|
||||
|
||||
return Response.ok(userCollectionToDtoMapper.map(page, pageSize, pageResult)).build();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new user.
|
||||
*
|
||||
* <strong>Note:</strong> This method requires "user" privileges.
|
||||
*
|
||||
* @param userDto The user to be created.
|
||||
* @return A response with the link to the new user (if created successfully).
|
||||
*/
|
||||
@POST
|
||||
@Path("")
|
||||
@StatusCodes({
|
||||
@ResponseCode(code = 201, condition = "create success", additionalHeaders = {
|
||||
@ResponseHeader(name = "Location", description = "uri to the created group")
|
||||
}),
|
||||
@ResponseCode(code = 403, condition = "forbidden, the current user has no admin privileges"),
|
||||
@ResponseCode(code = 201, condition = "create success"),
|
||||
@ResponseCode(code = 403, condition = "forbidden, the current user does not have the \"user\" privilege"),
|
||||
@ResponseCode(code = 500, condition = "internal server error")
|
||||
})
|
||||
@TypeHint(TypeHint.NO_CONTENT.class)
|
||||
@ResponseHeaders(@ResponseHeader(name = "Location", description = "uri to the created user"))
|
||||
public Response create(@Context UriInfo uriInfo, UserDto userDto) throws IOException, UserException {
|
||||
if (userDto == null) {
|
||||
return Response.status(400).build();
|
||||
|
||||
@@ -7,10 +7,8 @@ import javax.inject.Inject;
|
||||
|
||||
import static sonia.scm.api.v2.resources.ResourceLinks.userCollection;
|
||||
|
||||
/**
|
||||
* Mapstruct does not support parameterized (i.e. non-default) constructors. Thus, we need to use field injection.
|
||||
*/
|
||||
@java.lang.SuppressWarnings("squid:S3306")
|
||||
// Mapstruct does not support parameterized (i.e. non-default) constructors. Thus, we need to use field injection.
|
||||
@SuppressWarnings("squid:S3306")
|
||||
public class UserCollectionToDtoMapper extends BasicCollectionToDtoMapper<User, UserDto> {
|
||||
|
||||
private final UriInfoStore uriInfoStore;
|
||||
|
||||
@@ -5,12 +5,14 @@ import de.otto.edison.hal.HalRepresentation;
|
||||
import de.otto.edison.hal.Links;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.time.Instant;
|
||||
import java.util.Optional;
|
||||
|
||||
@Data @AllArgsConstructor @NoArgsConstructor
|
||||
@AllArgsConstructor @NoArgsConstructor
|
||||
@Data @EqualsAndHashCode(callSuper = false)
|
||||
public class UserDto extends HalRepresentation {
|
||||
private boolean active;
|
||||
private boolean admin;
|
||||
@@ -24,6 +26,7 @@ public class UserDto extends HalRepresentation {
|
||||
private String type;
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("squid:S1185") // We want to have this method available in this package
|
||||
protected HalRepresentation add(Links links) {
|
||||
return super.add(links);
|
||||
}
|
||||
|
||||
@@ -11,10 +11,8 @@ import javax.inject.Inject;
|
||||
|
||||
import static sonia.scm.api.rest.resources.UserResource.DUMMY_PASSWORT;
|
||||
|
||||
/**
|
||||
* Mapstruct does not support parameterized (i.e. non-default) constructors. Thus, we need to use field injection.
|
||||
*/
|
||||
@java.lang.SuppressWarnings("squid:S3306")
|
||||
// Mapstruct does not support parameterized (i.e. non-default) constructors. Thus, we need to use field injection.
|
||||
@SuppressWarnings("squid:S3306")
|
||||
@Mapper
|
||||
public abstract class UserDtoToUserMapper {
|
||||
|
||||
|
||||
@@ -26,6 +26,7 @@ import java.util.Collection;
|
||||
|
||||
@Produces(VndMediaType.USER)
|
||||
public class UserResource extends AbstractManagerResource<User, UserException> {
|
||||
|
||||
private final UserDtoToUserMapper dtoToUserMapper;
|
||||
private final UserToUserDtoMapper userToDtoMapper;
|
||||
|
||||
@@ -36,6 +37,15 @@ public class UserResource extends AbstractManagerResource<User, UserException> {
|
||||
this.userToDtoMapper = userToDtoMapper;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a user.
|
||||
*
|
||||
* <strong>Note:</strong> This method requires "user" privileges.
|
||||
*
|
||||
* @param request the current request
|
||||
* @param id the id/name of the user
|
||||
*
|
||||
*/
|
||||
@GET
|
||||
@Path("")
|
||||
@TypeHint(UserDto.class)
|
||||
@@ -54,11 +64,19 @@ public class UserResource extends AbstractManagerResource<User, UserException> {
|
||||
return Response.ok(userDto).build();
|
||||
}
|
||||
|
||||
/**
|
||||
* Modifies the given user.
|
||||
*
|
||||
* <strong>Note:</strong> This method requires "user" privileges.
|
||||
*
|
||||
* @param name name of the user to be modified
|
||||
* @param userDto user object to modify
|
||||
*/
|
||||
@PUT
|
||||
@Path("")
|
||||
@StatusCodes({
|
||||
@ResponseCode(code = 204, condition = "update success"),
|
||||
@ResponseCode(code = 403, condition = "forbidden, the current user has no admin privileges"),
|
||||
@ResponseCode(code = 403, condition = "forbidden, the current user does not have the \"user\" privilege"),
|
||||
@ResponseCode(code = 500, condition = "internal server error")
|
||||
})
|
||||
@TypeHint(TypeHint.NO_CONTENT.class)
|
||||
@@ -69,14 +87,23 @@ public class UserResource extends AbstractManagerResource<User, UserException> {
|
||||
return update(name, user);
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes a user.
|
||||
*
|
||||
* <strong>Note:</strong> This method requires "user" privileges.
|
||||
*
|
||||
* @param name the name of the user to delete.
|
||||
*
|
||||
*/
|
||||
@DELETE
|
||||
@Path("")
|
||||
@StatusCodes({
|
||||
@ResponseCode(code = 204, condition = "delete success"),
|
||||
@ResponseCode(code = 403, condition = "forbidden, the current user has no admin privileges"),
|
||||
@ResponseCode(code = 403, condition = "forbidden, the current user does not have the \"user\" privilege"),
|
||||
@ResponseCode(code = 500, condition = "internal server error")
|
||||
})
|
||||
@TypeHint(TypeHint.NO_CONTENT.class)
|
||||
@Override
|
||||
public Response delete(@PathParam("id") String name) {
|
||||
return super.delete(name);
|
||||
}
|
||||
|
||||
@@ -4,10 +4,13 @@ import javax.inject.Inject;
|
||||
import javax.inject.Provider;
|
||||
import javax.ws.rs.Path;
|
||||
|
||||
/**
|
||||
* RESTful Web Service Resource to manage users.
|
||||
*/
|
||||
@Path(UserRootResource.USERS_PATH_V2)
|
||||
public class UserRootResource {
|
||||
|
||||
public static final String USERS_PATH_V2 = "v2/users/";
|
||||
static final String USERS_PATH_V2 = "v2/users/";
|
||||
private final Provider<UserCollectionResource> userCollectionResource;
|
||||
private final Provider<UserResource> userResource;
|
||||
|
||||
|
||||
@@ -14,10 +14,8 @@ import static de.otto.edison.hal.Link.link;
|
||||
import static de.otto.edison.hal.Links.linkingTo;
|
||||
import static sonia.scm.api.v2.resources.ResourceLinks.user;
|
||||
|
||||
/**
|
||||
* Mapstruct does not support parameterized (i.e. non-default) constructors. Thus, we need to use field injection.
|
||||
*/
|
||||
@java.lang.SuppressWarnings("squid:S3306")
|
||||
// Mapstruct does not support parameterized (i.e. non-default) constructors. Thus, we need to use field injection.
|
||||
@SuppressWarnings("squid:S3306")
|
||||
@Mapper
|
||||
public abstract class UserToUserDtoMapper extends BaseMapper<User, UserDto> {
|
||||
|
||||
|
||||
@@ -80,7 +80,8 @@ public class UserRootResourceTest {
|
||||
UserCollectionResource userCollectionResource = new UserCollectionResource(userManager, dtoToUserMapper,
|
||||
userCollectionToDtoMapper);
|
||||
UserResource userResource = new UserResource(dtoToUserMapper, userToDtoMapper, userManager);
|
||||
UserRootResource userRootResource = new UserRootResource(MockProvider.of(userCollectionResource), MockProvider.of(userResource));
|
||||
UserRootResource userRootResource = new UserRootResource(MockProvider.of(userCollectionResource),
|
||||
MockProvider.of(userResource));
|
||||
|
||||
dispatcher.getRegistry().addSingletonResource(userRootResource);
|
||||
when(uriInfo.getBaseUri()).thenReturn(URI.create("/"));
|
||||
|
||||
Reference in New Issue
Block a user