mirror of
https://github.com/scm-manager/scm-manager.git
synced 2025-11-11 07:55:47 +01:00
merge + use the old search methods in the autocomplete feature
This commit is contained in:
@@ -115,12 +115,4 @@ public interface GenericDAO<T>
|
||||
*/
|
||||
public Collection<T> getAll();
|
||||
|
||||
/**
|
||||
* Returns items containing the searched string
|
||||
*
|
||||
* @param searched the search character
|
||||
* @param limit the max count of the result entities. if limit is <= 0 return all filtered entities
|
||||
* @return searched items
|
||||
*/
|
||||
Collection<T> getFiltered(String searched, int limit);
|
||||
}
|
||||
|
||||
@@ -47,6 +47,9 @@ public interface Manager<T extends ModelObject>
|
||||
extends HandlerBase<T>, LastModifiedAware
|
||||
{
|
||||
|
||||
int DEFAULT_LIMIT = 5;
|
||||
|
||||
|
||||
/**
|
||||
* Reloads a object from store and overwrites all changes.
|
||||
*
|
||||
@@ -77,15 +80,6 @@ public interface Manager<T extends ModelObject>
|
||||
*/
|
||||
Collection<T> getAll();
|
||||
|
||||
/**
|
||||
* Returns a {@link java.util.Collection} of filtered objects
|
||||
*
|
||||
* @param filter the searched string
|
||||
* @param limit the max count of the result entities. if limit is <= 0 return all filtered entities
|
||||
* @return all object in the store
|
||||
*/
|
||||
Collection<T> getFiltered(String filter, int limit);
|
||||
|
||||
/**
|
||||
* Returns all object of the store sorted by the given {@link java.util.Comparator}
|
||||
*
|
||||
|
||||
@@ -91,11 +91,6 @@ public class ManagerDecorator<T extends ModelObject> implements Manager<T> {
|
||||
decorated.refresh(object);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<T> getFiltered(String filter, int limit) {
|
||||
return decorated.getFiltered(filter, limit);
|
||||
}
|
||||
|
||||
@Override
|
||||
public T get(String id)
|
||||
{
|
||||
|
||||
@@ -44,7 +44,7 @@ import java.io.Serializable;
|
||||
*/
|
||||
public interface ModelObject
|
||||
extends TypedObject, LastModifiedAware, Cloneable, Validateable,
|
||||
Serializable, ReducedModelObject
|
||||
Serializable
|
||||
{
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,125 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2010, Sebastian Sdorra
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of SCM-Manager; nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* http://bitbucket.org/sdorra/scm-manager
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
|
||||
package sonia.scm.filter;
|
||||
|
||||
//~--- non-JDK imports --------------------------------------------------------
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import sonia.scm.Priority;
|
||||
import sonia.scm.util.WebUtil;
|
||||
import sonia.scm.web.filter.HttpFilter;
|
||||
|
||||
//~--- JDK imports ------------------------------------------------------------
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import javax.servlet.FilterChain;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
/**
|
||||
* Filter for gzip encoding.
|
||||
*
|
||||
* @author Sebastian Sdorra
|
||||
* @since 1.15
|
||||
*/
|
||||
@Priority(Filters.PRIORITY_PRE_BASEURL)
|
||||
@WebElement(value = Filters.PATTERN_RESOURCE_REGEX, regex = true)
|
||||
public class GZipFilter extends HttpFilter
|
||||
{
|
||||
|
||||
/**
|
||||
* the logger for GZipFilter
|
||||
*/
|
||||
private static final Logger logger =
|
||||
LoggerFactory.getLogger(GZipFilter.class);
|
||||
|
||||
//~--- get methods ----------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Return the configuration for the gzip filter.
|
||||
*
|
||||
*
|
||||
* @return gzip filter configuration
|
||||
*/
|
||||
public GZipFilterConfig getConfig()
|
||||
{
|
||||
return config;
|
||||
}
|
||||
|
||||
//~--- methods --------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Encodes the response, if the request has support for gzip encoding.
|
||||
*
|
||||
*
|
||||
* @param request http request
|
||||
* @param response http response
|
||||
* @param chain filter chain
|
||||
*
|
||||
* @throws IOException
|
||||
* @throws ServletException
|
||||
*/
|
||||
@Override
|
||||
protected void doFilter(HttpServletRequest request,
|
||||
HttpServletResponse response, FilterChain chain)
|
||||
throws IOException, ServletException
|
||||
{
|
||||
if (WebUtil.isGzipSupported(request))
|
||||
{
|
||||
if (logger.isTraceEnabled())
|
||||
{
|
||||
logger.trace("compress output with gzip");
|
||||
}
|
||||
|
||||
GZipResponseWrapper wrappedResponse = new GZipResponseWrapper(response,
|
||||
config);
|
||||
|
||||
chain.doFilter(request, wrappedResponse);
|
||||
wrappedResponse.finishResponse();
|
||||
}
|
||||
else
|
||||
{
|
||||
chain.doFilter(request, response);
|
||||
}
|
||||
}
|
||||
|
||||
//~--- fields ---------------------------------------------------------------
|
||||
|
||||
/** gzip filter configuration */
|
||||
private GZipFilterConfig config = new GZipFilterConfig();
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
package sonia.scm.filter;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import sonia.scm.util.WebUtil;
|
||||
|
||||
import javax.ws.rs.container.ContainerRequestContext;
|
||||
import javax.ws.rs.container.ContainerResponseContext;
|
||||
import javax.ws.rs.container.ContainerResponseFilter;
|
||||
import javax.ws.rs.ext.Provider;
|
||||
import java.io.IOException;
|
||||
import java.util.zip.GZIPOutputStream;
|
||||
|
||||
@Provider
|
||||
@Slf4j
|
||||
public class GZipResponseFilter implements ContainerResponseFilter {
|
||||
public void filter(ContainerRequestContext requestContext, ContainerResponseContext responseContext) throws IOException {
|
||||
if (WebUtil.isGzipSupported(requestContext::getHeaderString)) {
|
||||
log.trace("compress output with gzip");
|
||||
GZIPOutputStream wrappedResponse = new GZIPOutputStream(responseContext.getEntityStream());
|
||||
responseContext.getHeaders().add("Content-Encoding", "gzip");
|
||||
responseContext.setEntityStream(wrappedResponse);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -42,6 +42,7 @@ import com.google.common.base.Objects;
|
||||
import com.google.common.collect.Lists;
|
||||
import sonia.scm.BasicPropertiesAware;
|
||||
import sonia.scm.ModelObject;
|
||||
import sonia.scm.ReducedModelObject;
|
||||
import sonia.scm.util.Util;
|
||||
import sonia.scm.util.ValidationUtil;
|
||||
|
||||
@@ -64,7 +65,7 @@ import java.util.List;
|
||||
@XmlRootElement(name = "groups")
|
||||
@XmlAccessorType(XmlAccessType.FIELD)
|
||||
public class Group extends BasicPropertiesAware
|
||||
implements ModelObject, PermissionObject
|
||||
implements ModelObject, PermissionObject, ReducedModelObject
|
||||
{
|
||||
|
||||
/** Field description */
|
||||
|
||||
@@ -61,4 +61,14 @@ public interface GroupManager
|
||||
* @return all groups assigned to the given member
|
||||
*/
|
||||
public Collection<Group> getGroupsForMember(String member);
|
||||
|
||||
|
||||
/**
|
||||
* Returns a {@link java.util.Collection} of filtered objects
|
||||
*
|
||||
* @param filter the searched string
|
||||
* @return filtered object from the store
|
||||
*/
|
||||
Collection<Group> autocomplete(String filter);
|
||||
|
||||
}
|
||||
|
||||
@@ -109,6 +109,11 @@ public class GroupManagerDecorator
|
||||
return decorated.getGroupsForMember(member);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<Group> autocomplete(String filter) {
|
||||
return decorated.autocomplete(filter);
|
||||
}
|
||||
|
||||
//~--- fields ---------------------------------------------------------------
|
||||
|
||||
/** Field description */
|
||||
|
||||
@@ -256,11 +256,6 @@ public class Changeset extends BasicPropertiesAware implements ModelObject {
|
||||
return id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDisplayName() {
|
||||
return id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setLastModified(Long timestamp) {
|
||||
throw new UnsupportedOperationException("changesets are immutable");
|
||||
|
||||
@@ -60,8 +60,7 @@ import java.util.List;
|
||||
*/
|
||||
@StaticPermissions(
|
||||
value = "repository",
|
||||
permissions = {"read", "modify", "delete", "healthCheck", "pull", "push", "permissionRead", "permissionWrite"},
|
||||
globalPermissions = {"create", "autocomplete"}
|
||||
permissions = {"read", "modify", "delete", "healthCheck", "pull", "push", "permissionRead", "permissionWrite"}
|
||||
)
|
||||
@XmlAccessorType(XmlAccessType.FIELD)
|
||||
@XmlRootElement(name = "repositories")
|
||||
@@ -184,11 +183,6 @@ public class Repository extends BasicPropertiesAware implements ModelObject, Per
|
||||
return id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDisplayName() {
|
||||
return getNamespace() + "/" + getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Long getLastModified() {
|
||||
return lastModified;
|
||||
|
||||
@@ -70,6 +70,12 @@ public class SearchRequest
|
||||
this.ignoreCase = ignoreCase;
|
||||
}
|
||||
|
||||
public SearchRequest(String query, boolean ignoreCase, int maxResults) {
|
||||
this.query = query;
|
||||
this.ignoreCase = ignoreCase;
|
||||
this.maxResults = maxResults;
|
||||
}
|
||||
|
||||
//~--- get methods ----------------------------------------------------------
|
||||
|
||||
/**
|
||||
|
||||
@@ -41,6 +41,7 @@ import com.google.common.base.MoreObjects;
|
||||
import com.google.common.base.Objects;
|
||||
import sonia.scm.BasicPropertiesAware;
|
||||
import sonia.scm.ModelObject;
|
||||
import sonia.scm.ReducedModelObject;
|
||||
import sonia.scm.util.Util;
|
||||
import sonia.scm.util.ValidationUtil;
|
||||
|
||||
@@ -58,7 +59,7 @@ import java.security.Principal;
|
||||
@StaticPermissions(value = "user", globalPermissions = {"create", "list", "autocomplete"})
|
||||
@XmlRootElement(name = "users")
|
||||
@XmlAccessorType(XmlAccessType.FIELD)
|
||||
public class User extends BasicPropertiesAware implements Principal, ModelObject, PermissionObject
|
||||
public class User extends BasicPropertiesAware implements Principal, ModelObject, PermissionObject, ReducedModelObject
|
||||
{
|
||||
|
||||
/** Field description */
|
||||
|
||||
@@ -39,6 +39,7 @@ import sonia.scm.Manager;
|
||||
import sonia.scm.search.Searchable;
|
||||
|
||||
import java.text.MessageFormat;
|
||||
import java.util.Collection;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import static sonia.scm.user.ChangePasswordNotAllowedException.WRONG_USER_TYPE;
|
||||
@@ -90,5 +91,13 @@ public interface UserManager
|
||||
return getDefaultType().equals(user.getType());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a {@link java.util.Collection} of filtered objects
|
||||
*
|
||||
* @param filter the searched string
|
||||
* @return filtered object from the store
|
||||
*/
|
||||
Collection<User> autocomplete(String filter);
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -121,6 +121,11 @@ public class UserManagerDecorator extends ManagerDecorator<User>
|
||||
return decorated.getDefaultType();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<User> autocomplete(String filter) {
|
||||
return decorated.autocomplete(filter);
|
||||
}
|
||||
|
||||
//~--- fields ---------------------------------------------------------------
|
||||
|
||||
/** Field description */
|
||||
|
||||
@@ -49,6 +49,7 @@ import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
import java.util.Locale;
|
||||
import java.util.TimeZone;
|
||||
import java.util.function.Function;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
@@ -266,7 +267,12 @@ public final class WebUtil
|
||||
*/
|
||||
public static boolean isGzipSupported(HttpServletRequest request)
|
||||
{
|
||||
String enc = request.getHeader(HEADER_ACCEPTENCODING);
|
||||
return isGzipSupported(request::getHeader);
|
||||
}
|
||||
|
||||
public static boolean isGzipSupported(Function<String, String> headerResolver)
|
||||
{
|
||||
String enc = headerResolver.apply(HEADER_ACCEPTENCODING);
|
||||
|
||||
return (enc != null) && enc.contains("gzip");
|
||||
}
|
||||
|
||||
@@ -78,11 +78,6 @@ public class ManagerTest {
|
||||
return IntStream.range(0, givenItemCount).boxed().collect(toList());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection getFiltered(String filter, int limit) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection getAll(Comparator comparator) { return getAll(); }
|
||||
|
||||
|
||||
@@ -237,16 +237,6 @@ public abstract class AbstractXmlDAO<I extends ModelObject,
|
||||
return ImmutableList.copyOf(db.values());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<I> getFiltered(String searched, int limit) {
|
||||
int size = db.values().size();
|
||||
AssertUtil.assertIsNotEmpty(searched);
|
||||
return ImmutableList.copyOf(db.values().stream()
|
||||
.filter(item -> StringUtils.containsIgnoreCase(item.getId(), searched) || (item.getDisplayName() != null && StringUtils.containsIgnoreCase(item.getDisplayName() , searched)))
|
||||
.limit(limit <= 0 ? size : limit)
|
||||
.collect(Collectors.toList()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
|
||||
@@ -32,122 +32,45 @@
|
||||
|
||||
package sonia.scm.web;
|
||||
|
||||
//~--- non-JDK imports --------------------------------------------------------
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import sonia.scm.filter.GZipFilter;
|
||||
import sonia.scm.filter.GZipFilterConfig;
|
||||
import sonia.scm.filter.GZipResponseWrapper;
|
||||
import sonia.scm.repository.Repository;
|
||||
import sonia.scm.repository.SvnRepositoryHandler;
|
||||
import sonia.scm.repository.spi.ScmProviderHttpServlet;
|
||||
import sonia.scm.util.WebUtil;
|
||||
|
||||
import javax.servlet.FilterChain;
|
||||
import javax.servlet.FilterConfig;
|
||||
import javax.servlet.ServletConfig;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
|
||||
//~--- JDK imports ------------------------------------------------------------
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Sebastian Sdorra
|
||||
*/
|
||||
public class SvnGZipFilter extends GZipFilter implements ScmProviderHttpServlet
|
||||
{
|
||||
class SvnGZipFilter implements ScmProviderHttpServlet {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(SvnGZipFilter.class);
|
||||
|
||||
private final SvnRepositoryHandler handler;
|
||||
private final ScmProviderHttpServlet delegate;
|
||||
|
||||
//~--- constructors ---------------------------------------------------------
|
||||
private GZipFilterConfig config = new GZipFilterConfig();
|
||||
|
||||
/**
|
||||
* Constructs ...
|
||||
*
|
||||
*
|
||||
* @param handler
|
||||
*/
|
||||
public SvnGZipFilter(SvnRepositoryHandler handler, ScmProviderHttpServlet delegate)
|
||||
{
|
||||
SvnGZipFilter(SvnRepositoryHandler handler, ScmProviderHttpServlet delegate) {
|
||||
this.handler = handler;
|
||||
this.delegate = delegate;
|
||||
}
|
||||
|
||||
//~--- methods --------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @param filterConfig
|
||||
*
|
||||
* @throws ServletException
|
||||
*/
|
||||
@Override
|
||||
public void init(FilterConfig filterConfig) throws ServletException
|
||||
{
|
||||
super.init(filterConfig);
|
||||
getConfig().setBufferResponse(false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
*
|
||||
* @param request
|
||||
* @param response
|
||||
* @param chain
|
||||
*
|
||||
* @throws IOException
|
||||
* @throws ServletException
|
||||
*/
|
||||
@Override
|
||||
protected void doFilter(HttpServletRequest request,
|
||||
HttpServletResponse response, FilterChain chain)
|
||||
throws IOException, ServletException
|
||||
{
|
||||
if (handler.getConfig().isEnabledGZip())
|
||||
{
|
||||
if (logger.isTraceEnabled())
|
||||
{
|
||||
logger.trace("encode svn request with gzip");
|
||||
}
|
||||
|
||||
super.doFilter(request, response, chain);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (logger.isTraceEnabled())
|
||||
{
|
||||
logger.trace("skip gzip encoding");
|
||||
}
|
||||
|
||||
chain.doFilter(request, response);
|
||||
}
|
||||
config.setBufferResponse(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void service(HttpServletRequest request, HttpServletResponse response, Repository repository) throws ServletException, IOException {
|
||||
if (handler.getConfig().isEnabledGZip())
|
||||
{
|
||||
if (logger.isTraceEnabled())
|
||||
{
|
||||
logger.trace("encode svn request with gzip");
|
||||
}
|
||||
|
||||
super.doFilter(request, response, (servletRequest, servletResponse) -> delegate.service((HttpServletRequest) servletRequest, (HttpServletResponse) servletResponse, repository));
|
||||
}
|
||||
else
|
||||
{
|
||||
if (logger.isTraceEnabled())
|
||||
{
|
||||
if (handler.getConfig().isEnabledGZip() && WebUtil.isGzipSupported(request)) {
|
||||
logger.trace("compress svn response with gzip");
|
||||
GZipResponseWrapper wrappedResponse = new GZipResponseWrapper(response, config);
|
||||
delegate.service(request, wrappedResponse, repository);
|
||||
wrappedResponse.finishResponse();
|
||||
} else {
|
||||
logger.trace("skip gzip encoding");
|
||||
}
|
||||
|
||||
delegate.service(request, response, repository);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -58,8 +58,10 @@ public class WebResourceServlet extends HttpServlet {
|
||||
LOG.trace("try to load {}", uri);
|
||||
URL url = webResourceLoader.getResource(uri);
|
||||
if (url != null) {
|
||||
LOG.trace("found {} -- serve as resource {}", uri, url);
|
||||
serveResource(request, response, url);
|
||||
} else {
|
||||
LOG.trace("could not find {} -- dispatch", uri);
|
||||
dispatch(request, response, uri);
|
||||
}
|
||||
}
|
||||
@@ -79,6 +81,7 @@ public class WebResourceServlet extends HttpServlet {
|
||||
|
||||
private void serveResource(HttpServletRequest request, HttpServletResponse response, URL url) {
|
||||
try {
|
||||
LOG.debug("using sender to serve {}", request.getRequestURI());
|
||||
sender.resource(url).send(request, response);
|
||||
} catch (IOException ex) {
|
||||
LOG.warn("failed to serve resource: {}", url);
|
||||
|
||||
@@ -3,26 +3,25 @@ package sonia.scm.api.v2.resources;
|
||||
import com.webcohesion.enunciate.metadata.rs.ResponseCode;
|
||||
import com.webcohesion.enunciate.metadata.rs.StatusCodes;
|
||||
import org.hibernate.validator.constraints.NotEmpty;
|
||||
import sonia.scm.ReducedModelObject;
|
||||
import sonia.scm.group.GroupManager;
|
||||
import sonia.scm.repository.RepositoryManager;
|
||||
import sonia.scm.user.UserManager;
|
||||
import sonia.scm.web.VndMediaType;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.validation.constraints.Size;
|
||||
import javax.ws.rs.DefaultValue;
|
||||
import javax.ws.rs.GET;
|
||||
import javax.ws.rs.Path;
|
||||
import javax.ws.rs.Produces;
|
||||
import javax.ws.rs.QueryParam;
|
||||
import javax.ws.rs.core.Response;
|
||||
import java.util.Collection;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
|
||||
@Path(AutoCompleteResource.PATH)
|
||||
public class AutoCompleteResource {
|
||||
public static final String PATH = "v2/autocomplete/";
|
||||
public static final String DEFAULT_LIMIT = "5";
|
||||
public static final int MIN_SEARCHED_CHARS = 2;
|
||||
|
||||
public static final String PARAMETER_IS_REQUIRED = "The parameter is required.";
|
||||
@@ -33,14 +32,12 @@ public class AutoCompleteResource {
|
||||
|
||||
private UserManager userManager;
|
||||
private GroupManager groupManager;
|
||||
private RepositoryManager repositoryManager;
|
||||
|
||||
@Inject
|
||||
public AutoCompleteResource(ReducedObjectModelToDtoMapper mapper, UserManager userManager, GroupManager groupManager, RepositoryManager repositoryManager) {
|
||||
public AutoCompleteResource(ReducedObjectModelToDtoMapper mapper, UserManager userManager, GroupManager groupManager) {
|
||||
this.mapper = mapper;
|
||||
this.userManager = userManager;
|
||||
this.groupManager = groupManager;
|
||||
this.repositoryManager = repositoryManager;
|
||||
}
|
||||
|
||||
@GET
|
||||
@@ -53,13 +50,8 @@ public class AutoCompleteResource {
|
||||
@ResponseCode(code = 403, condition = "not authorized, the current user does not have the \"user:autocomplete\" privilege"),
|
||||
@ResponseCode(code = 500, condition = "internal server error")
|
||||
})
|
||||
public Response searchUser(@NotEmpty(message = PARAMETER_IS_REQUIRED) @Size(min = MIN_SEARCHED_CHARS, message = INVALID_PARAMETER_LENGTH) @QueryParam("filter") String filter,
|
||||
@DefaultValue(DEFAULT_LIMIT) @QueryParam("limit") Integer limit) {
|
||||
return Response.ok(userManager.getFiltered(filter, limit)
|
||||
.stream()
|
||||
.map(mapper::map)
|
||||
.collect(Collectors.toList()))
|
||||
.build();
|
||||
public Response searchUser(@NotEmpty(message = PARAMETER_IS_REQUIRED) @Size(min = MIN_SEARCHED_CHARS, message = INVALID_PARAMETER_LENGTH) @QueryParam("filter") String filter) {
|
||||
return map(userManager.autocomplete(filter));
|
||||
}
|
||||
|
||||
@GET
|
||||
@@ -72,28 +64,12 @@ public class AutoCompleteResource {
|
||||
@ResponseCode(code = 403, condition = "not authorized, the current user does not have the \"group:autocomplete\" privilege"),
|
||||
@ResponseCode(code = 500, condition = "internal server error")
|
||||
})
|
||||
public Response searchGroup(@NotEmpty(message = PARAMETER_IS_REQUIRED) @Size(min = MIN_SEARCHED_CHARS, message = INVALID_PARAMETER_LENGTH) @QueryParam("filter") String filter,
|
||||
@DefaultValue(DEFAULT_LIMIT) @QueryParam("limit") Integer limit) {
|
||||
return Response.ok(groupManager.getFiltered(filter, limit)
|
||||
.stream()
|
||||
.map(mapper::map)
|
||||
.collect(Collectors.toList()))
|
||||
.build();
|
||||
public Response searchGroup(@NotEmpty(message = PARAMETER_IS_REQUIRED) @Size(min = MIN_SEARCHED_CHARS, message = INVALID_PARAMETER_LENGTH) @QueryParam("filter") String filter) {
|
||||
return map(groupManager.autocomplete(filter));
|
||||
}
|
||||
|
||||
@GET
|
||||
@Path("repository")
|
||||
@Produces(VndMediaType.AUTOCOMPLETE)
|
||||
@StatusCodes({
|
||||
@ResponseCode(code = 200, condition = "success"),
|
||||
@ResponseCode(code = 400, condition = "if the searched string contains less than 2 characters"),
|
||||
@ResponseCode(code = 401, condition = "not authenticated / invalid credentials"),
|
||||
@ResponseCode(code = 403, condition = "not authorized, the current user does not have the \"repository:autocomplete\" privilege"),
|
||||
@ResponseCode(code = 500, condition = "internal server error")
|
||||
})
|
||||
public Response searchRepo(@NotEmpty(message = PARAMETER_IS_REQUIRED) @Size(min = MIN_SEARCHED_CHARS, message = INVALID_PARAMETER_LENGTH) @QueryParam("filter") String filter,
|
||||
@DefaultValue(DEFAULT_LIMIT) @QueryParam("limit") Integer limit) {
|
||||
return Response.ok(repositoryManager.getFiltered(filter, limit)
|
||||
private <T extends ReducedModelObject> Response map(Collection<T> autocomplete) {
|
||||
return Response.ok(autocomplete
|
||||
.stream()
|
||||
.map(mapper::map)
|
||||
.collect(Collectors.toList()))
|
||||
|
||||
@@ -243,10 +243,11 @@ public class DefaultGroupManager extends AbstractGroupManager
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<Group> getFiltered(String filter, int limit) {
|
||||
public Collection<Group> autocomplete(String filter) {
|
||||
GroupPermissions.autocomplete().check();
|
||||
return groupDAO.getFiltered(filter, limit);
|
||||
return search(new SearchRequest(filter,true, DEFAULT_LIMIT));
|
||||
}
|
||||
|
||||
/**
|
||||
* Method description
|
||||
*
|
||||
|
||||
@@ -243,12 +243,6 @@ public class DefaultRepositoryManager extends AbstractRepositoryManager {
|
||||
return repository;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<Repository> getFiltered(String filter, int limit) {
|
||||
RepositoryPermissions.autocomplete().check();
|
||||
return repositoryDAO.getFiltered(filter, limit);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<Repository> getAll(Comparator<Repository> comparator) {
|
||||
List<Repository> repositories = Lists.newArrayList();
|
||||
|
||||
@@ -260,7 +260,6 @@ public class DefaultAuthorizationCollector implements AuthorizationCollector
|
||||
builder.add(canReadOwnUser(user));
|
||||
builder.add(getUserAutocompletePermission());
|
||||
builder.add(getGroupAutocompletePermission());
|
||||
builder.add(getRepoAutocompletePermission());
|
||||
permissions = builder.build();
|
||||
}
|
||||
|
||||
@@ -269,10 +268,6 @@ public class DefaultAuthorizationCollector implements AuthorizationCollector
|
||||
return info;
|
||||
}
|
||||
|
||||
private String getRepoAutocompletePermission() {
|
||||
return RepositoryPermissions.autocomplete().asShiroString();
|
||||
}
|
||||
|
||||
private String getGroupAutocompletePermission() {
|
||||
return GroupPermissions.autocomplete().asShiroString();
|
||||
}
|
||||
|
||||
@@ -301,9 +301,9 @@ public class DefaultUserManager extends AbstractUserManager
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<User> getFiltered(String filter, int limit) {
|
||||
public Collection<User> autocomplete(String filter) {
|
||||
UserPermissions.autocomplete().check();
|
||||
return userDAO.getFiltered(filter, limit);
|
||||
return search(new SearchRequest(filter,true, DEFAULT_LIMIT));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -105,11 +105,6 @@ public class AbstractManagerResourceTest {
|
||||
return id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDisplayName() {
|
||||
return id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setLastModified(Long timestamp) {
|
||||
|
||||
|
||||
@@ -14,18 +14,11 @@ import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
import sonia.scm.SCMContextProvider;
|
||||
import sonia.scm.config.ScmConfiguration;
|
||||
import sonia.scm.Manager;
|
||||
import sonia.scm.group.DefaultGroupManager;
|
||||
import sonia.scm.group.Group;
|
||||
import sonia.scm.group.GroupManager;
|
||||
import sonia.scm.group.xml.XmlGroupDAO;
|
||||
import sonia.scm.repository.DefaultRepositoryManager;
|
||||
import sonia.scm.repository.NamespaceStrategy;
|
||||
import sonia.scm.repository.Repository;
|
||||
import sonia.scm.repository.RepositoryManager;
|
||||
import sonia.scm.repository.xml.XmlRepositoryDAO;
|
||||
import sonia.scm.security.KeyGenerator;
|
||||
import sonia.scm.store.ConfigurationStore;
|
||||
import sonia.scm.store.ConfigurationStoreFactory;
|
||||
import sonia.scm.user.DefaultUserManager;
|
||||
@@ -37,7 +30,6 @@ import sonia.scm.xml.XmlDatabase;
|
||||
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.IntStream;
|
||||
@@ -45,10 +37,8 @@ import java.util.stream.IntStream;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
import static org.mockito.MockitoAnnotations.initMocks;
|
||||
import static sonia.scm.api.v2.resources.DispatcherMock.createDispatcher;
|
||||
@@ -57,22 +47,17 @@ import static sonia.scm.api.v2.resources.DispatcherMock.createDispatcher;
|
||||
public class AutoCompleteResourceTest {
|
||||
|
||||
public static final String URL = "/" + AutoCompleteResource.PATH;
|
||||
private final Integer defaultLimit = Integer.valueOf(AutoCompleteResource.DEFAULT_LIMIT);
|
||||
private final Integer defaultLimit = Manager.DEFAULT_LIMIT;
|
||||
private Dispatcher dispatcher;
|
||||
|
||||
private final Subject subject = mock(Subject.class);
|
||||
private final ThreadState subjectThreadState = new SubjectThreadState(subject);
|
||||
|
||||
|
||||
private XmlUserDAO userDaoMock;
|
||||
|
||||
private XmlGroupDAO groupDaoMock;
|
||||
|
||||
private XmlRepositoryDAO repoDaoMock;
|
||||
private XmlUserDAO userDao;
|
||||
private XmlGroupDAO groupDao;
|
||||
private XmlDatabase xmlDB;
|
||||
private ObjectMapper jsonObjectMapper = new ObjectMapper();
|
||||
|
||||
|
||||
@Before
|
||||
public void prepareEnvironment() {
|
||||
initMocks(this);
|
||||
@@ -82,16 +67,13 @@ public class AutoCompleteResourceTest {
|
||||
when(storeConfig.get()).thenReturn(xmlDB);
|
||||
when(storeFactory.getStore(any(), any())).thenReturn(storeConfig);
|
||||
XmlUserDAO userDao = new XmlUserDAO(storeFactory);
|
||||
userDaoMock = spy(userDao);
|
||||
this.userDao = spy(userDao);
|
||||
XmlGroupDAO groupDAO = new XmlGroupDAO(storeFactory);
|
||||
groupDaoMock = spy(groupDAO);
|
||||
XmlRepositoryDAO repoDao = new XmlRepositoryDAO(storeFactory);
|
||||
repoDaoMock = spy(repoDao);
|
||||
groupDao = spy(groupDAO);
|
||||
ReducedObjectModelToDtoMapperImpl mapper = new ReducedObjectModelToDtoMapperImpl();
|
||||
UserManager userManager = new DefaultUserManager(userDaoMock);
|
||||
GroupManager groupManager = new DefaultGroupManager(groupDaoMock);
|
||||
RepositoryManager repositoryManager = new DefaultRepositoryManager(mock(ScmConfiguration.class), mock(SCMContextProvider.class), mock(KeyGenerator.class), repoDaoMock, new HashSet<>(), mock(NamespaceStrategy.class));
|
||||
AutoCompleteResource autoCompleteResource = new AutoCompleteResource(mapper, userManager, groupManager, repositoryManager);
|
||||
UserManager userManager = new DefaultUserManager(this.userDao);
|
||||
GroupManager groupManager = new DefaultGroupManager(groupDao);
|
||||
AutoCompleteResource autoCompleteResource = new AutoCompleteResource(mapper, userManager, groupManager);
|
||||
dispatcher = createDispatcher(autoCompleteResource);
|
||||
subjectThreadState.bind();
|
||||
ThreadContext.bind(subject);
|
||||
@@ -151,23 +133,6 @@ public class AutoCompleteResourceTest {
|
||||
assertTrue(response.getContentAsString().contains("\"displayName\":\"User 2\""));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldSearchUsersWithLimitLength() throws Exception {
|
||||
List<User> users = IntStream.range(0, 10).boxed().map(i -> createMockUser("user" + i, "User " + i)).collect(Collectors.toList());
|
||||
when(xmlDB.values()).thenReturn(users);
|
||||
MockHttpRequest request = MockHttpRequest
|
||||
.get("/" + AutoCompleteResource.PATH + "user?filter=user&limit=1")
|
||||
.contentType(VndMediaType.AUTOCOMPLETE)
|
||||
.accept(VndMediaType.AUTOCOMPLETE);
|
||||
MockHttpResponse response = new MockHttpResponse();
|
||||
|
||||
dispatcher.invoke(request, response);
|
||||
|
||||
assertEquals(HttpServletResponse.SC_OK, response.getStatus());
|
||||
verify(userDaoMock).getFiltered(eq("user"), eq(1));
|
||||
assertResultSize(response, 1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldSearchUsersWithDefaultLimitLength() throws Exception {
|
||||
List<User> userList = IntStream.range(0, 10).boxed().map(i -> createMockUser("user" + i, "User " + i)).collect(Collectors.toList());
|
||||
@@ -181,7 +146,6 @@ public class AutoCompleteResourceTest {
|
||||
dispatcher.invoke(request, response);
|
||||
|
||||
assertEquals(HttpServletResponse.SC_OK, response.getStatus());
|
||||
verify(userDaoMock).getFiltered(eq("user"), eq(defaultLimit));
|
||||
assertResultSize(response, defaultLimit);
|
||||
}
|
||||
|
||||
@@ -232,23 +196,6 @@ public class AutoCompleteResourceTest {
|
||||
assertTrue(response.getContentAsString().contains("\"displayName\":\"group_2\""));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldSearchGroupsWithLimitLength() throws Exception {
|
||||
List<Group> groups = IntStream.range(0, 10).boxed().map(i -> createMockGroup("group_" + i)).collect(Collectors.toList());
|
||||
when(xmlDB.values()).thenReturn(groups);
|
||||
MockHttpRequest request = MockHttpRequest
|
||||
.get("/" + AutoCompleteResource.PATH + "group?filter=group&limit=1")
|
||||
.contentType(VndMediaType.AUTOCOMPLETE)
|
||||
.accept(VndMediaType.AUTOCOMPLETE);
|
||||
MockHttpResponse response = new MockHttpResponse();
|
||||
|
||||
dispatcher.invoke(request, response);
|
||||
|
||||
assertEquals(HttpServletResponse.SC_OK, response.getStatus());
|
||||
verify(groupDaoMock).getFiltered(eq("group"), eq(1));
|
||||
assertResultSize(response, 1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldSearchGroupsWithDefaultLimitLength() throws Exception {
|
||||
List<Group> groups = IntStream.range(0, 10).boxed().map(i -> createMockGroup("group_" + i)).collect(Collectors.toList());
|
||||
@@ -262,107 +209,21 @@ public class AutoCompleteResourceTest {
|
||||
dispatcher.invoke(request, response);
|
||||
|
||||
assertEquals(HttpServletResponse.SC_OK, response.getStatus());
|
||||
verify(groupDaoMock).getFiltered(eq("group"), eq(defaultLimit));
|
||||
assertResultSize(response, defaultLimit);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void shouldGet400OnFailedParameterForRepoSearch() throws Exception {
|
||||
MockHttpRequest request = MockHttpRequest
|
||||
.get("/" + AutoCompleteResource.PATH + "repository")
|
||||
.contentType(VndMediaType.AUTOCOMPLETE)
|
||||
.accept(VndMediaType.AUTOCOMPLETE);
|
||||
MockHttpResponse response = new MockHttpResponse();
|
||||
|
||||
dispatcher.invoke(request, response);
|
||||
|
||||
assertEquals(400, response.getStatus());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldGet400IfParameterLengthLessThan2CharsForRepoSearch() throws Exception {
|
||||
MockHttpRequest request = MockHttpRequest
|
||||
.get("/" + AutoCompleteResource.PATH + "repository?filter=a")
|
||||
.contentType(VndMediaType.AUTOCOMPLETE)
|
||||
.accept(VndMediaType.AUTOCOMPLETE);
|
||||
MockHttpResponse response = new MockHttpResponse();
|
||||
|
||||
dispatcher.invoke(request, response);
|
||||
|
||||
assertEquals(400, response.getStatus());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldSearchRepos() throws Exception {
|
||||
List<Repository> repos = Lists.newArrayList(createMockRepo("YCannotFindMe"), createMockRepo("repo1"), createMockRepo("repo2"));
|
||||
when(xmlDB.values()).thenReturn(repos);
|
||||
MockHttpRequest request = MockHttpRequest
|
||||
.get("/" + AutoCompleteResource.PATH + "repository?filter=repo")
|
||||
.contentType(VndMediaType.AUTOCOMPLETE)
|
||||
.accept(VndMediaType.AUTOCOMPLETE);
|
||||
MockHttpResponse response = new MockHttpResponse();
|
||||
|
||||
dispatcher.invoke(request, response);
|
||||
|
||||
assertEquals(HttpServletResponse.SC_OK, response.getStatus());
|
||||
assertResultSize(response, 2);
|
||||
assertTrue(response.getContentAsString().contains("\"displayName\":\"space/repo1\""));
|
||||
assertTrue(response.getContentAsString().contains("\"displayName\":\"space/repo2\""));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldSearchReposWithLimitLength() throws Exception {
|
||||
List<Repository> repositories = IntStream.range(0, 10).boxed().map(i -> createMockRepo("repo" + i)).collect(Collectors.toList());
|
||||
when(xmlDB.values()).thenReturn(repositories);
|
||||
MockHttpRequest request = MockHttpRequest
|
||||
.get("/" + AutoCompleteResource.PATH + "repository?filter=repo&limit=1")
|
||||
.contentType(VndMediaType.AUTOCOMPLETE)
|
||||
.accept(VndMediaType.AUTOCOMPLETE);
|
||||
MockHttpResponse response = new MockHttpResponse();
|
||||
|
||||
dispatcher.invoke(request, response);
|
||||
|
||||
assertEquals(HttpServletResponse.SC_OK, response.getStatus());
|
||||
verify(repoDaoMock).getFiltered(eq("repo"), eq(1));
|
||||
assertResultSize(response, 1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldSearchReposWithDefaultLimitLength() throws Exception {
|
||||
List<Repository> repositories = IntStream.range(0, 10).boxed().map(i -> createMockRepo("repo" + i)).collect(Collectors.toList());
|
||||
when(xmlDB.values()).thenReturn(repositories);
|
||||
MockHttpRequest request = MockHttpRequest
|
||||
.get("/" + AutoCompleteResource.PATH + "repository?filter=repo")
|
||||
.contentType(VndMediaType.AUTOCOMPLETE)
|
||||
.accept(VndMediaType.AUTOCOMPLETE);
|
||||
MockHttpResponse response = new MockHttpResponse();
|
||||
|
||||
dispatcher.invoke(request, response);
|
||||
|
||||
assertEquals(HttpServletResponse.SC_OK, response.getStatus());
|
||||
verify(repoDaoMock).getFiltered(eq("repo"), eq(defaultLimit));
|
||||
assertResultSize(response, defaultLimit);
|
||||
}
|
||||
|
||||
|
||||
private User createMockUser(String id, String name) {
|
||||
return new User(id, name, "em@l.de");
|
||||
}
|
||||
|
||||
|
||||
private Group createMockGroup(String name) {
|
||||
Group group = new Group("type", name);
|
||||
group.setDescription(name);
|
||||
return group;
|
||||
}
|
||||
|
||||
private Repository createMockRepo(String repository) {
|
||||
return new Repository("id", "git", "space", repository);
|
||||
}
|
||||
|
||||
private void assertResultSize(MockHttpResponse response, int size) throws java.io.IOException {
|
||||
ReducedObjectModelDto[] reducedObjectModelDtos = jsonObjectMapper.readValue(response.getContentAsString(), ReducedObjectModelDto[].class);
|
||||
assertTrue(reducedObjectModelDtos.length == size);
|
||||
assertEquals(reducedObjectModelDtos.length, size);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -161,8 +161,8 @@ public class DefaultAuthorizationCollectorTest {
|
||||
|
||||
AuthorizationInfo authInfo = collector.collect();
|
||||
assertThat(authInfo.getRoles(), Matchers.contains(Role.USER));
|
||||
assertThat(authInfo.getStringPermissions(), hasSize(4));
|
||||
assertThat(authInfo.getStringPermissions(), containsInAnyOrder("user:autocomplete", "group:autocomplete", "repository:autocomplete", "user:read:trillian"));
|
||||
assertThat(authInfo.getStringPermissions(), hasSize(3));
|
||||
assertThat(authInfo.getStringPermissions(), containsInAnyOrder("user:autocomplete", "group:autocomplete", "user:read:trillian"));
|
||||
assertThat(authInfo.getObjectPermissions(), nullValue());
|
||||
}
|
||||
|
||||
@@ -209,7 +209,7 @@ public class DefaultAuthorizationCollectorTest {
|
||||
AuthorizationInfo authInfo = collector.collect();
|
||||
assertThat(authInfo.getRoles(), Matchers.containsInAnyOrder(Role.USER));
|
||||
assertThat(authInfo.getObjectPermissions(), nullValue());
|
||||
assertThat(authInfo.getStringPermissions(), containsInAnyOrder("user:autocomplete", "group:autocomplete","repository:autocomplete", "repository:read,pull:one", "repository:read,pull,push:two", "user:read:trillian"));
|
||||
assertThat(authInfo.getStringPermissions(), containsInAnyOrder("user:autocomplete", "group:autocomplete", "repository:read,pull:one", "repository:read,pull,push:two", "user:read:trillian"));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -230,7 +230,7 @@ public class DefaultAuthorizationCollectorTest {
|
||||
AuthorizationInfo authInfo = collector.collect();
|
||||
assertThat(authInfo.getRoles(), Matchers.containsInAnyOrder(Role.USER));
|
||||
assertThat(authInfo.getObjectPermissions(), nullValue());
|
||||
assertThat(authInfo.getStringPermissions(), containsInAnyOrder("one:one", "two:two", "user:read:trillian", "user:autocomplete" , "group:autocomplete", "repository:autocomplete"));
|
||||
assertThat(authInfo.getStringPermissions(), containsInAnyOrder("one:one", "two:two", "user:read:trillian", "user:autocomplete" , "group:autocomplete" ));
|
||||
}
|
||||
|
||||
private void authenticate(User user, String group, String... groups) {
|
||||
|
||||
Reference in New Issue
Block a user