From 54354590ac20253ec381fb8a79a910f1c08fa61b Mon Sep 17 00:00:00 2001 From: Johannes Schnatterer Date: Thu, 2 Aug 2018 13:04:06 +0200 Subject: [PATCH] SvnPlugin Config: Adds v2 endpoint --- scm-plugins/scm-svn-plugin/pom.xml | 18 -- .../scm/api/v2/resources/SvnConfigDto.java | 27 +++ .../SvnConfigDtoToSvnConfigMapper.java | 11 ++ .../api/v2/resources/SvnConfigResource.java | 94 +++++++++++ .../SvnConfigToSvnConfigDtoMapper.java | 45 +++++ .../java/sonia/scm/web/SvnServletModule.java | 12 +- .../java/sonia/scm/web/SvnVndMediaType.java | 8 + .../SvnConfigDtoToSvnConfigMapperTest.java | 42 +++++ .../v2/resources/SvnConfigResourceTest.java | 158 ++++++++++++++++++ .../SvnConfigToSvnConfigDtoMapperTest.java | 95 +++++++++++ .../sonia/scm/configuration/shiro.ini | 9 + 11 files changed, 497 insertions(+), 22 deletions(-) create mode 100644 scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/api/v2/resources/SvnConfigDto.java create mode 100644 scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/api/v2/resources/SvnConfigDtoToSvnConfigMapper.java create mode 100644 scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/api/v2/resources/SvnConfigResource.java create mode 100644 scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/api/v2/resources/SvnConfigToSvnConfigDtoMapper.java create mode 100644 scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/web/SvnVndMediaType.java create mode 100644 scm-plugins/scm-svn-plugin/src/test/java/sonia/scm/api/v2/resources/SvnConfigDtoToSvnConfigMapperTest.java create mode 100644 scm-plugins/scm-svn-plugin/src/test/java/sonia/scm/api/v2/resources/SvnConfigResourceTest.java create mode 100644 scm-plugins/scm-svn-plugin/src/test/java/sonia/scm/api/v2/resources/SvnConfigToSvnConfigDtoMapperTest.java create mode 100644 scm-plugins/scm-svn-plugin/src/test/resources/sonia/scm/configuration/shiro.ini diff --git a/scm-plugins/scm-svn-plugin/pom.xml b/scm-plugins/scm-svn-plugin/pom.xml index 9d37319394..701569e620 100644 --- a/scm-plugins/scm-svn-plugin/pom.xml +++ b/scm-plugins/scm-svn-plugin/pom.xml @@ -9,9 +9,7 @@ 2.0.0-SNAPSHOT - sonia.scm.plugins scm-svn-plugin - 2.0.0-SNAPSHOT scm-svn-plugin smp https://bitbucket.org/sdorra/scm-manager @@ -19,13 +17,6 @@ - - javax.servlet - javax.servlet-api - ${servlet.version} - provided - - sonia.svnkit svnkit @@ -44,15 +35,6 @@ ${svnkit.version} - - - - sonia.scm - scm-test - 2.0.0-SNAPSHOT - test - - diff --git a/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/api/v2/resources/SvnConfigDto.java b/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/api/v2/resources/SvnConfigDto.java new file mode 100644 index 0000000000..d0a36f1a85 --- /dev/null +++ b/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/api/v2/resources/SvnConfigDto.java @@ -0,0 +1,27 @@ +package sonia.scm.api.v2.resources; + +import de.otto.edison.hal.HalRepresentation; +import de.otto.edison.hal.Links; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; +import sonia.scm.repository.Compatibility; + +import java.io.File; + +@NoArgsConstructor +@Getter +@Setter +public class SvnConfigDto extends HalRepresentation { + + private boolean disabled; + private File repositoryDirectory; + + private boolean enabledGZip; + private Compatibility compatibility; + + @Override + protected HalRepresentation add(Links links) { + return super.add(links); + } +} diff --git a/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/api/v2/resources/SvnConfigDtoToSvnConfigMapper.java b/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/api/v2/resources/SvnConfigDtoToSvnConfigMapper.java new file mode 100644 index 0000000000..f996c49248 --- /dev/null +++ b/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/api/v2/resources/SvnConfigDtoToSvnConfigMapper.java @@ -0,0 +1,11 @@ +package sonia.scm.api.v2.resources; + +import org.mapstruct.Mapper; +import sonia.scm.repository.SvnConfig; + +// Mapstruct does not support parameterized (i.e. non-default) constructors. Thus, we need to use field injection. +@SuppressWarnings("squid:S3306") +@Mapper +public abstract class SvnConfigDtoToSvnConfigMapper { + public abstract SvnConfig map(SvnConfigDto dto); +} diff --git a/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/api/v2/resources/SvnConfigResource.java b/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/api/v2/resources/SvnConfigResource.java new file mode 100644 index 0000000000..c8050f41d3 --- /dev/null +++ b/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/api/v2/resources/SvnConfigResource.java @@ -0,0 +1,94 @@ +package sonia.scm.api.v2.resources; + +import com.webcohesion.enunciate.metadata.rs.ResponseCode; +import com.webcohesion.enunciate.metadata.rs.StatusCodes; +import com.webcohesion.enunciate.metadata.rs.TypeHint; +import sonia.scm.config.ConfigurationPermissions; +import sonia.scm.repository.SvnConfig; +import sonia.scm.repository.SvnRepositoryHandler; +import sonia.scm.web.SvnVndMediaType; + +import javax.inject.Inject; +import javax.ws.rs.Consumes; +import javax.ws.rs.GET; +import javax.ws.rs.PUT; +import javax.ws.rs.Path; +import javax.ws.rs.Produces; +import javax.ws.rs.core.Context; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.UriInfo; + +/** + * RESTful Web Service Resource to manage the configuration of the svn plugin. + */ +@Path(SvnConfigResource.SVN_CONFIG_PATH_V2) +public class SvnConfigResource { + + static final String SVN_CONFIG_PATH_V2 = "v2/config/svn"; + private final SvnConfigDtoToSvnConfigMapper dtoToConfigMapper; + private final SvnConfigToSvnConfigDtoMapper configToDtoMapper; + private final SvnRepositoryHandler repositoryHandler; + + @Inject + public SvnConfigResource(SvnConfigDtoToSvnConfigMapper dtoToConfigMapper, SvnConfigToSvnConfigDtoMapper configToDtoMapper, + SvnRepositoryHandler repositoryHandler) { + this.dtoToConfigMapper = dtoToConfigMapper; + this.configToDtoMapper = configToDtoMapper; + this.repositoryHandler = repositoryHandler; + } + + /** + * Returns the svn config. + */ + @GET + @Path("") + @Produces(SvnVndMediaType.SVN_CONFIG) + @TypeHint(SvnConfigDto.class) + @StatusCodes({ + @ResponseCode(code = 200, condition = "success"), + @ResponseCode(code = 401, condition = "not authenticated / invalid credentials"), + @ResponseCode(code = 403, condition = "not authorized, the current user has no privileges to read the git config"), + @ResponseCode(code = 500, condition = "internal server error") + }) + public Response get() { + + SvnConfig config = repositoryHandler.getConfig(); + + if (config == null) { + config = new SvnConfig(); + repositoryHandler.setConfig(config); + } + + ConfigurationPermissions.read(config).check(); + + return Response.ok(configToDtoMapper.map(config)).build(); + } + + /** + * Modifies the svn config. + * + * @param configDto new configuration object + */ + @PUT + @Path("") + @Consumes(SvnVndMediaType.SVN_CONFIG) + @StatusCodes({ + @ResponseCode(code = 204, condition = "update success"), + @ResponseCode(code = 401, condition = "not authenticated / invalid credentials"), + @ResponseCode(code = 403, condition = "not authorized, the current user has no privileges to update the git config"), + @ResponseCode(code = 500, condition = "internal server error") + }) + @TypeHint(TypeHint.NO_CONTENT.class) + public Response update(@Context UriInfo uriInfo, SvnConfigDto configDto) { + + SvnConfig config = dtoToConfigMapper.map(configDto); + + ConfigurationPermissions.write(config).check(); + + repositoryHandler.setConfig(config); + repositoryHandler.storeConfig(); + + return Response.noContent().build(); + } + +} diff --git a/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/api/v2/resources/SvnConfigToSvnConfigDtoMapper.java b/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/api/v2/resources/SvnConfigToSvnConfigDtoMapper.java new file mode 100644 index 0000000000..df974c3f3d --- /dev/null +++ b/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/api/v2/resources/SvnConfigToSvnConfigDtoMapper.java @@ -0,0 +1,45 @@ +package sonia.scm.api.v2.resources; + +import de.otto.edison.hal.Links; +import org.mapstruct.AfterMapping; +import org.mapstruct.Mapper; +import org.mapstruct.Mapping; +import org.mapstruct.MappingTarget; +import sonia.scm.config.ConfigurationPermissions; +import sonia.scm.repository.SvnConfig; + +import javax.inject.Inject; + +import static de.otto.edison.hal.Link.link; +import static de.otto.edison.hal.Links.linkingTo; + +// Mapstruct does not support parameterized (i.e. non-default) constructors. Thus, we need to use field injection. +@SuppressWarnings("squid:S3306") +@Mapper +public abstract class SvnConfigToSvnConfigDtoMapper { + + @Inject + private UriInfoStore uriInfoStore; + + @Mapping(target = "attributes", ignore = true) // We do not map HAL attributes + public abstract SvnConfigDto map(SvnConfig config); + + @AfterMapping + void appendLinks(SvnConfig config, @MappingTarget SvnConfigDto target) { + Links.Builder linksBuilder = linkingTo().self(self()); + if (ConfigurationPermissions.write(config).isPermitted()) { + linksBuilder.single(link("update", update())); + } + target.add(linksBuilder.build()); + } + + private String self() { + LinkBuilder linkBuilder = new LinkBuilder(uriInfoStore.get(), SvnConfigResource.class); + return linkBuilder.method("get").parameters().href(); + } + + private String update() { + LinkBuilder linkBuilder = new LinkBuilder(uriInfoStore.get(), SvnConfigResource.class); + return linkBuilder.method("update").parameters().href(); + } +} diff --git a/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/web/SvnServletModule.java b/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/web/SvnServletModule.java index 813f7fb0e6..9b5c8ae556 100644 --- a/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/web/SvnServletModule.java +++ b/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/web/SvnServletModule.java @@ -36,15 +36,16 @@ package sonia.scm.web; //~--- non-JDK imports -------------------------------------------------------- import com.google.inject.servlet.ServletModule; - +import org.mapstruct.factory.Mappers; +import sonia.scm.api.v2.resources.SvnConfigDtoToSvnConfigMapper; +import sonia.scm.api.v2.resources.SvnConfigToSvnConfigDtoMapper; import sonia.scm.plugin.Extension; -import sonia.scm.web.filter.AuthenticationFilter; - -//~--- JDK imports ------------------------------------------------------------ import java.util.HashMap; import java.util.Map; +//~--- JDK imports ------------------------------------------------------------ + /** * * @author Sebastian Sdorra @@ -72,6 +73,9 @@ public class SvnServletModule extends ServletModule filter(PATTERN_SVN).through(SvnBasicAuthenticationFilter.class); filter(PATTERN_SVN).through(SvnPermissionFilter.class); + bind(SvnConfigDtoToSvnConfigMapper.class).to(Mappers.getMapper(SvnConfigDtoToSvnConfigMapper.class).getClass()); + bind(SvnConfigToSvnConfigDtoMapper.class).to(Mappers.getMapper(SvnConfigToSvnConfigDtoMapper.class).getClass()); + Map parameters = new HashMap(); parameters.put(PARAMETER_SVN_PARENTPATH, diff --git a/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/web/SvnVndMediaType.java b/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/web/SvnVndMediaType.java new file mode 100644 index 0000000000..1e294df1fe --- /dev/null +++ b/scm-plugins/scm-svn-plugin/src/main/java/sonia/scm/web/SvnVndMediaType.java @@ -0,0 +1,8 @@ +package sonia.scm.web; + +public class SvnVndMediaType { + public static final String SVN_CONFIG = VndMediaType.PREFIX + "svnConfig" + VndMediaType.SUFFIX; + + private SvnVndMediaType() { + } +} diff --git a/scm-plugins/scm-svn-plugin/src/test/java/sonia/scm/api/v2/resources/SvnConfigDtoToSvnConfigMapperTest.java b/scm-plugins/scm-svn-plugin/src/test/java/sonia/scm/api/v2/resources/SvnConfigDtoToSvnConfigMapperTest.java new file mode 100644 index 0000000000..b111d0229f --- /dev/null +++ b/scm-plugins/scm-svn-plugin/src/test/java/sonia/scm/api/v2/resources/SvnConfigDtoToSvnConfigMapperTest.java @@ -0,0 +1,42 @@ +package sonia.scm.api.v2.resources; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.InjectMocks; +import org.mockito.runners.MockitoJUnitRunner; +import sonia.scm.repository.Compatibility; +import sonia.scm.repository.SvnConfig; + +import java.io.File; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +@RunWith(MockitoJUnitRunner.class) +public class SvnConfigDtoToSvnConfigMapperTest { + + @InjectMocks + private SvnConfigDtoToSvnConfigMapperImpl mapper; + + @Test + public void shouldMapFields() { + SvnConfigDto dto = createDefaultDto(); + SvnConfig config = mapper.map(dto); + + assertTrue(config.isDisabled()); + assertEquals("repository/directory", config.getRepositoryDirectory().getPath()); + + assertEquals(Compatibility.PRE15, config.getCompatibility()); + assertTrue(config.isEnabledGZip()); + } + + private SvnConfigDto createDefaultDto() { + SvnConfigDto configDto = new SvnConfigDto(); + configDto.setDisabled(true); + configDto.setRepositoryDirectory(new File("repository/directory")); + configDto.setCompatibility(Compatibility.PRE15); + configDto.setEnabledGZip(true); + + return configDto; + } +} diff --git a/scm-plugins/scm-svn-plugin/src/test/java/sonia/scm/api/v2/resources/SvnConfigResourceTest.java b/scm-plugins/scm-svn-plugin/src/test/java/sonia/scm/api/v2/resources/SvnConfigResourceTest.java new file mode 100644 index 0000000000..6c0601f977 --- /dev/null +++ b/scm-plugins/scm-svn-plugin/src/test/java/sonia/scm/api/v2/resources/SvnConfigResourceTest.java @@ -0,0 +1,158 @@ +package sonia.scm.api.v2.resources; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.node.ObjectNode; +import com.github.sdorra.shiro.ShiroRule; +import com.github.sdorra.shiro.SubjectAware; +import org.jboss.resteasy.core.Dispatcher; +import org.jboss.resteasy.mock.MockDispatcherFactory; +import org.jboss.resteasy.mock.MockHttpRequest; +import org.jboss.resteasy.mock.MockHttpResponse; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.junit.runner.RunWith; +import org.mockito.Answers; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.runners.MockitoJUnitRunner; +import sonia.scm.repository.SvnConfig; +import sonia.scm.repository.SvnRepositoryHandler; +import sonia.scm.web.SvnVndMediaType; + +import javax.servlet.http.HttpServletResponse; +import java.io.File; +import java.io.IOException; +import java.net.URI; +import java.net.URISyntaxException; + +import static junit.framework.TestCase.assertTrue; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.mockito.Mockito.when; + +@SubjectAware( + configuration = "classpath:sonia/scm/configuration/shiro.ini", + password = "secret" +) +@RunWith(MockitoJUnitRunner.class) +public class SvnConfigResourceTest { + + @Rule + public ShiroRule shiro = new ShiroRule(); + + @Rule + public ExpectedException thrown = ExpectedException.none(); + + private Dispatcher dispatcher = MockDispatcherFactory.createDispatcher(); + + private final URI baseUri = URI.create("/"); + + @InjectMocks + private SvnConfigDtoToSvnConfigMapperImpl dtoToConfigMapper; + + @Mock(answer = Answers.RETURNS_DEEP_STUBS) + private UriInfoStore uriInfoStore; + + @InjectMocks + private SvnConfigToSvnConfigDtoMapperImpl configToDtoMapper; + + @Mock + private SvnRepositoryHandler repositoryHandler; + + @Before + public void prepareEnvironment() { + SvnConfig gitConfig = createConfiguration(); + when(repositoryHandler.getConfig()).thenReturn(gitConfig); + SvnConfigResource gitConfigResource = new SvnConfigResource(dtoToConfigMapper, configToDtoMapper, repositoryHandler); + dispatcher.getRegistry().addSingletonResource(gitConfigResource); + when(uriInfoStore.get().getBaseUri()).thenReturn(baseUri); + } + + @Test + @SubjectAware(username = "readWrite") + public void shouldGetSvnConfig() throws URISyntaxException, IOException { + MockHttpResponse response = get(); + + assertEquals(HttpServletResponse.SC_OK, response.getStatus()); + + String responseString = response.getContentAsString(); + ObjectNode responseJson = new ObjectMapper().readValue(responseString, ObjectNode.class); + + assertTrue(responseString.contains("\"disabled\":false")); + assertTrue(responseJson.get("repositoryDirectory").asText().endsWith("repository/directory")); + assertTrue(responseString.contains("\"self\":{\"href\":\"/v2/config/svn")); + assertTrue(responseString.contains("\"update\":{\"href\":\"/v2/config/svn")); + } + + @Test + @SubjectAware(username = "readWrite") + public void shouldGetSvnConfigEvenWhenItsEmpty() throws URISyntaxException, IOException { + when(repositoryHandler.getConfig()).thenReturn(null); + + MockHttpResponse response = get(); + String responseString = response.getContentAsString(); + + assertTrue(responseString.contains("\"disabled\":false")); + } + + @Test + @SubjectAware(username = "readOnly") + public void shouldGetSvnConfigWithoutUpdateLink() throws URISyntaxException { + MockHttpResponse response = get(); + + assertEquals(HttpServletResponse.SC_OK, response.getStatus()); + + assertFalse(response.getContentAsString().contains("\"update\":{\"href\":\"/v2/config/svn")); + } + + @Test + @SubjectAware(username = "writeOnly") + public void shouldGetConfigOnlyWhenAuthorized() throws URISyntaxException { + thrown.expectMessage("Subject does not have permission [configuration:read:svn]"); + + get(); + } + + @Test + @SubjectAware(username = "writeOnly") + public void shouldUpdateConfig() throws URISyntaxException { + MockHttpResponse response = put(); + assertEquals(HttpServletResponse.SC_NO_CONTENT, response.getStatus()); + } + + @Test + @SubjectAware(username = "readOnly") + public void shouldUpdateConfigOnlyWhenAuthorized() throws URISyntaxException { + thrown.expectMessage("Subject does not have permission [configuration:write:svn]"); + + put(); + } + + private MockHttpResponse get() throws URISyntaxException { + MockHttpRequest request = MockHttpRequest.get("/" + SvnConfigResource.SVN_CONFIG_PATH_V2); + MockHttpResponse response = new MockHttpResponse(); + dispatcher.invoke(request, response); + return response; + } + + private MockHttpResponse put() throws URISyntaxException { + MockHttpRequest request = MockHttpRequest.put("/" + SvnConfigResource.SVN_CONFIG_PATH_V2) + .contentType(SvnVndMediaType.SVN_CONFIG) + .content("{\"disabled\":true}".getBytes()); + + MockHttpResponse response = new MockHttpResponse(); + dispatcher.invoke(request, response); + return response; + } + + private SvnConfig createConfiguration() { + SvnConfig config = new SvnConfig(); + config.setDisabled(false); + config.setRepositoryDirectory(new File("repository/directory")); + return config; + } + +} + diff --git a/scm-plugins/scm-svn-plugin/src/test/java/sonia/scm/api/v2/resources/SvnConfigToSvnConfigDtoMapperTest.java b/scm-plugins/scm-svn-plugin/src/test/java/sonia/scm/api/v2/resources/SvnConfigToSvnConfigDtoMapperTest.java new file mode 100644 index 0000000000..de7b0ecd31 --- /dev/null +++ b/scm-plugins/scm-svn-plugin/src/test/java/sonia/scm/api/v2/resources/SvnConfigToSvnConfigDtoMapperTest.java @@ -0,0 +1,95 @@ +package sonia.scm.api.v2.resources; + +import org.apache.shiro.subject.Subject; +import org.apache.shiro.subject.support.SubjectThreadState; +import org.apache.shiro.util.ThreadContext; +import org.apache.shiro.util.ThreadState; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Answers; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.runners.MockitoJUnitRunner; +import sonia.scm.repository.Compatibility; +import sonia.scm.repository.SvnConfig; + +import java.io.File; +import java.net.URI; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +@RunWith(MockitoJUnitRunner.class) +public class SvnConfigToSvnConfigDtoMapperTest { + + private URI baseUri = URI.create("http://example.com/base/"); + + @Mock(answer = Answers.RETURNS_DEEP_STUBS) + private UriInfoStore uriInfoStore; + + @InjectMocks + private SvnConfigToSvnConfigDtoMapperImpl mapper; + + private final Subject subject = mock(Subject.class); + private final ThreadState subjectThreadState = new SubjectThreadState(subject); + + private URI expectedBaseUri; + + @Before + public void init() { + when(uriInfoStore.get().getBaseUri()).thenReturn(baseUri); + expectedBaseUri = baseUri.resolve(SvnConfigResource.SVN_CONFIG_PATH_V2); + subjectThreadState.bind(); + ThreadContext.bind(subject); + } + + @After + public void unbindSubject() { + ThreadContext.unbindSubject(); + } + + @Test + public void shouldMapFields() { + SvnConfig config = createConfiguration(); + + when(subject.isPermitted("configuration:write:svn")).thenReturn(true); + SvnConfigDto dto = mapper.map(config); + + assertTrue(dto.isDisabled()); + assertEquals("repository/directory", dto.getRepositoryDirectory().getPath()); + + assertEquals(Compatibility.PRE15, dto.getCompatibility()); + assertTrue(dto.isEnabledGZip()); + + assertEquals(expectedBaseUri.toString(), dto.getLinks().getLinkBy("self").get().getHref()); + assertEquals(expectedBaseUri.toString(), dto.getLinks().getLinkBy("update").get().getHref()); + } + + @Test + public void shouldMapFieldsWithoutUpdate() { + SvnConfig config = createConfiguration(); + + when(subject.isPermitted("configuration:write:svn")).thenReturn(false); + SvnConfigDto dto = mapper.map(config); + + assertEquals(expectedBaseUri.toString(), dto.getLinks().getLinkBy("self").get().getHref()); + assertFalse(dto.getLinks().hasLink("update")); + } + + private SvnConfig createConfiguration() { + SvnConfig config = new SvnConfig(); + config.setDisabled(true); + config.setRepositoryDirectory(new File("repository/directory")); + + config.setCompatibility(Compatibility.PRE15); + config.setEnabledGZip(true); + + return config; + } + +} diff --git a/scm-plugins/scm-svn-plugin/src/test/resources/sonia/scm/configuration/shiro.ini b/scm-plugins/scm-svn-plugin/src/test/resources/sonia/scm/configuration/shiro.ini new file mode 100644 index 0000000000..7e4233b540 --- /dev/null +++ b/scm-plugins/scm-svn-plugin/src/test/resources/sonia/scm/configuration/shiro.ini @@ -0,0 +1,9 @@ +[users] +readOnly = secret, reader +writeOnly = secret, writer +readWrite = secret, readerWriter + +[roles] +reader = configuration:read:svn +writer = configuration:write:svn +readerWriter = configuration:*:svn