diff --git a/scm-webapp/src/main/java/sonia/scm/api/v2/resources/RepositoryCollectionResource.java b/scm-webapp/src/main/java/sonia/scm/api/v2/resources/RepositoryCollectionResource.java index ad9c29f14e..d8d5280456 100644 --- a/scm-webapp/src/main/java/sonia/scm/api/v2/resources/RepositoryCollectionResource.java +++ b/scm-webapp/src/main/java/sonia/scm/api/v2/resources/RepositoryCollectionResource.java @@ -5,12 +5,15 @@ import com.webcohesion.enunciate.metadata.rs.ResponseHeader; import com.webcohesion.enunciate.metadata.rs.ResponseHeaders; import com.webcohesion.enunciate.metadata.rs.StatusCodes; import com.webcohesion.enunciate.metadata.rs.TypeHint; +import org.apache.shiro.SecurityUtils; +import sonia.scm.repository.Permission; +import sonia.scm.repository.PermissionType; import sonia.scm.repository.Repository; import sonia.scm.repository.RepositoryManager; +import sonia.scm.user.User; import sonia.scm.web.VndMediaType; import javax.inject.Inject; -import javax.inject.Named; import javax.validation.Valid; import javax.ws.rs.Consumes; import javax.ws.rs.DefaultValue; @@ -21,6 +24,8 @@ import javax.ws.rs.Produces; import javax.ws.rs.QueryParam; import javax.ws.rs.core.Response; +import static java.util.Collections.singletonList; + public class RepositoryCollectionResource { private static final int DEFAULT_PAGE_SIZE = 10; @@ -89,7 +94,17 @@ public class RepositoryCollectionResource { @ResponseHeaders(@ResponseHeader(name = "Location", description = "uri to the created repository")) public Response create(@Valid RepositoryDto repository) { return adapter.create(repository, - () -> dtoToRepositoryMapper.map(repository, null), + () -> createModelObjectFromDto(repository), r -> resourceLinks.repository().self(r.getNamespace(), r.getName())); } + + private Repository createModelObjectFromDto(@Valid RepositoryDto repositoryDto) { + Repository repository = dtoToRepositoryMapper.map(repositoryDto, null); + repository.setPermissions(singletonList(new Permission(currentUser(), PermissionType.OWNER))); + return repository; + } + + private String currentUser() { + return SecurityUtils.getSubject().getPrincipals().oneByType(User.class).getName(); + } } 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 0b2e50b6d9..fe403088f2 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 @@ -4,6 +4,9 @@ import com.github.sdorra.shiro.ShiroRule; import com.github.sdorra.shiro.SubjectAware; import com.google.common.io.Resources; import com.google.inject.util.Providers; +import org.apache.shiro.subject.SimplePrincipalCollection; +import org.apache.shiro.subject.Subject; +import org.assertj.core.api.Assertions; import org.jboss.resteasy.core.Dispatcher; import org.jboss.resteasy.mock.MockHttpRequest; import org.jboss.resteasy.mock.MockHttpResponse; @@ -22,6 +25,7 @@ import sonia.scm.repository.RepositoryIsNotArchivedException; import sonia.scm.repository.RepositoryManager; import sonia.scm.repository.api.RepositoryService; import sonia.scm.repository.api.RepositoryServiceFactory; +import sonia.scm.user.User; import sonia.scm.web.VndMediaType; import javax.servlet.http.HttpServletResponse; @@ -37,6 +41,7 @@ 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; import static javax.servlet.http.HttpServletResponse.SC_PRECONDITION_FAILED; +import static org.assertj.core.api.AssertionsForClassTypes.assertThat; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; @@ -59,6 +64,8 @@ import static sonia.scm.api.v2.resources.DispatcherMock.createDispatcher; ) public class RepositoryRootResourceTest extends RepositoryTestBase { + private static final String REALM = "AdminRealm"; + private Dispatcher dispatcher; @Rule @@ -96,6 +103,13 @@ public class RepositoryRootResourceTest extends RepositoryTestBase { when(serviceFactory.create(any(Repository.class))).thenReturn(service); when(scmPathInfoStore.get()).thenReturn(uriInfo); when(uriInfo.getApiRestUri()).thenReturn(URI.create("/x/y")); + SimplePrincipalCollection trillian = new SimplePrincipalCollection("trillian", REALM); + trillian.add(new User("trillian"), REALM); + shiro.setSubject( + new Subject.Builder() + .principals(trillian) + .authenticated(true) + .buildSubject()); } @Test @@ -257,6 +271,34 @@ public class RepositoryRootResourceTest extends RepositoryTestBase { verify(repositoryManager).create(any(Repository.class)); } + @Test + public void shouldSetCurrentUserAsOwner() throws Exception { + ArgumentCaptor createCaptor = ArgumentCaptor.forClass(Repository.class); + when(repositoryManager.create(createCaptor.capture())).thenAnswer(invocation -> { + Repository repository = (Repository) invocation.getArguments()[0]; + repository.setNamespace("otherspace"); + return repository; + }); + + URL url = Resources.getResource("sonia/scm/api/v2/repository-test-update.json"); + byte[] repositoryJson = Resources.toByteArray(url); + + MockHttpRequest request = MockHttpRequest + .post("/" + RepositoryRootResource.REPOSITORIES_PATH_V2) + .contentType(VndMediaType.REPOSITORY) + .content(repositoryJson); + MockHttpResponse response = new MockHttpResponse(); + + dispatcher.invoke(request, response); + + Assertions.assertThat(createCaptor.getValue().getPermissions()) + .hasSize(1) + .allSatisfy(p -> { + assertThat(p.getName()).isEqualTo("trillian"); + assertThat(p.getType()).isEqualTo(PermissionType.OWNER); + }); + } + @Test public void shouldNotOverwriteExistingPermissionsOnUpdate() throws Exception { Repository existingRepository = mockRepository("space", "repo");