diff --git a/scm-core/src/main/java/sonia/scm/PageResult.java b/scm-core/src/main/java/sonia/scm/PageResult.java index 34fa37e5ee..87f880637d 100644 --- a/scm-core/src/main/java/sonia/scm/PageResult.java +++ b/scm-core/src/main/java/sonia/scm/PageResult.java @@ -3,6 +3,10 @@ package sonia.scm; import java.util.Collection; import java.util.Collections; +/** + * This represents the result of a page request. Contains the results for + * the page and a flag whether there are more pages or not. + */ public class PageResult { private final Collection entities; @@ -13,10 +17,16 @@ public class PageResult { this.hasMore = hasMore; } + /** + * The entities for the current page. + */ public Collection getEntities() { return Collections.unmodifiableCollection(entities); } + /** + * If this is true, there are more pages (that is, mor entities). + */ public boolean hasMore() { return hasMore; } diff --git a/scm-core/src/main/java/sonia/scm/web/JsonEnricher.java b/scm-core/src/main/java/sonia/scm/web/JsonEnricher.java index 9b0f078f8b..067136d71f 100644 --- a/scm-core/src/main/java/sonia/scm/web/JsonEnricher.java +++ b/scm-core/src/main/java/sonia/scm/web/JsonEnricher.java @@ -2,6 +2,11 @@ package sonia.scm.web; import sonia.scm.plugin.ExtensionPoint; +/** + * Implementing this extension point you can post process json response objects. + * To do so, you get a {@link JsonEnricherContext} with the complete json tree, + * that can be modified. + */ @ExtensionPoint public interface JsonEnricher { diff --git a/scm-core/src/main/java/sonia/scm/web/JsonEnricherContext.java b/scm-core/src/main/java/sonia/scm/web/JsonEnricherContext.java index 6dd88d326c..3b18a34f3f 100644 --- a/scm-core/src/main/java/sonia/scm/web/JsonEnricherContext.java +++ b/scm-core/src/main/java/sonia/scm/web/JsonEnricherContext.java @@ -5,6 +5,10 @@ import com.fasterxml.jackson.databind.JsonNode; import javax.ws.rs.core.MediaType; import java.net.URI; +/** + * Process data for the {@link JsonEnricher} extension point giving context for + * post processing json results. + */ public class JsonEnricherContext { private URI requestUri; @@ -17,14 +21,24 @@ public class JsonEnricherContext { this.responseEntity = responseEntity; } + /** + * The URI of the originating request. + */ public URI getRequestUri() { return requestUri; } + /** + * The media type of the response. Using this you can determine the content of the result. + * @see VndMediaType + */ public MediaType getResponseMediaType() { return responseMediaType; } + /** + * The json result represented by nodes, that can be modified. + */ public JsonNode getResponseEntity() { return responseEntity; } diff --git a/scm-core/src/main/java/sonia/scm/web/VndMediaType.java b/scm-core/src/main/java/sonia/scm/web/VndMediaType.java index 92b85b022f..d81986cd6e 100644 --- a/scm-core/src/main/java/sonia/scm/web/VndMediaType.java +++ b/scm-core/src/main/java/sonia/scm/web/VndMediaType.java @@ -2,6 +2,9 @@ package sonia.scm.web; import javax.ws.rs.core.MediaType; +/** + * Vendor media types used by SCMM. + */ public class VndMediaType { private static final String VERSION = "2"; private static final String TYPE = "application"; @@ -10,18 +13,14 @@ public class VndMediaType { private static final String SUFFIX = "+json;v=" + VERSION; public static final String USER = PREFIX + "user" + SUFFIX; + public static final String USER_COLLECTION = PREFIX + "userCollection" + SUFFIX; private VndMediaType() { } - public static MediaType jsonType(String resource) { - return MediaType.valueOf(json(resource)); - } - - public static String json(String resource) { - return PREFIX + resource + SUFFIX;// ".v2+json"; - } - + /** + * Checks whether the given media type is a media type used by SCMM. + */ public static boolean isVndType(MediaType type) { return type.getType().equals(TYPE) && type.getSubtype().startsWith(SUBTYPE_PREFIX); } diff --git a/scm-webapp/pom.xml b/scm-webapp/pom.xml index 4a01375ef4..26b0919d7b 100644 --- a/scm-webapp/pom.xml +++ b/scm-webapp/pom.xml @@ -23,7 +23,7 @@ sonia.scm scm-annotation-processor 2.0.0-SNAPSHOT - true + provided diff --git a/scm-webapp/src/main/java/sonia/scm/ScmContextListener.java b/scm-webapp/src/main/java/sonia/scm/ScmContextListener.java index cb272de38f..21ca876e41 100644 --- a/scm-webapp/src/main/java/sonia/scm/ScmContextListener.java +++ b/scm-webapp/src/main/java/sonia/scm/ScmContextListener.java @@ -39,10 +39,14 @@ import com.google.common.base.Throwables; import com.google.common.collect.Lists; import com.google.inject.Injector; import com.google.inject.Module; + import org.apache.shiro.guice.web.ShiroWebModule; -import org.jboss.resteasy.plugins.guice.GuiceResteasyBootstrapServletContextListener; + import org.slf4j.Logger; import org.slf4j.LoggerFactory; + +import org.jboss.resteasy.plugins.guice.GuiceResteasyBootstrapServletContextListener; + import sonia.scm.api.v2.resources.MapperModule; import sonia.scm.cache.CacheManager; import sonia.scm.debug.DebugModule; @@ -57,13 +61,14 @@ import sonia.scm.upgrade.UpgradeManager; import sonia.scm.user.UserManager; import sonia.scm.util.IOUtil; -import javax.servlet.ServletContext; -import javax.servlet.ServletContextEvent; -import java.util.Collections; +//~--- JDK imports ------------------------------------------------------------ + import java.util.List; import java.util.Set; +import java.util.Collections; -//~--- JDK imports ------------------------------------------------------------ +import javax.servlet.ServletContext; +import javax.servlet.ServletContextEvent; /** * diff --git a/scm-webapp/src/main/java/sonia/scm/ScmServletModule.java b/scm-webapp/src/main/java/sonia/scm/ScmServletModule.java index 2f6e7341bb..a09de33465 100644 --- a/scm-webapp/src/main/java/sonia/scm/ScmServletModule.java +++ b/scm-webapp/src/main/java/sonia/scm/ScmServletModule.java @@ -42,8 +42,10 @@ import com.google.inject.name.Names; import com.google.inject.servlet.RequestScoped; import com.google.inject.servlet.ServletModule; import com.google.inject.throwingproviders.ThrowingProviderBinder; + import org.slf4j.Logger; import org.slf4j.LoggerFactory; + import sonia.scm.api.rest.ObjectMapperProvider; import sonia.scm.cache.CacheManager; import sonia.scm.cache.GuavaCacheManager; @@ -56,13 +58,18 @@ import sonia.scm.group.GroupManagerProvider; import sonia.scm.group.xml.XmlGroupDAO; import sonia.scm.io.DefaultFileSystem; import sonia.scm.io.FileSystem; -import sonia.scm.net.SSLContextProvider; -import sonia.scm.net.ahc.*; import sonia.scm.plugin.DefaultPluginLoader; import sonia.scm.plugin.DefaultPluginManager; import sonia.scm.plugin.PluginLoader; import sonia.scm.plugin.PluginManager; -import sonia.scm.repository.*; +import sonia.scm.repository.DefaultRepositoryManager; +import sonia.scm.repository.DefaultRepositoryProvider; +import sonia.scm.repository.HealthCheckContextListener; +import sonia.scm.repository.Repository; +import sonia.scm.repository.RepositoryDAO; +import sonia.scm.repository.RepositoryManager; +import sonia.scm.repository.RepositoryManagerProvider; +import sonia.scm.repository.RepositoryProvider; import sonia.scm.repository.api.HookContextFactory; import sonia.scm.repository.api.RepositoryServiceFactory; import sonia.scm.repository.spi.HookEventFacade; @@ -71,15 +78,28 @@ import sonia.scm.resources.DefaultResourceManager; import sonia.scm.resources.DevelopmentResourceManager; import sonia.scm.resources.ResourceManager; import sonia.scm.resources.ScriptResourceServlet; -import sonia.scm.schedule.QuartzScheduler; -import sonia.scm.schedule.Scheduler; -import sonia.scm.security.*; -import sonia.scm.store.*; +import sonia.scm.security.CipherHandler; +import sonia.scm.security.CipherUtil; +import sonia.scm.security.DefaultKeyGenerator; +import sonia.scm.security.DefaultSecuritySystem; +import sonia.scm.security.KeyGenerator; +import sonia.scm.security.SecuritySystem; +import sonia.scm.store.BlobStoreFactory; +import sonia.scm.store.ConfigurationEntryStoreFactory; +import sonia.scm.store.DataStoreFactory; +import sonia.scm.store.FileBlobStoreFactory; +import sonia.scm.store.JAXBConfigurationEntryStoreFactory; +import sonia.scm.store.JAXBDataStoreFactory; +import sonia.scm.store.JAXBConfigurationStoreFactory; import sonia.scm.template.MustacheTemplateEngine; import sonia.scm.template.TemplateEngine; import sonia.scm.template.TemplateEngineFactory; import sonia.scm.template.TemplateServlet; -import sonia.scm.url.*; +import sonia.scm.url.RestJsonUrlProvider; +import sonia.scm.url.RestXmlUrlProvider; +import sonia.scm.url.UrlProvider; +import sonia.scm.url.UrlProviderFactory; +import sonia.scm.url.WebUIUrlProvider; import sonia.scm.user.DefaultUserManager; import sonia.scm.user.UserDAO; import sonia.scm.user.UserManager; @@ -87,18 +107,32 @@ import sonia.scm.user.UserManagerProvider; import sonia.scm.user.xml.XmlUserDAO; import sonia.scm.util.DebugServlet; import sonia.scm.util.ScmConfigurationUtil; -import sonia.scm.web.UserAgentParser; import sonia.scm.web.cgi.CGIExecutorFactory; import sonia.scm.web.cgi.DefaultCGIExecutorFactory; import sonia.scm.web.filter.LoggingFilter; import sonia.scm.web.security.AdministrationContext; import sonia.scm.web.security.DefaultAdministrationContext; -import javax.net.ssl.SSLContext; -import javax.servlet.ServletContext; - //~--- JDK imports ------------------------------------------------------------ + +import javax.servlet.ServletContext; +import sonia.scm.store.ConfigurationStoreFactory; + +import javax.net.ssl.SSLContext; +import sonia.scm.net.SSLContextProvider; +import sonia.scm.net.ahc.AdvancedHttpClient; +import sonia.scm.net.ahc.ContentTransformer; +import sonia.scm.net.ahc.DefaultAdvancedHttpClient; +import sonia.scm.net.ahc.JsonContentTransformer; +import sonia.scm.net.ahc.XmlContentTransformer; +import sonia.scm.schedule.QuartzScheduler; +import sonia.scm.schedule.Scheduler; +import sonia.scm.security.ConfigurableLoginAttemptHandler; +import sonia.scm.security.LoginAttemptHandler; +import sonia.scm.security.AuthorizationChangedEventProducer; +import sonia.scm.web.UserAgentParser; + /** * * @author Sebastian Sdorra diff --git a/scm-webapp/src/main/java/sonia/scm/api/rest/resources/AbstractManagerResource.java b/scm-webapp/src/main/java/sonia/scm/api/rest/resources/AbstractManagerResource.java index 62f77f2513..d4e7e71b03 100644 --- a/scm-webapp/src/main/java/sonia/scm/api/rest/resources/AbstractManagerResource.java +++ b/scm-webapp/src/main/java/sonia/scm/api/rest/resources/AbstractManagerResource.java @@ -37,8 +37,10 @@ package sonia.scm.api.rest.resources; import org.apache.commons.beanutils.BeanComparator; import org.apache.shiro.authz.AuthorizationException; + import org.slf4j.Logger; import org.slf4j.LoggerFactory; + import sonia.scm.LastModifiedAware; import sonia.scm.Manager; import sonia.scm.ModelObject; @@ -48,13 +50,19 @@ import sonia.scm.util.AssertUtil; import sonia.scm.util.HttpUtil; import sonia.scm.util.Util; -import javax.ws.rs.core.*; -import javax.ws.rs.core.Response.Status; +//~--- JDK imports ------------------------------------------------------------ + import java.util.Collection; import java.util.Comparator; import java.util.Date; -//~--- JDK imports ------------------------------------------------------------ +import javax.ws.rs.core.CacheControl; +import javax.ws.rs.core.EntityTag; +import javax.ws.rs.core.GenericEntity; +import javax.ws.rs.core.Request; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.Response.Status; +import javax.ws.rs.core.UriInfo; /** * @@ -559,7 +567,7 @@ public abstract class AbstractManagerResource fetchItems(String sortby, boolean desc, int start, + private Collection fetchItems(String sortby, boolean desc, int start, int limit) { AssertUtil.assertPositive(start); diff --git a/scm-webapp/src/main/java/sonia/scm/api/rest/resources/GroupResource.java b/scm-webapp/src/main/java/sonia/scm/api/rest/resources/GroupResource.java index c0643d095c..364a1b200e 100644 --- a/scm-webapp/src/main/java/sonia/scm/api/rest/resources/GroupResource.java +++ b/scm-webapp/src/main/java/sonia/scm/api/rest/resources/GroupResource.java @@ -41,17 +41,34 @@ import com.webcohesion.enunciate.metadata.rs.ResponseCode; import com.webcohesion.enunciate.metadata.rs.ResponseHeader; import com.webcohesion.enunciate.metadata.rs.StatusCodes; import com.webcohesion.enunciate.metadata.rs.TypeHint; + import org.apache.shiro.SecurityUtils; + import sonia.scm.group.Group; import sonia.scm.group.GroupException; import sonia.scm.group.GroupManager; import sonia.scm.security.Role; -import javax.ws.rs.*; -import javax.ws.rs.core.*; +//~--- JDK imports ------------------------------------------------------------ + import java.util.Collection; -//~--- JDK imports ------------------------------------------------------------ +import javax.ws.rs.Consumes; +import javax.ws.rs.DELETE; +import javax.ws.rs.DefaultValue; +import javax.ws.rs.GET; +import javax.ws.rs.POST; +import javax.ws.rs.PUT; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.Produces; +import javax.ws.rs.QueryParam; +import javax.ws.rs.core.Context; +import javax.ws.rs.core.GenericEntity; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Request; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.UriInfo; /** * RESTful Web Service Resource to manage groups and their members. diff --git a/scm-webapp/src/main/java/sonia/scm/api/rest/resources/RepositoryResource.java b/scm-webapp/src/main/java/sonia/scm/api/rest/resources/RepositoryResource.java index a4133d07ea..06345b9fdd 100644 --- a/scm-webapp/src/main/java/sonia/scm/api/rest/resources/RepositoryResource.java +++ b/scm-webapp/src/main/java/sonia/scm/api/rest/resources/RepositoryResource.java @@ -42,26 +42,66 @@ import com.webcohesion.enunciate.metadata.rs.ResponseCode; import com.webcohesion.enunciate.metadata.rs.ResponseHeader; import com.webcohesion.enunciate.metadata.rs.StatusCodes; import com.webcohesion.enunciate.metadata.rs.TypeHint; + import org.apache.shiro.SecurityUtils; -import org.apache.shiro.authz.AuthorizationException; + import org.slf4j.Logger; import org.slf4j.LoggerFactory; + import sonia.scm.config.ScmConfiguration; -import sonia.scm.repository.*; -import sonia.scm.repository.api.*; +import sonia.scm.repository.BlameResult; +import sonia.scm.repository.Branches; +import sonia.scm.repository.BrowserResult; +import sonia.scm.repository.Changeset; +import sonia.scm.repository.ChangesetPagingResult; +import sonia.scm.repository.HealthChecker; +import sonia.scm.repository.Permission; +import sonia.scm.repository.Repository; +import sonia.scm.repository.RepositoryException; +import sonia.scm.repository.RepositoryIsNotArchivedException; +import sonia.scm.repository.RepositoryManager; +import sonia.scm.repository.RepositoryNotFoundException; +import sonia.scm.repository.Tags; +import sonia.scm.repository.api.BlameCommandBuilder; +import sonia.scm.repository.api.BrowseCommandBuilder; +import sonia.scm.repository.api.CatCommandBuilder; +import sonia.scm.repository.api.CommandNotSupportedException; +import sonia.scm.repository.api.DiffCommandBuilder; +import sonia.scm.repository.api.DiffFormat; +import sonia.scm.repository.api.LogCommandBuilder; +import sonia.scm.repository.api.RepositoryService; +import sonia.scm.repository.api.RepositoryServiceFactory; import sonia.scm.util.AssertUtil; import sonia.scm.util.HttpUtil; import sonia.scm.util.IOUtil; import sonia.scm.util.Util; -import javax.ws.rs.*; -import javax.ws.rs.core.*; -import javax.ws.rs.core.Response.Status; +//~--- JDK imports ------------------------------------------------------------ + import java.io.IOException; + import java.util.ArrayList; import java.util.Collection; -//~--- JDK imports ------------------------------------------------------------ +import javax.ws.rs.Consumes; +import javax.ws.rs.DELETE; +import javax.ws.rs.DefaultValue; +import javax.ws.rs.GET; +import javax.ws.rs.POST; +import javax.ws.rs.PUT; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.Produces; +import javax.ws.rs.QueryParam; +import javax.ws.rs.core.Context; +import javax.ws.rs.core.GenericEntity; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Request; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.Response.Status; +import javax.ws.rs.core.StreamingOutput; +import javax.ws.rs.core.UriInfo; +import org.apache.shiro.authz.AuthorizationException; /** * Repository related RESTful Web Service Endpoint. diff --git a/scm-webapp/src/main/java/sonia/scm/api/rest/resources/UserResource.java b/scm-webapp/src/main/java/sonia/scm/api/rest/resources/UserResource.java index 2dbcc5130d..0aab581c3d 100644 --- a/scm-webapp/src/main/java/sonia/scm/api/rest/resources/UserResource.java +++ b/scm-webapp/src/main/java/sonia/scm/api/rest/resources/UserResource.java @@ -41,8 +41,10 @@ import com.webcohesion.enunciate.metadata.rs.ResponseCode; import com.webcohesion.enunciate.metadata.rs.ResponseHeader; import com.webcohesion.enunciate.metadata.rs.StatusCodes; import com.webcohesion.enunciate.metadata.rs.TypeHint; + import org.apache.shiro.SecurityUtils; import org.apache.shiro.authc.credential.PasswordService; + import sonia.scm.security.Role; import sonia.scm.user.User; import sonia.scm.user.UserException; @@ -50,11 +52,26 @@ import sonia.scm.user.UserManager; import sonia.scm.util.AssertUtil; import sonia.scm.util.Util; -import javax.ws.rs.*; -import javax.ws.rs.core.*; +//~--- JDK imports ------------------------------------------------------------ + import java.util.Collection; -//~--- JDK imports ------------------------------------------------------------ +import javax.ws.rs.Consumes; +import javax.ws.rs.DELETE; +import javax.ws.rs.DefaultValue; +import javax.ws.rs.GET; +import javax.ws.rs.POST; +import javax.ws.rs.PUT; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.Produces; +import javax.ws.rs.QueryParam; +import javax.ws.rs.core.Context; +import javax.ws.rs.core.GenericEntity; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Request; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.UriInfo; /** * RESTful Web Service Resource to manage users. diff --git a/scm-webapp/src/main/java/sonia/scm/api/v2/FieldContainerResponseFilter.java b/scm-webapp/src/main/java/sonia/scm/api/v2/FieldContainerResponseFilter.java index 4ba93a31d5..cc5291cb6b 100644 --- a/scm-webapp/src/main/java/sonia/scm/api/v2/FieldContainerResponseFilter.java +++ b/scm-webapp/src/main/java/sonia/scm/api/v2/FieldContainerResponseFilter.java @@ -13,6 +13,13 @@ import javax.ws.rs.ext.Provider; import java.util.List; import java.util.Optional; +/** + *

Post processor for rest requests filtering json responses when a {@value PARAMETER_FIELDS} query + * parameter is provided. In this case, only the given fields will returned. It is possible, to specify + * paths for nested fields. Multiple fields have to be devided using {@value FIELD_SEPARATOR}.

+ *

This requires the {@link JsonMarshallingResponseFilter} to be processed first to create + * the {@link JsonNode} tree.

+ */ @Provider @Priority(Priorities.USER) public class FieldContainerResponseFilter implements ContainerResponseFilter { diff --git a/scm-webapp/src/main/java/sonia/scm/api/v2/JsonMarshallingResponseFilter.java b/scm-webapp/src/main/java/sonia/scm/api/v2/JsonMarshallingResponseFilter.java index 3be159dbf8..8903ab8790 100644 --- a/scm-webapp/src/main/java/sonia/scm/api/v2/JsonMarshallingResponseFilter.java +++ b/scm-webapp/src/main/java/sonia/scm/api/v2/JsonMarshallingResponseFilter.java @@ -15,6 +15,10 @@ import javax.ws.rs.container.ContainerResponseFilter; import javax.ws.rs.ext.Provider; import java.util.Set; +/** + * Transforms json rest responses to {@link JsonNode} trees to support further post processing + * and processes all registered plugins for the {@link JsonEnricher} extension point. + */ @Provider @Priority(Priorities.USER + 1000) public class JsonMarshallingResponseFilter implements ContainerResponseFilter { diff --git a/scm-webapp/src/main/java/sonia/scm/api/v2/resources/ScmMediaType.java b/scm-webapp/src/main/java/sonia/scm/api/v2/resources/ScmMediaType.java deleted file mode 100644 index d9d8f0ecf1..0000000000 --- a/scm-webapp/src/main/java/sonia/scm/api/v2/resources/ScmMediaType.java +++ /dev/null @@ -1,4 +0,0 @@ -package sonia.scm.api.v2.resources; - -public class ScmMediaType { -} diff --git a/scm-webapp/src/main/java/sonia/scm/api/v2/resources/User2UserDtoMapper.java b/scm-webapp/src/main/java/sonia/scm/api/v2/resources/User2UserDtoMapper.java index 489fc588f4..eb984ecd7a 100644 --- a/scm-webapp/src/main/java/sonia/scm/api/v2/resources/User2UserDtoMapper.java +++ b/scm-webapp/src/main/java/sonia/scm/api/v2/resources/User2UserDtoMapper.java @@ -5,6 +5,7 @@ import org.mapstruct.*; import sonia.scm.api.rest.resources.UserResource; import sonia.scm.user.User; import sonia.scm.user.UserPermissions; +import sonia.scm.util.AssertUtil; import javax.ws.rs.core.UriInfo; import java.time.Instant; @@ -43,7 +44,7 @@ public abstract class User2UserDtoMapper { @Mapping(target = "creationDate") Instant mapTime(Long epochMilli) { - // TODO assert parameter not null + AssertUtil.assertIsNotNull(epochMilli); return Instant.ofEpochMilli(epochMilli); } diff --git a/scm-webapp/src/main/java/sonia/scm/api/v2/resources/UserCollection2DtoMapper.java b/scm-webapp/src/main/java/sonia/scm/api/v2/resources/UserCollection2DtoMapper.java index 7d4c049f77..2989f3ced9 100644 --- a/scm-webapp/src/main/java/sonia/scm/api/v2/resources/UserCollection2DtoMapper.java +++ b/scm-webapp/src/main/java/sonia/scm/api/v2/resources/UserCollection2DtoMapper.java @@ -29,7 +29,7 @@ public class UserCollection2DtoMapper { this.userToDtoMapper = userToDtoMapper; } - public UserCollectionDto userCollectionToUserDto(UriInfo uriInfo, int pageNumber, int pageSize, PageResult pageResult) { + public UserCollectionDto userCollectionToDto(UriInfo uriInfo, int pageNumber, int pageSize, PageResult pageResult) { NumberedPaging paging = zeroBasedNumberedPaging(pageNumber, pageSize, pageResult.hasMore()); List dtos = pageResult.getEntities().stream().map(user -> userToDtoMapper.userToUserDto(user, uriInfo)).collect(Collectors.toList()); diff --git a/scm-webapp/src/main/java/sonia/scm/api/v2/resources/UserCollectionResource.java b/scm-webapp/src/main/java/sonia/scm/api/v2/resources/UserCollectionResource.java index 715c8bc752..cb3fd82033 100644 --- a/scm-webapp/src/main/java/sonia/scm/api/v2/resources/UserCollectionResource.java +++ b/scm-webapp/src/main/java/sonia/scm/api/v2/resources/UserCollectionResource.java @@ -12,12 +12,21 @@ import sonia.scm.user.UserException; import sonia.scm.user.UserManager; import sonia.scm.web.VndMediaType; -import javax.ws.rs.*; -import javax.ws.rs.core.*; +import javax.ws.rs.DefaultValue; +import javax.ws.rs.GET; +import javax.ws.rs.POST; +import javax.ws.rs.Path; +import javax.ws.rs.Produces; +import javax.ws.rs.QueryParam; +import javax.ws.rs.core.Context; +import javax.ws.rs.core.GenericEntity; +import javax.ws.rs.core.Request; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.UriInfo; import java.io.IOException; import java.util.Collection; -@Produces(VndMediaType.USER) +@Produces(VndMediaType.USER_COLLECTION) public class UserCollectionResource extends AbstractManagerResource { public static final int DEFAULT_PAGE_SIZE = 10; private final UserDto2UserMapper dtoToUserMapper; @@ -57,9 +66,14 @@ public class UserCollectionResource extends AbstractManagerResource pageResult = fetchPage(sortby, desc, page, pageSize); - return Response.ok(new UserCollection2DtoMapper(userToDtoMapper).userCollectionToUserDto(uriInfo, page, pageSize, pageResult)).build(); + return Response.ok(new UserCollection2DtoMapper(userToDtoMapper).userCollectionToDto(uriInfo, page, pageSize, pageResult)).build(); } + /** + * Creates a new user. + * @param userDto The user to be created. + * @return A response with the link to the new user (if created successfully). + */ @POST @Path("") @StatusCodes({ diff --git a/scm-webapp/src/main/java/sonia/scm/api/v2/resources/UserSubResource.java b/scm-webapp/src/main/java/sonia/scm/api/v2/resources/UserSubResource.java index 53af57048d..8fd6dcaa74 100644 --- a/scm-webapp/src/main/java/sonia/scm/api/v2/resources/UserSubResource.java +++ b/scm-webapp/src/main/java/sonia/scm/api/v2/resources/UserSubResource.java @@ -12,8 +12,17 @@ import sonia.scm.user.UserException; import sonia.scm.user.UserManager; import sonia.scm.web.VndMediaType; -import javax.ws.rs.*; -import javax.ws.rs.core.*; +import javax.ws.rs.DELETE; +import javax.ws.rs.GET; +import javax.ws.rs.PUT; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.Produces; +import javax.ws.rs.core.Context; +import javax.ws.rs.core.GenericEntity; +import javax.ws.rs.core.Request; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.UriInfo; import java.util.Collection; diff --git a/scm-webapp/src/test/java/sonia/scm/api/v2/JsonMarshallingResponseFilterTest.java b/scm-webapp/src/test/java/sonia/scm/api/v2/JsonMarshallingResponseFilterTest.java index 43ac114f2d..3af1984e29 100644 --- a/scm-webapp/src/test/java/sonia/scm/api/v2/JsonMarshallingResponseFilterTest.java +++ b/scm-webapp/src/test/java/sonia/scm/api/v2/JsonMarshallingResponseFilterTest.java @@ -60,7 +60,7 @@ public class JsonMarshallingResponseFilterTest { public void testFilter() { when(responseContext.hasEntity()).thenReturn(Boolean.TRUE); when(responseContext.getEntity()).thenReturn(new JsonMarshallingResponseFilterTest.Sample("one-two-three")); - when(responseContext.getMediaType()).thenReturn(VndMediaType.jsonType("sample")); + when(responseContext.getMediaType()).thenReturn(MediaType.valueOf(VndMediaType.USER)); filter.filter(requestContext, responseContext); @@ -81,7 +81,7 @@ public class JsonMarshallingResponseFilterTest { when(responseContext.hasEntity()).thenReturn(Boolean.TRUE); when(responseContext.getEntity()).thenReturn(new JsonMarshallingResponseFilterTest.Sample("one-two-three")); - when(responseContext.getMediaType()).thenReturn(VndMediaType.jsonType("sample")); + when(responseContext.getMediaType()).thenReturn(MediaType.valueOf(VndMediaType.USER)); filter.filter(requestContext, responseContext); diff --git a/scm-webapp/src/test/java/sonia/scm/api/v2/resources/UserCollection2DtoMapperTest.java b/scm-webapp/src/test/java/sonia/scm/api/v2/resources/UserCollection2DtoMapperTest.java index c70a920ad6..628e38f436 100644 --- a/scm-webapp/src/test/java/sonia/scm/api/v2/resources/UserCollection2DtoMapperTest.java +++ b/scm-webapp/src/test/java/sonia/scm/api/v2/resources/UserCollection2DtoMapperTest.java @@ -45,28 +45,28 @@ public class UserCollection2DtoMapperTest { @Test public void shouldSetPageNumber() { PageResult pageResult = mockPageResult(true, "Hannes"); - UserCollectionDto userCollectionDto = mapper.userCollectionToUserDto(uriInfo, 1, 1, pageResult); + UserCollectionDto userCollectionDto = mapper.userCollectionToDto(uriInfo, 1, 1, pageResult); assertEquals(1, userCollectionDto.getPage()); } @Test public void shouldHaveSelfLink() { PageResult pageResult = mockPageResult(true, "Hannes"); - UserCollectionDto userCollectionDto = mapper.userCollectionToUserDto(uriInfo, 1, 1, pageResult); + UserCollectionDto userCollectionDto = mapper.userCollectionToDto(uriInfo, 1, 1, pageResult); assertTrue(userCollectionDto.getLinks().getLinkBy("self").get().getHref().startsWith(expectedBaseUri.toString())); } @Test public void shouldCreateNextPageLink_whenHasMore() { PageResult pageResult = mockPageResult(true, "Hannes"); - UserCollectionDto userCollectionDto = mapper.userCollectionToUserDto(uriInfo, 1, 1, pageResult); + UserCollectionDto userCollectionDto = mapper.userCollectionToDto(uriInfo, 1, 1, pageResult); assertTrue(userCollectionDto.getLinks().getLinkBy("next").get().getHref().contains("page=2")); } @Test public void shouldNotCreateNextPageLink_whenNoMore() { PageResult pageResult = mockPageResult(false, "Hannes"); - UserCollectionDto userCollectionDto = mapper.userCollectionToUserDto(uriInfo, 1, 1, pageResult); + UserCollectionDto userCollectionDto = mapper.userCollectionToDto(uriInfo, 1, 1, pageResult); assertFalse(userCollectionDto.getLinks().stream().anyMatch(link -> link.getHref().contains("page=2"))); } @@ -75,7 +75,7 @@ public class UserCollection2DtoMapperTest { PageResult pageResult = mockPageResult(false, "Hannes"); when(subject.isPermitted("user:create")).thenReturn(true); - UserCollectionDto userCollectionDto = mapper.userCollectionToUserDto(uriInfo, 1, 1, pageResult); + UserCollectionDto userCollectionDto = mapper.userCollectionToDto(uriInfo, 1, 1, pageResult); assertTrue(userCollectionDto.getLinks().getLinkBy("create").isPresent()); } @@ -85,7 +85,7 @@ public class UserCollection2DtoMapperTest { PageResult pageResult = mockPageResult(false, "Hannes"); when(subject.isPermitted("user:create")).thenReturn(false); - UserCollectionDto userCollectionDto = mapper.userCollectionToUserDto(uriInfo, 1, 1, pageResult); + UserCollectionDto userCollectionDto = mapper.userCollectionToDto(uriInfo, 1, 1, pageResult); assertFalse(userCollectionDto.getLinks().getLinkBy("create").isPresent()); } @@ -93,7 +93,7 @@ public class UserCollection2DtoMapperTest { @Test public void shouldMapUsers() { PageResult pageResult = mockPageResult(false, "Hannes", "Wurst"); - UserCollectionDto userCollectionDto = mapper.userCollectionToUserDto(uriInfo, 1, 2, pageResult); + UserCollectionDto userCollectionDto = mapper.userCollectionToDto(uriInfo, 1, 2, pageResult); List users = userCollectionDto.getEmbedded().getItemsBy("users"); assertEquals(2, users.size()); assertEquals("Hannes", ((UserDto) users.get(0)).getName());