#965 fixed handling of resources with spaces in its id

This commit is contained in:
Sebastian Sdorra
2018-02-08 22:36:54 +01:00
parent a8186a2492
commit c216692eab
6 changed files with 129 additions and 22 deletions

View File

@@ -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);
}
} }

View File

@@ -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 ---------------------------------------------------------------

View File

@@ -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;

View File

@@ -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));
}
}
} }

View File

@@ -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
* *

View File

@@ -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";
}
}
}