mirror of
https://github.com/scm-manager/scm-manager.git
synced 2025-11-12 00:15:44 +01:00
#965 fixed handling of resources with spaces in its id
This commit is contained in:
@@ -35,11 +35,14 @@ package sonia.scm.client.it;
|
|||||||
|
|
||||||
//~--- non-JDK imports --------------------------------------------------------
|
//~--- non-JDK imports --------------------------------------------------------
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
import sonia.scm.client.ClientHandler;
|
import sonia.scm.client.ClientHandler;
|
||||||
|
import sonia.scm.client.GroupClientHandler;
|
||||||
import sonia.scm.client.JerseyClientSession;
|
import sonia.scm.client.JerseyClientSession;
|
||||||
import sonia.scm.client.it.AbstractClientHandlerTestBase.ModifyTest;
|
|
||||||
import sonia.scm.group.Group;
|
import sonia.scm.group.Group;
|
||||||
|
|
||||||
|
import static sonia.scm.client.it.ClientTestUtil.createAdminSession;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @author Sebastian Sdorra
|
* @author Sebastian Sdorra
|
||||||
@@ -99,4 +102,24 @@ public class JerseyGroupClientHandlerITCase
|
|||||||
{
|
{
|
||||||
return new Group("xml", "group-" + number);
|
return new Group("xml", "group-" + number);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests crud operations with a group which name contains spaces.
|
||||||
|
*
|
||||||
|
* @see <a href="https://bitbucket.org/sdorra/scm-manager/issues/965/modify-a-group-with-spaces-not-allowed>#965</a>
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testGroupNamesWithSpaces() {
|
||||||
|
JerseyClientSession session = createAdminSession();
|
||||||
|
GroupClientHandler handler = session.getGroupHandler();
|
||||||
|
|
||||||
|
String name = "SCM Special Group";
|
||||||
|
handler.create(new Group("xml", name));
|
||||||
|
|
||||||
|
Group group = handler.get(name);
|
||||||
|
group.add("Some Member");
|
||||||
|
handler.modify(group);
|
||||||
|
|
||||||
|
handler.delete(name);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -35,6 +35,7 @@ package sonia.scm.url;
|
|||||||
|
|
||||||
//~--- non-JDK imports --------------------------------------------------------
|
//~--- non-JDK imports --------------------------------------------------------
|
||||||
|
|
||||||
|
import com.google.common.net.UrlEscapers;
|
||||||
import sonia.scm.util.HttpUtil;
|
import sonia.scm.util.HttpUtil;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -84,7 +85,8 @@ public class RestModelUrlProvider implements ModelUrlProvider
|
|||||||
@Override
|
@Override
|
||||||
public String getDetailUrl(String name)
|
public String getDetailUrl(String name)
|
||||||
{
|
{
|
||||||
return HttpUtil.append(base, name).concat(extension);
|
String escaped = UrlEscapers.urlPathSegmentEscaper().escape(name);
|
||||||
|
return HttpUtil.append(base, escaped).concat(extension);
|
||||||
}
|
}
|
||||||
|
|
||||||
//~--- fields ---------------------------------------------------------------
|
//~--- fields ---------------------------------------------------------------
|
||||||
|
|||||||
@@ -58,7 +58,7 @@ public abstract class ModelUrlProviderTestBase extends UrlTestBase
|
|||||||
public static final String MODEL_USERS = "users";
|
public static final String MODEL_USERS = "users";
|
||||||
|
|
||||||
/** Field description */
|
/** Field description */
|
||||||
private static final String[] MODELS = new String[] { MODEL_REPOSITORY,
|
protected static final String[] MODELS = new String[] { MODEL_REPOSITORY,
|
||||||
MODEL_USERS, MODEL_GROUPS };
|
MODEL_USERS, MODEL_GROUPS };
|
||||||
|
|
||||||
//~--- methods --------------------------------------------------------------
|
//~--- methods --------------------------------------------------------------
|
||||||
@@ -162,7 +162,7 @@ public abstract class ModelUrlProviderTestBase extends UrlTestBase
|
|||||||
*
|
*
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
private ModelUrlProvider createModelUrlProvider(String baseUrl, String model)
|
protected ModelUrlProvider createModelUrlProvider(String baseUrl, String model)
|
||||||
{
|
{
|
||||||
ModelUrlProvider urlProvider = null;
|
ModelUrlProvider urlProvider = null;
|
||||||
|
|
||||||
|
|||||||
@@ -34,8 +34,11 @@ package sonia.scm.url;
|
|||||||
|
|
||||||
//~--- non-JDK imports --------------------------------------------------------
|
//~--- non-JDK imports --------------------------------------------------------
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
import sonia.scm.util.HttpUtil;
|
import sonia.scm.util.HttpUtil;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @author Sebastian Sdorra
|
* @author Sebastian Sdorra
|
||||||
@@ -156,4 +159,16 @@ public abstract class RestModelUrlProviderTestBase
|
|||||||
return createRestUrl(baseUrl,
|
return createRestUrl(baseUrl,
|
||||||
model.concat(HttpUtil.SEPARATOR_PATH).concat(item));
|
model.concat(HttpUtil.SEPARATOR_PATH).concat(item));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testGetDetailUrlWithSpaces()
|
||||||
|
{
|
||||||
|
String item = "Item with Spaces";
|
||||||
|
|
||||||
|
for (String model : MODELS)
|
||||||
|
{
|
||||||
|
assertEquals(getExpectedDetailUrl(BASEURL, model, "Item%20with%20Spaces"),
|
||||||
|
createModelUrlProvider(BASEURL, model).getDetailUrl(item));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -35,33 +35,27 @@ package sonia.scm.api.rest.resources;
|
|||||||
|
|
||||||
//~--- non-JDK imports --------------------------------------------------------
|
//~--- non-JDK imports --------------------------------------------------------
|
||||||
|
|
||||||
|
import com.google.common.annotations.VisibleForTesting;
|
||||||
|
import com.google.common.net.UrlEscapers;
|
||||||
import org.apache.commons.beanutils.BeanComparator;
|
import org.apache.commons.beanutils.BeanComparator;
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import sonia.scm.LastModifiedAware;
|
import sonia.scm.LastModifiedAware;
|
||||||
import sonia.scm.Manager;
|
import sonia.scm.Manager;
|
||||||
import sonia.scm.ModelObject;
|
import sonia.scm.ModelObject;
|
||||||
import sonia.scm.api.rest.RestExceptionResult;
|
import sonia.scm.api.rest.RestExceptionResult;
|
||||||
import sonia.scm.security.ScmSecurityException;
|
import sonia.scm.security.ScmSecurityException;
|
||||||
import sonia.scm.util.AssertUtil;
|
import sonia.scm.util.AssertUtil;
|
||||||
import sonia.scm.util.HttpUtil;
|
|
||||||
import sonia.scm.util.Util;
|
import sonia.scm.util.Util;
|
||||||
|
|
||||||
//~--- JDK imports ------------------------------------------------------------
|
import javax.ws.rs.core.*;
|
||||||
|
import javax.ws.rs.core.Response.Status;
|
||||||
|
import java.net.URI;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Comparator;
|
import java.util.Comparator;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
|
||||||
import javax.ws.rs.core.CacheControl;
|
//~--- JDK imports ------------------------------------------------------------
|
||||||
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;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
@@ -140,18 +134,14 @@ public abstract class AbstractManagerResource<T extends ModelObject,
|
|||||||
{
|
{
|
||||||
preCreate(item);
|
preCreate(item);
|
||||||
|
|
||||||
Response response = null;
|
Response response;
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
manager.create(item);
|
manager.create(item);
|
||||||
|
|
||||||
String id = getId(item);
|
String id = getId(item);
|
||||||
|
response = Response.created(location(uriInfo, id)).build();
|
||||||
id = HttpUtil.encode(id);
|
|
||||||
response = Response.created(
|
|
||||||
uriInfo.getAbsolutePath().resolve(
|
|
||||||
getPathPart().concat("/").concat(id))).build();
|
|
||||||
}
|
}
|
||||||
catch (ScmSecurityException ex)
|
catch (ScmSecurityException ex)
|
||||||
{
|
{
|
||||||
@@ -167,6 +157,12 @@ public abstract class AbstractManagerResource<T extends ModelObject,
|
|||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@VisibleForTesting
|
||||||
|
URI location(UriInfo uriInfo, String id) {
|
||||||
|
String escaped = UrlEscapers.urlPathSegmentEscaper().escape(id);
|
||||||
|
return uriInfo.getAbsolutePath().resolve(getPathPart().concat("/").concat(escaped));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Method description
|
* Method description
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -0,0 +1,71 @@
|
|||||||
|
package sonia.scm.api.rest.resources;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
import org.mockito.Mock;
|
||||||
|
import org.mockito.runners.MockitoJUnitRunner;
|
||||||
|
import sonia.scm.Manager;
|
||||||
|
import sonia.scm.group.Group;
|
||||||
|
|
||||||
|
import javax.ws.rs.core.GenericEntity;
|
||||||
|
import javax.ws.rs.core.UriInfo;
|
||||||
|
import java.net.URI;
|
||||||
|
import java.net.URISyntaxException;
|
||||||
|
import java.util.Collection;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
|
@RunWith(MockitoJUnitRunner.class)
|
||||||
|
public class AbstractManagerResourceTest {
|
||||||
|
|
||||||
|
@Mock
|
||||||
|
private UriInfo uriInfo;
|
||||||
|
|
||||||
|
@Mock
|
||||||
|
private Manager<Group, Exception> manager;
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testLocation() throws URISyntaxException {
|
||||||
|
URI base = new URI("https://scm.scm-manager.org/");
|
||||||
|
|
||||||
|
TestManagerResource resource = new TestManagerResource(manager);
|
||||||
|
when(uriInfo.getAbsolutePath()).thenReturn(base);
|
||||||
|
|
||||||
|
URI uri = resource.location(uriInfo, "special-group");
|
||||||
|
assertEquals(new URI("https://scm.scm-manager.org/groups/special-group"), uri);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testLocationWithSpaces() throws URISyntaxException {
|
||||||
|
URI base = new URI("https://scm.scm-manager.org/");
|
||||||
|
|
||||||
|
TestManagerResource resource = new TestManagerResource(manager);
|
||||||
|
when(uriInfo.getAbsolutePath()).thenReturn(base);
|
||||||
|
|
||||||
|
URI uri = resource.location(uriInfo, "Scm Special Group");
|
||||||
|
assertEquals(new URI("https://scm.scm-manager.org/groups/Scm%20Special%20Group"), uri);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class TestManagerResource extends AbstractManagerResource<Group, Exception> {
|
||||||
|
|
||||||
|
private TestManagerResource(Manager<Group, Exception> manager) {
|
||||||
|
super(manager);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected GenericEntity<Collection<Group>> createGenericEntity(Collection<Group> items) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String getId(Group group) {
|
||||||
|
return group.getId();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String getPathPart() {
|
||||||
|
return "groups";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user