diff --git a/scm-webapp/src/main/java/sonia/scm/api/v2/resources/IdResourceManagerAdapter.java b/scm-webapp/src/main/java/sonia/scm/api/v2/resources/IdResourceManagerAdapter.java index c7bcc3b6b1..db5133dbf3 100644 --- a/scm-webapp/src/main/java/sonia/scm/api/v2/resources/IdResourceManagerAdapter.java +++ b/scm-webapp/src/main/java/sonia/scm/api/v2/resources/IdResourceManagerAdapter.java @@ -34,7 +34,11 @@ class IdResourceManagerAdapter applyChanges) { - return singleAdapter.update(() -> manager.get(id), applyChanges); + return singleAdapter.update( + () -> manager.get(id), + applyChanges, + changed -> changed.getId().equals(id) + ); } public Response getAll(int page, int pageSize, String sortBy, boolean desc, Function, CollectionDto> mapToDto) { diff --git a/scm-webapp/src/main/java/sonia/scm/api/v2/resources/RepositoryResource.java b/scm-webapp/src/main/java/sonia/scm/api/v2/resources/RepositoryResource.java index e6d8b80fd3..ee251051b1 100644 --- a/scm-webapp/src/main/java/sonia/scm/api/v2/resources/RepositoryResource.java +++ b/scm-webapp/src/main/java/sonia/scm/api/v2/resources/RepositoryResource.java @@ -94,7 +94,8 @@ public class RepositoryResource { public Response update(@PathParam("namespace") String namespace, @PathParam("name") String name, RepositoryDto repositoryDto) { return adapter.update( () -> manager.getByNamespace(namespace, name), - existing -> dtoToRepositoryMapper.map(repositoryDto, existing.getId()) + existing -> dtoToRepositoryMapper.map(repositoryDto, existing.getId()), + changed -> changed.getName().equals(name) && changed.getNamespace().equals(namespace) ); } diff --git a/scm-webapp/src/main/java/sonia/scm/api/v2/resources/SingleResourceManagerAdapter.java b/scm-webapp/src/main/java/sonia/scm/api/v2/resources/SingleResourceManagerAdapter.java index d5e7a97c51..547fd3654b 100644 --- a/scm-webapp/src/main/java/sonia/scm/api/v2/resources/SingleResourceManagerAdapter.java +++ b/scm-webapp/src/main/java/sonia/scm/api/v2/resources/SingleResourceManagerAdapter.java @@ -9,6 +9,7 @@ import javax.ws.rs.core.GenericEntity; import javax.ws.rs.core.Response; import java.util.Collection; import java.util.function.Function; +import java.util.function.Predicate; import java.util.function.Supplier; import static javax.ws.rs.core.Response.Status.BAD_REQUEST; @@ -48,13 +49,13 @@ class SingleResourceManagerAdapter reader, Function applyChanges) { + public Response update(Supplier reader, Function applyChanges, Predicate hasSameKey) { MODEL_OBJECT existingModelObject = reader.get(); if (existingModelObject == null) { return Response.status(Response.Status.NOT_FOUND).build(); } MODEL_OBJECT changedModelObject = applyChanges.apply(existingModelObject); - if (!getId(existingModelObject).equals(getId(changedModelObject))) { + if (!hasSameKey.test(changedModelObject)) { return Response.status(BAD_REQUEST).entity("illegal change of id").build(); } return update(getId(existingModelObject), changedModelObject); diff --git a/scm-webapp/src/test/java/sonia/scm/api/v2/resources/RepositoryRootResourceTest.java b/scm-webapp/src/test/java/sonia/scm/api/v2/resources/RepositoryRootResourceTest.java index c4ebf88c3d..c0fb0c0234 100644 --- a/scm-webapp/src/test/java/sonia/scm/api/v2/resources/RepositoryRootResourceTest.java +++ b/scm-webapp/src/test/java/sonia/scm/api/v2/resources/RepositoryRootResourceTest.java @@ -25,6 +25,7 @@ import java.net.URISyntaxException; import java.net.URL; import static java.util.Collections.singletonList; +import static javax.servlet.http.HttpServletResponse.SC_BAD_REQUEST; import static javax.servlet.http.HttpServletResponse.SC_NOT_FOUND; import static javax.servlet.http.HttpServletResponse.SC_NO_CONTENT; import static javax.servlet.http.HttpServletResponse.SC_OK; @@ -33,6 +34,7 @@ import static org.junit.Assert.assertTrue; import static org.mockito.Matchers.any; import static org.mockito.Matchers.anyObject; import static org.mockito.Matchers.eq; +import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import static org.mockito.MockitoAnnotations.initMocks; @@ -144,6 +146,25 @@ public class RepositoryRootResourceTest { verify(repositoryManager).modify(anyObject()); } + @Test + public void shouldHandleUpdateForExistingRepositoryForChangedNamespace() throws Exception { + mockRepository("wrong", "repo"); + + URL url = Resources.getResource("sonia/scm/api/v2/repository-test-update.json"); + byte[] repository = Resources.toByteArray(url); + + MockHttpRequest request = MockHttpRequest + .put("/" + RepositoryRootResource.REPOSITORIES_PATH_V2 + "wrong/repo") + .contentType(VndMediaType.REPOSITORY) + .content(repository); + MockHttpResponse response = new MockHttpResponse(); + + dispatcher.invoke(request, response); + + assertEquals(SC_BAD_REQUEST, response.getStatus()); + verify(repositoryManager, never()).modify(anyObject()); + } + @Test public void shouldHandleDeleteForExistingRepository() throws Exception { mockRepository("space", "repo");